diff --git a/source/md.h b/source/md.h index bd1c2d6..869607e 100644 --- a/source/md.h +++ b/source/md.h @@ -18,8 +18,7 @@ // [x] MD_StringMap_Next, for iterating matching slots in an MD_Map, that all // share the same key (important in the case of hash collisions) // [x] Helper for making a reference for a node, e.g. MD_ReferenceFromNode -// [ ] Organization decision for C generator helpers: splitting from md.h? file name? folder? - +// [x] Organization decision for C generator helpers: splitting from md.h? file name? folder? // NOTE(allen): "Plugin" functionality // @@ -132,9 +131,6 @@ # define MD_ARCH_32BIT 1 #endif -// NOTE(allen): Review @rjf; Building in C++ -// Added language cracking. Handy for a few pesky problems that can't be solved -// strictly within the intersection of C & C++ #if defined(__cplusplus) # define MD_LANG_CPP 1 #else @@ -195,12 +191,6 @@ # define MD_ZERO_STRUCT {0} #endif -// NOTE(allen): Review @rjf; Building in C++ -// In order to link to C functions from C++ code, we need to mark them as using -// C linkage. In particular I mean FindFirstFileA, FindNextFileA right now. -// We don't necessarily need to apply this to the DD functions if the user is -// building from source, so I haven't done that. - #if MD_LANG_C # define MD_C_LINKAGE_BEGIN # define MD_C_LINKAGE_END @@ -213,8 +203,6 @@ #include #include #include -// NOTE(allen): Review @rjf; Building in C++ -// In C++ compiler I have to include this to get memset and memcpy to compile #include typedef int8_t MD_i8; @@ -701,10 +689,13 @@ MD_FUNCTION MD_Node * MD_TagFromString(MD_Node *node, MD_String8 tag_string); MD_FUNCTION MD_Node * MD_ChildFromIndex(MD_Node *node, int n); MD_FUNCTION MD_Node * MD_TagFromIndex(MD_Node *node, int n); MD_FUNCTION MD_Node * MD_TagArgFromIndex(MD_Node *node, MD_String8 tag_string, int n); +MD_FUNCTION MD_Node * MD_TagArgFromString(MD_Node *node, MD_String8 tag_string, MD_String8 arg_string); MD_FUNCTION MD_b32 MD_NodeHasTag(MD_Node *node, MD_String8 tag_string); MD_FUNCTION MD_i64 MD_ChildCountFromNode(MD_Node *node); MD_FUNCTION MD_i64 MD_TagCountFromNode(MD_Node *node); MD_FUNCTION MD_Node * MD_Deref(MD_Node *node); +MD_FUNCTION MD_Node * MD_SeekNodeWithFlags(MD_Node *start, MD_NodeFlags one_past_last_flags); + // NOTE(rjf): For-Loop Helpers #define MD_EachNode(it, first) MD_Node *it = (first); !MD_NodeIsNil(it); it = it->next #define MD_EachNodeRef(it, first) MD_Node *it##_r = (first), *it = MD_Deref(it##_r); \ diff --git a/source/md_impl.c b/source/md_impl.c index 547d0cb..65cc923 100644 --- a/source/md_impl.c +++ b/source/md_impl.c @@ -2356,6 +2356,14 @@ MD_TagArgFromIndex(MD_Node *node, MD_String8 tag_string, int n) return MD_ChildFromIndex(tag, n); } +MD_FUNCTION_IMPL MD_Node * +MD_TagArgFromString(MD_Node *node, MD_String8 tag_string, MD_String8 arg_string) +{ + MD_Node *tag = MD_TagFromString(node, tag_string); + MD_Node *arg = MD_ChildFromString(tag, arg_string); + return arg; +} + MD_FUNCTION_IMPL MD_b32 MD_NodeHasTag(MD_Node *node, MD_String8 tag_string) { @@ -2412,7 +2420,8 @@ MD_TagCountFromNodeAndString(MD_Node *node, MD_String8 string, MD_MatchFlags fla return result; } -MD_FUNCTION_IMPL MD_Node * MD_Deref(MD_Node *node) +MD_FUNCTION_IMPL MD_Node * +MD_Deref(MD_Node *node) { MD_Node *result = node; while(result->kind == MD_NodeKind_Reference) @@ -2422,6 +2431,21 @@ MD_FUNCTION_IMPL MD_Node * MD_Deref(MD_Node *node) return result; } +MD_FUNCTION MD_Node * +MD_SeekNodeWithFlags(MD_Node *start, MD_NodeFlags one_past_last_flags) +{ + MD_Node *result = start; + for(MD_EachNode(it, start->next)) + { + if(it->flags & one_past_last_flags) + { + break; + } + result = it; + } + return result; +} + MD_FUNCTION_IMPL void MD_NodeMessage(MD_Node *node, MD_MessageKind kind, MD_String8 str) { diff --git a/tests/sanity_tests.c b/tests/sanity_tests.c index fe4c648..271e6ae 100644 --- a/tests/sanity_tests.c +++ b/tests/sanity_tests.c @@ -593,5 +593,53 @@ int main(void) } } + Test("Node-With-Flags Seeking") + { + + { + MD_ParseResult parse = MD_ParseOneNode(MD_S8Lit(""), MD_S8Lit("foo:{x y z; a b c}")); + MD_Node *node = parse.node; + MD_Node *group_first = node->first_child; + MD_Node *group_last = MD_SeekNodeWithFlags(group_first, MD_NodeFlag_AfterSemicolon); + + TestResult(MD_StringMatch(group_first->string, MD_S8Lit("x"), 0)); + TestResult(MD_StringMatch(group_first->next->string, MD_S8Lit("y"), 0)); + TestResult(MD_StringMatch(group_last->string, MD_S8Lit("z"), 0)); + + group_first = group_last->next; + group_last = MD_SeekNodeWithFlags(group_first, MD_NodeFlag_AfterSemicolon); + + TestResult(MD_StringMatch(group_first->string, MD_S8Lit("a"), 0)); + TestResult(MD_StringMatch(group_first->next->string, MD_S8Lit("b"), 0)); + TestResult(MD_StringMatch(group_last->string, MD_S8Lit("c"), 0)); + } + + { + MD_ParseResult parse = MD_ParseOneNode(MD_S8Lit(""), MD_S8Lit("foo:{a b c , d e f , g h i}")); + MD_Node *node = parse.node; + MD_Node *group_first = 0; + MD_Node *group_last = 0; + + group_first = node->first_child; + group_last = MD_SeekNodeWithFlags(group_first, MD_NodeFlag_AfterComma); + TestResult(MD_StringMatch(group_first->string, MD_S8Lit("a"), 0)); + TestResult(MD_StringMatch(group_first->next->string, MD_S8Lit("b"), 0)); + TestResult(MD_StringMatch(group_last->string, MD_S8Lit("c"), 0)); + + group_first = group_last->next; + group_last = MD_SeekNodeWithFlags(group_first, MD_NodeFlag_AfterComma); + TestResult(MD_StringMatch(group_first->string, MD_S8Lit("d"), 0)); + TestResult(MD_StringMatch(group_first->next->string, MD_S8Lit("e"), 0)); + TestResult(MD_StringMatch(group_last->string, MD_S8Lit("f"), 0)); + + group_first = group_last->next; + group_last = MD_SeekNodeWithFlags(group_first, MD_NodeFlag_AfterComma); + TestResult(MD_StringMatch(group_first->string, MD_S8Lit("g"), 0)); + TestResult(MD_StringMatch(group_first->next->string, MD_S8Lit("h"), 0)); + TestResult(MD_StringMatch(group_last->string, MD_S8Lit("i"), 0)); + } + + } + return 0; } \ No newline at end of file