/** delete a key from a hash table */ int hash_drop(hash_t *table, const char *key) { xmpp_ctx_t *ctx = table->ctx; hashentry_t *entry, *prev; int table_index = _hash_key(table, key); /* look up the hash entry */ entry = table->entries[table_index]; prev = NULL; while (entry != NULL) { /* traverse the linked list looking for the key */ if (!strcmp(key, entry->key)) { /* match, remove the entry */ xmpp_free(ctx, entry->key); if (table->free) table->free(ctx, entry->value); if (prev == NULL) { table->entries[table_index] = entry->next; } else { prev->next = entry->next; } xmpp_free(ctx, entry); table->num_keys--; return 0; } prev = entry; entry = entry->next; } /* no match */ return -1; }
/** add a key, value pair to a hash table. * each key can appear only once; the value of any * identical key will be replaced */ int hash_add(hash_t *table, const char * const key, void *data) { xmpp_ctx_t *ctx = table->ctx; hashentry_t *entry = NULL; int table_index = _hash_key(table, key); /* drop existing entry, if any */ hash_drop(table, key); /* allocate and fill a new entry */ entry = xmpp_alloc(ctx, sizeof(hashentry_t)); if (!entry) return -1; entry->key = xmpp_strdup(ctx, key); if (!entry->key) { xmpp_free(ctx, entry); return -1; } entry->value = data; /* insert ourselves in the linked list */ /* TODO: this leaks duplicate keys */ entry->next = table->entries[table_index]; table->entries[table_index] = entry; table->num_keys++; return 0; }
int hash_drop(hash_t *table, const char *key) { hashentry_t *entry, *prev; int index = _hash_key(table, key); // entry和key都需要释放 entry = table->entries[index]; prev = NULL; while (entry != NULL) { if (!im_strcmp(key, entry->key)) { safe_mem_free(entry->key); // 自定义释放 if (table->free) table->free(entry->value); if (prev == NULL) { table->entries[index] = entry->next; } else { prev->next = entry->next; } safe_mem_free(entry); table->num_keys--; return 0; } prev = entry; entry = entry->next; } // key不存在 return -1; }
int hash_add(hash_t *table, const char *key, void *data) { hashentry_t *entry = NULL; int index = _hash_key(table, key); if (table->free) { hash_drop(table, key); } else { // 没有指定释放函数,有冲突的话插入失败 if (!hash_get(table, key)) { return -1; } } entry = safe_mem_calloc(sizeof(hashentry_t), NULL); if (!entry) return -1; entry->key = im_strndup(key, im_strlen(key)); if (!entry->key) { safe_mem_free(entry); return -1; } entry->value = data; entry->next = table->entries[index]; table->entries[index] = entry; table->num_keys++; return 0; }
/** * 0 for not-found */ void* get(dict *d, char *key) { uint32_t idx = _hash_key(key) % d->size; struct entry *e = (d->table)[idx]; while (e) { if (strcmp(e->key, key) == 0) { return e->val; } e = e->next; } return NULL; }
// 获取一个键值 void *hash_get(hash_t *table, const char *key) { hashentry_t *entry; int index = _hash_key(table, key); void *result = NULL; entry = table->entries[index]; while (entry != NULL) { if (!im_strcmp(key, entry->key)) { // 匹配 result = entry->value; return result; } entry = entry->next; } // 没有匹配 return result; }
/** look up a key in a hash table */ void *hash_get(hash_t *table, const char *key) { hashentry_t *entry; int table_index = _hash_key(table, key); void *result = NULL; /* look up the hash entry */ entry = table->entries[table_index]; while (entry != NULL) { /* traverse the linked list looking for the key */ if (!strcmp(key, entry->key)) { /* match */ result = entry->value; return result; } entry = entry->next; } /* no match */ return result; }
void resize(dict *d, size_t size) { struct entry **table = malloc(size * sizeof(*table)); memset(table, 0, size * sizeof(*table)); // rehash int i; for (i = 0; i < d->size; i++) { struct entry *e = (d->table)[i]; while (e) { uint32_t idx = _hash_key(e->key) % size; // save next entry to rehash struct entry *next = e->next; e->next = table[idx]; table[idx] = e; e = next; } } // reset dict free(d->table); d->table = table; d->size = size; }
/** * val是引用,如果key已存在则覆盖 */ void add(dict *d, char *key, void *val) { uint32_t idx = _hash_key(key) % d->size; // find if KEY exists first struct entry *e = (d->table)[idx]; while (e) { if (strcmp(e->key, key) == 0) { e->val = val; return; } e = e->next; } // not found and create new one e = malloc(sizeof(*e)); e->key = malloc(strlen(key)); strcpy(e->key, key); e->val = val; e->next = (d->table)[idx]; (d->table)[idx] = e; }
/** * return VAL */ void* del(dict *d, char *key) { uint32_t idx = _hash_key(key) % d->size; struct entry *e = (d->table)[idx]; struct entry *pre = NULL; while (e) { if (strcmp(e->key, key) == 0) { // if e is the first one if (pre == NULL) { (d->table)[idx] = e->next; } else { pre->next = e->next; } // now delete e and free mem void* val = e->val; free(e->key); free(e); return val; } pre = e; e = e->next; } return NULL; }