LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/base - dict.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 77 97 79.4 %
Date: 2024-04-21 15:09:00 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2002, 1997 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include "baselocl.h"
      37             : 
      38             : struct hashentry {
      39             :     struct hashentry **prev;
      40             :     struct hashentry *next;
      41             :     heim_object_t key;
      42             :     heim_object_t value;
      43             : };
      44             : 
      45             : struct heim_dict_data {
      46             :     size_t size;
      47             :     struct hashentry **tab;
      48             : };
      49             : 
      50             : static void HEIM_CALLCONV
      51      209378 : dict_dealloc(void *ptr)
      52             : {
      53      209378 :     heim_dict_t dict = ptr;
      54        6826 :     struct hashentry **h, *g, *i;
      55             : 
      56     1465646 :     for (h = dict->tab; h < &dict->tab[dict->size]; ++h) {
      57     2233365 :         for (g = h[0]; g; g = i) {
      58      977097 :             i = g->next;
      59      977097 :             heim_release(g->key);
      60      977097 :             heim_release(g->value);
      61      977097 :             free(g);
      62             :         }
      63             :     }
      64      209378 :     free(dict->tab);
      65      209378 : }
      66             : 
      67             : struct heim_type_data dict_object = {
      68             :     HEIM_TID_DICT,
      69             :     "dict-object",
      70             :     NULL,
      71             :     dict_dealloc,
      72             :     NULL,
      73             :     NULL,
      74             :     NULL,
      75             :     NULL
      76             : };
      77             : 
      78             : static size_t
      79      341889 : isprime(size_t p)
      80             : {
      81       11893 :     size_t q, i;
      82             : 
      83     1046498 :     for(i = 2 ; i < p; i++) {
      84      941809 :         q = p / i;
      85             : 
      86      941809 :         if (i * q == p)
      87           0 :             return 0;
      88      941809 :         if (i * i > p)
      89      228720 :             return 1;
      90             :     }
      91      101276 :     return 1;
      92             : }
      93             : 
      94             : static size_t
      95      341889 : findprime(size_t p)
      96             : {
      97      341889 :     if (p % 2 == 0)
      98      104689 :         p++;
      99             : 
     100      353782 :     while (isprime(p) == 0)
     101           0 :         p += 2;
     102             : 
     103      341889 :     return p;
     104             : }
     105             : 
     106             : /**
     107             :  * Allocate an array
     108             :  *
     109             :  * @return A new allocated array, free with heim_release()
     110             :  */
     111             : 
     112             : heim_dict_t
     113      341889 : heim_dict_create(size_t size)
     114             : {
     115       11893 :     heim_dict_t dict;
     116             : 
     117      341889 :     dict = _heim_alloc_object(&dict_object, sizeof(*dict));
     118      341889 :     if (dict == NULL)
     119           0 :         return NULL;
     120             : 
     121      341889 :     dict->size = findprime(size);
     122      341889 :     if (dict->size == 0) {
     123           0 :         heim_release(dict);
     124           0 :         return NULL;
     125             :     }
     126             : 
     127      341889 :     dict->tab = calloc(dict->size, sizeof(dict->tab[0]));
     128      341889 :     if (dict->tab == NULL) {
     129           0 :         dict->size = 0;
     130           0 :         heim_release(dict);
     131           0 :         return NULL;
     132             :     }
     133             : 
     134      329996 :     return dict;
     135             : }
     136             : 
     137             : /**
     138             :  * Get type id of an dict
     139             :  *
     140             :  * @return the type id
     141             :  */
     142             : 
     143             : heim_tid_t
     144           0 : heim_dict_get_type_id(void)
     145             : {
     146           0 :     return HEIM_TID_DICT;
     147             : }
     148             : 
     149             : /* Intern search function */
     150             : 
     151             : static struct hashentry *
     152     5027567 : _search(heim_dict_t dict, heim_object_t ptr)
     153             : {
     154     5027567 :     uintptr_t v = heim_get_hash(ptr);
     155      163622 :     struct hashentry *p;
     156             : 
     157     6214191 :     for (p = dict->tab[v % dict->size]; p != NULL; p = p->next)
     158     3258957 :         if (heim_cmp(ptr, p->key) == 0)
     159     2072333 :             return p;
     160             : 
     161     2857792 :     return NULL;
     162             : }
     163             : 
     164             : /**
     165             :  * Search for element in hash table
     166             :  *
     167             :  * @value dict the dict to search in
     168             :  * @value key the key to search for
     169             :  *
     170             :  * @return a not-retained copy of the value for key or NULL if not found
     171             :  */
     172             : 
     173             : heim_object_t
     174      996949 : heim_dict_get_value(heim_dict_t dict, heim_object_t key)
     175             : {
     176       35606 :     struct hashentry *p;
     177      996949 :     p = _search(dict, key);
     178      996949 :     if (p == NULL)
     179      841354 :         return NULL;
     180             : 
     181      124685 :     return p->value;
     182             : }
     183             : 
     184             : /**
     185             :  * Search for element in hash table
     186             :  *
     187             :  * @value dict the dict to search in
     188             :  * @value key the key to search for
     189             :  *
     190             :  * @return a retained copy of the value for key or NULL if not found
     191             :  */
     192             : 
     193             : heim_object_t
     194     2860742 : heim_dict_copy_value(heim_dict_t dict, heim_object_t key)
     195             : {
     196       85881 :     struct hashentry *p;
     197     2860742 :     p = _search(dict, key);
     198     2860742 :     if (p == NULL)
     199      947386 :         return NULL;
     200             : 
     201     1886619 :     return heim_retain(p->value);
     202             : }
     203             : 
     204             : /**
     205             :  * Add key and value to dict
     206             :  *
     207             :  * @value dict the dict to add too
     208             :  * @value key the key to add
     209             :  * @value value the value to add
     210             :  *
     211             :  * @return 0 if added, errno if not
     212             :  */
     213             : 
     214             : int
     215     1169876 : heim_dict_set_value(heim_dict_t dict, heim_object_t key, heim_object_t value)
     216             : {
     217       42135 :     struct hashentry **tabptr, *h;
     218             : 
     219     1169876 :     h = _search(dict, key);
     220     1169876 :     if (h) {
     221       61029 :         heim_release(h->value);
     222       61029 :         h->value = heim_retain(value);
     223             :     } else {
     224       39795 :         uintptr_t v;
     225             : 
     226     1108847 :         h = malloc(sizeof(*h));
     227     1108847 :         if (h == NULL)
     228           0 :             return ENOMEM;
     229             : 
     230     1108847 :         h->key = heim_retain(key);
     231     1108847 :         h->value = heim_retain(value);
     232             : 
     233     1108847 :         v = heim_get_hash(key);
     234             : 
     235     1108847 :         tabptr = &dict->tab[v % dict->size];
     236     1108847 :         h->next = *tabptr;
     237     1108847 :         *tabptr = h;
     238     1108847 :         h->prev = tabptr;
     239     1108847 :         if (h->next)
     240      313906 :             h->next->prev = &h->next;
     241             :     }
     242             : 
     243     1127741 :     return 0;
     244             : }
     245             : 
     246             : /**
     247             :  * Delete element with key key
     248             :  *
     249             :  * @value dict the dict to delete from
     250             :  * @value key the key to delete
     251             :  */
     252             : 
     253             : void
     254           0 : heim_dict_delete_key(heim_dict_t dict, heim_object_t key)
     255             : {
     256           0 :     struct hashentry *h = _search(dict, key);
     257             : 
     258           0 :     if (h == NULL)
     259           0 :         return;
     260             : 
     261           0 :     heim_release(h->key);
     262           0 :     heim_release(h->value);
     263             : 
     264           0 :     if ((*(h->prev) = h->next) != NULL)
     265           0 :         h->next->prev = h->prev;
     266             : 
     267           0 :     free(h);
     268             : }
     269             : 
     270             : /**
     271             :  * Do something for each element
     272             :  *
     273             :  * @value dict the dict to interate over
     274             :  * @value func the function to search for
     275             :  * @value arg argument to func
     276             :  */
     277             : 
     278             : void
     279     1465724 : heim_dict_iterate_f(heim_dict_t dict, void *arg, heim_dict_iterator_f_t func)
     280             : {
     281       43794 :     struct hashentry **h, *g;
     282             : 
     283    17588688 :     for (h = dict->tab; h < &dict->tab[dict->size]; ++h)
     284    18461096 :         for (g = *h; g; g = g->next)
     285     2338132 :             func(g->key, g->value, arg);
     286     1465724 : }
     287             : 
     288             : #ifdef __BLOCKS__
     289             : /**
     290             :  * Do something for each element
     291             :  *
     292             :  * @value dict the dict to interate over
     293             :  * @value func the function to search for
     294             :  */
     295             : 
     296             : void
     297             : heim_dict_iterate(heim_dict_t dict, void (^func)(heim_object_t, heim_object_t))
     298             : {
     299             :     struct hashentry **h, *g;
     300             : 
     301             :     for (h = dict->tab; h < &dict->tab[dict->size]; ++h)
     302             :         for (g = *h; g; g = g->next)
     303             :             func(g->key, g->value);
     304             : }
     305             : #endif

Generated by: LCOV version 1.14