#include #include #include "ds.h" ds_sll_t *ds_sll_init(void) { return ds_sll_new_node(NULL); } ds_dll_t *ds_dll_init(void) { return ds_dll_new_node(NULL); } ds_sll_t *ds_sll_new_node(void *data) { ds_sll_t *node; node = calloc(1, sizeof(ds_sll_t)); node->data = data; node->next = NULL; return node; } ds_dll_t *ds_dll_new_node(void *data) { ds_dll_t *node; node = calloc(1, sizeof(ds_dll_t)); node->data = data; node->next = node->prev = NULL; return node; } int ds_sll_insert(ds_sll_t *ll, void *data) { if (!ll || !data) { return -1; } ds_ll_foreach(ds_sll_t, ll) { if (!cur->data) { cur->data = data; return 0; } else if (!cur->next) { cur->next = ds_sll_new_node(data); return 0; } } return -1; } int ds_dll_insert(ds_dll_t *ll, void *data) { if (!ll || !data) { return -1; } ds_ll_foreach(ds_dll_t, ll) { if (!cur->data) { cur->data = data; return 0; } else if (!cur->next) { cur->next = ds_dll_new_node(data); cur->next->prev = cur; return 0; } } return -1; } void *ds_sll_remove(ds_sll_t **ll, unsigned idx) { int i; void *data; ds_sll_t *cur, *rm; rm = NULL; if (!ll || !*ll) { return NULL; } for (i = -1, cur = *ll; cur; i++, cur = cur->next) { if (i + 1 == idx) { if (idx == 0) { rm = cur; if (!rm) { return NULL; } *ll = cur->next; } else { rm = cur->next; if (!rm) { return NULL; } cur->next = cur->next->next; } break; } } if (!rm) { return NULL; } data = rm->data; free(rm); return data; } void *ds_dll_remove(ds_dll_t **ll, unsigned idx) { int i; void *data; ds_dll_t *cur, *rm; rm = NULL; if (!ll || !*ll) { return NULL; } for (i = -1, cur = *ll; cur; i++, cur = cur->next) { if (i + 1 == idx) { if (idx == 0) { rm = cur; if (!rm) { return NULL; } if (cur->next) { cur->next->prev = NULL; *ll = cur->next; } } else { rm = cur->next; if (!rm) { return NULL; } cur->next = cur->next->next; if (cur->next) { cur->next->prev = cur; } } break; } } if (!rm) { return NULL; } data = rm->data; free(rm); return data; } ds_hmp_t *ds_hmp_init(int data_len) { ds_hmp_t *hmp; if (!data_len) { return NULL; } hmp = calloc(1, sizeof(ds_hmp_t)); hmp->data_len = data_len; hmp->data = calloc(data_len, sizeof(ds_sll_t **)); return hmp; } int ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv)) { int i; _ds_hmp_kv_t *kv; ds_sll_t *ll; if (!hmp || !*hmp) { return -1; } for (i = 0; i < (*hmp)->data_len; i++) { ll = (*hmp)->data[i]; while (ll && ll->data) { if ((kv = ds_sll_remove(&ll, 0))) { if (kv_callback) { kv_callback(kv); } free(kv); } } if (ll) { free(ll); } } free((*hmp)->data); free(*hmp); return 0; } int _ds_hmp_gen_hash(char *str) { unsigned long hash = 5381; int c; while ((c = *str++)) { hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ } return hash; } int ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data) { _ds_hmp_kv_t *kv; ds_sll_t *ll; unsigned hash_pos; if (!hmp || !key || !data) { return -1; } kv = malloc(sizeof(_ds_hmp_kv_t)); kv->key = key; kv->val = data; hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; if (!hmp->data[hash_pos]) { hmp->data[hash_pos] = ds_sll_init(); if (!hmp->data[hash_pos]) { return -1; } } /* get the ll and put the data into it */ ll = hmp->data[hash_pos]; if (ds_sll_insert(ll, kv) != 0) { return -1; } return 0; } void *ds_hmp_get(ds_hmp_t *hmp, char *key) { ds_sll_t *cur, *ll; unsigned hash_pos; if (!hmp || !key) { return NULL; } hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; ll = hmp->data[hash_pos]; if (!ll) { return NULL; } ds_ll_foreach(ds_sll_t, ll) { if (strcmp(((_ds_hmp_kv_t *)cur->data)->key, key) == 0) { return ((_ds_hmp_kv_t *)cur->data)->val; } } return NULL; } void *ds_hmp_remove(ds_hmp_t *hmp, char *key) { int i; void *data; unsigned hash_pos; ds_sll_t *ll, *cur; _ds_hmp_kv_t *kv; if (!hmp || !key) { return NULL; } hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; ll = hmp->data[hash_pos]; if (!ll) { return NULL; } for (i = 0, cur = ll; cur; i++, cur = cur->next) { if (strcmp(((_ds_hmp_kv_t *)cur->data)->key, key) == 0) { kv = ds_sll_remove(&ll, i); hmp->data[hash_pos] = ll; if (!kv) { return NULL; } data = kv->val; free(kv); return data; } } return NULL; }