-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
replaced hsearch which was causing problems on APPLE with custom hash…
…table - issue #76
- Loading branch information
Showing
7 changed files
with
423 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,4 +26,6 @@ rtree.c \ | |
svg.c \ | ||
svg_landscape.c \ | ||
util.c \ | ||
utree.c | ||
utree.c \ | ||
hash.c \ | ||
list.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/* | ||
Copyright (C) 2015-2017 Tomas Flouri | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as | ||
published by the Free Software Foundation, either version 3 of the | ||
License, or (at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
Contact: Tomas Flouri <[email protected]>, | ||
Heidelberg Institute for Theoretical Studies, | ||
Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany | ||
*/ | ||
|
||
#include "mptp.h" | ||
|
||
|
||
/* Daniel J. Bernstein 2a hash function */ | ||
unsigned long hash_djb2a(char * s) | ||
{ | ||
unsigned long hash = 5381; | ||
unsigned long c; | ||
|
||
while ((c = (unsigned long)*s++)) | ||
hash = ((hash << 5) + hash) ^ c; /* hash*33 ^ c */ | ||
|
||
return hash; | ||
} | ||
|
||
/* Fowler–Noll–Vo 1a hash function */ | ||
unsigned long hash_fnv(char * s) | ||
{ | ||
unsigned long hash = 14695981039346656037UL; | ||
unsigned long c; | ||
|
||
while ((c = (unsigned long)*s++)) | ||
{ | ||
hash ^= c; | ||
hash *= 1099511628211UL; | ||
} | ||
|
||
return hash; | ||
} | ||
|
||
static ht_item_t * hashitem_create(unsigned long key, void * value) | ||
{ | ||
ht_item_t * hi = (ht_item_t *)xmalloc(sizeof(ht_item_t)); | ||
|
||
hi->key = key; | ||
hi->value = value; | ||
|
||
return hi; | ||
} | ||
|
||
int hashtable_strcmp(void * x, void * y) | ||
{ | ||
return !strcmp((char *)x, (char *)y); | ||
} | ||
|
||
int hashtable_ptrcmp(void * x, void * y) | ||
{ | ||
return (x == y); | ||
} | ||
|
||
int hashtable_paircmp(void * stored, void * query) | ||
{ | ||
pair_t * stored_pair = (pair_t *)stored; | ||
char * query_label = (char *)query; | ||
|
||
return !strcmp(stored_pair->label, query_label); | ||
} | ||
|
||
void * hashtable_find(hashtable_t * ht, | ||
void * x, | ||
unsigned long hash, | ||
int (*cb_cmp)(void *, void *)) | ||
{ | ||
unsigned long index = hash & (ht->table_size-1); | ||
list_item_t * li = (list_item_t *)(ht->entries[index]->head); | ||
|
||
while (li) | ||
{ | ||
ht_item_t * hi = (ht_item_t *)(li->data); | ||
|
||
if ((hash == hi->key) && cb_cmp(hi->value, x)) | ||
return hi->value; | ||
|
||
li = li->next; | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
|
||
hashtable_t * hashtable_create(unsigned long items_count) | ||
{ | ||
unsigned long i; | ||
unsigned long size = 1; | ||
|
||
if (!items_count) return NULL; | ||
|
||
/* compute a size of at least double the items count that is a | ||
multiple of 2 */ | ||
items_count <<= 1; | ||
while (size < items_count) | ||
size <<= 1; | ||
|
||
/* allocate and init hash table */ | ||
hashtable_t * ht = (hashtable_t *)xmalloc(sizeof(hashtable_t)); | ||
ht->table_size = size; | ||
ht->entries_count = 0; | ||
|
||
/* allocate and init entries array */ | ||
ht->entries = (list_t **)xmalloc(size*sizeof(list_t *)); | ||
for (i = 0; i < size; ++i) | ||
{ | ||
ht->entries[i] = (list_t *)xmalloc(sizeof(list_t)); | ||
memset(ht->entries[i], 0, sizeof(list_t)); | ||
} | ||
|
||
return ht; | ||
} | ||
|
||
int hashtable_insert(hashtable_t * ht, | ||
void * x, | ||
unsigned long hash, | ||
int (*cb_cmp)(void *, void *)) | ||
{ | ||
/* size is always a multiple of 2 and greater than 2 */ | ||
unsigned long index = hash & (ht->table_size-1); | ||
|
||
list_t * list = ht->entries[index]; | ||
|
||
|
||
if (hashtable_find(ht, x, hash, cb_cmp)) | ||
return 0; | ||
|
||
ht_item_t * item = hashitem_create(hash,x); | ||
list_append(list, item); | ||
|
||
ht->entries_count++; | ||
|
||
return 1; | ||
} | ||
|
||
void hashtable_destroy(hashtable_t * ht, void (*cb_dealloc)(void *)) | ||
{ | ||
unsigned long i; | ||
|
||
if (cb_dealloc) | ||
{ | ||
for (i = 0; i < ht->table_size; ++i) | ||
{ | ||
list_t * list = ht->entries[i]; | ||
|
||
list_item_t * head = list->head; | ||
while (head) | ||
{ | ||
ht_item_t * hi = (ht_item_t *)(head->data); | ||
cb_dealloc(hi->value); | ||
head = head->next; | ||
} | ||
} | ||
} | ||
|
||
for (i = 0; i < ht->table_size; ++i) | ||
{ | ||
list_clear(ht->entries[i], free); | ||
free(ht->entries[i]); | ||
} | ||
free(ht->entries); | ||
free(ht); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
Copyright (C) 2015 Tomas Flouri | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as | ||
published by the Free Software Foundation, either version 3 of the | ||
License, or (at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
Contact: Tomas Flouri <[email protected]>, | ||
Heidelberg Institute for Theoretical Studies, | ||
Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany | ||
*/ | ||
|
||
#include "mptp.h" | ||
|
||
#define DEF_LIST_APPEND 0 | ||
#define DEF_LIST_PREPEND 1 | ||
|
||
static int list_insert(list_t * list, void * data, int where) | ||
{ | ||
if (!list) return 0; | ||
|
||
/* create list item */ | ||
list_item_t * item = (list_item_t *)xmalloc(sizeof(list_item_t)); | ||
item->data = data; | ||
|
||
/* if list is empty */ | ||
if (!(list->count)) | ||
{ | ||
list->head = list->tail = item; | ||
list->count = 1; | ||
item->next = NULL; | ||
return 1; | ||
} | ||
|
||
/* append */ | ||
if (where == DEF_LIST_APPEND) | ||
{ | ||
list->tail->next = item; | ||
list->tail = item; | ||
item->next = NULL; | ||
list->count++; | ||
return 1; | ||
} | ||
|
||
/* prepend */ | ||
item->next = list->head; | ||
list->head = item; | ||
list->count++; | ||
|
||
return 1; | ||
} | ||
|
||
void list_append(list_t * list, void * data) | ||
{ | ||
list_insert(list, data, DEF_LIST_APPEND); | ||
} | ||
|
||
void list_prepend(list_t * list, void * data) | ||
{ | ||
list_insert(list, data, DEF_LIST_PREPEND); | ||
} | ||
|
||
void list_clear(list_t * list, void (*cb_dealloc)(void *)) | ||
{ | ||
if (!list) return; | ||
|
||
list_item_t * head = list->head; | ||
|
||
while (head) | ||
{ | ||
list_item_t * temp = head; | ||
head = head->next; | ||
if (cb_dealloc) | ||
cb_dealloc(temp->data); | ||
free(temp); | ||
} | ||
|
||
list->head = list->tail = NULL; | ||
list->count = 0; | ||
} | ||
|
||
list_t * list_create(void * data) | ||
{ | ||
list_t * list = (list_t *)xmalloc(sizeof(list_t)); | ||
list->count = 0; | ||
list_append(list, data); | ||
|
||
return list; | ||
} |
Oops, something went wrong.