diff --git a/m-dict.h b/m-dict.h index 06820cbe..65247df8 100644 --- a/m-dict.h +++ b/m-dict.h @@ -253,6 +253,7 @@ ARRAY_DEF(m_array_index, m_indexhash_t, M_POD_OPLIST) M_ASSERT( M_POWEROF2_P((dict)->mask+1)); \ M_ASSERT( (dict)->mask+1 >= M_D1CT_INITIAL_SIZE); \ M_ASSERT( (dict)->upper_limit <= (dict)->mask+1); \ + M_ASSERT( (dict)->freelist_first_data != 0 || (dict)->count+2 == (dict)->freelist_count); \ } while (0) @@ -392,6 +393,7 @@ ARRAY_DEF(m_array_index, m_indexhash_t, M_POD_OPLIST) M_INLINE void \ M_C3(m_d1ct_,name,_release_bucket)(dict_t map, m_index_t d) \ { \ + M_ASSERT(d >= 2 && d < map->freelist_count); \ map->data[d].freelist = map->freelist_first_data; \ map->freelist_first_data = d; \ } \ @@ -429,17 +431,22 @@ ARRAY_DEF(m_array_index, m_indexhash_t, M_POD_OPLIST) \ /* resize can be called just to delete the items */ \ if (newSize > oldSize) { \ - M_F(name, _freelist_ct) *data = M_CALL_REALLOC(key_oplist, M_F(name, _freelist_ct), h->data, (size_t) 2+newSize); \ - if (M_UNLIKELY_NOMEM (data == NULL) ) { \ - M_MEMORY_FULL((2+newSize)*sizeof (M_F(name, _freelist_ct))); \ - return ; \ + /* h->data is not always the same size than h->index: it may be bigger \ + if there is some erase of items: h->index will shrink, but not h->data \ + To have an estimate of the size, we look at the maximum index of it: \ + if it is bigger than our new size, then we don't need to reallocate */ \ + if (newSize > h->freelist_count) { \ + h->data = M_CALL_REALLOC(key_oplist, M_F(name, _freelist_ct), h->data, (size_t) 2+newSize); \ + if (M_UNLIKELY_NOMEM (h->data == NULL) ) { \ + M_MEMORY_FULL((2+newSize)*sizeof (M_F(name, _freelist_ct))); \ + return ; \ + } \ } \ m_indexhash_t *index = M_MEMORY_REALLOC(m_indexhash_t, h->index,(size_t) 0+newSize); \ if (M_UNLIKELY_NOMEM (index == NULL) ) { \ M_MEMORY_FULL(newSize*sizeof(m_indexhash_t)); \ return ; \ } \ - h->data = data; \ h->index = index; \ \ /* First mark the extended space as empty */ \ diff --git a/tests/test-mdict.c b/tests/test-mdict.c index dd17aa8a..27df9cbf 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -37,7 +37,6 @@ DICT_DEF2(dict_str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) DICT_OA_DEF2(dict_oa_int, int, M_OPEXTEND(M_BASIC_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int, M_OPEXTEND(M_BASIC_OPLIST, ADD(update_value M_IPTR))) END_COVERAGE -DICT_STOREHASH_DEF2(dict_str2, string_t, STRING_OPLIST, string_t, STRING_OPLIST) DICT_SET_DEF(dict_setstr, string_t, STRING_OPLIST) DICT_DEF2(dict_int, int, M_BASIC_OPLIST, int, M_BASIC_OPLIST) DICT_DEF2(dict_mpz, string_t, STRING_OPLIST, testobj_t, TESTOBJ_OPLIST) @@ -407,6 +406,34 @@ static void test_init(void) assert (dict_str_equal_p (d2, d1)); } + // Create some items, delete some, create others, delete all + M_LET(str1, str2, STRING_OPLIST) + M_LET(d1, DICT_OPLIST(dict_str, STRING_OPLIST, STRING_OPLIST)){ + for(int s = 32; s < 512; s++) { + for(int i = 0; i < s; i++) { + string_printf(str1, "%d", 2*i); + string_printf(str2, "%d", 2*i+1); + dict_str_set_at (d1, str1, str2); + } + for(int i = 0; i < s; i+=3) { + string_printf(str1, "%d", 2*i); + bool b = dict_str_erase (d1, str1); + assert (b); + } + for(int i = 0; i < s; i++) { + string_printf(str1, "%d", 2*i); + string_printf(str2, "%d", 2*i+1); + dict_str_set_at (d1, str1, str2); + } + for(int i = 0; i < s; i++) { + string_printf(str1, "%d", 2*i); + bool b = dict_str_erase (d1, str1); + assert (b); + } + assert(dict_str_empty_p(d1)); + } + } + M_LET( (d1, (STRING_CTE("H1"), STRING_CTE("EE")), (("H2"), ("EF"))), DICT_OPLIST(dict_str, STRING_OPLIST, STRING_OPLIST)){ string_t * p = dict_str_get(d1, STRING_CTE("H1"));