From 71a50956b1ff6b45b8265afa8e7e0264c465cec8 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 8 Nov 2011 16:57:20 +0100 Subject: [PATCH] dict.c: added two lower level methods for directly manipulating hash entries. This is useful in order to set 64 bit integers as values directly inside the hash entry (in order to save memory), without casting, and even in 32 bit builds. --- src/dict.c | 41 ++++++++++++++++++++++++++++++++++++++--- src/dict.h | 2 ++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/dict.c b/src/dict.c index f98fdd0e..9d336841 100644 --- a/src/dict.c +++ b/src/dict.c @@ -258,6 +258,30 @@ static void _dictRehashStep(dict *d) { /* Add an element to the target hash table */ int dictAdd(dict *d, void *key, void *val) +{ + dictEntry *entry = dictAddRaw(d,key); + + if (!entry) return DICT_ERR; + dictSetHashVal(d, entry, val); + return DICT_OK; +} + +/* Low level add. This function adds the entry but instead of setting + * a value returns the dictEntry structure to the user, that will make + * sure to fill the value field as he wishes. + * + * This function is also directly expoed to user API to be called + * mainly in order to store non-pointers inside the hash value, example: + * + * entry = dictAddRaw(dict,mykey); + * if (entry != NULL) dictSetValSignedInteger(entry,1000); + * + * Return values: + * + * If key already exists NULL is returned. + * If key was added, the hash entry is returned to be manipulated by the caller. + */ +dictEntry *dictAddRaw(dict *d, void *key) { int index; dictEntry *entry; @@ -268,7 +292,7 @@ int dictAdd(dict *d, void *key, void *val) /* Get the index of the new element, or -1 if * the element already exists. */ if ((index = _dictKeyIndex(d, key)) == -1) - return DICT_ERR; + return NULL; /* Allocate the memory and store the new entry */ ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0]; @@ -279,8 +303,7 @@ int dictAdd(dict *d, void *key, void *val) /* Set the hash entry fields. */ dictSetHashKey(d, entry, key); - dictSetHashVal(d, entry, val); - return DICT_OK; + return entry; } /* Add an element, discarding the old if the key already exists. @@ -308,6 +331,18 @@ int dictReplace(dict *d, void *key, void *val) return 0; } +/* dictReplaceRaw() is simply a version of dictAddRaw() that always + * returns the hash entry of the specified key, even if the key already + * exists and can't be added (in that case the entry of the already + * existing key is returned.) + * + * See dictAddRaw() for more information. */ +dictEntry *dictReplaceRaw(dict *d, void *key) { + dictEntry *entry = dictFind(d,key); + + return entry ? entry : dictAddRaw(d,key); +} + /* Search and remove an element */ static int dictGenericDelete(dict *d, const void *key, int nofree) { diff --git a/src/dict.h b/src/dict.h index 31cd6564..23b1fc52 100644 --- a/src/dict.h +++ b/src/dict.h @@ -133,7 +133,9 @@ typedef struct dictIterator { dict *dictCreate(dictType *type, void *privDataPtr); int dictExpand(dict *d, unsigned long size); int dictAdd(dict *d, void *key, void *val); +dictEntry *dictAddRaw(dict *d, void *key); int dictReplace(dict *d, void *key, void *val); +dictEntry *dictReplaceRaw(dict *d, void *key); int dictDelete(dict *d, const void *key); int dictDeleteNoFree(dict *d, const void *key); void dictRelease(dict *d); -- 2.45.2