First version of IO for the tree container
This commit is contained in:
1 parent
950ea224ff
commit
dcb1eb0d94
1 file changed
+103
-1
@@ -187,7 +187,8 @@ typedef int32_t m_tr33_index_t;
|
|||||||
} it_t; \
|
} it_t; \
|
||||||
\
|
\
|
||||||
M_TR33_DEF_P4_CORE(name, type, oplist, tree_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 the core & unique methods of a tree */
|
||||||
#define M_TR33_DEF_P4_CORE(name, type, oplist, tree_t, it_t) \
|
#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 */ ) \
|
, /* 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:
|
// TODO:
|
||||||
// * insertion function with move semantics (or _raw methods?)
|
// * insertion function with move semantics (or _raw methods?)
|
||||||
// * emplace insertion
|
// * emplace insertion
|
||||||
|
|||||||
Reference in new issue
Block a user