|
@@ -178,7 +178,11 @@ void abort(void);
|
|
|
return ret_val; \
|
|
return ret_val; \
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#define _r_ __restrict__
|
|
|
|
|
|
|
+# define _r_ __restrict__
|
|
|
|
|
+
|
|
|
|
|
+# define SIZEOF_MEMBER(Struct, Member) sizeof(((Struct *)0)->Member)
|
|
|
|
|
+
|
|
|
|
|
+# define CAST(Type, Var) ((Type) (Var))
|
|
|
|
|
|
|
|
/* ------------------------------ END LIB DEF ------------------------------ */
|
|
/* ------------------------------ END LIB DEF ------------------------------ */
|
|
|
|
|
|
|
@@ -546,7 +550,41 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
|
|
|
} \
|
|
} \
|
|
|
(da).data[(da).size++] = (val); \
|
|
(da).data[(da).size++] = (val); \
|
|
|
LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
|
|
LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
|
|
|
- } while(0);
|
|
|
|
|
|
|
+ } while(0)
|
|
|
|
|
+
|
|
|
|
|
+# define DAV_APPEND(Da, Val, ValSize, ErrVar) \
|
|
|
|
|
+ do { \
|
|
|
|
|
+ if ( ErrVar != NULL ) { \
|
|
|
|
|
+ if ( *ErrVar != ERR_OK ) { \
|
|
|
|
|
+ break; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ } \
|
|
|
|
|
+ /* printf("ValSize -> %5ld\tused_bytes -> %5ld\tcap_bytes -> %5ld\n", (ValSize), (Da).used_bytes, (Da).cap_bytes); */ \
|
|
|
|
|
+ if ( (Da).used_bytes + (ValSize) >= (Da).cap_bytes ) { \
|
|
|
|
|
+ (Da).cap_bytes *= 2; \
|
|
|
|
|
+ (Da).data = realloc((Da).data, (Da).cap_bytes); \
|
|
|
|
|
+ if ( (Da).data == NULL ) { \
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_REALLOC); \
|
|
|
|
|
+ break; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ } \
|
|
|
|
|
+ if ( (Da).data == NULL ) { \
|
|
|
|
|
+ if ( (Da).cap_bytes == 0 ) { \
|
|
|
|
|
+ (Da).cap_bytes = 32; \
|
|
|
|
|
+ (Da).size = 0; \
|
|
|
|
|
+ (Da).used_bytes = 0; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ (Da).data = malloc(sizeof(u64) * (Da).cap_bytes); \
|
|
|
|
|
+ if ( (Da).data == NULL ) { \
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_ALLOC); \
|
|
|
|
|
+ break; \
|
|
|
|
|
+ } \
|
|
|
|
|
+ } \
|
|
|
|
|
+ memcpy(CAST(u8*, (Da).data) + (Da).used_bytes, (Val), (ValSize)); \
|
|
|
|
|
+ (Da).used_bytes += (ValSize); \
|
|
|
|
|
+ ++(Da).size; \
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL((ErrVar), ERR_OK); \
|
|
|
|
|
+ } while(0)
|
|
|
|
|
|
|
|
/* ----------------------------- END DA DEF -------------------------------- */
|
|
/* ----------------------------- END DA DEF -------------------------------- */
|
|
|
|
|
|
|
@@ -554,14 +592,27 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
|
|
|
|
|
|
|
|
# if defined(WANT_MAP) || defined(WANT_ALL)
|
|
# 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); \
|
|
|
|
|
|
|
+# define MAP_FOR_EACH(Map, VIndex, VKey) \
|
|
|
|
|
+ for ( (VIndex = (Map)->indexs.data, VKey = (Map)->keys.data); \
|
|
|
|
|
+ VIndex < ((Map)->indexs.data + (Map)->indexs.size); \
|
|
|
|
|
+ (++VIndex, VKey = CAST(struct key_bytes *, CAST(u8*, VKey->key) + VKey->size)) )
|
|
|
|
|
+
|
|
|
|
|
+# define MAP_FOR_EACH_INDEXS(Map, Var) \
|
|
|
|
|
+ for ( Var = (Map)->indexs.data; \
|
|
|
|
|
+ Var < ((Map)->indexs.data + (Map)->indexs.size); \
|
|
|
++Var )
|
|
++Var )
|
|
|
|
|
|
|
|
|
|
+# define MAP_GET_INDEX(Map, Index) \
|
|
|
|
|
+ ((struct map_item *)(((u8*)(Map)->data) + ((Map)->_item_size * (Index))))
|
|
|
|
|
+
|
|
|
|
|
+struct key_bytes {
|
|
|
|
|
+ u64 size;
|
|
|
|
|
+ u8 key[1];
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
struct map_item {
|
|
struct map_item {
|
|
|
u64 key[4];
|
|
u64 key[4];
|
|
|
- u8 item[1];
|
|
|
|
|
|
|
+ u8 item[1];
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
struct map {
|
|
struct map {
|
|
@@ -571,7 +622,13 @@ struct map {
|
|
|
u64 *data;
|
|
u64 *data;
|
|
|
u64 size;
|
|
u64 size;
|
|
|
u64 cap;
|
|
u64 cap;
|
|
|
- } used;
|
|
|
|
|
|
|
+ } indexs;
|
|
|
|
|
+ struct {
|
|
|
|
|
+ struct key_bytes *data;
|
|
|
|
|
+ u64 size;
|
|
|
|
|
+ u64 used_bytes;
|
|
|
|
|
+ u64 cap_bytes;
|
|
|
|
|
+ } keys;
|
|
|
u64 _cap;
|
|
u64 _cap;
|
|
|
u64 _size_bytes;
|
|
u64 _size_bytes;
|
|
|
u64 _item_size;
|
|
u64 _item_size;
|
|
@@ -612,26 +669,41 @@ map_create(u64 elem_size, u64 cap, enum err *out_err)
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
|
|
|
|
|
|
m._cap = cap;
|
|
m._cap = cap;
|
|
|
- m._item_size = sizeof(struct map_item) + (elem_size-1);
|
|
|
|
|
|
|
+ m._elem_size = elem_size;
|
|
|
|
|
+ m._item_size = SIZEOF_MEMBER(struct map_item, key) + m._elem_size + 1;
|
|
|
m._size_bytes = m._item_size * m._cap;
|
|
m._size_bytes = m._item_size * m._cap;
|
|
|
m.data = malloc(m._size_bytes);
|
|
m.data = malloc(m._size_bytes);
|
|
|
if ( m.data == NULL ) {
|
|
if ( m.data == NULL ) {
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
- return empty;
|
|
|
|
|
|
|
+ goto err_exit;
|
|
|
}
|
|
}
|
|
|
|
|
+ memset(m.data, 0, m._size_bytes);
|
|
|
|
|
|
|
|
- m.used.cap = 32;
|
|
|
|
|
- m.used.data = malloc(m.used.cap);
|
|
|
|
|
- if ( m.used.data == NULL ) {
|
|
|
|
|
- free(m.data);
|
|
|
|
|
|
|
+ m.indexs.cap = m._cap;
|
|
|
|
|
+ m.indexs.data = malloc(sizeof(*m.indexs.data) * m.indexs.cap);
|
|
|
|
|
+ if ( m.indexs.data == NULL ) {
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
- return empty;
|
|
|
|
|
|
|
+ goto err_exit;
|
|
|
}
|
|
}
|
|
|
|
|
+ memset(m.indexs.data, 0, sizeof(*m.indexs.data) * m.indexs.cap);
|
|
|
|
|
+
|
|
|
|
|
+ m.keys.cap_bytes = m._cap;
|
|
|
|
|
+ m.keys.data = malloc(sizeof(u64) * m.keys.cap_bytes);
|
|
|
|
|
+ if ( m.keys.data == NULL ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
|
|
+ goto err_exit;
|
|
|
|
|
+ }
|
|
|
|
|
+ memset(m.keys.data, 0, m.keys.cap_bytes);
|
|
|
|
|
|
|
|
m.hash = map_default_hasher;
|
|
m.hash = map_default_hasher;
|
|
|
|
|
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
return m;
|
|
return m;
|
|
|
|
|
+err_exit:
|
|
|
|
|
+ if ( m.data != NULL ) free(m.data);
|
|
|
|
|
+ if ( m.indexs.data != NULL ) free(m.indexs.data);
|
|
|
|
|
+ if ( m.keys.data != NULL ) free(m.keys.data);
|
|
|
|
|
+ return empty;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
enum err
|
|
enum err
|
|
@@ -640,6 +712,7 @@ map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
|
|
|
enum err err = ERR_OK;
|
|
enum err err = ERR_OK;
|
|
|
enum err *perr = &err;
|
|
enum err *perr = &err;
|
|
|
|
|
|
|
|
|
|
+ struct map old = {0};
|
|
|
struct map nm = {0};
|
|
struct map nm = {0};
|
|
|
u64 *index = 0;
|
|
u64 *index = 0;
|
|
|
|
|
|
|
@@ -657,14 +730,28 @@ map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
|
|
|
goto err_exit;
|
|
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);
|
|
|
|
|
|
|
+ MAP_FOR_EACH_INDEXS(m, index) {
|
|
|
|
|
+ struct map_item *mi = MAP_GET_INDEX(m, (*index));
|
|
|
|
|
+ map_add_hashed_key(&nm, mi->key, mi->item, perr);
|
|
|
if ( *perr != ERR_OK ) {
|
|
if ( *perr != ERR_OK ) {
|
|
|
goto err_exit;
|
|
goto err_exit;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ old = *m;
|
|
|
|
|
+
|
|
|
|
|
+ m->data = nm.data;
|
|
|
|
|
+ m->size = nm.size;
|
|
|
|
|
+ m->indexs = nm.indexs;
|
|
|
|
|
+ m->keys = nm.keys;
|
|
|
|
|
+ m->_cap = nm._cap;
|
|
|
|
|
+ m->_size_bytes = nm._size_bytes;
|
|
|
|
|
+ m->_item_size = nm._item_size;
|
|
|
|
|
+ m->_elem_size = nm._elem_size;
|
|
|
|
|
+ m->hash = nm.hash;
|
|
|
|
|
+
|
|
|
|
|
+ map_destroy(&old, NULL);
|
|
|
|
|
+
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
return ERR_OK;
|
|
return ERR_OK;
|
|
|
err_exit:
|
|
err_exit:
|
|
@@ -681,6 +768,7 @@ map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
|
|
|
|
|
u64 i = 0;
|
|
u64 i = 0;
|
|
|
struct map_item *it = NULL;
|
|
struct map_item *it = NULL;
|
|
|
|
|
+
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
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, out_err);
|
|
@@ -702,14 +790,18 @@ map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
return *perr;
|
|
return *perr;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- it = (m->data + (m->_item_size * (i++)));
|
|
|
|
|
|
|
+ it = MAP_GET_INDEX(m, i++);
|
|
|
} while (it->key[0] != 0 || it->key[1] != 0
|
|
} while (it->key[0] != 0 || it->key[1] != 0
|
|
|
|| it->key[2] != 0 || it->key[3] != 0);
|
|
|| it->key[2] != 0 || it->key[3] != 0);
|
|
|
|
|
+ /*
|
|
|
|
|
+ printf("cap=%-5ld\telem_size=%-5ld\tsize_bytes=%-5ld\n",
|
|
|
|
|
+ m->_cap, m->_elem_size, m->_size_bytes);
|
|
|
|
|
+ */
|
|
|
|
|
|
|
|
memcpy(it->key, key, sizeof(u64) * 4);
|
|
memcpy(it->key, key, sizeof(u64) * 4);
|
|
|
memcpy(it->item, elem, m->_elem_size);
|
|
memcpy(it->item, elem, m->_elem_size);
|
|
|
|
|
|
|
|
- DA_APPEND(m->used, i-1, perr);
|
|
|
|
|
|
|
+ DA_APPEND(m->indexs, i-1, perr);
|
|
|
if ( *perr != ERR_OK ) {
|
|
if ( *perr != ERR_OK ) {
|
|
|
memset(it->key, 0, sizeof(u64) * 4);
|
|
memset(it->key, 0, sizeof(u64) * 4);
|
|
|
memset(it->item, 0, m->_elem_size);
|
|
memset(it->item, 0, m->_elem_size);
|
|
@@ -726,6 +818,8 @@ map_add(struct map *m, void *key, u64 key_size, void *elem, enum err *out_err)
|
|
|
enum err err = ERR_OK;
|
|
enum err err = ERR_OK;
|
|
|
enum err *perr = &err;
|
|
enum err *perr = &err;
|
|
|
|
|
|
|
|
|
|
+ struct key_bytes *sb = NULL;
|
|
|
|
|
+
|
|
|
u64 *hash = NULL;
|
|
u64 *hash = NULL;
|
|
|
|
|
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
@@ -747,12 +841,72 @@ map_add(struct map *m, void *key, u64 key_size, void *elem, enum err *out_err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
map_add_hashed_key(m, hash, elem, perr);
|
|
map_add_hashed_key(m, hash, elem, perr);
|
|
|
|
|
+ free(hash);
|
|
|
|
|
+
|
|
|
if ( *perr != ERR_OK ) {
|
|
if ( *perr != ERR_OK ) {
|
|
|
- free(hash);
|
|
|
|
|
return *perr;
|
|
return *perr;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- free(hash);
|
|
|
|
|
|
|
+ sb = malloc(SIZEOF_MEMBER(struct key_bytes, size) + key_size);
|
|
|
|
|
+ if ( sb == NULL ) {
|
|
|
|
|
+ *perr = ERR_FAILED_ALLOC;
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
+ memset(sb, 0, SIZEOF_MEMBER(struct key_bytes, size) + key_size);
|
|
|
|
|
+
|
|
|
|
|
+ sb->size = key_size;
|
|
|
|
|
+ memcpy(sb->key, key, key_size);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ DAV_APPEND(
|
|
|
|
|
+ m->keys, sb,
|
|
|
|
|
+ SIZEOF_MEMBER(struct key_bytes, size) + key_size,
|
|
|
|
|
+ perr
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ do {
|
|
|
|
|
+ if (perr != ((void * ) 0)) {
|
|
|
|
|
+ if ( * perr != ERR_OK) {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((m -> keys).used_bytes + (sizeof(((struct key_bytes * ) 0) -> size) + key_size) >= (m -> keys).cap_bytes) {
|
|
|
|
|
+ (m -> keys).cap_bytes *= 2;
|
|
|
|
|
+ (m -> keys).data = realloc((m -> keys).data, (m -> keys).cap_bytes);
|
|
|
|
|
+ if ((m -> keys).data == ((void * ) 0)) {
|
|
|
|
|
+ if ((perr) != ((void * ) 0)) {
|
|
|
|
|
+ *(perr) = ERR_FAILED_REALLOC;
|
|
|
|
|
+ };
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((m -> keys).data == ((void * ) 0)) {
|
|
|
|
|
+ if ((m -> keys).cap_bytes == 0) {
|
|
|
|
|
+ (m -> keys).cap_bytes = 32;
|
|
|
|
|
+ (m -> keys).size = 0;
|
|
|
|
|
+ (m -> keys).used_bytes = 0;
|
|
|
|
|
+ }(m -> keys).data = malloc(sizeof(u64) * (m -> keys).cap_bytes);
|
|
|
|
|
+ if ((m -> keys).data == ((void * ) 0)) {
|
|
|
|
|
+ if ((perr) != ((void * ) 0)) {
|
|
|
|
|
+ *(perr) = ERR_FAILED_ALLOC;
|
|
|
|
|
+ };
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ memcpy(((u8 * )((m -> keys).data)) + (m -> keys).used_bytes, (sb), (sizeof(((struct key_bytes * ) 0) -> size) + key_size));
|
|
|
|
|
+ (m -> keys).used_bytes += (sizeof(((struct key_bytes * ) 0) -> size) + key_size);
|
|
|
|
|
+ ++(m -> keys).size;
|
|
|
|
|
+ if ((perr) != ((void * ) 0)) {
|
|
|
|
|
+ *(perr) = ERR_OK;
|
|
|
|
|
+ };
|
|
|
|
|
+ } while (0);
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+ free(sb);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ return *perr;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
*perr = ERR_OK;
|
|
*perr = ERR_OK;
|
|
|
return ERR_OK;
|
|
return ERR_OK;
|
|
@@ -781,7 +935,7 @@ map_get(struct map *m, void *key, u64 key_size, enum err *out_err)
|
|
|
free(hash);
|
|
free(hash);
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
- it = (m->data + (m->_item_size * (i++)));
|
|
|
|
|
|
|
+ it = MAP_GET_INDEX(m, i++);
|
|
|
} while (it->key[0] != hash[0] || it->key[1] != hash[1]
|
|
} while (it->key[0] != hash[0] || it->key[1] != hash[1]
|
|
|
|| it->key[2] != hash[2] || it->key[3] != hash[3]);
|
|
|| it->key[2] != hash[2] || it->key[3] != hash[3]);
|
|
|
|
|
|
|
@@ -819,7 +973,7 @@ map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
|
|
|
*perr = ERR_NOT_FOUND;
|
|
*perr = ERR_NOT_FOUND;
|
|
|
return *perr;
|
|
return *perr;
|
|
|
}
|
|
}
|
|
|
- it = (m->data + (m->_item_size * (i++)));
|
|
|
|
|
|
|
+ it = MAP_GET_INDEX(m, i++);
|
|
|
} while (it->key[0] != key[0] || it->key[1] != key[1]
|
|
} while (it->key[0] != key[0] || it->key[1] != key[1]
|
|
|
|| it->key[2] != key[2] || it->key[3] != key[3]);
|
|
|| it->key[2] != key[2] || it->key[3] != key[3]);
|
|
|
|
|
|
|
@@ -877,8 +1031,9 @@ map_destroy(struct map *m, enum err *out_err)
|
|
|
|
|
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
|
|
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);
|
|
|
|
|
|
|
+ if ( m->data != NULL ) free(m->data);
|
|
|
|
|
+ if ( m->indexs.data != NULL ) free(m->indexs.data);
|
|
|
|
|
+ if ( m->keys.data != NULL ) free(m->keys.data);
|
|
|
|
|
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
return ERR_OK;
|
|
return ERR_OK;
|