LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/geojson/jsonc - linkhash.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 110 61 55.5 %
Date: 2010-01-09 Functions: 15 8 53.3 %

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

Generated by: LCOV version 1.7