the only actual difference is a oneline change which makes pushing append instead of prepend the new data.
455 lines
6.8 KiB
C
455 lines
6.8 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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_add(ds_sll_t **ll, void *data, unsigned x)
|
|
{
|
|
int i;
|
|
ds_sll_t *cur, *prev, *new;
|
|
if (!ll || !data) {
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0, cur = *ll; cur; prev = cur, cur = cur->next, i++) {
|
|
if (i == x) {
|
|
if (!cur->data) {
|
|
cur->data = data;
|
|
return 0;
|
|
}
|
|
new = ds_sll_new_node(data);
|
|
new->next = cur;
|
|
if (i == 0) {
|
|
*ll = new;
|
|
} else {
|
|
prev->next = new;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
ds_dll_add(ds_dll_t **ll, void *data, unsigned x)
|
|
{
|
|
int i;
|
|
ds_dll_t *cur, *new;
|
|
if (!ll || !data) {
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0, cur = *ll; cur; cur = cur->next, i++) {
|
|
if (i == x) {
|
|
if (!cur->data) {
|
|
cur->data = data;
|
|
return 0;
|
|
}
|
|
new = ds_dll_new_node(data);
|
|
new->next = cur;
|
|
new->prev = cur->prev;
|
|
cur->prev = new;
|
|
if (i == 0) {
|
|
*ll = new;
|
|
} else {
|
|
cur->prev->next = new;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
ds_sll_append(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_append(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;
|
|
}
|
|
|
|
if (idx == 0) {
|
|
rm = *ll;
|
|
*ll = rm->next;
|
|
} else {
|
|
for (i = -1, cur = *ll; cur; i++, cur = cur->next) {
|
|
if (idx == i + 1) {
|
|
rm = cur->next;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!rm) {
|
|
return NULL;
|
|
}
|
|
|
|
cur->next = rm->next;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (idx == 0) {
|
|
rm = *ll;
|
|
*ll = rm->next;
|
|
if (rm->next) {
|
|
rm->next->prev = NULL;
|
|
}
|
|
} else {
|
|
for (i = 0, cur = *ll; cur; i++, cur = cur->next) {
|
|
if (i == idx) {
|
|
rm = cur;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!rm) {
|
|
return NULL;
|
|
}
|
|
|
|
rm->prev->next = rm->next;
|
|
if (rm->next) {
|
|
rm->next->prev = rm->prev;
|
|
}
|
|
}
|
|
|
|
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_append(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;
|
|
}
|
|
|
|
ds_stack_t
|
|
*ds_stack_init(void)
|
|
{
|
|
ds_stack_t *stack = malloc(sizeof(ds_stack_t));
|
|
stack->n = 0;
|
|
|
|
return stack;
|
|
}
|
|
|
|
int
|
|
ds_stack_push(ds_stack_t *stack, void *data)
|
|
{
|
|
if (stack->n == 0) {
|
|
stack->items = ds_sll_new_node(data);
|
|
stack->n++;
|
|
return 0;
|
|
}
|
|
int r = ds_sll_add(&stack->items, data, 0);
|
|
if (!r) {
|
|
stack->n++;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void
|
|
*ds_stack_pop(ds_stack_t *stack)
|
|
{
|
|
void *r = ds_sll_remove(&stack->items, 0);
|
|
if (r != NULL) {
|
|
stack->n--;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void
|
|
*ds_stack_peek(ds_stack_t *stack, unsigned x)
|
|
{
|
|
int i;
|
|
ds_sll_t *cur;
|
|
|
|
if (x > stack->n) {
|
|
return NULL;
|
|
}
|
|
|
|
for (cur = stack->items, i = 0; cur; cur = cur->next, i++) {
|
|
if (i == x) {
|
|
return cur->data;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ds_queue_t
|
|
*ds_queue_init(void)
|
|
{
|
|
return ds_stack_init();
|
|
}
|
|
|
|
int
|
|
ds_queue_push(ds_queue_t *queue, void *data)
|
|
{
|
|
if (queue->n == 0) {
|
|
queue->items = ds_sll_new_node(data);
|
|
queue->n++;
|
|
return 0;
|
|
}
|
|
int r = ds_sll_append(queue->items, data);
|
|
if (!r) {
|
|
queue->n++;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void
|
|
*ds_queue_pop(ds_queue_t *queue)
|
|
{
|
|
return ds_stack_pop((ds_stack_t *)queue);
|
|
}
|
|
|
|
void
|
|
*ds_queue_peek(ds_queue_t *queue, unsigned x)
|
|
{
|
|
return ds_stack_peek((ds_stack_t *)queue, x);
|
|
}
|