diff options
author | John MacFarlane <fiddlosopher@gmail.com> | 2014-12-11 13:55:21 -0800 |
---|---|---|
committer | John MacFarlane <fiddlosopher@gmail.com> | 2014-12-12 15:24:05 -0800 |
commit | 4cc37256fdc47faeefe6296cdcce022ec6a60719 (patch) | |
tree | 48828269a62913d9725a35d1d39e4963cb4b8915 /src | |
parent | 550230aa5575b120782ef307a17317c6827f032e (diff) |
Added cmark_node_handler and cmark_walk to header.
Diffstat (limited to 'src')
-rw-r--r-- | src/cmark.h | 7 | ||||
-rw-r--r-- | src/node.c | 59 |
2 files changed, 66 insertions, 0 deletions
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. @@ -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; +} |