Rename _set_at to _push method for SET dictionnary.

Add proper _splice method for SET dictionnary.
This commit is contained in:
Patrick Pelissier committed 2018-07-03 10:40:26 +02:00
1 parent 362c64aa9c
commit 4b0f7543ee
3 files changed
+75 -12

No files matched your search

+71 -11
View File
@@ -112,8 +112,8 @@
USAGE: DICT_SET_OPLIST(name[, oplist of the key type]) */
#define DICT_SET_OPLIST(...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(DICTI_OPLIST(__VA_ARGS__, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST ), \
DICTI_OPLIST(__VA_ARGS__ , M_RET_ARG2 (__VA_ARGS__, ) ))
(DICTI_SET_OPLIST(__VA_ARGS__, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST ), \
DICTI_SET_OPLIST(__VA_ARGS__ , M_RET_ARG2 (__VA_ARGS__, ) ))
/* Define a dictionary with the key key_type to the value value_type
@@ -286,6 +286,8 @@
M_C(name, _array_list_pair_get)(map->table, i); \
if (M_C(name, _list_pair_empty_p)(*list)) \
continue; \
/* We need to scan each item and recompute its hash to know \
if it remains inplace or shall be moved to the upper part.*/ \
M_C(name, _list_pair_it_t) it; \
M_C(name, _list_pair_it)(it, *list); \
while (!M_C(name, _list_pair_end_p)(it)) { \
@@ -296,6 +298,7 @@
M_C(name, _list_pair_t) *new_list = \
M_C(name, _array_list_pair_get)(map->table, i + old_size); \
M_C(name, _list_pair_splice_back)(*new_list, *list, it); \
/* Splice_back has updated the iterator to the next one */ \
} else { \
M_C(name, _list_pair_next)(it); \
} \
@@ -313,7 +316,7 @@
assert ((old_size % 2) == 0); \
size_t new_size = old_size / 2; \
assert (new_size >= DICTI_INITIAL_SIZE); \
/* Move all items to the lower part of the dictionnary */ \
/* Move all items from the upper part to the lower part of the table */ \
/* NOTE: We don't need to recompute the hash to move them! */ \
for(size_t i = new_size; i < old_size; i++) { \
M_C(name, _list_pair_t) *list = \
@@ -324,15 +327,16 @@
M_C(name, _array_list_pair_get)(map->table, i - new_size); \
M_C(name, _list_pair_splice)(*new_list, *list); \
} \
/* Resize the dictionary */ \
/* Resize the table of the dictionary */ \
M_C(name, _array_list_pair_resize)(map->table, new_size); \
map->upper_limit = DICTI_UPPER_BOUND(new_size); \
map->lower_limit = DICTI_LOWER_BOUND(new_size); \
} \
\
static inline void \
M_C(name, _set_at)(dict_t map, key_type const key \
M_IF(isSet)(, M_DEFERRED_COMMA value_type const value)) \
M_IF(isSet)(M_C(name, _push), M_C(name, _set_at)) \
(dict_t map, key_type const key \
M_IF(isSet)(, M_DEFERRED_COMMA value_type const value)) \
{ \
DICTI_CONTRACT(name, map); \
\
@@ -607,8 +611,11 @@
if (b == false || c != ':') { goto exit; } \
b = M_GET_PARSE_STR value_oplist (value, str, &str); \
if (b == false) { goto exit; } \
M_C(name, _set_at)(dict, key \
M_IF(isSet)( , M_DEFERRED_COMMA value)); \
M_IF(isSet)( \
M_C(name, _push)(dict, key); \
, \
M_C(name, _set_at)(dict, key, value); \
) \
do { c = *str++; } while (isspace(c)); \
} while (c == ','); \
M_GET_CLEAR key_oplist (key); \
@@ -646,8 +653,11 @@
if (c != ':') { c = 0; break; } \
b = M_GET_IN_STR value_oplist (value, file); \
if (b == false) { c = 0; break; } \
M_C(name, _set_at)(dict, key \
M_IF(isSet)( , M_DEFERRED_COMMA value)); \
M_IF(isSet)( \
M_C(name, _push)(dict, key); \
, \
M_C(name, _set_at)(dict, key, value); \
) \
do { c = fgetc(file); } while (isspace(c)); \
} while (c == ','); \
M_GET_CLEAR key_oplist (key); \
@@ -656,6 +666,22 @@
} \
, /* no IN_STR */ ) \
\
/* TBC: What to do if the container is a set for splice? */ \
M_IF(isSet)( \
static inline void \
M_C(name, _splice)(dict_t d1, dict_t d2) \
{ \
dict_it_t it; \
/* NOTE: Despite using set_at, the accessing of the item in d1 \
is not as random as other uses of the HASH table as d2 \
uses the same order than d1 */ \
for (M_C(name, _it)(it, d2); !M_C(name, _end_p)(it); M_C(name, _next)(it)){ \
const struct M_C(name, _pair_s) *item = M_C(name, _cref)(it); \
M_C(name, _push)(d1, item->key); \
} \
M_C(name, _clean)(d2); \
} \
, \
M_IF_METHOD(UPDATE, value_oplist)( \
static inline void \
M_C(name, _splice)(dict_t d1, dict_t d2) \
@@ -675,7 +701,7 @@
} \
M_C(name, _clean)(d2); \
} \
, /* NO UPDATE */) \
, /* NO UPDATE */) ) \
\
/* HASH method for dictionnary itself seems hard to implement: \
we have to handle the case where two dictionnaries are structuraly \
@@ -720,6 +746,40 @@
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
/* Define the oplist of a set */
#define DICTI_SET_OPLIST(name, key_oplist, value_oplist) \
(INIT(M_C(name, _init)), \
INIT_SET(M_C(name, _init_set)), \
SET(M_C(name, _set)), \
CLEAR(M_C(name, _clear)), \
INIT_MOVE(M_C(name, _init_move)), \
MOVE(M_C(name, _move)), \
SWAP(M_C(name, _swap)), \
TYPE(M_C(name, _t)), \
SUBTYPE(struct M_C(name, _pair_s)), \
PUSH(M_C(name,_push)), \
IT_TYPE(M_C(name, _it_t)), \
IT_FIRST(M_C(name,_it)), \
IT_SET(M_C(name, _it_set)), \
IT_END_P(M_C(name,_end_p)), \
IT_LAST_P(M_C(name,_last_p)), \
IT_NEXT(M_C(name,_next)), \
IT_REF(M_C(name,_ref)), \
IT_CREF(M_C(name,_cref)) \
,OPLIST(PAIR_OPLIST(key_oplist, value_oplist)) \
,M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)(GET_STR(M_C(name, _get_str)),) \
,M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)(PARSE_STR(M_C(name, _parse_str)),) \
,M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)(OUT_STR(M_C(name, _out_str)),) \
,M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)(IN_STR(M_C(name, _in_str)),) \
,M_IF_METHOD(EQUAL, value_oplist)(EQUAL(M_C(name, _equal_p)),) \
,KEY_OPLIST(key_oplist) \
,VALUE_OPLIST(value_oplist) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
#define DICTI_LOWER_BOUND(s) ((s) <= DICTI_INITIAL_SIZE ? 0 : (s) * 1 / 4)
#define DICTI_UPPER_BOUND(s) ((s) * 2 / 3)
#define DICTI_INITIAL_SIZE 16