Add method _get_at:

_get or create an entry.
This commit is contained in:
Patrick Pelissier committed 2018-06-29 19:41:34 +02:00
1 parent e16d352e71
commit bf2a04ff66
2 files changed
+131

No files matched your search

+81
View File
@@ -353,6 +353,35 @@
if (M_UNLIKELY (map->used > map->upper_limit) ) \
M_C(name,_int_resize_up)(map); \
DICTI_CONTRACT(name, map); \
} \
\
static inline value_type * \
M_C(name, _get_at)(dict_t map, key_type const key) \
{ \
DICTI_CONTRACT(name, map); \
\
size_t hash = M_GET_HASH key_oplist(key); \
size_t i = 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, i); \
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); \
M_IF(isStoreHash)(if (ref->hash != hash) continue;, ) \
if (M_GET_EQUAL key_oplist(ref->key, key)) { \
return &ref->M_IF(isSet)(key, value); \
} \
} \
M_C(name, _pair_t) *ref = M_C(name, _list_pair_push_new)(*list_ptr);\
M_IF(isStoreHash)(M_C(name, _pair_set_hash)(*ref, hash);,) \
M_C(name, _pair_set_key)(*ref, key); \
map->used ++; \
if (M_UNLIKELY (map->used > map->upper_limit) ) \
M_C(name,_int_resize_up)(map); \
DICTI_CONTRACT(name, map); \
return &(*ref)->M_IF(isSet)(key, value); \
} \
\
static inline bool \
@@ -956,6 +985,58 @@ typedef enum {
M_C(name,_int_resize_up)(dict, newSize, true); \
} \
DICTI_OA_CONTRACT(dict); \
} \
\
static inline value_type * \
M_C(name,_get_at)(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_C(name, _pair_t) *const data = dict->data; \
const size_t mask = dict->mask; \
size_t p = M_GET_HASH key_oplist (key) & mask; \
\
if (M_GET_EQUAL key_oplist (data[p].key, key)) { \
return &data[p].value; \
} \
if (M_UNLIKELY (!oor_equal_p(data[p].key, DICTI_OA_EMPTY) ) ) { \
size_t delPos = -1; \
if (oor_equal_p(data[p].key, DICTI_OA_DELETED)) delPos = p; \
size_t s = 1; \
do { \
p = (p + DICTI_OA_PROBING(s)) & mask; \
if (M_GET_EQUAL key_oplist (data[p].key, key)) { \
return &data[p].value; \
} \
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; \
dict->count_delete --; \
} \
} \
\
M_GET_INIT_SET key_oplist (data[p].key, key); \
M_GET_INIT value_oplist (data[p].value); \
dict->count++; \
dict->count_delete ++; \
\
if (M_UNLIKELY (dict->count_delete >= dict->upper_limit)) { \
size_t newSize = dict->mask+1; \
if (dict->count > (dict->mask / 2)) { \
newSize += newSize; \
if (M_UNLIKELY (newSize <= dict->mask+1)) { \
M_MEMORY_FULL((size_t)-1); \
} \
} \
M_C(name,_int_resize_up)(dict, newSize, true); \
} \
DICTI_OA_CONTRACT(dict); \
return &data[p].value; \
} \
\
static inline void \
+50
View File
@@ -133,11 +133,17 @@ static void test_set(void)
string_printf(str, "%d", i);
dict_setstr_set_at(set, str);
}
assert(dict_setstr_size(set) == 100);
for(int i = 0; i < 100; i++) {
string_printf(str, "%d", i);
string_t *p = dict_setstr_get(set, str);
assert (p != NULL);
assert(string_equal_p (*p, str));
p = dict_setstr_get_at(set, str);
assert (p != NULL);
assert(string_equal_p (*p, str));
}
assert(dict_setstr_size(set) == 100);
}
}
@@ -151,6 +157,18 @@ static void test_init(void)
dict_str_set_at (d1, str1, str2);
}
assert (dict_str_size (d1) == 100);
for(size_t i = 0; i < 100; i++) {
string_printf(str1, "%d", 2*i);
string_printf(str2, "%d", 2*i+1);
string_t *p = dict_str_get (d1, str1);
assert (p != NULL);
assert (string_equal_p(*p, str2));
p = dict_str_get_at (d1, str1);
assert (p != NULL);
assert (string_equal_p(*p, str2));
}
dict_str_t d3;
dict_str_init_set (d3, d1);
assert (dict_str_equal_p (d3, d1));
@@ -193,6 +211,23 @@ static void test_init(void)
dict_str_clean (d2);
assert (dict_str_size (d2) == 0);
assert (dict_str_size (d1) == 100);
for(size_t i = 100; i < 200; i++) {
string_printf(str1, "%d", 2*i);
string_printf(*dict_str_get_at (d1, str1), "%d", 2*i+1);
}
assert (dict_str_size (d1) == 200);
for(size_t i = 100; i < 200; i++) {
string_printf(str1, "%d", 2*i);
string_printf(str2, "%d", 2*i+1);
string_t *p = dict_str_get (d1, str1);
assert (p != NULL);
assert (string_equal_p(*p, str2));
p = dict_str_get_at (d1, str1);
assert (p != NULL);
assert (string_equal_p(*p, str2));
}
//assert (dict_str_hash (d2) != 0);
}
}
@@ -301,6 +336,21 @@ static void test_oa(void)
assert (p == NULL);
}
}
assert(dict_oa_int_size(d) == 50);
for(size_t i = 1 ; i < 150; i+= 3)
*dict_oa_int_get_at(d, i) = i*i;
assert(dict_oa_int_size(d) == 100);
for(size_t i = 0 ; i < 150; i++) {
int *p = dict_oa_int_get(d, i);
if ((i % 3) != 2) {
assert (p != NULL);
assert (*p == M_ASSIGN_CAST(int, i*i));
} else {
assert (p == NULL);
}
}
assert(dict_oa_int_size(d) == 100);
dict_oa_int_clear(d);
}