From 4cc37256fdc47faeefe6296cdcce022ec6a60719 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Thu, 11 Dec 2014 13:55:21 -0800 Subject: Added cmark_node_handler and cmark_walk to header. --- src/cmark.h | 7 +++++++ src/node.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) (limited to 'src') diff --git a/src/cmark.h b/src/cmark.h index f96cea9..d77749c 100644 --- a/src/cmark.h +++ b/src/cmark.h @@ -86,6 +86,8 @@ typedef enum { typedef struct cmark_node cmark_node; typedef struct cmark_parser cmark_parser; +typedef int (*cmark_node_handler)(cmark_node*, int, void*); + /** * .SH CREATING AND DESTROYING NODES */ @@ -307,6 +309,11 @@ char *cmark_render_ast(cmark_node *root); CMARK_EXPORT char *cmark_render_html(cmark_node *root); +/** + */ +CMARK_EXPORT +int cmark_walk(cmark_node *root, cmark_node_handler handler, void *state); + /** .SH AUTHORS * * John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. diff --git a/src/node.c b/src/node.c index 243c3e6..040aeda 100644 --- a/src/node.c +++ b/src/node.c @@ -767,3 +767,62 @@ cmark_node_check(cmark_node *node, FILE *out) return errors; } + +int S_is_leaf_node(cmark_node *current_node) +{ + switch (cmark_node_get_type(current_node)) { + case CMARK_NODE_HTML: + case CMARK_NODE_HRULE: + case CMARK_NODE_REFERENCE_DEF: + case CMARK_NODE_TEXT: + case CMARK_NODE_SOFTBREAK: + case CMARK_NODE_LINEBREAK: + case CMARK_NODE_INLINE_CODE: + case CMARK_NODE_INLINE_HTML: + return 1; + default: + return 0; + } +} + +int cmark_walk(cmark_node *root, cmark_node_handler handler, void *state) +{ + int begin = 1; + cmark_node *current_node = root; + int depth = 0; + cmark_node *next, *parent, *first_child; + + while (current_node != NULL && depth >= 0) { + + next = current_node->next; + parent = current_node->parent; + + if (!handler(current_node, begin, state)) { + return 0; + } + + if (begin && !S_is_leaf_node(current_node)) { + first_child = current_node->first_child; + if (first_child == NULL) { + begin = 0; // stay on this node + } else { + depth += 1; + current_node = first_child; + } + } else { + if (current_node) { + next = current_node->next; + parent = current_node->parent; + } + if (next) { + begin = 1; + current_node = next; + } else { + begin = 0; + depth -= 1; + current_node = parent; + } + } + } + return 1; +} -- cgit v1.2.3