"Fossies" - the Fresh Open Source Software Archive

Member "FunctionCheck-3.2.0/src/fcmanager/fc_xhash.c" (26 May 2012, 11109 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "fc_tools.h"
    2 #include "fc_xhash.h"
    3 
    4 /* list of prime numbers to compute size of the hash-table */
    5 static const unsigned int fc_primes[] ={
    6     109,
    7     163,
    8     251,
    9     367,
   10     557,
   11     823,
   12     1237,
   13     1861,
   14     2777,
   15     4177,
   16     6247,
   17     9371,
   18     14057,
   19     21089,
   20     31627,
   21     47431,
   22     71143,
   23     106721,
   24     160073,
   25     240101,
   26     360163,
   27     540217,
   28     810343,
   29     1215497,
   30     1823231,
   31     2734867,
   32     4102283,
   33     6153409,
   34     9230113,
   35     13845163,
   36 };
   37 
   38 static const unsigned fc_nprimes = sizeof (fc_primes) / sizeof (fc_primes[0]);
   39 
   40 /* gives the nearest prime number */
   41 unsigned int fc_spaced_primes_closest(unsigned int num)
   42 {
   43     unsigned int i;
   44 
   45     for (i = 0; i < fc_nprimes; i++)
   46         if (fc_primes[i] > num)
   47             return (fc_primes[i]);
   48 
   49     return (fc_primes[fc_nprimes - 1]);
   50 }
   51 
   52 /* gives the first prime number */
   53 #define fc_first_prime_number() (fc_primes[0])
   54 
   55 /* (!) create a hash-table */
   56 FC_Hash *fc_hash_new(void)
   57 {
   58     FC_Hash *hash;
   59     int i;
   60 
   61     hash = malloc(sizeof (FC_Hash));
   62     if (hash == NULL)
   63     {
   64         fc_message("cannot allocate a hash-table");
   65         return NULL;
   66     }
   67 
   68     /* create the initial list of nodes */
   69     hash->nodes = calloc(fc_first_prime_number(), sizeof (FC_HNode*));
   70     if (hash->nodes == NULL)
   71     {
   72         fc_message("cannot allocate nodes list for a hash-table");
   73         free(hash);
   74         return NULL;
   75     }
   76 
   77     /* create the initial nodes */
   78     hash->nb_rnodes = 0;
   79     hash->max_rnodes = 64;
   80     hash->rnodes = calloc(hash->max_rnodes, sizeof (FC_HNode));
   81     if (hash->rnodes == NULL)
   82     {
   83         fc_message("cannot allocate nodes for a hash-table");
   84         free(hash->rnodes);
   85         free(hash);
   86         return NULL;
   87     }
   88 
   89     /* initialize the nodes */
   90     for (i = 0; i < hash->max_rnodes; i++)
   91     {
   92         hash->rnodes[i].fnext = i < hash->max_rnodes - 1 ? &(hash->rnodes[i + 1]) : NULL;
   93     }
   94 
   95     hash->free_entry = &(hash->rnodes[0]);
   96 
   97     /* initialize the elements */
   98     hash->size = fc_first_prime_number();
   99     hash->nb = 0;
  100     hash->frozen = 0;
  101     hash->nb_add_rnodes = 0;
  102 
  103     for (i = 0; i < FC_HASH_MAX_ADD; i++)
  104     {
  105         hash->add_rnodes[i] = NULL;
  106     }
  107 
  108     return hash;
  109 }
  110 
  111 /* (!) destroy a hash-table */
  112 void fc_hash_destroy(FC_Hash *hash)
  113 {
  114     int i;
  115 
  116     if (hash == NULL)
  117         return;
  118 
  119     if (hash->nodes != NULL)
  120         free(hash->nodes);
  121     if (hash->rnodes != NULL)
  122         free(hash->rnodes);
  123 
  124     for (i = 0; i < hash->nb_add_rnodes; i++)
  125     {
  126         if (hash->add_rnodes[i] != NULL)
  127             free(hash->add_rnodes[i]);
  128     }
  129 
  130     free(hash);
  131 }
  132 
  133 /* (!) found a free entry in the rnode list */
  134 static FC_HNode *fc_hash_get_a_node(FC_Hash *hash)
  135 {
  136     FC_HNode *tmp;
  137     int i;
  138 
  139     /* get the next available node */
  140     tmp = hash->free_entry;
  141     /* this entry is no more free */
  142     hash->free_entry = tmp->fnext;
  143 
  144     hash->nb_rnodes++;
  145 
  146     /* no more entry available (after this one) */
  147     if (hash->free_entry == NULL)
  148     {
  149         /* reallocation of the list */
  150 
  151         /* no more blocks of nodes available */
  152         if (hash->nb_add_rnodes == FC_HASH_MAX_ADD)
  153         {/* nax number of node blocks */
  154             fc_message("no more block of nodes availalbe. Table destroyed.");
  155             fc_hash_destroy(hash);
  156             return NULL;
  157         }
  158 
  159         /* allocate a new block of nodes */
  160         hash->add_rnodes[hash->nb_add_rnodes] =
  161                 malloc(sizeof (FC_HNode)*(2 * hash->max_rnodes));
  162         if (hash->add_rnodes[hash->nb_add_rnodes] == NULL)
  163         {
  164             fc_message("cannot reallocate nodes for a hash-table. Table destroyed.");
  165             fc_hash_destroy(hash);
  166             return NULL;
  167         }
  168 
  169         /* initialize the new list of nodes */
  170         for (i = 0; i < 2 * hash->max_rnodes; i++)
  171         {
  172             hash->add_rnodes[hash->nb_add_rnodes][i].fnext =
  173                     (i < 2 * hash->max_rnodes - 1) ? &(hash->add_rnodes[hash->nb_add_rnodes][i + 1]) : NULL;
  174         }
  175 
  176         hash->free_entry = &(hash->add_rnodes[hash->nb_add_rnodes][0]);
  177         hash->max_rnodes *= 2;
  178         hash->nb_add_rnodes++;
  179     }
  180 
  181     return tmp;
  182 }
  183 
  184 /* insert the given node in the temporary list */
  185 
  186 /* the field fnext is used to keep the new links */
  187 static void fc_hash_insert_known(FC_HNode **nodes, FC_HNode *nd, int size)
  188 {
  189     int index;
  190     FC_HNode *tmp;
  191 
  192     /* compute its new index */
  193     index = (((unsigned int) (nd->key))) % size;
  194 
  195     nd->next = NULL;
  196     if (nodes[index] == NULL)
  197     {
  198         nodes[index] = nd;
  199     }
  200     else
  201     {
  202         tmp = nodes[index];
  203         while (tmp->next != NULL)
  204         {
  205             tmp = tmp->next;
  206         }
  207         tmp->next = nd;
  208     }
  209 }
  210 
  211 /* (!) increase the size of the hash-table */
  212 static void fc_hash_increase_size(FC_Hash *hash)
  213 {
  214     FC_HNode **new_nodes = NULL, *tmp = NULL;
  215     int new_size = 0;
  216     int i;
  217 
  218     if (hash->frozen)
  219         return;
  220 
  221     /* to prevent re-calls to this functions */
  222     hash->frozen = 1;
  223 
  224     new_size = (int) fc_spaced_primes_closest((unsigned int) hash->size);
  225 
  226     /* create the new list */
  227     new_nodes = calloc(new_size, sizeof (FC_HNode*));
  228 
  229     /* for each existing entry, re-hash it in the new table */
  230     for (i = 0; i < hash->size; i++)
  231     {
  232         tmp = hash->nodes[i];
  233         while (tmp != NULL)
  234         {
  235             /* remove it from the current list */
  236             hash->nodes[i] = tmp->next;
  237             /* and re-insert it in the table (without creation) */
  238             fc_hash_insert_known(new_nodes, tmp, new_size);
  239 
  240             /* agin until this part is empty */
  241             tmp = hash->nodes[i];
  242         }
  243     }
  244     /* replace the new list */
  245     hash->nodes = new_nodes;
  246     hash->size = new_size;
  247 
  248     hash->frozen = 0;
  249 }
  250 
  251 /* debug */
  252 void fc_hash_debug(FC_Hash *hash)
  253 {
  254     int i;
  255     FC_HNode *tmp;
  256 
  257     if (hash == NULL)
  258         return;
  259 
  260     for (i = 0; i < hash->size; i++)
  261     {
  262         printf("Point %d: [%p]\n", i, hash->nodes[i]);
  263         tmp = hash->nodes[i];
  264         while (tmp != NULL)
  265         {
  266             printf("k=%p [%p] : ", tmp->key, tmp);
  267             tmp = tmp->next;
  268         }
  269         printf("\n");
  270     }
  271 }
  272 
  273 /* returns the corresp. node if any */
  274 static FC_HNode *fc_hash_lookup_node(FC_Hash *hash, void *key)
  275 {
  276     int index;
  277     FC_HNode *tmp;
  278 
  279     if ((hash == NULL) || (key == NULL))
  280         return NULL;
  281 
  282     /* compute the hash position */
  283     index = (((unsigned int) key)) % hash->size;
  284 
  285     tmp = hash->nodes[index];
  286 
  287     while (tmp != NULL)
  288     {
  289         if (tmp->key == key)
  290         {
  291             return tmp;
  292         }
  293         tmp = tmp->next;
  294     }
  295 
  296     /* not found */
  297     return NULL;
  298 }
  299 
  300 /* (!) insert an element in a hash-table */
  301 void fc_hash_insert(FC_Hash *hash, void *key,
  302                     int val, void *ptr1, void *ptr2)
  303 {
  304     int index;
  305     FC_HNode *tmp, *pos;
  306 
  307     if ((hash == NULL) || (key == NULL))
  308         return;
  309 
  310     /* first try to get the element */
  311     tmp = fc_hash_lookup_node(hash, key);
  312 
  313     /* still here, just modify it */
  314     if (tmp != NULL)
  315     {
  316         tmp->key = key;
  317         tmp->value = val;
  318         tmp->ptr1 = ptr1;
  319         tmp->ptr2 = ptr2;
  320         return;
  321     }
  322 
  323     /* compute the hash position */
  324     index = (((unsigned int) key)) % hash->size;
  325 
  326     /* get a new node */
  327     tmp = fc_hash_get_a_node(hash);
  328     tmp->key = key;
  329     tmp->value = val;
  330     tmp->ptr1 = ptr1;
  331     tmp->ptr2 = ptr2;
  332 
  333     /* insert it */
  334     tmp->next = NULL;
  335     if (hash->nodes[index] == NULL)
  336     {
  337         hash->nodes[index] = tmp;
  338     }
  339     else
  340     {
  341         pos = hash->nodes[index];
  342         while (pos->next != NULL)
  343         {
  344             pos = pos->next;
  345         }
  346         pos->next = tmp;
  347     }
  348 
  349     /* one more element */
  350     hash->nb++;
  351 
  352     /* if the number of element is too high, resize */
  353     if ((float) hash->nb / hash->size > 0.85)
  354     {
  355         fc_hash_increase_size(hash);
  356     }
  357 }
  358 
  359 /* (!) search an element in a hash-table */
  360 int fc_hash_lookup(FC_Hash *hash, void *key,
  361                    int *val, void **ptr1, void **ptr2)
  362 {
  363     int index;
  364     FC_HNode *tmp;
  365 
  366     if ((hash == NULL) || (key == NULL))
  367         return 0;
  368 
  369     /* compute the hash position */
  370     index = (((unsigned int) key)) % hash->size;
  371 
  372     tmp = hash->nodes[index];
  373 
  374     while (tmp != NULL)
  375     {
  376         if (tmp->key == key)
  377         {
  378             *val = tmp->value;
  379             *ptr1 = tmp->ptr1;
  380             *ptr2 = tmp->ptr2;
  381             return 1;
  382         }
  383         tmp = tmp->next;
  384     }
  385 
  386     return 0;
  387 }
  388 
  389 /* (!) search an element in a hash-table and return pointers
  390    on the entries (in order to modify their values without
  391    having to remove/modify/insert.
  392    WARNING: these pointers are only valid until you perfom
  393             an other action on this hash-table. after any
  394             operation they may become invalid */
  395 int fc_hash_lookup_modify(FC_Hash *hash, void *key,
  396                           int **val, void ***ptr1, void ***ptr2)
  397 {
  398     int index;
  399     FC_HNode *tmp;
  400 
  401     if ((hash == NULL) || (key == NULL))
  402         return 0;
  403 
  404     /* compute the hash position */
  405     index = (((unsigned int) key)) % hash->size;
  406 
  407     tmp = hash->nodes[index];
  408 
  409     while (tmp != NULL)
  410     {
  411         if (tmp->key == key)
  412         {
  413             *val = &(tmp->value);
  414             *ptr1 = &(tmp->ptr1);
  415             *ptr2 = &(tmp->ptr2);
  416             return 1;
  417         }
  418         tmp = tmp->next;
  419     }
  420 
  421     *val = NULL;
  422     *ptr1 = NULL;
  423     *ptr2 = NULL;
  424     return 0;
  425 }
  426 
  427 /* (!) remove an element from a hash-table */
  428 void fc_hash_remove(FC_Hash *hash, void *key)
  429 {
  430     int index;
  431     FC_HNode *tmp, *otmp;
  432 
  433     if ((hash == NULL) || (key == NULL))
  434         return;
  435 
  436     /* compute the hash position */
  437     index = (((unsigned int) key)) % hash->size;
  438 
  439     otmp = NULL;
  440     tmp = hash->nodes[index];
  441 
  442     while (tmp != NULL)
  443     {
  444         if (tmp->key == key)
  445         {
  446             /* the old one points to the current next */
  447             if (otmp != NULL)
  448             {
  449                 otmp->next = tmp->next;
  450             }
  451             else
  452             {
  453                 /* the first */
  454                 hash->nodes[index] = tmp->next;
  455             }
  456 
  457             /* add the node in the free list */
  458             tmp->fnext = hash->free_entry;
  459             hash->free_entry = tmp;
  460             tmp->key = NULL;
  461             hash->nb--;
  462 
  463             /* done */
  464             return;
  465         }
  466         /* next entry */
  467         otmp = tmp;
  468         tmp = tmp->next;
  469     }
  470 
  471     /* entry not found */
  472 }
  473 
  474 /* (!) apply a function to each elements of the hash-table */
  475 void fc_hash_foreach(FC_Hash *hash, FC_HFunc func, void *data)
  476 {
  477     int i;
  478     FC_HNode *tmp;
  479 
  480     if ((hash == NULL) || (func == NULL))
  481         return;
  482 
  483     /* for each list */
  484     for (i = 0; i < hash->size; i++)
  485     {
  486         tmp = hash->nodes[i];
  487         while (tmp != NULL)
  488         {
  489             (func) (tmp->key, tmp->value, tmp->ptr1,
  490                     tmp->ptr2, data);
  491 
  492             tmp = tmp->next;
  493         }
  494     }
  495 }
  496 
  497 /* (!) get the number of elements in the hash-table */
  498 int fc_hash_size(FC_Hash *hash)
  499 {
  500     if (hash == NULL)
  501         return (0);
  502     return (hash->nb);
  503 }
  504