From f75bd05a02a71b289f75b528b96824801c77688c Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sun, 17 Sep 2017 11:29:00 +0200 Subject: [PATCH] Fix issue with dict equal_p --- m-dict.h | 24 ++++++++++++++++++++---- tests/test-mdict.c | 27 +++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/m-dict.h b/m-dict.h index 48713366..d23cf9e1 100644 --- a/m-dict.h +++ b/m-dict.h @@ -435,10 +435,26 @@ { \ 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); \ + /* Easy case */ \ + if (M_LIKELY (dict1->used != dict2-> used)) \ + return false; \ + if (M_UNLIKELY (dict1->used == 0)) \ + return true; \ + /* Otherwise this is the slow path */ \ + dict_it_t it; \ + for(M_C(name, _it)(it, dict1) ; \ + !M_C(name, _end_p)(it); \ + M_C(name, _next)(it)) { \ + const M_C(name, _pair_t) *item = M_C(name, _cref)(it); \ + value_type *ptr = M_C(name, _get)(dict2, (*item)->key); \ + if (ptr == NULL) \ + return false; \ + M_IF(isSet)(, \ + if (M_GET_EQUAL value_oplist ((*item)->value, *ptr) == false) \ + return false; \ + ) \ + } \ + return true; \ } \ , /* no value equal */ ) \ \ diff --git a/tests/test-mdict.c b/tests/test-mdict.c index 43512560..2fea9754 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -111,7 +111,7 @@ static void check_io(void) 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)); */ + assert (dict_str_equal_p (dict, dict2)); } fclose (f); } @@ -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(dict_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); @@ -189,6 +189,28 @@ static void test_init(void) } } +// this test generates dict equal but with different physical representation +static void test_equal(void) +{ + for(int n = 10 ; n < 500; n+=2) { + M_LET(str1, str2, string_t) + M_LET(d1, d2, DICT_OPLIST(dict_str, STRING_OPLIST, STRING_OPLIST)){ + for(int i = 0 ; i < n; i++) { + string_printf(str1, "%d", i); + dict_str_set_at(d1, str1, str1); + } + for(int i = 0 ; i < n; i++) { + string_printf(str1, "%d", i); + dict_str_set_at(d2, str1, str1); + string_printf(str1, "%d", n-1-i); + dict_str_remove(d1, str1); + assert(dict_str_equal_p(d1, d2) == ((i+1) == (n+1)/2)); + assert(dict_str_equal_p(d2, d1) == ((i+1) == (n+1)/2)); + } + } + } +} + static void test1(void) { dict_str_t dict; @@ -386,6 +408,7 @@ int main(void) test1(); test_set(); test_init(); + test_equal(); test_oa(); test_init_oa(); test_it_oa();