diff options
| author | 2016-11-18 03:22:25 +0100 | |
|---|---|---|
| committer | 2016-11-18 03:22:25 +0100 | |
| commit | 582c59bf7dcf37270c2fd7e99b4982ebc9bcbc74 (patch) | |
| tree | 91b8c594acd89e4c53a8c00bd730446bbfc0c6cf /src/hashtable.c | |
| parent | f1f2bcebc8690c9b420288aeede2e52c5bf18ccd (diff) | |
| download | libplist-582c59bf7dcf37270c2fd7e99b4982ebc9bcbc74.tar.gz libplist-582c59bf7dcf37270c2fd7e99b4982ebc9bcbc74.tar.bz2 | |
Improve plist_dict_set_item performance for large dictionaries with hash table
Diffstat (limited to 'src/hashtable.c')
| -rw-r--r-- | src/hashtable.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/hashtable.c b/src/hashtable.c index 3568f3c..dd6dbfc 100644 --- a/src/hashtable.c +++ b/src/hashtable.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * hashtable.c | 2 | * hashtable.c |
| 3 | * really simple hash table implementation | 3 | * really simple hash table implementation |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | 5 | * Copyright (c) 2011-2016 Nikias Bassen, All Rights Reserved. |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or | 7 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public | 8 | * modify it under the terms of the GNU Lesser General Public |
| @@ -20,7 +20,7 @@ | |||
| 20 | */ | 20 | */ |
| 21 | #include "hashtable.h" | 21 | #include "hashtable.h" |
| 22 | 22 | ||
| 23 | hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func) | 23 | hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func, free_func_t free_func) |
| 24 | { | 24 | { |
| 25 | hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t)); | 25 | hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t)); |
| 26 | int i; | 26 | int i; |
| @@ -30,6 +30,7 @@ hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func) | |||
| 30 | ht->count = 0; | 30 | ht->count = 0; |
| 31 | ht->hash_func = hash_func; | 31 | ht->hash_func = hash_func; |
| 32 | ht->compare_func = compare_func; | 32 | ht->compare_func = compare_func; |
| 33 | ht->free_func = free_func; | ||
| 33 | return ht; | 34 | return ht; |
| 34 | } | 35 | } |
| 35 | 36 | ||
| @@ -42,7 +43,9 @@ void hash_table_destroy(hashtable_t *ht) | |||
| 42 | if (ht->entries[i]) { | 43 | if (ht->entries[i]) { |
| 43 | hashentry_t* e = ht->entries[i]; | 44 | hashentry_t* e = ht->entries[i]; |
| 44 | while (e) { | 45 | while (e) { |
| 45 | free(e->value); | 46 | if (ht->free_func) { |
| 47 | ht->free_func(e->value); | ||
| 48 | } | ||
| 46 | hashentry_t* old = e; | 49 | hashentry_t* old = e; |
| 47 | e = e->next; | 50 | e = e->next; |
| 48 | free(old); | 51 | free(old); |
| @@ -104,3 +107,34 @@ void* hash_table_lookup(hashtable_t* ht, void *key) | |||
| 104 | } | 107 | } |
| 105 | return NULL; | 108 | return NULL; |
| 106 | } | 109 | } |
| 110 | |||
| 111 | void hash_table_remove(hashtable_t* ht, void *key) | ||
| 112 | { | ||
| 113 | if (!ht || !key) return; | ||
| 114 | |||
| 115 | unsigned int hash = ht->hash_func(key); | ||
| 116 | |||
| 117 | int idx0 = hash & 0xFFF; | ||
| 118 | |||
| 119 | // get the idx0 list | ||
| 120 | hashentry_t* e = ht->entries[idx0]; | ||
| 121 | hashentry_t* last = e; | ||
| 122 | while (e) { | ||
| 123 | if (ht->compare_func(e->key, key)) { | ||
| 124 | // found element, remove it from the list | ||
| 125 | hashentry_t* old = e; | ||
| 126 | if (e == ht->entries[idx0]) { | ||
| 127 | ht->entries[idx0] = e->next; | ||
| 128 | } else { | ||
| 129 | last->next = e->next; | ||
| 130 | } | ||
| 131 | if (ht->free_func) { | ||
| 132 | ht->free_func(old->value); | ||
| 133 | } | ||
| 134 | free(old); | ||
| 135 | return; | ||
| 136 | } | ||
| 137 | last = e; | ||
| 138 | e = e->next; | ||
| 139 | } | ||
| 140 | } | ||
