#include "stellar/kv.h" #include "uthash/uthash.h" #include #include struct kv *kv_new_with_interger(const char *key, size_t key_sz, long long value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_INTEGER; kv->value_longlong = value; return kv; } struct kv *kv_new_with_double(const char *key, size_t key_sz, double value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_DOUBLE; kv->value_double = value; return kv; } struct kv *kv_new_with_string(const char *key, size_t key_sz, const char *value, size_t value_sz) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_STRING; kv->value_str.str = malloc(value_sz); memcpy(kv->value_str.str, value, value_sz); kv->value_str.sz = value_sz; return kv; } struct kv *kv_new_with_uuid(const char *key, size_t key_sz, const uuid_t value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_UUID; memcpy(kv->value_uuid, value, sizeof(uuid_t)); return kv; } struct kv *kv_new_with_interger_array(const char *key, size_t key_sz, long long value[], size_t n_value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_INTERGE_ARRAY; kv->value_interger_array.elems = malloc(sizeof(long long) * n_value); memcpy(kv->value_interger_array.elems, value, sizeof(long long) * n_value); kv->value_interger_array.n_elems = n_value; return kv; } struct kv *kv_new_with_double_array(const char *key, size_t key_sz, double value[], size_t n_value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_DOUBLE_ARRAY; kv->value_double_array.elems = malloc(sizeof(double) * n_value); memcpy(kv->value_double_array.elems, value, sizeof(double) * n_value); kv->value_double_array.n_elems = n_value; return kv; } struct kv *kv_new_with_string_array(const char *key, size_t key_sz, const char* value[], size_t value_sz[], size_t n_value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_STRING_ARRAY; kv->value_str_array.elems = malloc(sizeof(char*) * n_value); kv->value_str_array.sz = malloc(sizeof(size_t) * n_value); for (size_t i = 0; i < n_value; i++) { kv->value_str_array.elems[i] = malloc(value_sz[i]); memcpy(kv->value_str_array.elems[i], value[i], value_sz[i]); kv->value_str_array.sz[i] = value_sz[i]; } kv->value_str_array.n_elems = n_value; return kv; } struct kv *kv_new_with_uuid_array(const char *key, size_t key_sz, const uuid_t value[], size_t n_value) { struct kv *kv = malloc(sizeof(struct kv)); kv->key = malloc(key_sz); memcpy(kv->key, key, key_sz); kv->key_sz = key_sz; kv->vtype = KV_VALUE_TYPE_UUID_ARRAY; kv->value_uuid_array.elems = malloc(sizeof(uuid_t) * n_value); memcpy(kv->value_uuid_array.elems, value, sizeof(uuid_t) * n_value); kv->value_uuid_array.n_elems = n_value; return kv; } struct kv *kv_duplicate(const struct kv *kv) { if(kv == NULL)return NULL; struct kv *new_kv = malloc(sizeof(struct kv)); new_kv->key = malloc(kv->key_sz); memcpy(new_kv->key, kv->key, kv->key_sz); new_kv->key_sz = kv->key_sz; new_kv->vtype = kv->vtype; switch (kv->vtype) { case KV_VALUE_TYPE_STRING: new_kv->value_str.str = malloc(kv->value_str.sz); memcpy(new_kv->value_str.str, kv->value_str.str, kv->value_str.sz); new_kv->value_str.sz = kv->value_str.sz; break; case KV_VALUE_TYPE_INTERGE_ARRAY: new_kv->value_interger_array.elems = malloc(sizeof(long long) * kv->value_interger_array.n_elems); memcpy(new_kv->value_interger_array.elems, kv->value_interger_array.elems, sizeof(long long) * kv->value_interger_array.n_elems); new_kv->value_interger_array.n_elems = kv->value_interger_array.n_elems; break; case KV_VALUE_TYPE_DOUBLE_ARRAY: new_kv->value_double_array.elems = malloc(sizeof(double) * kv->value_double_array.n_elems); memcpy(new_kv->value_double_array.elems, kv->value_double_array.elems, sizeof(double) * kv->value_double_array.n_elems); new_kv->value_double_array.n_elems = kv->value_double_array.n_elems; break; case KV_VALUE_TYPE_STRING_ARRAY: new_kv->value_str_array.elems = malloc(sizeof(char*) * kv->value_str_array.n_elems); new_kv->value_str_array.sz = malloc(sizeof(size_t) * kv->value_str_array.n_elems); for (size_t i = 0; i < kv->value_str_array.n_elems; i++) { new_kv->value_str_array.elems[i] = malloc(kv->value_str_array.sz[i]); memcpy(new_kv->value_str_array.elems[i], kv->value_str_array.elems[i], kv->value_str_array.sz[i]); new_kv->value_str_array.sz[i] = kv->value_str_array.sz[i]; } new_kv->value_str_array.n_elems = kv->value_str_array.n_elems; break; case KV_VALUE_TYPE_UUID_ARRAY: new_kv->value_uuid_array.elems = malloc(sizeof(uuid_t) * kv->value_uuid_array.n_elems); memcpy(new_kv->value_uuid_array.elems, kv->value_uuid_array.elems, sizeof(uuid_t) * kv->value_uuid_array.n_elems); new_kv->value_uuid_array.n_elems = kv->value_uuid_array.n_elems; break; default: break; } return new_kv; } void kv_free(struct kv *kv) { if(kv == NULL)return; if(kv->key)free(kv->key); switch (kv->vtype) { case KV_VALUE_TYPE_STRING: if(kv->value_str.str)free(kv->value_str.str); break; case KV_VALUE_TYPE_INTERGE_ARRAY: if(kv->value_interger_array.elems)free(kv->value_interger_array.elems); break; case KV_VALUE_TYPE_DOUBLE_ARRAY: if(kv->value_double_array.elems)free(kv->value_double_array.elems); break; case KV_VALUE_TYPE_STRING_ARRAY: for (size_t i = 0; i < kv->value_str_array.n_elems; i++) { if(kv->value_str_array.elems[i])free(kv->value_str_array.elems[i]); } if(kv->value_str_array.elems)free(kv->value_str_array.elems); if(kv->value_str_array.sz)free(kv->value_str_array.sz); break; case KV_VALUE_TYPE_UUID_ARRAY: if(kv->value_uuid_array.elems)free(kv->value_uuid_array.elems); break; default: break; } free(kv); } struct kv_table_elem { struct kv *kv; kv_ref_cleanup_cb *ref_cleanup_cb; void *cleanup_cb_arg; UT_hash_handle hh; }; struct kv_table { struct kv_table_elem *elems; struct kv_table_elem *iter; }; struct kv_table *kv_table_new(size_t n_reserved __attribute__((unused))) { struct kv_table *table = malloc(sizeof(struct kv_table)); table->elems = NULL; table->iter = NULL; return table; } void kv_table_free(struct kv_table *table) { if(table == NULL)return; struct kv_table_elem *elem, *tmp; HASH_ITER(hh, table->elems, elem, tmp) { HASH_DEL(table->elems, elem); if(elem->ref_cleanup_cb)elem->ref_cleanup_cb(elem->kv, elem->cleanup_cb_arg); free(elem); } free(table); } int kv_table_add(struct kv_table *table, const struct kv *kv) { if(table == NULL || kv == NULL)return -1; struct kv_table_elem *elem = malloc(sizeof(struct kv_table_elem)); elem->kv = kv_duplicate(kv); elem->ref_cleanup_cb = NULL; elem->cleanup_cb_arg = NULL; HASH_ADD_KEYPTR(hh, table->elems, kv->key, kv->key_sz, elem); return 0; } int kv_table_del(struct kv_table *table, const char *key, size_t key_sz);