From dcb1eb0d94f00bfbd5ca4f2097301da2ca32a49b Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sat, 25 Jun 2022 17:29:04 +0200 Subject: [PATCH] First version of IO for the tree container --- m-tree.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/m-tree.h b/m-tree.h index 7fec99e1..242a22c2 100644 --- a/m-tree.h +++ b/m-tree.h @@ -187,7 +187,8 @@ typedef int32_t m_tr33_index_t; } it_t; \ \ M_TR33_DEF_P4_CORE(name, type, oplist, tree_t, it_t) \ - M_TR33_DEF_P4_CLASSIC(name, type, oplist, tree_t, it_t) + M_TR33_DEF_P4_CLASSIC(name, type, oplist, tree_t, it_t) \ + M_TR33_DEF_P4_IO(name, type, oplist, tree_t, it_t) /* Define the core & unique methods of a tree */ #define M_TR33_DEF_P4_CORE(name, type, oplist, tree_t, it_t) \ @@ -1143,6 +1144,107 @@ typedef int32_t m_tr33_index_t; } \ , /* No HASH */ ) \ + +/* Define the IO methods of a tree */ +#define M_TR33_DEF_P4_IO(name, type, oplist, tree_t, it_t) \ +M_IF_METHOD(GET_STR, oplist)( \ +static inline void \ +M_C(name, _get_str)(string_t str, tree_t tree, bool append) { \ + (append ? m_string_cat_str : m_string_set_str) (str, "["); \ + it_t it = M_C(name, _it)(tree); \ + while (!M_C(name, _end_p)(it)) { \ + m_string_push_back (str, '{'); \ + type const *item = M_C(name, _cref)(it); \ + M_CALL_GET_STR(oplist, str, *item, true); \ + /* Go down the tree */ \ + if (M_C(name, _it_down)(&it)) { \ + m_string_push_back (str, M_GET_SEPARATOR oplist); \ + m_string_push_back (str, '['); \ + continue; \ + } \ + m_string_push_back (str, '}'); \ + if (M_C(name, _it_right)(&it)) { \ + m_string_push_back (str, M_GET_SEPARATOR oplist); \ + continue; \ + } \ + while (M_C(name, _it_up)(&it)) { \ + m_string_push_back (str, ']'); \ + m_string_push_back (str, '}'); \ + if (M_C(name, _it_right)(&it)) { \ + m_string_push_back (str, M_GET_SEPARATOR oplist); \ + goto continue_tree; \ + } \ + } \ + it = M_C(name, _it_end)(tree); \ + continue_tree: \ + (void) 0; \ + } \ + m_string_push_back (str, ']'); \ +} \ +, /* No GET_STR */ ) \ + \ +M_IF_METHOD(PARSE_STR, oplist)( \ +static inline bool \ +M_C(name, _parse_str)(tree_t tree, const char str[], const char **endp) { \ + M_C(name, _reset)(tree); \ + 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; \ + type item; \ + M_CALL_INIT(oplist, item); \ + it_t it = M_C(name, _it_end)(tree); \ + int cmd = 0; \ + while (true) { \ + c = *str++; \ + if (c != '{') goto exit_clear; \ + bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \ + c = *str++; \ + if (b == false || c == 0) { goto exit_clear; } \ + /* Insert the item as the root or as a right sibling or as a child */ \ + switch (cmd) { \ + case 0: it = M_C(name, _set_root)(tree, item); break; \ + case 1: it = M_C(name, _insert_right)(it, item); break; \ + case 2: it = M_C(name, _insert_child)(it, item); break; \ + default: M_ASSERT(0); \ + } \ + if (c == ',') { \ + /* The current item has some children */ \ + c = *str++; \ + if (c != '[') { goto exit_clear; } \ + /* next is a child: push_down */ \ + cmd = 2; \ + continue; \ + } \ + /* The current item has no children. */ \ + if (c != '}') { goto exit_clear; } \ + /* Scan the next character to decide where to move (right or up) */ \ + c = *str++; \ + if (c == ']') { \ + do { \ + /* move up. It we cannot, we have reached the end */ \ + if (!M_C(name, _it_up)(&it)) { goto exit_success; } \ + c = *str++; \ + if (c != '}') { goto exit_clear; } \ + c = *str++; \ + } while (c == ']'); \ + } \ + if (c != ',') { goto exit_clear; } \ + /* next is a sibling: push_right */ \ + cmd = 1; \ + } \ +exit_success: \ + success = true; \ +exit_clear: \ + M_CALL_CLEAR(oplist, item); \ +exit: \ + if (endp) *endp = str; \ + return success; \ +} \ +, /* No PARSE_STR */ ) \ + // TODO: // * insertion function with move semantics (or _raw methods?) // * emplace insertion