diff --git a/README.md b/README.md index e7787c7e..0851b82b 100644 --- a/README.md +++ b/README.md @@ -988,7 +988,7 @@ This method is only defined if the type of the element defines a EQUAL method it #### DICT\_DEF2(name, key\_type, key\_oplist, value\_type, value\_oplist) -Define the dictionary 'dict\_##name##\_t' and its associated methods as "static inline" functions. +Define the dictionary 'name##\_t' and its associated methods as "static inline" functions. A dictionary (or associative array, map, symbol table) is an abstract data type composed of a collection of (key, value) pairs, such that each possible key appears at most once in the collection. @@ -996,7 +996,7 @@ such that each possible key appears at most once in the collection. Current implementation uses chained Hash-Table and as such, elements in the dictionary are **unordered**. It shall be done once per type and per compilation unit. -It also define the iterator dict\_it\_##name##\_t and its associated methods as "static inline" functions. +It also define the iterator name##\_it\_t and its associated methods as "static inline" functions. The object oplists are expected to have the following operators (INIT, INIT\_SET, SET and CLEAR), otherwise default operators are used. If there is no given oplist, the default operators are also used. The created methods will use the operators to init, set and clear the contained object. @@ -1006,7 +1006,7 @@ Interface is subjected to minor change. Example: - DICT_DEF2(str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) + DICT_DEF2(dict_str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) dict_str_t my_dict; void f(string_t key, string_t value) { dict_str_set_at (my_dict, key, value); @@ -1015,13 +1015,13 @@ Example: #### DICT\_OA\_DEF2(name, key\_type, key\_oplist, value\_type, value\_oplist) -Define the dictionary 'dict\_##name##\_t' and its associated methods +Define the dictionary 'name##\_t' and its associated methods as "static inline" functions much like DICT\_DEF2. The difference is that it uses an Open Addressiong Hash-Table as container. It shall be done once per type and per compilation unit. -It also define the iterator dict\_it\_##name##\_t and its associated methods as "static inline" functions. +It also define the iterator name##\_it\_t and its associated methods as "static inline" functions. The object oplists are expected to have the following operators (INIT, INIT\_SET, SET, CLEAR), otherwise default operators are used. @@ -1044,7 +1044,7 @@ Example: *k = (int)-n-1; } - DICT_OA_DEF2(int, int, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int64_t, M_DEFAULT_OPLIST) + DICT_OA_DEF2(dict_int, int, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int64_t, M_DEFAULT_OPLIST) dict_int_t my_dict; void f(int key, int64_t value) { @@ -1058,11 +1058,11 @@ Return the oplist of the dictionary defined by calling DICT\_DEF2 with name & ke #### DICT\_SET\_DEF2(name, key\_type, key\_oplist) -Define the set 'dict\_##name##\_t' and its associated methods as "static inline" functions. +Define the set 'name##\_t' and its associated methods as "static inline" functions. A set is a specialized version of a dictionary with no value. It shall be done once per type and per compilation unit. -It also define the iterator dict\_it\_##name##\_t and its associated methods as "static inline" functions. +It also define the iterator name##\_it\_t and its associated methods as "static inline" functions. The oplist is expected to have the following operators (INIT, INIT\_SET, SET, CLEAR, HASH and EQUAL), otherwise default operators are used. If there is no given oplist, the default operators are also used. The created methods will use the operators to init, set and clear the contained object. @@ -1071,7 +1071,7 @@ Interface is subjected to minor change. Example: - DICT_SET_DEF2(strSet, string_t, STRING_OPLIST) + DICT_SET_DEF2(dict_strSet, string_t, STRING_OPLIST) dict_strSet_t set; void f(string_t key) { dict_strSet_set_at (set, key); @@ -1086,112 +1086,112 @@ Return the oplist of the set defined by calling DICT\_SET\_DEF2 with name & key\ In the following methods, name stands for the name given to the macro which is used to identify the type. The following types are automatically defined by the previous macro: -##### dict\_name\_t +##### name\_t Type of the dictionary of 'key_type' --> 'value_type'. -##### dict\_it\_name\_t +##### name\_it\_t Type of an iterator over this dictionary. The following methods are automatically and properly created by the previous macro: -##### void dict\_name\_init(dict\_name\_t dict) +##### void name\_init(name\_t dict) Initialize the dictionary 'dict' to be empty. -##### void dict\_name\_clear(dict\_name\_t dict) +##### void name\_clear(name\_t dict) Clear the dictionary 'dict'. -##### void dict\_name\_init\_set(dict\_name\_t dict, const dict\_name\_t ref) +##### void name\_init\_set(name\_t dict, const name\_t ref) Initialize the dictionary 'dict' to be the same as 'ref'. -##### void dict\_name\_set(dict\_name\_t dict, const dict\_name\_t ref) +##### void name\_set(name\_t dict, const name\_t ref) Set the dictionary 'dict' to be the same as 'ref'. -##### void dict\_name\_init\_move(dict\_name\_t dict, dict\_name\_t ref) +##### void name\_init\_move(name\_t dict, name\_t ref) Initialize the dictionary 'dict' by stealing as resource as possible from 'ref' and clear 'ref'. -##### void dict\_name\_move(dict\_name\_t dict, dict\_name\_t ref) +##### void name\_move(name\_t dict, name\_t ref) Set the dictionary 'dict' by stealing as resource as possible from 'ref' and clear 'ref'. -##### void dict\_name\_clean(dict\_name\_t dict) +##### void name\_clean(name\_t dict) Clean the dictionary 'dict'. 'dict' remains initialized. -##### size\_t dict\_name\_size(const dict\_name\_t dict) +##### size\_t name\_size(const name\_t dict) Return the number of elements of the dictionary. -##### value\_type \*dict\_name\_get(const dict\_name\_t dict, const key\_type key) +##### value\_type \*name\_get(const name\_t dict, const key\_type key) Return a pointer to the value associated to the key 'key' in dictionary 'dict' or NULL if the key is not found. -##### void dict\_name\_set\_at(dict\_name\_t dict, const key\_type key, const value\_type value) +##### void name\_set\_at(name\_t dict, const key\_type key, const value\_type value) Set the value referenced by key 'key' in the dictionary 'dict' to 'value'. -##### void dict\_name\_remove(dict\_name\_t dict, const key\_type key) +##### void name\_remove(name\_t dict, const key\_type key) Remove the element referenced by key 'key' in the dictionary 'dict'. Do nothing if 'key' is no present in the dictionary. -##### void dict\_name\_it(dict\_it\_name\_t it, dict\_name\_t dict) +##### void name\_it(name\_it\_t it, name\_t dict) Set the iterator 'it' to the first element of 'dict'. -##### void dict\_name\_it\_set(dict\_it\_name\_t it, const dict\_it\_name\_t ref) +##### void name\_it\_set(name\_it\_t it, const name\_it\_t ref) Set the iterator 'it' to the same element than 'ref'. -##### bool dict\_name\_end\_p(const dict\_it\_name\_t it) +##### bool name\_end\_p(const name\_it\_t it) Return true if 'it' references no longer a valid element. -##### bool dict\_name\_last\_p(const dict\_it\_name\_t it) +##### bool name\_last\_p(const name\_it\_t it) Return true if 'it' references the last element or is no longer valid. -##### void dict\_name\_next(dict\_it\_name\_t it) +##### void name\_next(name\_it\_t it) Update the iterator 'it' to the next element. -##### dict\_pair\_name\_t *dict\_name\_ref(dict\_it\_name\_t it) +##### name\_pair\_t *name\_ref(name\_it\_t it) Return a pointer to the pair composed by the key and its value. 'key' element can not be modified. This pointer remains valid until the dictionary is modified by another method. -##### const dict\_pair\_name\_t *dict\_name\_ref(dict\_it\_name\_t it) +##### const name\_pair\_t *name\_ref(name\_it\_t it) Return a constant pointer to the pair composed by the key and its value. This pointer remains valid until the dictionary is modified by another method. -##### void dict\_name\_get\_str(string\_t str, const dict\_name\_t dict, bool append) +##### void name\_get\_str(string\_t str, const name\_t dict, bool append) Generate a string representation of the dict 'dict' and set 'str' to this representation (if 'append' is false) or append 'str' with this representation (if 'append' is true). This method is only defined if the type of the element defines a GET\_STR method itself. -##### void dict\_name\_out\_str(FILE *file, const dict\_name\_t dict) +##### void name\_out\_str(FILE *file, const name\_t dict) Generate a string representation of the dict 'dict' and outputs it into the FILE 'file'. This method is only defined if the type of the element defines a OUT\_STR method itself. -##### void dict\_name\_in\_str(FILE *file, const dict\_name\_t dict) +##### void name\_in\_str(FILE *file, const name\_t dict) Read from the file 'file' a string representation of a dict and set 'dict' to this representation. This method is only defined if the type of the element defines a IN\_STR method itself. -##### bool dict\_name\_equal\_p(const dict\_name\_t dict1, const dict\_name\_t dict2) +##### bool name\_equal\_p(const name\_t dict1, const name\_t dict2) Return true if both dicts 'dict1' and 'dict2' are equal. This method is only defined if the type of the element defines a EQUAL method itself. diff --git a/bench/bench-mlib.c b/bench/bench-mlib.c index df9d1b0e..ffb4df44 100644 --- a/bench/bench-mlib.c +++ b/bench/bench-mlib.c @@ -100,9 +100,9 @@ static void test_rbtree(size_t n) /********************************************************************************************/ #ifdef USE_MEMPOOL -DICT_DEF2(ulong, unsigned long, M_OPEXTEND(M_DEFAULT_OPLIST, MEMPOOL(dict_mpool), MEMPOOL_LINKAGE(static)), unsigned long, M_DEFAULT_OPLIST) +DICT_DEF2(dict_ulong, unsigned long, M_OPEXTEND(M_DEFAULT_OPLIST, MEMPOOL(dict_mpool), MEMPOOL_LINKAGE(static)), unsigned long, M_DEFAULT_OPLIST) #else -DICT_DEF2(ulong, unsigned long, M_DEFAULT_OPLIST, unsigned long, M_DEFAULT_OPLIST) +DICT_DEF2(dict_ulong, unsigned long, M_DEFAULT_OPLIST, unsigned long, M_DEFAULT_OPLIST) #endif static void @@ -111,7 +111,7 @@ test_dict(unsigned long n) #ifdef USE_MEMPOOL mempool_list_dict_pair_ulong_init(dict_mpool); #endif - M_LET(dict, DICT_OPLIST(ulong)) { + M_LET(dict, DICT_OPLIST(dict_ulong)) { for (size_t i = 0; i < n; i++) { unsigned long key = rand_get(); dict_ulong_set_at(dict, key, rand_get() ); @@ -142,12 +142,14 @@ static inline void oor_set(unsigned long *k, unsigned char n) *k = (unsigned long)n; } -DICT_OA_DEF2(oa_ulong, unsigned long, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), unsigned long, M_DEFAULT_OPLIST) +DICT_OA_DEF2(dict_oa_ulong, + unsigned long, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), + unsigned long, M_DEFAULT_OPLIST) static void test_dict_oa(unsigned long n) { - M_LET(dict, DICT_OPLIST(oa_ulong)) { + M_LET(dict, DICT_OPLIST(dict_oa_ulong)) { for (size_t i = 0; i < n; i++) { dict_oa_ulong_set_at(dict, rand_get(), rand_get() ); } @@ -175,9 +177,9 @@ static size_t char_hash(const char_array_t a) { return m_core_hash (a, strlen(a) #define CHAR_OPLIST (INIT(char_init), INIT_SET(char_set), SET(char_set), CLEAR(char_init), HASH(char_hash), EQUAL(char_equal_p)) #ifdef USE_MEMPOOL -DICT_DEF2(char, char_array_t, M_OPEXTEND(CHAR_OPLIST,MEMPOOL(dict_mpool2), MEMPOOL_LINKAGE(static)), char_array_t, CHAR_OPLIST) +DICT_DEF2(dict_char, char_array_t, M_OPEXTEND(CHAR_OPLIST,MEMPOOL(dict_mpool2), MEMPOOL_LINKAGE(static)), char_array_t, CHAR_OPLIST) #else -DICT_DEF2(char, char_array_t, CHAR_OPLIST, char_array_t, CHAR_OPLIST) +DICT_DEF2(dict_char, char_array_t, CHAR_OPLIST, char_array_t, CHAR_OPLIST) #endif static void @@ -186,7 +188,7 @@ test_dict_big(unsigned long n) #ifdef USE_MEMPOOL mempool_list_dict_pair_char_init(dict_mpool2); #endif - M_LET(dict, DICT_OPLIST(char)) { + M_LET(dict, DICT_OPLIST(dict_char)) { for (size_t i = 0; i < n; i++) { char_array_t s1, s2; sprintf(s1, "%u", rand_get()); @@ -212,9 +214,9 @@ test_dict_big(unsigned long n) /********************************************************************************************/ #ifdef USE_MEMPOOL -DICT_DEF2(str, string_t, M_OPEXTEND(STRING_OPLIST, MEMPOOL(dict_mpool3), MEMPOOL_LINKAGE(static)), string_t, STRING_OPLIST) +DICT_DEF2(dict_str, string_t, M_OPEXTEND(STRING_OPLIST, MEMPOOL(dict_mpool3), MEMPOOL_LINKAGE(static)), string_t, STRING_OPLIST) #else -DICT_DEF2(str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) +DICT_DEF2(dict_str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) #endif static void @@ -224,7 +226,7 @@ test_dict_str(unsigned long n) mempool_list_dict_pair_str_init(dict_mpool3); #endif M_LET(s1, s2, STRING_OPLIST) - M_LET(dict, DICT_OPLIST(str)) { + M_LET(dict, DICT_OPLIST(dict_str)) { for (size_t i = 0; i < n; i++) { string_printf(s1, "%u", rand_get()); string_printf(s2, "%u", rand_get()); diff --git a/example/ex-dict01.c b/example/ex-dict01.c index 72836509..7661900d 100644 --- a/example/ex-dict01.c +++ b/example/ex-dict01.c @@ -6,7 +6,7 @@ // Define a dictionnary of string --> int // named 'str' -DICT_DEF2(str, string_t, STRING_OPLIST, int, M_DEFAULT_OPLIST) +DICT_DEF2(dict_str, string_t, STRING_OPLIST, int, M_DEFAULT_OPLIST) int main(void) { @@ -39,10 +39,10 @@ int main(void) printf ("Max occurence = %d\n", max); // Iterate on the dictionnary - dict_it_str_t it; + dict_str_it_t it; for(dict_str_it(it, h); !dict_str_end_p(it); dict_str_next(it)) { // Get a constant reference on the pair stored in the dictionnary - const dict_pair_str_t *pair = dict_str_cref(it); + const dict_str_pair_t *pair = dict_str_cref(it); printf ("Key=%s Value=%d\n", string_get_cstr((*pair)->key), (*pair)->value); } diff --git a/example/ex-dict02.c b/example/ex-dict02.c index b9f4aeec..6c720901 100644 --- a/example/ex-dict02.c +++ b/example/ex-dict02.c @@ -1,10 +1,10 @@ #include "m-dict.h" // Let's define a dictionary of 'unsigned int' --> 'char -DICT_DEF2(m32, unsigned int, M_DEFAULT_OPLIST, char, M_DEFAULT_OPLIST) +DICT_DEF2(dict_m32, unsigned int, M_DEFAULT_OPLIST, char, M_DEFAULT_OPLIST) // Let's create a synonym for its oplist. -#define M32_OPLIST DICT_OPLIST(m32, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST) +#define M32_OPLIST DICT_OPLIST(dict_m32, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST) #if 1 // Non macro version. @@ -16,9 +16,9 @@ int main(void) { int is_missing = (k != NULL); // true assert (is_missing); dict_m32_remove(h, 5); // h is now empty - dict_it_m32_t it; // iterate over all dictionnary + dict_m32_it_t it; // iterate over all dictionnary for (dict_m32_it (it, h) ; !dict_m32_end_p (it); dict_m32_next(it)) { - dict_pair_m32_t *item = dict_m32_ref(it); + dict_m32_pair_t *item = dict_m32_ref(it); (*item)->value = 1; // Set its value to 1 } dict_m32_clear(h); // h is cleared diff --git a/example/ex-dict03.c b/example/ex-dict03.c index 98ce72d1..e98c99da 100644 --- a/example/ex-dict03.c +++ b/example/ex-dict03.c @@ -5,12 +5,12 @@ #include "m-dict.h" #include "m-string.h" -DICT_DEF2(map, char, M_DEFAULT_OPLIST, int, M_DEFAULT_OPLIST) +DICT_DEF2(dict_map, char, M_DEFAULT_OPLIST, int, M_DEFAULT_OPLIST) int main(void) { dict_map_t mp; - dict_it_map_t it; + dict_map_it_t it; int choice, item; string_t str; char s; @@ -76,7 +76,7 @@ int main(void) printf("Displaying Map by Iterator:\n"); for (dict_map_it(it, mp); !dict_map_end_p(it); dict_map_next(it)) { - const dict_pair_map_t *cref = dict_map_cref(it); + const dict_map_pair_t *cref = dict_map_cref(it); printf ("%d : %d\n", (*cref)->key, (*cref)->value); } break; diff --git a/example/ex-dict04.c b/example/ex-dict04.c index 6ab3965a..6dbca119 100644 --- a/example/ex-dict04.c +++ b/example/ex-dict04.c @@ -5,12 +5,12 @@ /* program that reads text from standard-input, and prints the total number of distinct words found in the text. */ -DICT_SET_DEF2(str, string_t, STRING_OPLIST) +DICT_SET_DEF2(dict_str, string_t, STRING_OPLIST) int main(void) { M_LET(word, STRING_OPLIST) - M_LET(wordcount, DICT_SET_OPLIST(str, STRING_OPLIST)) { + M_LET(wordcount, DICT_SET_OPLIST(dict_str, STRING_OPLIST)) { while (string_fget_word(word, " \t\n,.!;:?", stdin)) dict_str_set_at(wordcount, word); printf ("Words: %lu\n", dict_str_size(wordcount)); diff --git a/example/ex-multi02.c b/example/ex-multi02.c index 456a0111..ae6199cd 100644 --- a/example/ex-multi02.c +++ b/example/ex-multi02.c @@ -16,11 +16,11 @@ VARIANT_DEF2(integer, #define INTEGER_OPLIST VARIANT_OPLIST(integer, M_DEFAULT_OPLIST, M_CLASSIC_OPLIST(mpz)) /* Define a dictionary of string --> integer named dict_my_t */ -DICT_DEF2(my, +DICT_DEF2(dict_my, string_t, STRING_OPLIST, integer_t, INTEGER_OPLIST) /* Define the oplist associated to this dictionary */ -#define MY_DICT_OPLIST DICT_OPLIST(my, STRING_OPLIST, INTEGER_OPLIST) +#define MY_DICT_OPLIST DICT_OPLIST(dict_my, STRING_OPLIST, INTEGER_OPLIST) /* Define an array of such dictionary named array_my_t */ ARRAY_DEF(array_my, dict_my_t, MY_DICT_OPLIST) diff --git a/example/ex-multi03.c b/example/ex-multi03.c index ea3c8c5f..bc0239f2 100644 --- a/example/ex-multi03.c +++ b/example/ex-multi03.c @@ -76,7 +76,7 @@ extern bool json_in_str(json_t *, FILE *); INIT_SET(json_init_set M_IPTR), SET(json_set M_IPTR), \ OUT_STR(json_out_str), IN_STR(json_in_str M_IPTR) ) -DICT_DEF2(json, string_t, STRING_OPLIST, json_t, JSON_OPLIST) +DICT_DEF2(dict_json, string_t, STRING_OPLIST, json_t, JSON_OPLIST) ARRAY_DEF(array_json, json_t, JSON_OPLIST) @@ -84,7 +84,7 @@ VARIANT_DEF2(variant_json, (boolean, bool, M_OPEXTEND(M_DEFAULT_OPLIST, OUT_STR(boolean_out_str), IN_STR(boolean_in_str M_IPTR)) ), (real, float, M_OPEXTEND (M_DEFAULT_OPLIST, OUT_STR(real_out_str), IN_STR(real_in_str M_IPTR))), (array, array_json_t, ARRAY_OPLIST(array_json, JSON_OPLIST)), - (dict, dict_json_t, DICT_OPLIST(json, STRING_OPLIST, JSON_OPLIST))) + (dict, dict_json_t, DICT_OPLIST(dict_json, STRING_OPLIST, JSON_OPLIST))) struct json_node_s { variant_json_t json; diff --git a/m-dict.h b/m-dict.h index e8f356ce..bcd768cf 100644 --- a/m-dict.h +++ b/m-dict.h @@ -33,16 +33,23 @@ USAGE: DICT_DEF2(name, key_type, key_oplist, value_type, value_oplist) */ #define DICT_DEF2(name, key_type, key_oplist, value_type, value_oplist) \ - TUPLE_DEF2(M_C(dict_pair_, name), (key, key_type, key_oplist), (value, value_type, value_oplist)) \ - M_IF_METHOD(MEMPOOL, key_oplist)( \ - LIST_DEF(M_C(list_dict_pair_, name), M_C3(dict_pair_,name,_t), \ - M_OPEXTEND(TUPLE_OPLIST(M_C(dict_pair_, name), key_oplist, value_oplist), MEMPOOL(M_GET_MEMPOOL key_oplist), MEMPOOL_LINKAGE(M_GET_MEMPOOL_LINKAGE key_oplist))) \ - , \ - LIST_DEF(M_C(list_dict_pair_, name), M_C3(dict_pair_,name,_t), TUPLE_OPLIST(M_C(dict_pair_, name), key_oplist, value_oplist)) \ - ) \ - ARRAY_DEF(M_C(array_list_dict_pair_,name), M_C3(list_dict_pair_,name,_t), LIST_OPLIST(M_C(list_dict_pair_, name), TUPLE_OPLIST(M_C(dict_pair_, name), key_oplist, value_oplist))) \ - \ - DICTI_DEF2_FUNC(name, key_type, key_oplist, value_type, value_oplist, 0, M_C3(dict_, name, _t), M_C3(dict_it_, name, _t)) + \ + TUPLE_DEF2(M_C(name, _pair), (key, key_type, key_oplist), (value, value_type, value_oplist)) \ + \ + M_IF_METHOD(MEMPOOL, key_oplist) \ + ( \ + LIST_DEF(M_C(name, _list_pair), M_C(name, _pair_t), \ + M_OPEXTEND(TUPLE_OPLIST(M_C(name, _pair), key_oplist, value_oplist), \ + MEMPOOL(M_GET_MEMPOOL key_oplist), MEMPOOL_LINKAGE(M_GET_MEMPOOL_LINKAGE key_oplist))) \ + , \ + LIST_DEF(M_C(name, _list_pair), M_C(name, _pair_t), \ + TUPLE_OPLIST(M_C(name, _pair), key_oplist, value_oplist)) \ + ) \ + \ + ARRAY_DEF(M_C(name, _array_list_pair), M_C(name, _list_pair_t), \ + LIST_OPLIST(M_C(name, _list_pair), TUPLE_OPLIST(M_C(name, _pair), key_oplist, value_oplist))) \ + \ + DICTI_FUNC_DEF2(name, key_type, key_oplist, value_type, value_oplist, 0, M_C(name, _t), M_C(name, _it_t)) /* Define the oplist of a dictionnary. @@ -57,19 +64,25 @@ USAGE: DICT_SET_DEF2(name, key_type, key_oplist) */ #define DICT_SET_DEF2(name, key_type, key_oplist) \ - TUPLE_DEF2(M_C(dict_pair_, name), (key, key_type, key_oplist)) \ - M_IF_METHOD(MEMPOOL, key_oplist)( \ - LIST_DEF(M_C(list_dict_pair_, name), M_C3(dict_pair_,name,_t), \ - M_OPEXTEND(TUPLE_OPLIST(M_C(dict_pair_, name), key_oplist), MEMPOOL(M_GET_MEMPOOL key_oplist), MEMPOOL_LINKAGE(M_GET_MEMPOOL_LINKAGE key_oplist))) \ - , \ - LIST_DEF(M_C(list_dict_pair_, name), M_C3(dict_pair_,name,_t), TUPLE_OPLIST(M_C(dict_pair_, name), key_oplist)) \ - ) \ - ARRAY_DEF(M_C(array_list_dict_pair_,name), M_C3(list_dict_pair_,name,_t), LIST_OPLIST(M_C(list_dict_pair_, name), TUPLE_OPLIST(M_C(dict_pair_, name), key_oplist))) \ + \ + TUPLE_DEF2(M_C(name, _pair), (key, key_type, key_oplist)) \ + \ + M_IF_METHOD(MEMPOOL, key_oplist) \ + ( \ + LIST_DEF(M_C(name, _list_pair), M_C(name, _pair_t), \ + M_OPEXTEND(TUPLE_OPLIST(M_C(name, _pair), key_oplist), \ + MEMPOOL(M_GET_MEMPOOL key_oplist), MEMPOOL_LINKAGE(M_GET_MEMPOOL_LINKAGE key_oplist))) \ + , \ + LIST_DEF(M_C(name, _list_pair), M_C(name, _pair_t), TUPLE_OPLIST(M_C(name, _pair), key_oplist)) \ + ) \ + \ + ARRAY_DEF(M_C(name, _array_list_pair), M_C(name, _list_pair_t), \ + LIST_OPLIST(M_C(name, _list_pair), TUPLE_OPLIST(M_C(name, _pair), key_oplist))) \ \ - DICTI_DEF2_FUNC(name, key_type, key_oplist, key_type, \ + DICTI_FUNC_DEF2(name, key_type, key_oplist, key_type, \ (INIT(M_EMPTY_DEFAULT), INIT_SET(M_EMPTY_DEFAULT), SET(M_EMPTY_DEFAULT), CLEAR(M_EMPTY_DEFAULT), \ EQUAL(M_EMPTY_DEFAULT), GET_STR(M_EMPTY_DEFAULT), OUT_STR(M_EMPTY_DEFAULT), IN_STR(M_TRUE_DEFAULT)), \ - 1, M_C3(dict_, name, _t), M_C3(dict_it_, name, _t)) + 1, M_C(name, _t), M_C(name, _it_t)) /* Define the oplist of a dictionnary. @@ -80,137 +93,139 @@ DICTI_OPLIST(__VA_ARGS__ , M_RET_ARG2 (__VA_ARGS__, ) )) -/* Open Addressing implementation. Same oplist. - Need OOR_EQUAL & OOR_SET as methods of the key */ +/* Define a dictionary with the key key_type to the value value_type + with an Open Addressing implementation. Same oplist. + KEY_OPLIST needs OOR_EQUAL & OOR_SET as methods of the key */ #define DICT_OA_DEF2(name, key_type, key_oplist, value_type, value_oplist) \ DICTI_OA_DEFI(name, key_type, key_oplist, value_type, value_oplist, \ M_GET_OOR_EQUAL key_oplist, M_GET_OOR_SET key_oplist, \ - 0.2, 0.7, M_C3(dict_,name,_t), M_C3(dict_it_,name,_t) ) + 0.2, 0.7, M_C(name,_t), M_C(name, _it_t) ) /********************************** INTERNAL ************************************/ /* Define a chained dictionnary */ -#define DICTI_DEF2_FUNC(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t) \ +#define DICTI_FUNC_DEF2(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t) \ \ - typedef struct M_C3(dict_, name, _s) { \ + typedef struct M_C(name, _s) { \ size_t used, lower_limit, upper_limit; \ - M_C3(array_list_dict_pair_,name,_t) table; \ + M_C(name, _array_list_pair_t) table; \ } dict_t[1]; \ \ - typedef struct M_C3(dict_it_, name, _s) { \ - M_C3(array_list_dict_pair_, name, _it_t) array_it; \ - M_C3(list_dict_pair_, name, _it_t) list_it; \ - } dict_it_t[1]; \ + typedef struct M_C(name, _it_s) { \ + M_C(name, _array_list_pair_it_t) array_it; \ + M_C(name, _list_pair_it_t) list_it; \ + } dict_it_t[1]; \ \ static inline void \ - M_C3(dict_, name, _init)(dict_t map) \ + M_C(name, _init)(dict_t map) \ { \ + assert (map != NULL); \ map->used = 0; \ - M_C3(array_list_dict_pair_,name,_init)(map->table); \ - M_C3(array_list_dict_pair_,name,_resize)(map->table, DICTI_INITIAL_SIZE); \ + M_C(name, _array_list_pair_init)(map->table); \ + M_C(name, _array_list_pair_resize)(map->table, DICTI_INITIAL_SIZE); \ map->lower_limit = DICTI_LOWER_BOUND(DICTI_INITIAL_SIZE); \ map->upper_limit = DICTI_UPPER_BOUND(DICTI_INITIAL_SIZE); \ DICTI_CONTRACT(name, map); \ } \ \ static inline void \ - M_C3(dict_, name, _init_set)(dict_t map, const dict_t org) \ + M_C(name, _init_set)(dict_t map, const dict_t org) \ { \ DICTI_CONTRACT(name, org); \ assert (map != org); \ map->used = org->used; \ map->lower_limit = org->lower_limit; \ map->upper_limit = org->upper_limit; \ - M_C3(array_list_dict_pair_,name,_init_set)(map->table, org->table); \ + M_C(name, _array_list_pair_init_set)(map->table, org->table); \ DICTI_CONTRACT(name, map); \ } \ \ static inline void \ - M_C3(dict_, name, _set)(dict_t map, const dict_t org) \ + M_C(name, _set)(dict_t map, const dict_t org) \ { \ DICTI_CONTRACT(name, map); \ DICTI_CONTRACT(name, org); \ map->used = org->used; \ map->lower_limit = org->lower_limit; \ map->upper_limit = org->upper_limit; \ - M_C3(array_list_dict_pair_,name,_set)(map->table, org->table); \ + M_C(name, _array_list_pair_set)(map->table, org->table); \ DICTI_CONTRACT(name, map); \ } \ \ static inline void \ - M_C3(dict_,name,_clear)(dict_t map) \ + M_C(name,_clear)(dict_t map) \ { \ DICTI_CONTRACT(name, map); \ - M_C3(array_list_dict_pair_,name,_clear)(map->table); \ + M_C(name, _array_list_pair_clear)(map->table); \ } \ \ static inline void \ - M_C3(dict_, name, _init_move)(dict_t map, dict_t org) \ + M_C(name, _init_move)(dict_t map, dict_t org) \ { \ DICTI_CONTRACT(name, org); \ map->used = org->used; \ map->lower_limit = org->lower_limit; \ map->upper_limit = org->upper_limit; \ - M_C3(array_list_dict_pair_,name,_init_move)(map->table, org->table); \ + M_C(name, _array_list_pair_init_move)(map->table, org->table); \ DICTI_CONTRACT(name, map); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _swap)(dict_t d1, dict_t d2) \ + M_C(name, _swap)(dict_t d1, dict_t d2) \ { \ DICTI_CONTRACT(name, d1); \ DICTI_CONTRACT(name, d2); \ M_SWAP (size_t, d1->used, d2->used); \ M_SWAP (size_t, d1->lower_limit, d2->lower_limit); \ M_SWAP (size_t, d1->upper_limit, d2->upper_limit); \ - M_C3(array_list_dict_pair_,name,_swap)(d1->table, d2->table); \ + M_C(name, _array_list_pair_swap)(d1->table, d2->table); \ DICTI_CONTRACT(name, d1); \ DICTI_CONTRACT(name, d2); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _move)(dict_t map, dict_t org) \ + M_C(name, _move)(dict_t map, dict_t org) \ { \ DICTI_CONTRACT(name, map); \ DICTI_CONTRACT(name, org); \ assert (map != org); \ - M_C3(dict_,name,_clear)(map); \ - M_C3(dict_,name,_init_move)(map, org); \ + M_C(name,_clear)(map); \ + M_C(name,_init_move)(map, org); \ DICTI_CONTRACT(name, map); \ } \ - \ + \ static inline void \ - M_C3(dict_,name,_clean)(dict_t map) \ + M_C(name,_clean)(dict_t map) \ { \ - M_C3(array_list_dict_pair_,name,_clean)(map->table); \ - M_C3(array_list_dict_pair_,name,_resize)(map->table, DICTI_INITIAL_SIZE); \ + M_C(name, _array_list_pair_clean)(map->table); \ + M_C(name, _array_list_pair_resize)(map->table, DICTI_INITIAL_SIZE); \ map->lower_limit = DICTI_LOWER_BOUND(DICTI_INITIAL_SIZE); \ map->upper_limit = DICTI_UPPER_BOUND(DICTI_INITIAL_SIZE); \ map->used = 0; \ DICTI_CONTRACT(name, map); \ } \ - \ + \ static inline size_t \ - M_C3(dict_,name,_size)(const dict_t map) \ + M_C(name,_size)(const dict_t map) \ { \ DICTI_CONTRACT(name, map); \ return map->used; \ } \ \ static inline value_type * \ - M_C3(dict_,name,_get)(const dict_t map, const key_type key) \ + M_C(name, _get)(const dict_t map, const key_type key) \ { \ DICTI_CONTRACT(name, map); \ size_t hash = M_GET_HASH key_oplist (key); \ - hash = hash & (M_C3(array_list_dict_pair_,name,_size)(map->table) - 1); \ - const M_C3(list_dict_pair_,name,_t) *list_ptr = \ - M_C3(array_list_dict_pair_,name,_cget)(map->table, hash); \ - M_C3(list_dict_pair_,name,_it_t) it; \ - for(M_C3(list_dict_pair_,name,_it)(it, *list_ptr); \ - !M_C3(list_dict_pair_,name,_end_p)(it); \ - M_C3(list_dict_pair_,name,_next)(it)) { \ - M_C3(dict_pair_,name,_t) *ref = M_C3(list_dict_pair_,name,_ref)(it); \ + hash = hash & (M_C(name, _array_list_pair_size)(map->table) - 1); \ + const M_C(name, _list_pair_t) *list_ptr = \ + M_C(name, _array_list_pair_cget)(map->table, hash); \ + M_C(name, _list_pair_it_t) it; \ + for(M_C(name, _list_pair_it)(it, *list_ptr); \ + !M_C(name, _list_pair_end_p)(it); \ + M_C(name, _list_pair_next)(it)) { \ + M_C(name, _pair_t) *ref = M_C(name, _list_pair_ref)(it); \ if (M_GET_EQUAL key_oplist ((*ref)->key, key)) \ return &(*ref)->M_IF(isSet)(key, value); \ } \ @@ -218,31 +233,31 @@ } \ \ static inline void \ - M_C3(dicti_,name,_resize_up)(dict_t map) \ + M_C(name, _int_resize_up)(dict_t map) \ { \ /* NOTE: Contract may not be fullfilled here */ \ - size_t old_size = M_C3(array_list_dict_pair_,name,_size)(map->table); \ + size_t old_size = M_C(name, _array_list_pair_size)(map->table); \ size_t new_size = old_size * 2; \ - /* Resize the dictionnary */ \ - M_C3(array_list_dict_pair_,name,_resize)(map->table, new_size); \ + /* Resize the table of the dictionnary */ \ + M_C(name, _array_list_pair_resize)(map->table, new_size); \ /* Move the items to the new upper part */ \ for(size_t i = 0; i < old_size; i++) { \ - M_C3(list_dict_pair_,name,_t) *list = \ - M_C3(array_list_dict_pair_,name,_get)(map->table, i); \ - if (M_C3(list_dict_pair_,name,_empty_p)(*list)) \ + M_C(name, _list_pair_t) *list = \ + M_C(name, _array_list_pair_get)(map->table, i); \ + if (M_C(name, _list_pair_empty_p)(*list)) \ continue; \ - M_C3(list_dict_pair_,name,_it_t) it; \ - M_C3(list_dict_pair_,name,_it)(it, *list); \ - while (!M_C3(list_dict_pair_,name,_end_p)(it)) { \ - M_C3(dict_pair_,name,_ptr) pair = *M_C3(list_dict_pair_,name,_ref)(it); \ + 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)) { \ + M_C(name, _pair_ptr) pair = *M_C(name, _list_pair_ref)(it); \ size_t hash = M_GET_HASH key_oplist (pair->key); \ if ((hash & (new_size-1)) >= old_size) { \ assert( (hash & (new_size-1)) == (i + old_size)); \ - M_C3(list_dict_pair_,name,_t) *new_list = \ - M_C3(array_list_dict_pair_,name,_get)(map->table, i + old_size); \ - M_C3(list_dict_pair_,name,_splice_back)(*new_list, *list, it); \ + 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); \ } else { \ - M_C3(list_dict_pair_,name,_next)(it); \ + M_C(name, _list_pair_next)(it); \ } \ } \ } \ @@ -251,247 +266,249 @@ } \ \ static inline void \ - M_C3(dicti_,name,_resize_down)(dict_t map) \ + M_C(name, _int_resize_down)(dict_t map) \ { \ /* NOTE: Contract may not be fullfilled here */ \ - size_t old_size = M_C3(array_list_dict_pair_,name,_size)(map->table); \ + size_t old_size = M_C(name, _array_list_pair_size)(map->table); \ 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 */ \ + /* NOTE: We don't need to recompute the hash to move them! */ \ for(size_t i = new_size; i < old_size; i++) { \ - M_C3(list_dict_pair_,name,_t) *list = \ - M_C3(array_list_dict_pair_,name,_get)(map->table, i); \ - if (M_C3(list_dict_pair_,name,_empty_p)(*list)) \ + M_C(name, _list_pair_t) *list = \ + M_C(name, _array_list_pair_get)(map->table, i); \ + if (M_C(name, _list_pair_empty_p)(*list)) \ continue; \ - M_C3(list_dict_pair_,name,_it_t) it; \ - M_C3(list_dict_pair_,name,_it)(it, *list); \ - while (!M_C3(list_dict_pair_,name,_end_p)(it)) { \ - M_IF_DEBUG(M_C3(dict_pair_,name,_ptr) pair = *M_C3(list_dict_pair_,name,_ref)(it);) \ - M_IF_DEBUG(size_t hash = M_GET_HASH key_oplist (pair->key);) \ - M_IF_DEBUG(assert ((hash & (old_size -1)) == i);) \ + /* TODO: Use of _splice instead ? */ \ + 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)) { \ + M_IF_DEBUG(M_C(name, _pair_ptr) pair = *M_C(name, _list_pair_ref)(it);) \ + M_IF_DEBUG(size_t hash = M_GET_HASH key_oplist (pair->key);) \ + M_IF_DEBUG(assert ((hash & (old_size -1)) == i);) \ M_IF_DEBUG(assert ((hash & (new_size -1)) == i - new_size);) \ - M_C3(list_dict_pair_,name,_t) *new_list = \ - M_C3(array_list_dict_pair_,name,_get)(map->table, i - new_size); \ - M_C3(list_dict_pair_,name,_splice_back)(*new_list, *list, it); \ + M_C(name, _list_pair_t) *new_list = \ + M_C(name, _array_list_pair_get)(map->table, i - new_size); \ + M_C(name, _list_pair_splice_back)(*new_list, *list, it); \ } \ } \ /* Resize the dictionary */ \ - M_C3(array_list_dict_pair_,name,_resize)(map->table, new_size); \ + 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_C3(dict_,name,_set_at)(dict_t map, key_type const key \ - M_IF(isSet)(, M_DEFERRED_COMMA value_type const value)) \ + 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); \ - \ + \ size_t hash = M_GET_HASH key_oplist(key); \ - hash = hash & (M_C3(array_list_dict_pair_,name,_size)(map->table) - 1); \ - M_C3(list_dict_pair_,name,_t) *list_ptr = \ - M_C3(array_list_dict_pair_,name,_get)(map->table, hash); \ - M_C3(list_dict_pair_,name,_it_t) it; \ - for(M_C3(list_dict_pair_,name,_it)(it, *list_ptr); \ - !M_C3(list_dict_pair_,name,_end_p)(it); \ - M_C3(list_dict_pair_,name,_next)(it)) { \ - M_C3(dict_pair_,name,_ptr) ref = *M_C3(list_dict_pair_,name,_ref)(it); \ + hash = hash & (M_C(name, _array_list_pair_size)(map->table) - 1); \ + M_C(name, _list_pair_t) *list_ptr = \ + M_C(name, _array_list_pair_get)(map->table, hash); \ + M_C(name, _list_pair_it_t) it; \ + for(M_C(name, _list_pair_it)(it, *list_ptr); \ + !M_C(name, _list_pair_end_p)(it); \ + M_C(name, _list_pair_next)(it)) { \ + M_C(name, _pair_ptr) ref = *M_C(name, _list_pair_ref)(it); \ if (M_GET_EQUAL key_oplist(ref->key, key)) { \ M_GET_SET value_oplist(ref->value, value); \ return; \ } \ } \ - M_C3(dict_pair_,name,_init_set2)(*M_C3(list_dict_pair_,name,_push_raw)(*list_ptr), \ - key M_IF(isSet)(, M_DEFERRED_COMMA value)); \ + M_C(name, _pair_init_set2)(*M_C(name, _list_pair_push_raw)(*list_ptr), \ + key M_IF(isSet)(, M_DEFERRED_COMMA value)); \ map->used ++; \ if (M_UNLIKELY (map->used > map->upper_limit) ) \ - M_C3(dicti_,name,_resize_up)(map); \ + M_C(name,_int_resize_up)(map); \ DICTI_CONTRACT(name, map); \ } \ \ static inline bool \ - M_C3(dict_,name,_remove)(dict_t map, key_type const key) \ + M_C(name, _remove)(dict_t map, key_type const key) \ { \ DICTI_CONTRACT(name, map); \ \ bool ret = false; \ size_t hash = M_GET_HASH key_oplist(key); \ - hash = hash & (M_C3(array_list_dict_pair_,name,_size)(map->table) - 1); \ - M_C3(list_dict_pair_,name,_t) *list_ptr = \ - M_C3(array_list_dict_pair_,name,_get)(map->table, hash); \ - M_C3(list_dict_pair_,name,_it_t) it; \ - for(M_C3(list_dict_pair_,name,_it)(it, *list_ptr); \ - !M_C3(list_dict_pair_,name,_end_p)(it); \ - M_C3(list_dict_pair_,name,_next)(it)) { \ - M_C3(dict_pair_,name,_ptr) ref = *M_C3(list_dict_pair_,name,_ref)(it); \ + hash = hash & (M_C(name, _array_list_pair_size)(map->table) - 1); \ + M_C(name, _list_pair_t) *list_ptr = \ + M_C(name, _array_list_pair_get)(map->table, hash); \ + M_C(name, _list_pair_it_t) it; \ + for(M_C(name, _list_pair_it)(it, *list_ptr); \ + !M_C(name, _list_pair_end_p)(it); \ + M_C(name, _list_pair_next)(it)) { \ + M_C(name, _pair_ptr) ref = *M_C(name, _list_pair_ref)(it); \ if (M_GET_EQUAL key_oplist(ref->key, key)) { \ - M_C3(list_dict_pair_,name,_remove)(*list_ptr, it); \ + M_C(name, _list_pair_remove)(*list_ptr, it); \ map->used --; \ ret = true; \ break; \ } \ } \ if (M_UNLIKELY (map->used < map->lower_limit) ) \ - M_C3(dicti_, name, _resize_down)(map); \ + M_C(name, _int_resize_down)(map); \ return ret; \ } \ \ - static inline void \ - M_C3(dict_, name, _it)(dict_it_t it, const dict_t d) \ - { \ - DICTI_CONTRACT(name, d); \ - M_C3(array_list_dict_pair_, name, _it)(it->array_it, d->table); \ - M_C3(list_dict_pair_,name,_t) *ref = \ - M_C3(array_list_dict_pair_, name, _ref)(it->array_it); \ - M_C3(list_dict_pair_, name, _it)(it->list_it, *ref); \ - while (M_C3(list_dict_pair_, name, _end_p)(it->list_it)) { \ - M_C3(array_list_dict_pair_, name, _next)(it->array_it); \ - if (M_C3(array_list_dict_pair_, name, _end_p)(it->array_it)) \ - break; \ - ref = M_C3(array_list_dict_pair_, name, _ref)(it->array_it); \ - M_C3(list_dict_pair_, name, _it)(it->list_it, *ref); \ - } \ - } \ + static inline void \ + M_C(name, _it)(dict_it_t it, const dict_t d) \ + { \ + DICTI_CONTRACT(name, d); \ + M_C(name, _array_list_pair_it)(it->array_it, d->table); \ + M_C(name, _list_pair_t) *ref = \ + M_C(name, _array_list_pair_ref)(it->array_it); \ + M_C(name, _list_pair_it)(it->list_it, *ref); \ + while (M_C(name, _list_pair_end_p)(it->list_it)) { \ + M_C(name, _array_list_pair_next)(it->array_it); \ + if (M_UNLIKELY (M_C(name, _array_list_pair_end_p)(it->array_it))) \ + break; \ + ref = M_C(name, _array_list_pair_ref)(it->array_it); \ + M_C(name, _list_pair_it)(it->list_it, *ref); \ + } \ + } \ + \ + static inline void \ + M_C(name, _it_set)(dict_it_t it, const dict_it_t ref) \ + { \ + assert (it != NULL && ref != NULL); \ + M_C(name, _array_list_pair_it_set)(it->array_it, \ + ref->array_it); \ + M_C(name, _list_pair_it_set)(it->list_it, ref->list_it); \ + } \ + \ + static inline bool \ + M_C(name, _end_p)(const dict_it_t it) \ + { \ + assert (it != NULL); \ + return M_C(name, _list_pair_end_p)(it->list_it); \ + } \ + \ + static inline void \ + M_C(name, _next)(dict_it_t it) \ + { \ + assert(it != NULL); \ + M_C(name, _list_pair_next)(it->list_it); \ + M_C(name, _list_pair_t) *ref; \ + while (M_C(name, _list_pair_end_p)(it->list_it)) { \ + M_C(name, _array_list_pair_next)(it->array_it); \ + if (M_C(name, _array_list_pair_end_p)(it->array_it)) \ + break; \ + ref = M_C(name, _array_list_pair_ref)(it->array_it); \ + M_C(name, _list_pair_it)(it->list_it, *ref); \ + } \ + } \ + \ + static inline bool \ + M_C(name, _last_p)(const dict_it_t it) \ + { \ + assert (it != NULL); \ + dict_it_t it2; \ + M_C(name,_it_set)(it2, it); \ + M_C(name, _next)(it2); \ + return M_C(name, _end_p)(it2); \ + } \ + \ + static inline bool \ + M_C(name, _it_equal_p)(const dict_it_t it1, const dict_it_t it2) \ + { \ + assert (it1 != NULL && it2 != NULL); \ + return M_C(name, _list_pair_it_equal_p)(it1->list_it, \ + it2->list_it); \ + } \ + \ + static inline M_C(name, _pair_t) * \ + M_C(name, _ref)(const dict_it_t it) \ + { \ + assert(it != NULL); \ + /* NOTE: partially unsafe if the user modify the 'key'. */ \ + return M_C(name, _list_pair_ref)(it->list_it); \ + } \ + \ + static inline const M_C(name, _pair_t) * \ + M_C(name, _cref)(const dict_it_t it) \ + { \ + assert(it != NULL); \ + return M_C(name, _list_pair_cref)(it->list_it); \ + } \ \ - static inline void \ - M_C3(dict_, name, _it_set)(dict_it_t it, const dict_it_t ref) \ - { \ - assert (it != NULL && ref != NULL); \ - M_C3(array_list_dict_pair_, name, _it_set)(it->array_it, \ - ref->array_it); \ - M_C3(list_dict_pair_, name, _it_set)(it->list_it, ref->list_it); \ - } \ + M_IF_METHOD(EQUAL, value_oplist)( \ + static inline bool \ + M_C(name, _equal_p)(dict_t dict1, dict_t dict2) \ + { \ + assert (dict1 != NULL && dict2 != NULL); \ + /* NOTE: Key type has mandatory equal operator */ \ + /* TODO: Broken is tables have different size (which is possible)*/ \ + return dict1->used == dict2-> used && \ + M_C(name, _array_list_pair_equal_p)(dict1->table, \ + dict2->table); \ + } \ + , /* no value equal */ ) \ \ - static inline bool \ - M_C3(dict_, name, _end_p)(const dict_it_t it) \ - { \ - assert (it != NULL); \ - return M_C3(list_dict_pair_, name, _end_p)(it->list_it); \ - } \ - \ - static inline void \ - M_C3(dict_, name, _next)(dict_it_t it) \ - { \ - assert(it != NULL); \ - M_C3(list_dict_pair_, name, _next)(it->list_it); \ - M_C3(list_dict_pair_,name,_t) *ref; \ - while (M_C3(list_dict_pair_, name, _end_p)(it->list_it)) { \ - M_C3(array_list_dict_pair_, name, _next)(it->array_it); \ - if (M_C3(array_list_dict_pair_, name, _end_p)(it->array_it)) \ - break; \ - ref = M_C3(array_list_dict_pair_, name, _ref)(it->array_it); \ - M_C3(list_dict_pair_, name, _it)(it->list_it, *ref); \ - } \ - } \ - \ - static inline bool \ - M_C3(dict_, name, _last_p)(const dict_it_t it) \ - { \ - assert (it != NULL); \ - dict_it_t it2; \ - M_C3(dict_, name,_it_set)(it2, it); \ - M_C3(dict_, name, _next)(it2); \ - return M_C3(dict_, name, _end_p)(it2); \ - } \ - \ - static inline bool \ - M_C3(dict_, name, _it_equal_p)(const dict_it_t it1, const dict_it_t it2) \ - { \ - assert (it1 != NULL && it2 != NULL); \ - return M_C3(list_dict_pair_, name, _it_equal_p)(it1->list_it, \ - it2->list_it); \ - } \ - \ - static inline M_C3(dict_pair_,name,_t) * \ - M_C3(dict_, name, _ref)(const dict_it_t it) \ - { \ - assert(it != NULL); \ - /* NOTE: partially unsafe if the user modify the 'key'. */ \ - return M_C3(list_dict_pair_, name, _ref)(it->list_it); \ - } \ - \ - static inline const M_C3(dict_pair_,name,_t) * \ - M_C3(dict_, name, _cref)(const dict_it_t it) \ - { \ - assert(it != NULL); \ - return M_C3(list_dict_pair_, name, _cref)(it->list_it); \ - } \ - \ - M_IF_METHOD(EQUAL, value_oplist)( \ - static inline bool \ - M_C3(dict_, name, _equal_p)(dict_t dict1, dict_t dict2) \ - { \ - assert (dict1 != NULL && dict2 != NULL); \ - /* NOTE: Key type has mandatory equal operator */ \ - return dict1->used == dict2-> used && \ - M_C3(array_list_dict_pair_, name, _equal_p)(dict1->table, \ - dict2->table); \ - } \ - , /* no value equal */ ) \ - \ - DICTI_DEF2_FUNC_ADDITIONAL(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t) + DICTI_FUNC_ADDITIONAL_DEF2(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t) /* Define additional functions for dictionnary. Do not used any fields of the dictionnary */ -#define DICTI_DEF2_FUNC_ADDITIONAL(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t) \ - \ - M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)( \ - static inline void \ - M_C3(dict_, name, _get_str)(string_t str, dict_t dict, \ - const bool append) \ +#define DICTI_FUNC_ADDITIONAL_DEF2(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t) \ + \ + M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)( \ + static inline void \ + M_C(name, _get_str)(string_t str, dict_t dict, const bool append) \ { \ STRING_CONTRACT (str); \ DICTI_CONTRACT(name, dict); \ (append ? string_cat_str : string_set_str) (str, "{"); \ dict_it_t it; \ - for (M_C3(dict_, name, _it)(it, dict) ; \ - !M_C3(dict_, name, _end_p)(it); \ - M_C3(dict_, name, _next)(it)){ \ - const M_C3(dict_pair_,name,_t) *item = \ - M_C3(dict_, name, _cref)(it); \ + for (M_C(name, _it)(it, dict) ; \ + !M_C(name, _end_p)(it); \ + M_C(name, _next)(it)){ \ + const M_C(name, _pair_t) *item = \ + M_C(name, _cref)(it); \ M_GET_GET_STR key_oplist (str, (*item)->key, true); \ string_push_back (str, ':'); \ M_GET_GET_STR value_oplist (str, (*item)->value, true); \ - if (!M_C3(dict_, name, _last_p)(it)) \ + if (!M_C(name, _last_p)(it)) \ string_push_back (str, ','); \ } \ string_push_back (str, '}'); \ STRING_CONTRACT(str); \ } \ - , /* no GET_STR */ ) \ + , /* no GET_STR */ ) \ \ - M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)( \ - static inline void \ - M_C3(dict_, name, _out_str)(FILE *file, const dict_t dict) \ + M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)( \ + static inline void \ + M_C(name, _out_str)(FILE *file, const dict_t dict) \ { \ assert (file != NULL); \ DICTI_CONTRACT(name, dict); \ fputc ('{', file); \ dict_it_t it; \ - for (M_C3(dict_, name, _it)(it, dict) ; \ - !M_C3(dict_, name, _end_p)(it); \ - M_C3(dict_, name, _next)(it)){ \ - const M_C3(dict_pair_,name,_t) *item = \ - M_C3(dict_, name, _cref)(it); \ + for (M_C(name, _it)(it, dict) ; \ + !M_C(name, _end_p)(it); \ + M_C(name, _next)(it)){ \ + const M_C(name, _pair_t) *item = \ + M_C(name, _cref)(it); \ M_GET_OUT_STR key_oplist (file, (*item)->key); \ fputc (':', file); \ M_GET_OUT_STR value_oplist (file, (*item)->value); \ - if (!M_C3(dict_, name, _last_p)(it)) \ + if (!M_C(name, _last_p)(it)) \ fputc (',', file); \ } \ fputc ('}', file); \ } \ - , /* no OUT_STR */ ) \ - \ - M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)( \ - static inline bool \ - M_C3(dict_, name, _in_str)(dict_t dict, FILE *file) \ + , /* no OUT_STR */ ) \ + \ + M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)( \ + static inline bool \ + M_C(name, _in_str)(dict_t dict, FILE *file) \ { \ assert (file != NULL); \ DICTI_CONTRACT(name, dict); \ - M_C3(dict_, name, _clean)(dict); \ + M_C(name, _clean)(dict); \ char c = fgetc(file); \ if (c != '{') return false; \ c = fgetc(file); \ @@ -508,41 +525,41 @@ if (c != ':') { c = 0; break; } \ b = M_GET_IN_STR value_oplist (value, file); \ if (!b) { c = 0; break; } \ - M_C3(dict_, name, _set_at)(dict, key \ - M_IF(isSet)( , M_DEFERRED_COMMA value)); \ + M_C(name, _set_at)(dict, key \ + M_IF(isSet)( , M_DEFERRED_COMMA value)); \ c = fgetc(file); \ } while (c == ',' && !feof(file) && !ferror(file)); \ M_GET_CLEAR key_oplist (key); \ M_GET_CLEAR value_oplist (value); \ return c == '}'; \ } \ - , /* no IN_STR */ ) \ - \ + , /* no IN_STR */ ) \ + /* Define the oplist of a dictionnary */ -#define DICTI_OPLIST(name, key_oplist, value_oplist) \ - (INIT(M_C3(dict_, name, _init)), \ - INIT_SET(M_C3(dict_, name, _init_set)), \ - SET(M_C3(dict_, name, _set)), \ - CLEAR(M_C3(dict_, name, _clear)), \ - INIT_MOVE(M_C3(dict_, name, _init_move)), \ - MOVE(M_C3(dict_, name, _move)), \ - SWAP(M_C3(dict_, name, _swap)), \ - TYPE(M_C3(dict_, name, _t)), \ - SUBTYPE(M_C3(dict_pair_,name,_t)), \ - IT_TYPE(M_C3(dict_it_,name,_t)), \ - IT_FIRST(M_C3(dict_,name,_it)), \ - IT_SET(M_C3(dict_, name, _it_set)), \ - IT_END_P(M_C3(dict_,name,_end_p)), \ - IT_LAST_P(M_C3(dict_,name,_last_p)), \ - IT_NEXT(M_C3(dict_,name,_next)), \ - IT_REF(M_C3(dict_,name,_ref)), \ - IT_CREF(M_C3(dict_,name,_cref)) \ +#define DICTI_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(M_C(name, _pair_t)), \ + 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_C3(dict_, name, _get_str)),) \ - ,M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)(OUT_STR(M_C3(dict_, name, _out_str)),) \ - ,M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)(IN_STR(M_C3(dict_, name, _in_str)),) \ - ,M_IF_METHOD(EQUAL, value_oplist)(EQUAL(M_C3(dict_, name, _equal_p)),) \ + ,M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)(GET_STR(M_C(name, _get_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),) \ @@ -556,7 +573,7 @@ #define DICTI_CONTRACT(name, map) do { \ assert(map->used <= map->upper_limit); \ - assert(M_POWEROF2_P(M_C3(array_list_dict_pair_,name,_size)(map->table))); \ + assert(M_POWEROF2_P(M_C(name, _array_list_pair_size)(map->table))); \ } while (0) @@ -570,57 +587,60 @@ typedef enum { /* Performing Quadratic probing Replace it by '1' to perform linear probing */ +#ifndef DICTI_OA_PROBING #define DICTI_OA_PROBING(s) ((s)++) +#endif -#define DICTI_OA_CONTRACT(dict) \ - assert ( (dict) != NULL); \ - assert( (dict)->lower_limit <= (dict)->count && (dict)->count <= (dict)->upper_limit ); \ - assert( (dict)->data != NULL); \ - assert( M_POWEROF2_P((dict)->mask+1)); \ - assert( (dict)->mask+1 >= DICTI_INITIAL_SIZE); \ - assert( (dict)->count <= (dict)->mask+1); \ +#define DICTI_OA_CONTRACT(dict) do { \ + assert ( (dict) != NULL); \ + assert( (dict)->lower_limit <= (dict)->count && (dict)->count <= (dict)->upper_limit ); \ + assert( (dict)->data != NULL); \ + assert( M_POWEROF2_P((dict)->mask+1)); \ + assert( (dict)->mask+1 >= DICTI_INITIAL_SIZE); \ + assert( (dict)->count <= (dict)->mask+1); \ + } while (0) #define DICTI_OA_DEFI(name, key_type, key_oplist, value_type, value_oplist, oor_equal_p, oor_set, coeff_down, coeff_up, dict_t, dict_it_t) \ - \ - typedef struct M_C3(dict_pair_,name,_s) { \ + \ + typedef struct M_C(name, _pair_s) { \ key_type key; \ value_type value; \ - } M_C3(dict_pair_,name,_t); \ - \ + } M_C(name, _pair_t); \ + \ /* NOTE: We don't want a real oplist for this type */ \ - ARRAY_DEF(M_C(array_dicti_,name), M_C3(dict_pair_,name,_t), \ + ARRAY_DEF(M_C(name, _array_pair), M_C(name, _pair_t), \ (INIT(M_NOTHING_DEFAULT), SET(M_MEMCPY_DEFAULT), \ INIT_SET(M_MEMCPY_DEFAULT), CLEAR(M_NOTHING_DEFAULT))) \ \ - typedef struct M_C3(dict_,name,_s) { \ + typedef struct M_C(name,_s) { \ size_t mask, count, count_delete; \ size_t upper_limit, lower_limit; \ - M_C3(dict_pair_,name,_t) *data; \ + M_C(name, _pair_t) *data; \ } dict_t[1]; \ - \ - typedef struct M_C3(dict_it_,name,_s) { \ - struct M_C3(dict_,name,_s) *dict; \ + \ + typedef struct M_C(name, _it_s) { \ + struct M_C(name,_s) *dict; \ size_t index; \ } dict_it_t[1]; \ \ static inline void \ - M_C3(dicti_,name,_limit)(dict_t dict, size_t size) \ + M_C(name,_int_limit)(dict_t dict, size_t size) \ { \ dict->upper_limit = (size_t) (size * coeff_up) - 1; \ dict->lower_limit = (size <= DICTI_INITIAL_SIZE) ? 0 : (size_t) (size * coeff_down) ; \ } \ \ static inline void \ - M_C3(dict_,name,_init)(dict_t dict) \ + M_C(name, _init)(dict_t dict) \ { \ assert(0 <= (coeff_down) && (coeff_down)*2 < (coeff_up) && (coeff_up) < 1); \ dict->mask = DICTI_INITIAL_SIZE-1; \ dict->count = 0; \ dict->count_delete = 0; \ - M_C3(dicti_,name,_limit)(dict, DICTI_INITIAL_SIZE); \ - dict->data = M_GET_REALLOC key_oplist (M_C3(dict_pair_,name,_t), NULL, DICTI_INITIAL_SIZE); \ + M_C(name,_int_limit)(dict, DICTI_INITIAL_SIZE); \ + dict->data = M_GET_REALLOC key_oplist (M_C(name, _pair_t), NULL, DICTI_INITIAL_SIZE); \ if (dict->data == NULL) { \ - M_MEMORY_FULL(sizeof (M_C3(dict_pair_,name,_t)) * DICTI_INITIAL_SIZE); \ + M_MEMORY_FULL(sizeof (M_C(name, _pair_t)) * DICTI_INITIAL_SIZE); \ return ; \ } \ for(size_t i = 0; i < DICTI_INITIAL_SIZE; i++) { \ @@ -628,9 +648,9 @@ typedef enum { } \ DICTI_OA_CONTRACT(dict); \ } \ - \ + \ static inline void \ - M_C3(dict_,name,_clear)(dict_t dict) \ + M_C(name, _clear)(dict_t dict) \ { \ DICTI_OA_CONTRACT(dict); \ for(size_t i = 0; i <= dict->mask; i++) { \ @@ -645,15 +665,16 @@ typedef enum { dict->mask = 0; \ dict->data = NULL; \ } \ - \ + \ static inline value_type * \ - M_C3(dict_,name,_get)(const dict_t dict, key_type const key) \ + M_C(name, _get)(const dict_t dict, key_type const key) \ { \ DICTI_OA_CONTRACT(dict); \ + /* NOTE: Key can not be the representation of empty or deleted */ \ assert (!oor_equal_p(key, DICTI_OA_EMPTY)); \ assert (!oor_equal_p(key, DICTI_OA_DELETED)); \ - \ - M_C3(dict_pair_,name,_t) *const data = dict->data; \ + \ + M_C(name, _pair_t) *const data = dict->data; \ const size_t mask = dict->mask; \ size_t p = M_GET_HASH key_oplist (key) & mask; \ \ @@ -662,7 +683,7 @@ typedef enum { return &data[p].value; \ else if (M_LIKELY (oor_equal_p (data[p].key, DICTI_OA_EMPTY)) ) \ return NULL; \ - \ + \ /* Unlikely case */ \ size_t s = 1; \ do { \ @@ -671,15 +692,16 @@ typedef enum { return &data[p].value; \ assert (s <= dict->mask); \ } while (!oor_equal_p(data[p].key, DICTI_OA_EMPTY) ); \ - \ + \ return NULL; \ } \ \ M_IF_DEBUG( \ static inline bool \ - M_C3(dicti_,name,_control_after_resize)(const dict_t h) \ + M_C(name,_int_control_after_resize)(const dict_t h) \ { \ - M_C3(dict_pair_,name,_t) *data = h->data; \ + /* This function checks if the reshashing of the dict is ok */ \ + M_C(name, _pair_t) *data = h->data; \ size_t empty = 0; \ size_t del = 0; \ for(size_t i = 0 ; i <= h->mask ; i++) { \ @@ -693,16 +715,17 @@ typedef enum { ) \ \ static inline void \ - M_C3(dicti_,name,_resize_up)(dict_t h, size_t newSize, bool updateLimit) \ + M_C(name,_int_resize_up)(dict_t h, size_t newSize, bool updateLimit) \ { \ size_t oldSize = h->mask+1; \ assert (newSize >= oldSize); \ assert (M_POWEROF2_P(newSize)); \ - M_C3(dict_pair_,name,_t) *data = h->data; \ + M_C(name, _pair_t) *data = h->data; \ + /* resize can be called just to delete the items */ \ if (newSize > oldSize) { \ - data = M_GET_REALLOC key_oplist (M_C3(dict_pair_,name,_t), data, newSize); \ + data = M_GET_REALLOC key_oplist (M_C(name, _pair_t), data, newSize); \ if (M_UNLIKELY (data == NULL) ) { \ - M_MEMORY_FULL(sizeof (M_C3(dict_pair_,name,_t)) * newSize); \ + M_MEMORY_FULL(sizeof (M_C(name, _pair_t)) * newSize); \ return ; \ } \ \ @@ -716,19 +739,19 @@ typedef enum { It has been measured that the size of this 'tmp' array is \ around 6% of the size of updated dictionnary. \ NOTE: This should be much cache friendly than typical hash code */ \ - M_C3(array_dicti_,name,_t) tmp; \ - M_C3(array_dicti_,name,_init)(tmp); \ + M_C(name, _array_pair_t) tmp; \ + M_C(name, _array_pair_init)(tmp); \ const size_t mask = (newSize -1); \ \ for(size_t i = 0 ; i < oldSize; i++) { \ if (!oor_equal_p(data[i].key, DICTI_OA_DELETED) && !oor_equal_p(data[i].key, DICTI_OA_EMPTY)) { \ size_t p = M_GET_HASH key_oplist (data[i].key) & mask; \ if (p != i) { \ - if (oor_equal_p(data[p].key, DICTI_OA_EMPTY) || oor_equal_p(data[p].key, DICTI_OA_DELETED)) { \ + if (M_LIKELY (oor_equal_p(data[p].key, DICTI_OA_EMPTY) || oor_equal_p(data[p].key, DICTI_OA_DELETED))) { \ M_DO_INIT_MOVE(key_oplist, data[p].key, data[i].key); \ M_DO_INIT_MOVE(value_oplist, data[p].value, data[i].value); \ } else { \ - M_C3(dict_pair_,name,_t) *ptr = M_C3(array_dicti_,name,_push_raw) (tmp); \ + M_C(name, _pair_t) *ptr = M_C(name, _array_pair_push_raw) (tmp); \ M_DO_INIT_MOVE(key_oplist, ptr->key, data[i].key); \ M_DO_INIT_MOVE(value_oplist, ptr->value, data[i].value); \ } \ @@ -742,9 +765,10 @@ typedef enum { /* Let's put back the entries in the tmp array in their right place */ \ /* NOTE: There should be very few entries in this array \ which contains what we weren't be able to fit in the first pass */ \ - for(size_t i = 0; i < M_C3(array_dicti_,name,_size)(tmp); i++) { \ - M_C3(dict_pair_,name,_t) *item = M_C3(array_dicti_,name,_get)(tmp, i); \ + for(size_t i = 0; i < M_C(name, _array_pair_size)(tmp); i++) { \ + M_C(name, _pair_t) *item = M_C(name, _array_pair_get)(tmp, i); \ size_t p = M_GET_HASH key_oplist (item->key) & mask; \ + /* NOTE: since the first pass, the bucket might be free now */ \ if (!oor_equal_p(data[p].key, DICTI_OA_EMPTY)) { \ size_t s = 1; \ do { \ @@ -757,29 +781,30 @@ typedef enum { M_GET_INIT_SET value_oplist (data[p].value, item->value); \ } \ \ - M_C3(array_dicti_,name,_clear) (tmp); \ + M_C(name, _array_pair_clear) (tmp); \ h->mask = newSize-1; \ h->count_delete = h->count; \ if (updateLimit == true) { \ - M_C3(dicti_,name,_limit)(h, newSize); \ + M_C(name,_int_limit)(h, newSize); \ } \ h->data = data; \ - M_IF_DEBUG (assert (M_C3(dicti_,name,_control_after_resize)(h));) \ + M_IF_DEBUG (assert (M_C(name,_int_control_after_resize)(h));) \ DICTI_OA_CONTRACT(h); \ } \ - \ + \ static inline void \ - M_C3(dict_,name,_set_at)(dict_t dict, key_type const key, \ - value_type const value) \ + M_C(name,_set_at)(dict_t dict, key_type const key, \ + value_type const value) \ { \ DICTI_OA_CONTRACT(dict); \ + /* NOTE: key can not be the representation of empty or deleted */ \ assert (!oor_equal_p(key, DICTI_OA_EMPTY)); \ assert (!oor_equal_p(key, DICTI_OA_DELETED)); \ - \ - M_C3(dict_pair_,name,_t) *const data = dict->data; \ + \ + M_C(name, _pair_t) *const data = dict->data; \ const size_t mask = dict->mask; \ size_t p = M_GET_HASH key_oplist (key) & mask; \ - \ + \ /* NOTE: Likely cache miss */ \ if (M_UNLIKELY (M_GET_EQUAL key_oplist (data[p].key, key)) ) { \ M_GET_SET value_oplist (data[p].value, value); \ @@ -798,8 +823,10 @@ typedef enum { assert (s <= dict->mask); \ if (oor_equal_p(data[p].key, DICTI_OA_DELETED) && delPos == (size_t)-1) delPos = p; \ } while (!oor_equal_p(data[p].key, DICTI_OA_EMPTY) ); \ - if (delPos != (size_t) -1) p = delPos; \ - if (oor_equal_p(data[p].key, DICTI_OA_DELETED)) dict->count_delete-=1; \ + if (delPos != (size_t) -1) { \ + p = delPos; \ + dict->count_delete --; \ + } \ } \ \ M_GET_INIT_SET key_oplist (data[p].key, key); \ @@ -810,23 +837,23 @@ typedef enum { if (M_UNLIKELY (dict->count_delete >= dict->upper_limit)) { \ size_t newSize = dict->mask+1; \ if (dict->count > (dict->mask / 2)) newSize += newSize; \ - M_C3(dicti_,name,_resize_up)(dict, newSize, true); \ + M_C(name,_int_resize_up)(dict, newSize, true); \ } \ DICTI_OA_CONTRACT(dict); \ } \ \ static inline void \ - M_C3(dicti_,name,_resize_down)(dict_t h, size_t newSize) \ + M_C(name,_int_resize_down)(dict_t h, size_t newSize) \ { \ size_t oldSize = h->mask+1; \ assert (newSize <= oldSize && M_POWEROF2_P(newSize)); \ if (M_UNLIKELY (newSize < DICTI_INITIAL_SIZE)) \ newSize = DICTI_INITIAL_SIZE; \ const size_t mask = newSize -1; \ - M_C3(dict_pair_,name,_t) *data = h->data; \ - M_C3(array_dicti_,name,_t) tmp; \ - M_C3(array_dicti_,name,_init)(tmp); \ - \ + M_C(name, _pair_t) *data = h->data; \ + M_C(name, _array_pair_t) tmp; \ + M_C(name, _array_pair_init)(tmp); \ + \ /* Pass 1: scan lower entries, and move them if needed */ \ for(size_t i = 0; i < newSize; i++) { \ if (oor_equal_p(data[i].key, DICTI_OA_EMPTY)) \ @@ -841,7 +868,7 @@ typedef enum { M_DO_INIT_MOVE(key_oplist, data[p].key, data[i].key); \ M_DO_INIT_MOVE(value_oplist, data[p].value, data[i].value); \ } else { \ - M_C3(dict_pair_,name,_t) *ptr = M_C3(array_dicti_,name,_push_raw) (tmp); \ + M_C(name, _pair_t) *ptr = M_C(name, _array_pair_push_raw) (tmp); \ M_DO_INIT_MOVE(key_oplist, ptr->key, data[i].key); \ M_DO_INIT_MOVE(value_oplist, ptr->value, data[i].value); \ } \ @@ -866,8 +893,8 @@ typedef enum { } \ } \ /* Pass 3: scan moved entries and move them back */ \ - for(size_t i = 0; i < M_C3(array_dicti_,name,_size)(tmp); i++) { \ - M_C3(dict_pair_,name,_t) *item = M_C3(array_dicti_,name,_get)(tmp, i); \ + for(size_t i = 0; i < M_C(name, _array_pair_size)(tmp); i++) { \ + M_C(name, _pair_t) *item = M_C(name, _array_pair_get)(tmp, i); \ size_t p = M_GET_HASH key_oplist (item->key) & mask; \ if (!oor_equal_p(data[p].key, DICTI_OA_EMPTY)) { \ size_t s = 1; \ @@ -879,28 +906,29 @@ typedef enum { M_GET_INIT_SET key_oplist (data[p].key, item->key); \ M_GET_INIT_SET value_oplist (data[p].value, item->value); \ } \ - \ - M_C3(array_dicti_,name,_clear) (tmp); \ + \ + M_C(name, _array_pair_clear) (tmp); \ h->count_delete = h->count; \ if (newSize != oldSize) { \ h->mask = newSize-1; \ - M_C3(dicti_,name,_limit)(h, newSize); \ - h->data = M_GET_REALLOC key_oplist (M_C3(dict_pair_,name,_t), data, newSize); \ + M_C(name,_int_limit)(h, newSize); \ + h->data = M_GET_REALLOC key_oplist (M_C(name, _pair_t), data, newSize); \ assert (h->data != NULL); \ } \ - M_IF_DEBUG (assert (M_C3(dicti_,name,_control_after_resize)(h));) \ + M_IF_DEBUG (assert (M_C(name,_int_control_after_resize)(h));) \ assert (h->lower_limit < h->count && h->count < h->upper_limit); \ DICTI_OA_CONTRACT(h); \ } \ \ static inline bool \ - M_C3(dict_,name,_remove)(dict_t dict, const key_type key) \ + M_C(name,_remove)(dict_t dict, const key_type key) \ { \ DICTI_OA_CONTRACT(dict); \ + /* NOTE: key can't be the representation of empty or deleted */ \ assert (!oor_equal_p(key, DICTI_OA_EMPTY)); \ assert (!oor_equal_p(key, DICTI_OA_DELETED)); \ - \ - M_C3(dict_pair_,name,_t) *const data = dict->data; \ + \ + M_C(name, _pair_t) *const data = dict->data; \ const size_t mask = dict->mask; \ size_t p = M_GET_HASH key_oplist (key) & mask; \ \ @@ -922,21 +950,21 @@ typedef enum { assert (dict->count >= 1); \ dict->count--; \ if (M_UNLIKELY (dict->count < dict->lower_limit)) { \ - M_C3(dicti_,name,_resize_down)(dict, (dict->mask+1) >> 1); \ + M_C(name,_int_resize_down)(dict, (dict->mask+1) >> 1); \ } \ DICTI_OA_CONTRACT(dict); \ return true; \ } \ - \ + \ static inline size_t \ - M_C3(dict_,name,_size)(const dict_t dict) \ + M_C(name,_size)(const dict_t dict) \ { \ DICTI_OA_CONTRACT(dict); \ return dict->count; \ } \ \ static inline void \ - M_C3(dict_, name, _init_set)(dict_t map, const dict_t org) \ + M_C(name, _init_set)(dict_t map, const dict_t org) \ { \ DICTI_OA_CONTRACT(org); \ assert (map != org); \ @@ -945,9 +973,9 @@ typedef enum { map->count_delete = org->count_delete; \ map->upper_limit = org->upper_limit; \ map->lower_limit = org->lower_limit; \ - map->data = M_GET_REALLOC key_oplist (M_C3(dict_pair_,name,_t), NULL, map->mask+1); \ + map->data = M_GET_REALLOC key_oplist (M_C(name, _pair_t), NULL, map->mask+1); \ if (map->data == NULL) { \ - M_MEMORY_FULL(sizeof (M_C3(dict_pair_,name,_t)) * (map->mask+1)); \ + M_MEMORY_FULL(sizeof (M_C(name, _pair_t)) * (map->mask+1)); \ return ; \ } \ for(size_t i = 0; i <= org->mask; i++) { \ @@ -962,21 +990,21 @@ typedef enum { } \ DICTI_OA_CONTRACT(map); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _set)(dict_t map, const dict_t org) \ + M_C(name, _set)(dict_t map, const dict_t org) \ { \ DICTI_OA_CONTRACT(map); \ DICTI_OA_CONTRACT(org); \ if (M_LIKELY (map != org)) { \ - M_C3(dict_, name, _clear)(map); \ - M_C3(dict_, name, _init_set)(map, org); \ + M_C(name, _clear)(map); \ + M_C(name, _init_set)(map, org); \ } \ DICTI_OA_CONTRACT(map); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _init_move)(dict_t map, dict_t org) \ + M_C(name, _init_move)(dict_t map, dict_t org) \ { \ DICTI_OA_CONTRACT(org); \ assert (map != org); \ @@ -991,21 +1019,21 @@ typedef enum { org->data = NULL; \ DICTI_OA_CONTRACT(map); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _move)(dict_t map, dict_t org) \ + M_C(name, _move)(dict_t map, dict_t org) \ { \ DICTI_OA_CONTRACT(map); \ DICTI_OA_CONTRACT(org); \ if (M_LIKELY (map != org)) { \ - M_C3(dict_, name, _clear)(map); \ - M_C3(dict_, name, _init_move)(map, org); \ + M_C(name, _clear)(map); \ + M_C(name, _init_move)(map, org); \ } \ DICTI_OA_CONTRACT(map); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _swap)(dict_t d1, dict_t d2) \ + M_C(name, _swap)(dict_t d1, dict_t d2) \ { \ DICTI_OA_CONTRACT(d1); \ DICTI_OA_CONTRACT(d2); \ @@ -1014,13 +1042,13 @@ typedef enum { M_SWAP (size_t, d1->count_delete, d2->count_delete); \ M_SWAP (size_t, d1->upper_limit, d2->upper_limit); \ M_SWAP (size_t, d1->lower_limit, d2->lower_limit); \ - M_SWAP (M_C3(dict_pair_,name,_t) *, d1->data, d2->data); \ + M_SWAP (M_C(name, _pair_t) *, d1->data, d2->data); \ DICTI_OA_CONTRACT(d1); \ DICTI_OA_CONTRACT(d2); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _clean)(dict_t d) \ + M_C(name, _clean)(dict_t d) \ { \ DICTI_OA_CONTRACT(d); \ for(size_t i = 0; i <= d->mask; i++) { \ @@ -1034,14 +1062,14 @@ typedef enum { d->count = 0; \ d->count_delete = 0; \ d->mask = DICTI_INITIAL_SIZE-1; \ - M_C3(dicti_,name,_limit)(d, DICTI_INITIAL_SIZE); \ - d->data = M_GET_REALLOC key_oplist (M_C3(dict_pair_,name,_t), \ + M_C(name,_int_limit)(d, DICTI_INITIAL_SIZE); \ + d->data = M_GET_REALLOC key_oplist (M_C(name, _pair_t), \ d->data, DICTI_INITIAL_SIZE); \ DICTI_OA_CONTRACT(d); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _it)(dict_it_t it, dict_t d) \ + M_C(name, _it)(dict_it_t it, dict_t d) \ { \ DICTI_OA_CONTRACT(d); \ assert (it != NULL); \ @@ -1054,9 +1082,9 @@ typedef enum { } \ it->index = i; \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _it_set)(dict_it_t it, const dict_it_t ref) \ + M_C(name, _it_set)(dict_it_t it, const dict_it_t ref) \ { \ assert (it != NULL); \ assert (ref != NULL); \ @@ -1064,9 +1092,9 @@ typedef enum { it->index = ref->index; \ DICTI_OA_CONTRACT (it->dict); \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _it_last)(dict_it_t it, dict_t d) \ + M_C(name, _it_last)(dict_it_t it, dict_t d) \ { \ DICTI_OA_CONTRACT(d); \ assert (it != NULL); \ @@ -1079,26 +1107,26 @@ typedef enum { } \ it->index = i; \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _it_end)(dict_it_t it, dict_t d) \ + M_C(name, _it_end)(dict_it_t it, dict_t d) \ { \ DICTI_OA_CONTRACT(d); \ assert (it != NULL); \ it->dict = d; \ it->index = d->mask+1; \ } \ - \ + \ static inline bool \ - M_C3(dict_, name, _end_p)(const dict_it_t it) \ + M_C(name, _end_p)(const dict_it_t it) \ { \ assert (it != NULL); \ DICTI_OA_CONTRACT (it->dict); \ return it->index > it->dict->mask; \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _next)(dict_it_t it) \ + M_C(name, _next)(dict_it_t it) \ { \ assert (it != NULL); \ DICTI_OA_CONTRACT (it->dict); \ @@ -1110,9 +1138,9 @@ typedef enum { } \ it->index = i; \ } \ - \ + \ static inline void \ - M_C3(dict_, name, _previous)(dict_it_t it) \ + M_C(name, _previous)(dict_it_t it) \ { \ assert (it != NULL); \ DICTI_OA_CONTRACT (it->dict); \ @@ -1125,29 +1153,29 @@ typedef enum { } \ it->index = i; \ } \ - \ + \ static inline bool \ - M_C3(dict_, name, _last_p)(const dict_it_t it) \ + M_C(name, _last_p)(const dict_it_t it) \ { \ assert (it != NULL); \ dict_it_t it2; \ - M_C3(dict_, name,_it_set)(it2, it); \ - M_C3(dict_, name, _next)(it2); \ - return M_C3(dict_, name, _end_p)(it2); \ + M_C(name,_it_set)(it2, it); \ + M_C(name, _next)(it2); \ + return M_C(name, _end_p)(it2); \ } \ - \ + \ static inline bool \ - M_C3(dict_, name, _it_equal_p)(const dict_it_t it1,const dict_it_t it2) \ + M_C(name, _it_equal_p)(const dict_it_t it1,const dict_it_t it2) \ { \ assert (it1 != NULL && it2 != NULL); \ DICTI_OA_CONTRACT (it1->dict); \ DICTI_OA_CONTRACT (it2->dict); \ return it1->dict == it2->dict && it1->index == it2->index; \ } \ - \ + \ /* FIXME: Wrong level of indirection compared to std dict? */ \ - static inline M_C3(dict_pair_,name,_t) * \ - M_C3(dict_, name, _ref)(const dict_it_t it) \ + static inline M_C(name, _pair_t) * \ + M_C(name, _ref)(const dict_it_t it) \ { \ assert (it != NULL); \ DICTI_OA_CONTRACT (it -> dict); \ @@ -1157,9 +1185,9 @@ typedef enum { assert (!oor_equal_p (it->dict->data[i].key, DICTI_OA_DELETED)); \ return &it->dict->data[i]; \ } \ - \ + \ static inline void \ - M_C3(dict_,name,_reserve)(dict_t dict, size_t capacity) \ + M_C(name,_reserve)(dict_t dict, size_t capacity) \ { \ DICTI_OA_CONTRACT(dict); \ size_t size; \ @@ -1168,12 +1196,12 @@ typedef enum { assert (M_POWEROF2_P(size)); \ if (size > dict->mask+1) { \ dict->upper_limit = (size_t) (size * coeff_up) - 1; \ - M_C3(dicti_,name,_resize_up)(dict, size, false); \ + M_C(name,_int_resize_up)(dict, size, false); \ } \ DICTI_OA_CONTRACT(dict); \ } \ - \ - DICTI_DEF2_FUNC_ADDITIONAL(name, key_type, key_oplist, value_type, value_oplist, 0, dict_t, dict_it_t) + \ + DICTI_FUNC_ADDITIONAL_DEF2(name, key_type, key_oplist, value_type, value_oplist, 0, dict_t, dict_it_t) #endif diff --git a/tests/test-mdict.c b/tests/test-mdict.c index aa9b1eac..43512560 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -38,11 +38,11 @@ static inline void oor_set(int *k, unsigned char n) #include "coverage.h" START_COVERAGE -DICT_DEF2(str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) -DICT_OA_DEF2(oa_int, int, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int, M_DEFAULT_OPLIST) +DICT_DEF2(dict_str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) +DICT_OA_DEF2(dict_oa_int, int, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int, M_DEFAULT_OPLIST) END_COVERAGE -DICT_SET_DEF2(setstr, string_t, STRING_OPLIST) +DICT_SET_DEF2(dict_setstr, string_t, STRING_OPLIST) /* Helper structure */ ARRAY_DEF(array_string, string_t, STRING_OPLIST) @@ -92,7 +92,7 @@ static void test_data(void) static void check_io(void) { M_LET(str, STRING_OPLIST) - M_LET(dict, DICT_OPLIST(str)) { + M_LET(dict, DICT_OPLIST(dict_str)) { dict_str_get_str(str, dict, false); assert (string_cmp_str (str, "{}") == 0); dict_str_set_at (dict, STRING_CTE("LICENCE"), STRING_CTE("BSD3")); @@ -108,7 +108,7 @@ static void check_io(void) fclose (f); f = fopen ("a.dat", "rt"); if (!f) abort(); - M_LET(dict2, DICT_OPLIST(str)) { + M_LET(dict2, DICT_OPLIST(dict_str)) { bool b = dict_str_in_str(dict2, f); assert (b == true); /* assert (dict_str_equal_p (dict, dict2)); */ @@ -120,7 +120,7 @@ static void check_io(void) static void test_set(void) { M_LET(str, STRING_OPLIST) - M_LET(set, DICT_SET_OPLIST(setstr, STRING_OPLIST)) { + M_LET(set, DICT_SET_OPLIST(dict_setstr, STRING_OPLIST)) { for(int i = 0; i < 100; i++) { string_printf(str, "%d", i); dict_setstr_set_at(set, str); @@ -136,7 +136,7 @@ static void test_set(void) static void test_init(void) { M_LET(str1, str2, STRING_OPLIST) - M_LET(d1, d2, DICT_OPLIST(str, STRING_OPLIST_, STRING_OPLIST)){ + M_LET(d1, d2, DICT_OPLIST(dict_str, STRING_OPLIST_, STRING_OPLIST)){ for(size_t i = 0; i < 100; i++) { string_printf(str1, "%d", 2*i); string_printf(str2, "%d", 2*i+1); @@ -233,7 +233,7 @@ static void test1(void) size_t s = 0; bool check1 = false, check2= false; - for M_EACH(r, dict, DICT_OPLIST(str)) { + for M_EACH(r, dict, DICT_OPLIST(dict_str)) { if (string_cmp_str((*r)->key, "README") == 0) check1 = true; if (string_cmp_str((*r)->value, "BSD3") == 0) @@ -277,7 +277,7 @@ static void test_oa(void) static void test_init_oa(void) { - M_LET(d1, d2, DICT_OPLIST(oa_int, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST)){ + M_LET(d1, d2, DICT_OPLIST(dict_oa_int, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST)){ for(size_t i = 0; i < 100; i++) { dict_oa_int_set_at (d1, 2*i, 2*i+1); } @@ -337,16 +337,16 @@ static void test_init_oa(void) static void test_it_oa(void) { - M_LET(d1, DICT_OPLIST(oa_int, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST)){ + M_LET(d1, DICT_OPLIST(dict_oa_int, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST)){ for(size_t i = 0; i < 100; i++) { dict_oa_int_set_at (d1, 2*i, 2*i+1); } assert (dict_oa_int_size (d1) == 100); - dict_it_oa_int_t it; + dict_oa_int_it_t it; size_t s = 0; for(dict_oa_int_it(it, d1); !dict_oa_int_end_p(it); dict_oa_int_next(it)) { - dict_pair_oa_int_t *pair = dict_oa_int_ref(it); + dict_oa_int_pair_t *pair = dict_oa_int_ref(it); assert (pair->key >= 0 && pair->key < 200); assert (pair->value == pair->key + 1); s++; @@ -359,7 +359,7 @@ static void test_it_oa(void) dict_oa_int_previous(it); assert (!dict_oa_int_end_p(it)); assert (dict_oa_int_last_p(it)); - dict_it_oa_int_t it2; + dict_oa_int_it_t it2; dict_oa_int_it_last(it2, d1); assert (dict_oa_int_it_equal_p(it2, it)); dict_oa_int_it(it2, d1); @@ -372,7 +372,7 @@ static void test_it_oa(void) s = 0; for(dict_oa_int_it_last(it, d1); !dict_oa_int_end_p(it); dict_oa_int_previous(it)) { - dict_pair_oa_int_t *pair = dict_oa_int_ref(it); + dict_oa_int_pair_t *pair = dict_oa_int_ref(it); assert (pair->key >= 0 && pair->key < 200); assert (pair->value == pair->key + 1); s++;