diff --git a/include/stellar/kv.h b/include/stellar/kv.h new file mode 100644 index 0000000..9f8bcc1 --- /dev/null +++ b/include/stellar/kv.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include + +struct kv +{ + char *key; + size_t key_sz; + enum + { + KV_VALUE_TYPE_INTEGER, + KV_VALUE_TYPE_DOUBLE, + KV_VALUE_TYPE_STRING, + KV_VALUE_TYPE_UUID, + KV_VALUE_TYPE_INTERGE_ARRAY, + KV_VALUE_TYPE_DOUBLE_ARRAY, + KV_VALUE_TYPE_STRING_ARRAY, + KV_VALUE_TYPE_UUID_ARRAY + }vtype; + union + { + long long value_longlong; + double value_double; + struct + { + char *str; + size_t sz; + }value_str; + uuid_t value_uuid; + struct + { + long long *elems; + size_t n_elems; + }value_interger_array; + struct + { + double *elems; + size_t n_elems; + }value_double_array; + struct + { + char **elems; + size_t *sz; + size_t n_elems; + }value_str_array; + struct + { + uuid_t *elems; + size_t n_elems; + }value_uuid_array; +/* + struct + { + struct kv *elems; + size_t n_elems; + }value_list; +*/ + }; +}; + +struct kv *kv_new_with_interger(const char *key, size_t key_sz, long long value); +struct kv *kv_new_with_double(const char *key, size_t key_sz, double value); +struct kv *kv_new_with_string(const char *key, size_t key_sz, const char *value, size_t value_sz); +struct kv *kv_new_with_uuid(const char *key, size_t key_sz, const uuid_t value); +struct kv *kv_new_with_interger_array(const char *key, size_t key_sz, long long value[], size_t n_value); +struct kv *kv_new_with_double_array(const char *key, size_t key_sz, double value[], size_t n_value); +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_new_with_uuid_array(const char *key, size_t key_sz, const uuid_t value[], size_t n_value); + +struct kv *kv_duplicate(const struct kv *kv); + +void kv_free(struct kv *kv); + +struct kv_table; + +struct kv_table *kv_table_new(size_t initial_size); +void kv_table_free(struct kv_table *table); + +//struct kv_table *kv_table_new_by_indexing(struct kv *kv); + +int kv_table_add(struct kv_table *table, const struct kv *kv); +int kv_table_del(struct kv_table *table, const char *key, size_t key_sz); + +typedef void (kv_ref_cleanup_cb)(const struct kv *kv, void *arg); +int kv_table_add_reference(struct kv_table *table, const struct kv *kv, kv_ref_cleanup_cb *cleanup_cb, void *arg); + +const struct kv *kv_table_get0(struct kv_table *table, const char *key, size_t key_sz); + +void kv_table_reset_iter(struct kv_table *table); +const struct kv *kv_table_next(struct kv_table *table); + +struct kv_table *kv_table_duplicate(const struct kv_table *table); +int kv_table_union(struct kv_table *dst, const struct kv_table *src); + +void kv_table_serialize(const struct kv_table *table, char **blob, size_t *blob_len); +struct kv_table *kv_table_deserialize(const char *blob, size_t blob_len); + +int kv_table_export_json(const struct kv_table *table, char **blob, size_t *blob_len); +int kv_table_export_msgpack(const struct kv_table *table, char **blob, size_t *blob_len); \ No newline at end of file diff --git a/include/stellar/mq.h b/include/stellar/mq.h index 0a0bb9e..c273658 100644 --- a/include/stellar/mq.h +++ b/include/stellar/mq.h @@ -13,7 +13,7 @@ typedef void mq_msg_free_cb_func(void *msg, void *msg_free_arg); typedef void on_msg_cb_func(int topic_id, void *msg, void *on_msg_arg); typedef void on_msg_dispatch_cb_func(int topic_id, void *msg, - on_msg_cb_func* on_msg_cb, + on_msg_cb_func *on_msg_cb, void *on_msg_cb_arg, void *dispatch_arg); diff --git a/infra/kv/kv.c b/infra/kv/kv.c new file mode 100644 index 0000000..78fe347 --- /dev/null +++ b/infra/kv/kv.c @@ -0,0 +1,236 @@ +#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);