From a6c0a1e8b3d2f3456972dad61a435684cac52cb5 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Mon, 17 Nov 2014 21:35:39 -0800 Subject: Make parse_inlines add directly to parent. Previously parse_inlines returned a list of parsed inlines. This had to be added to the parent, and fix_parents had to be called to manually add the 'parent' links to the children, and the 'last_child' link to the parent. Now parse_inlines takes the parent block as a parameter, and uses cmark_node_append_child to add the children, so that the pointers should be properly managed. This avoids the need for the fix_parents pass. --- src/blocks.c | 16 +------------- src/inlines.c | 70 +++++++++++++++-------------------------------------------- src/inlines.h | 2 +- src/node.c | 1 + 4 files changed, 21 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 0e68259..58162b5 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -283,19 +283,6 @@ typedef struct BlockStack { cmark_node *next_sibling; } block_stack; -static void fix_parents(cmark_node *node) { - cmark_node *cur = node->first_child; - if (cur == NULL) { - return; - } - while (cur->next != NULL) { - cur->parent = node; - cur = cur->next; - } - cur->parent = node; - node->last_child = cur; -} - // Walk through cmark_node and all children, recursively, parsing // string content into inline content where appropriate. static void process_inlines(cmark_node* cur, reference_map *refmap) @@ -308,8 +295,7 @@ static void process_inlines(cmark_node* cur, reference_map *refmap) case NODE_PARAGRAPH: case NODE_ATX_HEADER: case NODE_SETEXT_HEADER: - cur->first_child = parse_inlines(&cur->string_content, refmap); - fix_parents(cur); + parse_inlines(cur, refmap); break; default: diff --git a/src/inlines.c b/src/inlines.c index a8d14fb..f681080 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -41,8 +41,7 @@ typedef struct Subject { delimiter_stack *delimiters; } subject; -static cmark_node *parse_inlines_from_subject(subject* subj); -static int parse_inline(subject* subj, cmark_node ** last); +static int parse_inline(subject* subj, cmark_node * parent); static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap); static int subject_find_special_char(subject *subj); @@ -184,22 +183,6 @@ static inline chunk take_while(subject* subj, int (*f)(int)) return chunk_dup(&subj->input, startpos, len); } -// Append inline list b to the end of inline list a. -// Return pointer to head of new list. -static inline cmark_node* cmark_append_inlines(cmark_node* a, cmark_node* b) -{ - if (a == NULL) { // NULL acts like an empty list - return b; - } - cmark_node* cur = a; - while (cur->next != NULL) { - cur = cur->next; - } - cur->next = b; - b->prev = cur; - return a; -} - // Try to process a backtick code span that began with a // span of ticks of length openticklength length (already // parsed). Return 0 if you don't find matching closing @@ -327,7 +310,7 @@ static delimiter_stack * push_delimiter(subject *subj, // Parse strong/emph or a fallback. // Assumes the subject has '_' or '*' at the current position. -static cmark_node* handle_strong_emph(subject* subj, unsigned char c, cmark_node **last) +static cmark_node* handle_strong_emph(subject* subj, unsigned char c) { int numdelims; cmark_node * inl_text; @@ -436,7 +419,7 @@ static void process_emphasis(subject *subj, delimiter_stack *stack_bottom) if (tmp->next) { tmp->next->prev = emph; } - tmp->next = NULL; + cmark_node_unlink(tmp); cmark_free_nodes(tmp); // remove closer from stack tempstack = closer->next; @@ -637,7 +620,7 @@ static int link_label(subject* subj, chunk *raw_label) } // Return a link, an image, or a literal close bracket. -static cmark_node* handle_close_bracket(subject* subj, cmark_node **last) +static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent) { int initial_pos; int starturl, endurl, starttitle, endtitle, endall; @@ -752,7 +735,7 @@ match: tmp->parent = inl; inl->last_child = tmp; } - *last = inl; + parent->last_child = inl; // process_emphasis will remove this delimiter and all later ones. // Now, if we have a link, we also want to remove earlier link @@ -792,23 +775,6 @@ static cmark_node* handle_newline(subject *subj) } } -// Parse inlines til end of subject, returning inlines. -extern cmark_node* parse_inlines_from_subject(subject* subj) -{ - cmark_node* result = NULL; - cmark_node** last = &result; - cmark_node* first = NULL; - while (!is_eof(subj) && parse_inline(subj, last)) { - if (!first) { - first = *last; - } - } - - process_emphasis(subj, NULL); - - return first; -} - static int subject_find_special_char(subject *subj) { // "\n\\`&_*[]input.len; } -// Parse an inline, advancing subject, and add it to last element. -// Adjust tail to point to new last element of list. +// Parse an inline, advancing subject, and add it as a child of parent. // Return 0 if no inline can be parsed, 1 otherwise. -static int parse_inline(subject* subj, cmark_node ** last) +static int parse_inline(subject* subj, cmark_node * parent) { cmark_node* new_inl = NULL; chunk contents; @@ -872,7 +837,7 @@ static int parse_inline(subject* subj, cmark_node ** last) break; case '*': case '_': - new_inl = handle_strong_emph(subj, c, last); + new_inl = handle_strong_emph(subj, c); break; case '[': advance(subj); @@ -880,7 +845,7 @@ static int parse_inline(subject* subj, cmark_node ** last) subj->delimiters = push_delimiter(subj, 1, '[', true, false, new_inl); break; case ']': - new_inl = handle_close_bracket(subj, last); + new_inl = handle_close_bracket(subj, parent); break; case '!': advance(subj); @@ -904,21 +869,22 @@ static int parse_inline(subject* subj, cmark_node ** last) new_inl = make_str(contents); } - if (*last == NULL) { - *last = new_inl; - } else if (new_inl) { - cmark_append_inlines(*last, new_inl); - *last = new_inl; + if (new_inl != NULL) { + cmark_node_append_child(parent, new_inl); } return 1; } -extern cmark_node* parse_inlines(strbuf *input, reference_map *refmap) +// Parse inlines from parent's string_content, adding as children of parent. +extern void cmark_parse_inlines(cmark_node* parent, cmark_reference_map *refmap) { subject subj; - subject_from_buf(&subj, input, refmap); - return parse_inlines_from_subject(&subj); + subject_from_buf(&subj, &parent->string_content, refmap); + + while (!is_eof(&subj) && parse_inline(&subj, parent)) ; + + process_emphasis(&subj, NULL); } // Parse zero or more space characters, including at most one newline. diff --git a/src/inlines.h b/src/inlines.h index 422b8e3..92b3b7a 100644 --- a/src/inlines.h +++ b/src/inlines.h @@ -8,7 +8,7 @@ extern "C" { unsigned char *cmark_clean_url(cmark_chunk *url); unsigned char *cmark_clean_title(cmark_chunk *title); -cmark_node* cmark_parse_inlines(cmark_strbuf *input, cmark_reference_map *refmap); +void cmark_parse_inlines(cmark_node* parent, cmark_reference_map *refmap); int cmark_parse_reference_inline(cmark_strbuf *input, cmark_reference_map *refmap); diff --git a/src/node.c b/src/node.c index 88c2106..23e8265 100644 --- a/src/node.c +++ b/src/node.c @@ -114,6 +114,7 @@ cmark_node_unlink(cmark_node *node) { node->next = NULL; node->prev = NULL; node->parent = NULL; + } int -- cgit v1.2.3