|
@@ -1,3 +1,4 @@
|
|
|
|
|
+/* vim: set filetype=c : */
|
|
|
#ifndef LIB_H
|
|
#ifndef LIB_H
|
|
|
# define LIB_H
|
|
# define LIB_H
|
|
|
|
|
|
|
@@ -59,7 +60,9 @@ enum err {
|
|
|
ERR_FAILED_WRITE,
|
|
ERR_FAILED_WRITE,
|
|
|
ERR_WROTE_WRONG_AMOUNT,
|
|
ERR_WROTE_WRONG_AMOUNT,
|
|
|
ERR_FAILED_ALLOC,
|
|
ERR_FAILED_ALLOC,
|
|
|
|
|
+ ERR_FAILED_REALLOC,
|
|
|
ERR_MKDIR_FAILED,
|
|
ERR_MKDIR_FAILED,
|
|
|
|
|
+ ERR_FAILED_HASHING,
|
|
|
ERR_STR_EMPTY,
|
|
ERR_STR_EMPTY,
|
|
|
ERR_PATH_EMPTY,
|
|
ERR_PATH_EMPTY,
|
|
|
ERR_PATH_INVALID,
|
|
ERR_PATH_INVALID,
|
|
@@ -82,7 +85,9 @@ const char *err_to_name[] = {
|
|
|
"ERR_FAILED_WRITE",
|
|
"ERR_FAILED_WRITE",
|
|
|
"ERR_WROTE_WRONG_AMOUNT",
|
|
"ERR_WROTE_WRONG_AMOUNT",
|
|
|
"ERR_FAILED_ALLOC",
|
|
"ERR_FAILED_ALLOC",
|
|
|
|
|
+ "ERR_FAILED_REALLOC",
|
|
|
"ERR_MKDIR_FAILED",
|
|
"ERR_MKDIR_FAILED",
|
|
|
|
|
+ "ERR_FAILED_HASHING",
|
|
|
"ERR_PATH_EMPTY",
|
|
"ERR_PATH_EMPTY",
|
|
|
"ERR_PATH_INVALID",
|
|
"ERR_PATH_INVALID",
|
|
|
"ERR_PATH_FILE_EMPTY",
|
|
"ERR_PATH_FILE_EMPTY",
|
|
@@ -173,6 +178,7 @@ void abort(void);
|
|
|
return ret_val; \
|
|
return ret_val; \
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#define _r_ __restrict__
|
|
|
|
|
|
|
|
/* ------------------------------ END LIB DEF ------------------------------ */
|
|
/* ------------------------------ END LIB DEF ------------------------------ */
|
|
|
|
|
|
|
@@ -237,6 +243,7 @@ struct str_tokenizer {
|
|
|
struct str str;
|
|
struct str str;
|
|
|
u64 cur;
|
|
u64 cur;
|
|
|
char c;
|
|
char c;
|
|
|
|
|
+ bool (*f)(char c);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
struct str str_from_cstr(const char *cstr, u64 cstr_size,
|
|
struct str str_from_cstr(const char *cstr, u64 cstr_size,
|
|
@@ -259,6 +266,7 @@ u64 str_lindex(struct str str, char c);
|
|
|
u64 str_rindex(struct str str, char c);
|
|
u64 str_rindex(struct str str, char c);
|
|
|
|
|
|
|
|
struct str_tokenizer str_tokenize(struct str str, char c);
|
|
struct str_tokenizer str_tokenize(struct str str, char c);
|
|
|
|
|
+struct str_tokenizer str_tokenize_func(struct str str, bool (*f)(char c));
|
|
|
struct str str_tokenizer_next(struct str_tokenizer *st);
|
|
struct str str_tokenizer_next(struct str_tokenizer *st);
|
|
|
|
|
|
|
|
struct str str_slice(struct str str, u64 from, u64 to);
|
|
struct str str_slice(struct str str, u64 from, u64 to);
|
|
@@ -508,6 +516,406 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
|
|
|
|
|
|
|
|
/* --------------------------- END DYN ARR DEF ----------------------------- */
|
|
/* --------------------------- END DYN ARR DEF ----------------------------- */
|
|
|
|
|
|
|
|
|
|
+/* ---------------------------- START DA DEF ------------------------------- */
|
|
|
|
|
+
|
|
|
|
|
+# define DA_APPEND(da, val, err_var) \
|
|
|
|
|
+ do { \
|
|
|
|
|
+ if ( err_var != NULL ) { \
|
|
|
|
|
+ if ( *err_var != ERR_OK ) { \
|
|
|
|
|
+ break; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ } \
|
|
|
|
|
+ if ( (da).size + 1 >= (da).cap ) { \
|
|
|
|
|
+ (da).cap *= 2; \
|
|
|
|
|
+ (da).data = realloc((da).data, (da).cap); \
|
|
|
|
|
+ if ( (da).data == NULL ) { \
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_REALLOC); \
|
|
|
|
|
+ break; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ } \
|
|
|
|
|
+ if ( (da).data == NULL ) { \
|
|
|
|
|
+ if ( (da).cap == 0 ) { \
|
|
|
|
|
+ (da).cap = 32; \
|
|
|
|
|
+ (da).size = 0; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ (da).data = malloc(sizeof(*(da).data) * (da).cap); \
|
|
|
|
|
+ if ( (da).data == NULL ) { \
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_ALLOC); \
|
|
|
|
|
+ break; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ } \
|
|
|
|
|
+ (da).data[(da).size++] = (val); \
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
|
|
|
|
|
+ } while(0);
|
|
|
|
|
+
|
|
|
|
|
+/* ----------------------------- END DA DEF -------------------------------- */
|
|
|
|
|
+
|
|
|
|
|
+/* ---------------------------- START MAP DEF ------------------------------ */
|
|
|
|
|
+
|
|
|
|
|
+# if defined(WANT_MAP) || defined(WANT_ALL)
|
|
|
|
|
+
|
|
|
|
|
+# define MAP_FOR_EACH_USED(Map, Var) \
|
|
|
|
|
+ for ( Var = (Map)->used.data; \
|
|
|
|
|
+ Var < ((Map)->used.data + (Map)->used.size); \
|
|
|
|
|
+ ++Var )
|
|
|
|
|
+
|
|
|
|
|
+struct map_item {
|
|
|
|
|
+ u64 key[4];
|
|
|
|
|
+ u8 item[1];
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct map {
|
|
|
|
|
+ struct map_item *data;
|
|
|
|
|
+ u64 size;
|
|
|
|
|
+ struct {
|
|
|
|
|
+ u64 *data;
|
|
|
|
|
+ u64 size;
|
|
|
|
|
+ u64 cap;
|
|
|
|
|
+ } used;
|
|
|
|
|
+ u64 _cap;
|
|
|
|
|
+ u64 _size_bytes;
|
|
|
|
|
+ u64 _item_size;
|
|
|
|
|
+ u64 _elem_size;
|
|
|
|
|
+ u64 *(*hash)(void *key, u64 key_size);
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct map map_create(u64 elem_size, u64 cap, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+enum err map_inc_cap(struct map *_r_ m, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+enum err map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
+enum err map_add(struct map *_r_ m, void *_r_ key, u64 key_size, void *_r_ elem,
|
|
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+void *map_get(struct map *_r_ m, void *_r_ key, u64 key_size, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+enum err map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
+enum err map_set(struct map *_r_ m, void *_r_ key, u64 key_size,
|
|
|
|
|
+ void *_r_ elem, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+void *map_pop(struct map *_r_ m, void *_r_ key, u64 key_size, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+enum err map_destroy(struct map *_r_ m, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+u64 *map_default_hasher(void *key, u64 key_size);
|
|
|
|
|
+
|
|
|
|
|
+# if defined(IMP) || defined(IMP_MAP)
|
|
|
|
|
+
|
|
|
|
|
+struct map
|
|
|
|
|
+map_create(u64 elem_size, u64 cap, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ struct map empty = {0};
|
|
|
|
|
+ struct map m = {0};
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
|
|
|
+
|
|
|
|
|
+ m._cap = cap;
|
|
|
|
|
+ m._item_size = sizeof(struct map_item) + (elem_size-1);
|
|
|
|
|
+ m._size_bytes = m._item_size * m._cap;
|
|
|
|
|
+ m.data = malloc(m._size_bytes);
|
|
|
|
|
+ if ( m.data == NULL ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
|
|
+ return empty;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ m.used.cap = 32;
|
|
|
|
|
+ m.used.data = malloc(m.used.cap);
|
|
|
|
|
+ if ( m.used.data == NULL ) {
|
|
|
|
|
+ free(m.data);
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
|
|
+ return empty;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ m.hash = map_default_hasher;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return m;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ struct map nm = {0};
|
|
|
|
|
+ u64 *index = 0;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m , out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
|
|
+ perr = out_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nm = map_create(m->_elem_size, (m->_cap * 2), perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ goto err_exit;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ MAP_FOR_EACH_USED(m, index) {
|
|
|
|
|
+ struct map_item mi = m->data[*index];
|
|
|
|
|
+ map_add_hashed_key(&nm, mi.key, mi.item, perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ goto err_exit;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+err_exit:
|
|
|
|
|
+ map_destroy(&nm, NULL);
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
|
|
+ enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ u64 i = 0;
|
|
|
|
|
+ struct map_item *it = NULL;
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
|
|
+ perr = out_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ i = (key[0] + key[1] + key[2] + key[3]) % m->_cap;
|
|
|
|
|
+
|
|
|
|
|
+ do {
|
|
|
|
|
+ if ( i >= m->_cap ) {
|
|
|
|
|
+ map_inc_cap(m, perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ it = (m->data + (m->_item_size * (i++)));
|
|
|
|
|
+ } while (it->key[0] != 0 || it->key[1] != 0
|
|
|
|
|
+ || it->key[2] != 0 || it->key[3] != 0);
|
|
|
|
|
+
|
|
|
|
|
+ memcpy(it->key, key, sizeof(u64) * 4);
|
|
|
|
|
+ memcpy(it->item, elem, m->_elem_size);
|
|
|
|
|
+
|
|
|
|
|
+ DA_APPEND(m->used, i-1, perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ memset(it->key, 0, sizeof(u64) * 4);
|
|
|
|
|
+ memset(it->item, 0, m->_elem_size);
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ *perr = ERR_OK;
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+map_add(struct map *m, void *key, u64 key_size, void *elem, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ u64 *hash = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
|
|
+ perr = out_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hash = m->hash(key, key_size);
|
|
|
|
|
+ if ( hash == NULL ) {
|
|
|
|
|
+ *perr = ERR_FAILED_HASHING;
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ map_add_hashed_key(m, hash, elem, perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+
|
|
|
|
|
+ *perr = ERR_OK;
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void *
|
|
|
|
|
+map_get(struct map *m, void *key, u64 key_size, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ u64 i = 0;
|
|
|
|
|
+ struct map_item *it = NULL;
|
|
|
|
|
+ u64 *hash = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(m , out_err, NULL);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(m->data, out_err, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(key , out_err, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ hash = m->hash(key, key_size);
|
|
|
|
|
+ i = (hash[0] + hash[1] + hash[2] + hash[3]) % m->_cap;
|
|
|
|
|
+
|
|
|
|
|
+ do {
|
|
|
|
|
+ if ( i >= m->_cap ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_NOT_FOUND);
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ it = (m->data + (m->_item_size * (i++)));
|
|
|
|
|
+ } while (it->key[0] != hash[0] || it->key[1] != hash[1]
|
|
|
|
|
+ || it->key[2] != hash[2] || it->key[3] != hash[3]);
|
|
|
|
|
+
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return it->item;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
|
|
+ enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ u64 i = 0;
|
|
|
|
|
+ struct map_item *it = NULL;
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
|
|
+ perr = out_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ i = (key[0] + key[1] + key[2] + key[3]) % m->_cap;
|
|
|
|
|
+
|
|
|
|
|
+ do {
|
|
|
|
|
+ if ( i >= m->_cap ) {
|
|
|
|
|
+ *perr = ERR_NOT_FOUND;
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+ it = (m->data + (m->_item_size * (i++)));
|
|
|
|
|
+ } while (it->key[0] != key[0] || it->key[1] != key[1]
|
|
|
|
|
+ || it->key[2] != key[2] || it->key[3] != key[3]);
|
|
|
|
|
+
|
|
|
|
|
+ memcpy(it->item, elem, m->_elem_size);
|
|
|
|
|
+
|
|
|
|
|
+ *perr = ERR_OK;
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+map_set(struct map *_r_ m, void *_r_ key, u64 key_size, void *_r_ elem,
|
|
|
|
|
+ enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ u64 *hash = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
|
|
+ perr = out_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hash = m->hash(key, key_size);
|
|
|
|
|
+ if ( hash == NULL ) {
|
|
|
|
|
+ *perr = ERR_FAILED_HASHING;
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ map_set_hashed_key(m, hash, elem, perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+
|
|
|
|
|
+ *perr = ERR_OK;
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void *map_pop(struct map *m, void *key, u64 key_size, enum err *out_err);
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+map_destroy(struct map *m, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( m->data != NULL ) free(m->data);
|
|
|
|
|
+ if ( m->used.data != NULL ) free(m->used.data);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+u64 *
|
|
|
|
|
+map_default_hasher(void *key, u64 key_size)
|
|
|
|
|
+{
|
|
|
|
|
+ u64 i = 0;
|
|
|
|
|
+ u64 *k = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ k = malloc(sizeof(u64) * 4);
|
|
|
|
|
+ if ( k == NULL ) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ k[0] = 0;
|
|
|
|
|
+ k[1] = 0;
|
|
|
|
|
+ k[2] = 0;
|
|
|
|
|
+ k[3] = 0;
|
|
|
|
|
+
|
|
|
|
|
+ for ( i = 0; i < key_size; ++i ) {
|
|
|
|
|
+ k[0] += ((u8*)key)[i] * 31;
|
|
|
|
|
+ k[1] += ((u8*)key)[i] * 127;
|
|
|
|
|
+ k[2] += ((u8*)key)[i] * 233;
|
|
|
|
|
+ k[3] += ((u8*)key)[i] * 353;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return k;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# endif /* defined(IMP) || defined(IMP_MAP) */
|
|
|
|
|
+
|
|
|
|
|
+# endif /* defined(WANT_MAP) || defined(WANT_ALL) */
|
|
|
|
|
+
|
|
|
|
|
+/* ----------------------------- END MAP DEF ------------------------------- */
|
|
|
|
|
+
|
|
|
/* ---------------------------- START ENV DEF ------------------------------ */
|
|
/* ---------------------------- START ENV DEF ------------------------------ */
|
|
|
|
|
|
|
|
# if defined(WANT_ENV) || defined(WANT_ALL)
|
|
# if defined(WANT_ENV) || defined(WANT_ALL)
|
|
@@ -1489,6 +1897,52 @@ gui_close_window(struct gui *gui, enum err *out_err)
|
|
|
|
|
|
|
|
/* ----------------------------- END GUI DEF ------------------------------- */
|
|
/* ----------------------------- END GUI DEF ------------------------------- */
|
|
|
|
|
|
|
|
|
|
+/* ---------------------------- START SLOP DEF ----------------------------- */
|
|
|
|
|
+
|
|
|
|
|
+# if defined(WANT_SLOP) || defined(WANT_ALL)
|
|
|
|
|
+
|
|
|
|
|
+u8 *slop_file_slurp(const char *_r_ path, u64 *_r_ out_size,
|
|
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
+enum err slop_file_save(const char *_r_ path, u8 *_r_ data, u64 size,
|
|
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+# if defined(IMP) || defined(IMP_SLOP)
|
|
|
|
|
+
|
|
|
|
|
+u8 *
|
|
|
|
|
+slop_file_slurp(const char *_r_ path, u64 *_r_ out_size, enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ struct path p = {0};
|
|
|
|
|
+ struct file f = {0};
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(path, out_err, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
|
|
+ perr = out_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ p = path_from_cstr_ns(path, perr);
|
|
|
|
|
+ f = path_file_read_all(&p, perr);
|
|
|
|
|
+ if ( out_size != NULL ) {
|
|
|
|
|
+ *out_size = f.size;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return f.data;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err slop_file_save(const char *_r_ path, u8 *_r_ data, u64 size,
|
|
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+# endif /* defined(IMP) || defined(IMP_SLOP) */
|
|
|
|
|
+
|
|
|
|
|
+# endif /* defined(WANT_SLOP) || defined(WANT_ALL) */
|
|
|
|
|
+
|
|
|
|
|
+/* ----------------------------- END SLOP DEF ------------------------------ */
|
|
|
|
|
+
|
|
|
# if defined(IMP) || defined(IMP_STR)
|
|
# if defined(IMP) || defined(IMP_STR)
|
|
|
|
|
|
|
|
# define _SET_IF_NOT_NULL(var, err) \
|
|
# define _SET_IF_NOT_NULL(var, err) \
|
|
@@ -1742,7 +2196,6 @@ str_from_i64_temp(i64 num)
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
struct str
|
|
struct str
|
|
|
str_dup(struct str str)
|
|
str_dup(struct str str)
|
|
|
{
|
|
{
|
|
@@ -1856,6 +2309,15 @@ str_tokenize(struct str str, char c)
|
|
|
return st;
|
|
return st;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+struct str_tokenizer
|
|
|
|
|
+str_tokenize_func(struct str str, bool (*f)(char c))
|
|
|
|
|
+{
|
|
|
|
|
+ struct str_tokenizer st = {0};
|
|
|
|
|
+ st.str = str;
|
|
|
|
|
+ st.f = f;
|
|
|
|
|
+ return st;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
struct str
|
|
struct str
|
|
|
str_tokenizer_next(struct str_tokenizer *st)
|
|
str_tokenizer_next(struct str_tokenizer *st)
|
|
|
{
|
|
{
|
|
@@ -1877,10 +2339,18 @@ str_tokenizer_next(struct str_tokenizer *st)
|
|
|
str.data += st->cur;
|
|
str.data += st->cur;
|
|
|
str.size = 0;
|
|
str.size = 0;
|
|
|
|
|
|
|
|
- while ( str.data[str.size] != st->c
|
|
|
|
|
- && st->cur < st->str.size ) {
|
|
|
|
|
- ++str.size;
|
|
|
|
|
- ++st->cur;
|
|
|
|
|
|
|
+ if ( st->f != NULL ) {
|
|
|
|
|
+ while ( (! st->f(str.data[str.size]))
|
|
|
|
|
+ && st->cur < st->str.size ) {
|
|
|
|
|
+ ++str.size;
|
|
|
|
|
+ ++st->cur;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ while ( str.data[str.size] != st->c
|
|
|
|
|
+ && st->cur < st->str.size ) {
|
|
|
|
|
+ ++str.size;
|
|
|
|
|
+ ++st->cur;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
++st->cur;
|
|
++st->cur;
|
|
|
|
|
|