/* Add an element to the target hash table */ int dictAdd(dict *d, void *key, void *val) { int index; dictEntry *entry; dictht *ht; if (dictIsRehashing(d)) _dictRehashStep(d); /* Get the index of the new element, or -1 if * the element already exists. */ if ((index = _dictKeyIndex(d, key)) == -1) return DICT_ERR; /* Allocates the memory and stores key */ ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0]; entry = zmalloc(sizeof(*entry)); entry->next = ht->table[index]; ht->table[index] = entry; ht->used++; /* Set the hash entry fields. */ dictSetHashKey(d, entry, key); dictSetHashVal(d, entry, val); return DICT_OK; }
/* 添加元素的底层实现函数(由 dictAdd 调用) * * 新元素的添加操作被分为两步: * 1) 创建节点并设置节点的 key ,然后返回节点 * 2) 设置节点的值 * 这个函数执行第一步,第二步由函数 dictSetVal 进行 * * Args: * d 字典 * key 新节点的关键字 * * Returns: * NULL 关键字已经存在 * entry 设置了关键字的新节点,返回给调用者进行进一步的处理 */ dictEntry *dictAddRaw(dict *d, void *key) { int index; dictEntry *entry; dictht *ht; // 检查字典(的哈希表)能否执行 rehash 操作 // 如果可以的话,执行平摊 rehash 操作 if (dictIsRehashing(d)) _dictRehashStep(d); // 计算 key 的 index 值 // 如果 key 已经存在,_dictKeyIndex 返回 -1 if ((index = _dictKeyIndex(d, key)) == -1) return NULL; // 如果字典正在进行 rehash ,那么将新元素添加到 1 号哈希表, // 否则,使用 0 号哈希表 ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0]; entry = zmalloc(sizeof(*entry)); // 为新节点分配内存 entry->next = ht->table[index]; // 调整节点的 next 指针 ht->table[index] = entry; // 然后将新节点设为链头 ht->used++; // 更新正在使用的节点数量 // 设置节点的 key 域 dictSetKey(d, entry, key); return entry; // 返回新节点 }
//这个函数也可以作为向外部提供的API使用,外部用户可以添加一个键值不为void*类型的值 //它向字典中添加一个key值并且返回新创建的 entry对象,这个对象交给调用者操作 dictEntry *dictAddRaw(dict *d, void *key) { int index; dictEntry *entry; dictht *ht; if (dictIsRehashing(d)) _dictRehashStep(d); /* Get the index of the new element, or -1 if * the element already exists. */ //获取对应key的bucket索引 if ((index = _dictKeyIndex(d, key)) == -1) return NULL; /* Allocate the memory and store the new entry */ //如果当前在执行rehash,说明需要将ht[0]上的entry转移到ht[1]上,并且尚未执行结束 //这时候就需要加入到ht[1]中,否则加入到ht[0]中 ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0]; entry = zmalloc(sizeof(*entry)); //加入到链表的表头 entry->next = ht->table[index]; ht->table[index] = entry; ht->used++; /* Set the hash entry fields. */ //最后设置该项的key dictSetKey(d, entry, key); return entry; }
/* 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 exposed to the user API to be called * mainly in order to store non-pointers inside the hash value, example: * * entry = dictAddRaw(dict,mykey); * if (entry != NULL) dictSetSignedIntegerVal(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; dictht *ht; if (dictIsRehashing(d)) _dictRehashStep(d); /* Get the index of the new element, or -1 if * the element already exists. */ if ((index = _dictKeyIndex(d, key)) == -1) return NULL; /* Allocate the memory and store the new entry */ ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0]; entry = zmalloc(sizeof(*entry)); entry->next = ht->table[index]; ht->table[index] = entry; ht->used++; /* Set the hash entry fields. */ //使用dictType中的keyDup函数 dictSetKey(d, entry, key); return entry; }
/* Add an element to the target hash table */ static int dictAdd(dict *ht, void *key, void *val) { int index; dictEntry *entry; /* Get the index of the new element, or -1 if * the element already exists. */ if ((index = _dictKeyIndex(ht, key)) == -1) return DICT_ERR; /* Allocates the memory and stores key */ entry = malloc(sizeof(*entry)); entry->next = ht->table[index]; ht->table[index] = entry; /* Set the hash entry fields. */ dictSetHashKey(ht, entry, key); dictSetHashVal(ht, entry, val); ht->used++; return DICT_OK; }