From 188b329eaebf640ea8c1e8b24814c7092e8e16fb Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Thu, 3 May 2018 17:43:40 +0200 Subject: [PATCH] Add method _parse_str for dict. --- m-dict.h | 41 ++++++++++++++++++++++++++++++++++++++++- tests/test-mdict.c | 21 +++++++++++++++------ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/m-dict.h b/m-dict.h index a8415fb3..d7f7c6ef 100644 --- a/m-dict.h +++ b/m-dict.h @@ -104,7 +104,7 @@ \ 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)), \ + EQUAL(M_EMPTY_DEFAULT), GET_STR(M_EMPTY_DEFAULT), OUT_STR(M_EMPTY_DEFAULT), IN_STR(M_TRUE_DEFAULT), PARSE_STR(M_TRUE_DEFAULT)), \ 1, 0, M_C(name, _t), M_C(name, _it_t)) @@ -540,6 +540,44 @@ } \ , /* no OUT_STR */ ) \ \ + M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)( \ + static inline bool \ + M_C(name, _parse_str)(dict_t dict, const char str[], const char **endp) \ + { \ + assert (str != NULL); \ + DICTI_CONTRACT(name, dict); \ + M_C(name, _clean)(dict); \ + bool success = false; \ + int c = *str++; \ + if (M_UNLIKELY (c != '{')) goto exit; \ + c = *str++; \ + if (M_UNLIKELY (c == '}')) { success = true; goto exit;} \ + if (M_UNLIKELY (c == 0)) goto exit; \ + str--; \ + key_type key; \ + M_IF(isSet)( ,value_type value); \ + M_GET_INIT key_oplist (key); \ + M_GET_INIT value_oplist (value); \ + do { \ + while (isspace(*str)) str++; \ + bool b = M_GET_PARSE_STR key_oplist (key, str, &str); \ + do { c = *str++; } while (isspace(c)); \ + if (b == false || c != ':') { goto exit; } \ + b = M_GET_PARSE_STR value_oplist (value, str, &str); \ + if (b == false) { goto exit; } \ + M_C(name, _set_at)(dict, key \ + M_IF(isSet)( , M_DEFERRED_COMMA value)); \ + do { c = *str++; } while (isspace(c)); \ + } while (c == ','); \ + M_GET_CLEAR key_oplist (key); \ + M_GET_CLEAR value_oplist (value); \ + success = (c == '}'); \ + exit: \ + if (endp) *endp = str; \ + return success; \ + } \ + , /* no PARSE_STR */ ) \ + \ M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)( \ static inline bool \ M_C(name, _in_str)(dict_t dict, FILE *file) \ @@ -619,6 +657,7 @@ 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_C(name, _get_str)),) \ + ,M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)(PARSE_STR(M_C(name, _parse_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)),) \ diff --git a/tests/test-mdict.c b/tests/test-mdict.c index 925cadcd..61062fd3 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -89,9 +89,15 @@ static void test_data(void) static void check_io(void) { M_LET(str, STRING_OPLIST) - M_LET(dict, DICT_OPLIST(dict_str)) { + M_LET(dict, dict2, DICT_OPLIST(dict_str)) { dict_str_get_str(str, dict, false); assert (string_cmp_str (str, "{}") == 0); + const char *sp; + bool b = dict_str_parse_str(dict2, string_get_cstr(str), &sp); + assert (b); + assert (*sp == 0); + assert (dict_str_equal_p(dict, dict2)); + dict_str_set_at (dict, STRING_CTE("LICENCE"), STRING_CTE("BSD3")); dict_str_get_str(str, dict, false); assert (string_cmp_str (str, "{\"LICENCE\":\"BSD3\"}") == 0); @@ -99,17 +105,20 @@ static void check_io(void) dict_str_get_str(str, dict, false); //NOTE: order is dependent on the hash system. assert (string_cmp_str (str, "{\"LICENCE\":\"BSD3\",\"AUTHOR\":\"PP\"}") == 0 || string_cmp_str (str, "{\"AUTHOR\":\"PP\",\"LICENCE\":\"BSD3\"}") == 0); + b = dict_str_parse_str(dict2, string_get_cstr(str), &sp); + assert (b); + assert (*sp == 0); + assert (dict_str_equal_p(dict, dict2)); + FILE *f = fopen ("a-mdict.dat", "wt"); if (!f) abort(); dict_str_out_str(f, dict); fclose (f); f = fopen ("a-mdict.dat", "rt"); if (!f) abort(); - 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)); - } + b = dict_str_in_str(dict2, f); + assert (b == true); + assert (dict_str_equal_p (dict, dict2)); fclose (f); } }