LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/geojson/jsonc - linkhash.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 111 79 71.2 %
Date: 2012-12-26 Functions: 15 10 66.7 %

       1                 : /*
       2                 :  * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
       3                 :  *
       4                 :  * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
       5                 :  * Michael Clark <michael@metaparadigm.com>
       6                 :  *
       7                 :  * This library is free software; you can redistribute it and/or modify
       8                 :  * it under the terms of the MIT license. See COPYING for details.
       9                 :  *
      10                 :  */
      11                 : 
      12                 : #include <stdio.h>
      13                 : #include <string.h>
      14                 : #include <stdlib.h>
      15                 : #include <stdarg.h>
      16                 : #include <stddef.h>
      17                 : #include <limits.h>
      18                 : 
      19                 : #include "linkhash.h"
      20                 : 
      21               0 : void lh_abort(const char *msg, ...)
      22                 : {
      23                 :   va_list ap;
      24               0 :   va_start(ap, msg);
      25               0 :   vprintf(msg, ap);
      26               0 :   va_end(ap);
      27               0 :   exit(1);
      28                 : }
      29                 : 
      30               0 : unsigned long lh_ptr_hash(const void *k)
      31                 : {
      32                 :   /* CAW: refactored to be 64bit nice */
      33               0 :   return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
      34                 : }
      35                 : 
      36               0 : int lh_ptr_equal(const void *k1, const void *k2)
      37                 : {
      38               0 :   return (k1 == k2);
      39                 : }
      40                 : 
      41           12697 : unsigned long lh_char_hash(const void *k)
      42                 : {
      43           12697 :   unsigned int h = 0;
      44           12697 :   const char* data = (const char*)k;
      45                 :  
      46           12697 :   while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
      47                 : 
      48           12697 :   return h;
      49                 : }
      50                 : 
      51            4108 : int lh_char_equal(const void *k1, const void *k2)
      52                 : {
      53            4108 :   return (strcmp((const char*)k1, (const char*)k2) == 0);
      54                 : }
      55                 : 
      56            1441 : struct lh_table* lh_table_new(int size, const char *name,
      57                 :             lh_entry_free_fn *free_fn,
      58                 :             lh_hash_fn *hash_fn,
      59                 :             lh_equal_fn *equal_fn)
      60                 : {
      61                 :   int i;
      62                 :   struct lh_table *t;
      63                 : 
      64            1441 :   t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
      65            1441 :   if(!t) lh_abort("lh_table_new: calloc failed\n");
      66            1441 :   t->count = 0;
      67            1441 :   t->size = size;
      68            1441 :   t->name = name;
      69            1441 :   t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
      70            1441 :   if(!t->table) lh_abort("lh_table_new: calloc failed\n");
      71            1441 :   t->free_fn = free_fn;
      72            1441 :   t->hash_fn = hash_fn;
      73            1441 :   t->equal_fn = equal_fn;
      74            1441 :   for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
      75            1441 :   return t;
      76                 : }
      77                 : 
      78            1394 : struct lh_table* lh_kchar_table_new(int size, const char *name,
      79                 :             lh_entry_free_fn *free_fn)
      80                 : {
      81            1394 :   return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
      82                 : }
      83                 : 
      84               0 : struct lh_table* lh_kptr_table_new(int size, const char *name,
      85                 :            lh_entry_free_fn *free_fn)
      86                 : {
      87               0 :   return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
      88                 : }
      89                 : 
      90              47 : void lh_table_resize(struct lh_table *t, int new_size)
      91                 : {
      92                 :   struct lh_table *new_t;
      93                 :   struct lh_entry *ent;
      94                 : 
      95              47 :   new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
      96              47 :   ent = t->head;
      97             611 :   while(ent) {
      98             517 :     lh_table_insert(new_t, ent->k, ent->v);
      99             517 :     ent = ent->next;
     100                 :   }
     101              47 :   free(t->table);
     102              47 :   t->table = new_t->table;
     103              47 :   t->size = new_size;
     104              47 :   t->head = new_t->head;
     105              47 :   t->tail = new_t->tail;
     106              47 :   t->resizes++;
     107              47 :   free(new_t);
     108              47 : }
     109                 : 
     110            1394 : void lh_table_free(struct lh_table *t)
     111                 : {
     112                 :   struct lh_entry *c;
     113            6744 :   for(c = t->head; c != NULL; c = c->next) {
     114            5350 :     if(t->free_fn) {
     115            5350 :       t->free_fn(c);
     116                 :     }
     117                 :   }
     118            1394 :   free(t->table);
     119            1394 :   free(t);
     120            1394 : }
     121                 : 
     122                 : 
     123            5867 : int lh_table_insert(struct lh_table *t, void *k, const void *v)
     124                 : {
     125                 :   unsigned long h, n;
     126                 : 
     127            5867 :   t->inserts++;
     128            5867 :   if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2);
     129                 : 
     130            5867 :   h = t->hash_fn(k);
     131            5867 :   n = h % t->size;
     132                 : 
     133                 :   while( 1 ) {
     134            7947 :     if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
     135            2080 :     t->collisions++;
     136            2080 :     if(++n == t->size) n = 0;
     137            2080 :   }
     138                 : 
     139            5867 :   t->table[n].k = k;
     140            5867 :   t->table[n].v = v;
     141            5867 :   t->count++;
     142                 : 
     143            5867 :   if(t->head == NULL) {
     144            1369 :     t->head = t->tail = &t->table[n];
     145            1369 :     t->table[n].next = t->table[n].prev = NULL;
     146                 :   } else {
     147            4498 :     t->tail->next = &t->table[n];
     148            4498 :     t->table[n].prev = t->tail;
     149            4498 :     t->table[n].next = NULL;
     150            4498 :     t->tail = &t->table[n];
     151                 :   }
     152                 : 
     153            5867 :   return 0;
     154                 : }
     155                 : 
     156                 : 
     157            6830 : struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
     158                 : {
     159            6830 :   unsigned long h = t->hash_fn(k);
     160            6830 :   unsigned long n = h % t->size;
     161                 : 
     162            6830 :   t->lookups++;
     163                 :   while( 1 ) {
     164            9668 :     if(t->table[n].k == LH_EMPTY) return NULL;
     165            8216 :     if(t->table[n].k != LH_FREED &&
     166            5378 :        t->equal_fn(t->table[n].k, k)) return &t->table[n];
     167            2838 :     if(++n == t->size) n = 0;
     168            2838 :   }
     169                 :   return NULL;
     170                 : }
     171                 : 
     172                 : 
     173            1480 : const void* lh_table_lookup(struct lh_table *t, const void *k)
     174                 : {
     175            1480 :   struct lh_entry *e = lh_table_lookup_entry(t, k);
     176            1480 :   if(e) return e->v;
     177             210 :   return NULL;
     178                 : }
     179                 : 
     180                 : 
     181               0 : int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
     182                 : {
     183               0 :   ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
     184                 : 
     185                 :   /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
     186               0 :   if(n < 0) { return -2; }
     187                 : 
     188               0 :   if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
     189               0 :   t->count--;
     190               0 :   if(t->free_fn) t->free_fn(e);
     191               0 :   t->table[n].v = NULL;
     192               0 :   t->table[n].k = LH_FREED;
     193               0 :   if(t->tail == &t->table[n] && t->head == &t->table[n]) {
     194               0 :     t->head = t->tail = NULL;
     195               0 :   } else if (t->head == &t->table[n]) {
     196               0 :     t->head->next->prev = NULL;
     197               0 :     t->head = t->head->next;
     198               0 :   } else if (t->tail == &t->table[n]) {
     199               0 :     t->tail->prev->next = NULL;
     200               0 :     t->tail = t->tail->prev;
     201                 :   } else {
     202               0 :     t->table[n].prev->next = t->table[n].next;
     203               0 :     t->table[n].next->prev = t->table[n].prev;
     204                 :   }
     205               0 :   t->table[n].next = t->table[n].prev = NULL;
     206               0 :   return 0;
     207                 : }
     208                 : 
     209                 : 
     210            5350 : int lh_table_delete(struct lh_table *t, const void *k)
     211                 : {
     212            5350 :   struct lh_entry *e = lh_table_lookup_entry(t, k);
     213            5350 :   if(!e) return -1;
     214               0 :   return lh_table_delete_entry(t, e);
     215                 : }
     216                 : 

Generated by: LCOV version 1.7