#include "xl_hash.h"
xl_hash *xl_hash_init(xl_hash_type *type){
return xl_hash_init_with_size(type, 0);
}
xl_hash *xl_hash_init_with_size(xl_hash_type *type, XL_HASH_KEY_TYPE size){
xl_hash *hash = (xl_hash *)calloc(1, sizeof(xl_hash));
hash->type = type;
hash->size = size;
hash->entry = (xl_hash_entry **)calloc(size, sizeof(xl_hash_entry *));
return hash;
}
xl_hash_entry *xl_hash_find(xl_hash *hash, XL_KEY_TYPE key){
xl_hash_entry *entry = hash->entry[XL_HASH_CALC(hash, key)];
for(; entry != NULL; entry = entry->next){
if(XL_HASH_KEY_COMP(hash, key, entry->key))return entry;
}
return NULL;
}
int xl_hash_delete(xl_hash *hash, XL_KEY_TYPE key){
xl_hash_entry *entry = xl_hash_find(hash, key);
if(entry != NULL){
if(entry->pre) entry->pre->next = entry->next;
else hash->entry[XL_HASH_CALC(hash, key)] = entry->next;
if(entry->next)entry->next->pre =entry->pre;
free(entry->value);
free(entry->key);
free(entry);
return 1;
}
return 0;
}
xl_hash_entry *xl_hash_new_entry(xl_hash *hash, XL_VALUE_TYPE val, XL_KEY_TYPE key){
xl_hash_entry *entry = calloc(1, sizeof(xl_hash_entry));
entry->value = (XL_VALUE_TYPE)calloc(1, hash->type->value_size);
entry->key = (XL_KEY_TYPE) calloc(1, hash->type->key_size);
memcpy(entry->value, val, hash->type->value_size);
memcpy(entry->key , key, hash->type->key_size);
entry->pre = NULL;
entry->next = NULL;
return entry;
}
int xl_hash_add_first(xl_hash *hash, XL_VALUE_TYPE val, XL_KEY_TYPE key){
XL_HASH_KEY_TYPE hash_key = XL_HASH_CALC(hash, key);
xl_hash_entry **p_entry = hash->entry + hash_key;
xl_hash_entry *new_entry = xl_hash_new_entry(hash, val, key);
new_entry->next = *p_entry;
*p_entry = new_entry;
return 1;
}
int xl_hash_add_last(xl_hash *hash, XL_VALUE_TYPE val, XL_KEY_TYPE key){
XL_HASH_KEY_TYPE hash_key = XL_HASH_CALC(hash, key);
xl_hash_entry *entry = hash->entry[hash_key];
xl_hash_entry *new_entry = xl_hash_new_entry(hash, val, key);
if(entry == NULL){
hash->entry[hash_key] = new_entry;
}
else{
for(; entry->next != NULL; entry = entry->next);
new_entry->pre = entry;
entry->next = new_entry;
}
return 1;
}
void xl_hash_foreach(xl_hash *hash, void (*func)(XL_VALUE_TYPE)){
int i;
xl_hash_entry *entry = NULL, *next = NULL;
for(i = 0; i < hash->size; i++){
for(entry = hash->entry[i]; entry != NULL; entry = next){
next = entry->next;
(*func)(entry->value);
}
}
}
xl_hash *xl_hash_lookup(xl_hash *hash, int (*func)(XL_VALUE_TYPE)){
int i;
xl_hash_entry *entry = NULL, *next = NULL;
xl_hash *new_hash = xl_hash_init_with_size(hash->type, hash->size);
for(i = 0; i < hash->size; i++){
for(entry = hash->entry[i]; entry != NULL; entry = next){
next = entry->next;
if((*func)(entry->value))xl_hash_add_first(new_hash, entry->value, entry->key);
}
}
return new_hash;
}
void xl_hash_free(xl_hash *hash){
xl_hash_clear(hash);
free(hash->entry);
free(hash);
}
void xl_hash_clear(xl_hash *hash){
int i;
xl_hash_entry *entry = NULL, *next = NULL;
for(i = 0; i < hash->size; i++){
for(entry = hash->entry[i]; entry != NULL; entry = next){
next = entry->next;
free(entry->value);
free(entry->key);
free(entry);
}
hash->entry[i] = NULL;
}
}