From 0b6733fdcb7188b224f415bedb499a2f52fe456f Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Fri, 3 May 2024 16:40:35 +0200 Subject: [PATCH] Ass _reserve method for standard dict --- m-dict.h | 49 ++++++++++++++++++++++++++-------------------- tests/test-mdict.c | 4 ++++ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/m-dict.h b/m-dict.h index e07f5fe2..1250b788 100644 --- a/m-dict.h +++ b/m-dict.h @@ -310,6 +310,7 @@ ARRAY_DEF(m_array_index, m_indexhash_t, M_POD_OPLIST) typedef key_type M_F(name, _key_ct); \ typedef value_type M_F(name, _value_ct); \ typedef dict_it_t M_F(name, _it_ct); \ + typedef m_index_t M_F(name, _index_ct); \ \ M_INLINE void \ M_C3(m_d1ct_,name,_update_limit)(dict_t map, m_index_t size) \ @@ -942,6 +943,32 @@ ARRAY_DEF(m_array_index, m_indexhash_t, M_POD_OPLIST) return map->count; \ } \ \ + M_INLINE void \ + M_F(name,_reserve)(dict_t dict, size_t capacity) \ + { \ + if (capacity == 0) { \ + /* Perform a shrink to fit: copy everything to a new dict properly, and move it back */ \ + dict_t tmp; \ + M_F(name, _init_set)(tmp, dict); \ + M_F(name, _init_move)(dict, tmp); \ + return; \ + } \ + /* Get the size which will allow to fit this capacity \ + NOTE: Strictly speaking we need to perform a round up to ensure \ + that no reallocation of the hash map occurs up to capacity */ \ + M_F(name, _index_ct) size = (M_F(name, _index_ct)) \ + m_core_roundpow2 ((uint64_t) (1.0+(double) capacity * (1.0 / M_D1CT_OA_UPPER_BOUND))); \ + M_ASSERT (M_POWEROF2_P(size)); \ + /* Test for overflow of the computation */ \ + if (M_UNLIKELY_NOMEM (size < capacity)) { \ + M_MEMORY_FULL((size_t)-1); \ + } \ + if (size > dict->mask+1) { \ + dict->upper_limit = (M_F(name, _index_ct)) ((double) size * M_D1CT_OA_UPPER_BOUND) - 1; \ + M_C3(m_d1ct_,name,_resize_up)(dict, size, false); \ + } \ + } \ + \ M_IF_METHOD(EQUAL, value_oplist)( \ M_INLINE bool \ M_F(name, _equal_p)(const dict_t dict1, const dict_t dict2) \ @@ -1430,6 +1457,7 @@ enum m_d1ct_oa_element_e { typedef key_type M_F(name, _key_ct); \ typedef value_type M_F(name, _value_ct); \ typedef dict_it_t M_F(name, _it_ct); \ + typedef size_t M_F(name, _index_ct); \ \ M_INLINE void \ M_C3(m_d1ct_,name,_update_limit)(dict_t dict, size_t size) \ @@ -1974,27 +2002,6 @@ enum m_d1ct_oa_element_e { return M_CONST_CAST(it_deref_t, M_F(name, _ref)(it)); \ } \ \ - M_INLINE void \ - M_F(name,_reserve)(dict_t dict, size_t capacity) \ - { \ - M_D1CT_OA_CONTRACT(dict); \ - size_t size; \ - /* Get the size which will allow to fit this capacity \ - NOTE: Strictly speaking we need to perform a round up to ensure \ - that no reallocation of the hash map occurs up to capacity */ \ - size = (size_t) m_core_roundpow2 ((uint64_t) ((double) capacity * (1.0 / coeff_up))); \ - /* Test for overflow of the computation */ \ - if (M_UNLIKELY_NOMEM (size < capacity)) { \ - M_MEMORY_FULL((size_t)-1); \ - } \ - M_ASSERT (M_POWEROF2_P(size)); \ - if (size > dict->mask+1) { \ - dict->upper_limit = (size_t) ((double) size * coeff_up) - 1; \ - M_C3(m_d1ct_,name,_resize_up)(dict, size, false); \ - } \ - M_D1CT_OA_CONTRACT(dict); \ - } \ - \ M_D1CT_FUNC_ADDITIONAL_DEF2(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t, it_deref_t) diff --git a/tests/test-mdict.c b/tests/test-mdict.c index f90bf0d8..e2c2f993 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -404,6 +404,10 @@ static void test_init(void) assert (!dict_str_equal_p (d2, d1)); dict_str_set_at (d2, STRING_CTE("X"), STRING_CTE("2")); assert (dict_str_equal_p (d2, d1)); + dict_str_reserve(d1, 0); + dict_str_equal_p (d2, d1); + dict_str_reserve(d2, 4000); + dict_str_equal_p (d2, d1); } // Create some items, delete some, create others, delete all