summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2014-11-17 21:35:39 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2014-11-17 21:43:47 -0800
commita6c0a1e8b3d2f3456972dad61a435684cac52cb5 (patch)
tree541e7147baf6b053c967bfae05487c250d1ba3db
parent4a7d4e01348660c8deb71bd55231439a4149ab05 (diff)
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.
-rw-r--r--src/blocks.c16
-rw-r--r--src/inlines.c70
-rw-r--r--src/inlines.h2
-rw-r--r--src/node.c1
4 files changed, 21 insertions, 68 deletions
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\\`&_*[]<!"
@@ -841,10 +807,9 @@ static int subject_find_special_char(subject *subj)
return subj->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