From a3030f985a973b3b835645313fdad1a8a72ff432 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Sat, 13 Dec 2014 14:13:58 -0800 Subject: Added iterator interface to API, removed cmark_walk. * Added `iterator.c`, `iterator.h`. * Removed `cmark_walk`. * Replaced `cmark_walk` with iterator in HTML renderer. * Replaced API test for `cmark_walk` with simple iterator test. --- src/iterator.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/iterator.c (limited to 'src/iterator.c') diff --git a/src/iterator.c b/src/iterator.c new file mode 100644 index 0000000..a9e6d20 --- /dev/null +++ b/src/iterator.c @@ -0,0 +1,86 @@ +#include + +#include "config.h" +#include "node.h" +#include "cmark.h" +#include "iterator.h" + +cmark_iter* +cmark_iter_new(cmark_node *root) +{ + cmark_iter *iter = (cmark_iter*)malloc(sizeof(cmark_iter)); + if (iter == NULL) { + return NULL; + } else { + iter->root = root; + iter->current = root; + iter->event_type = CMARK_EVENT_ENTER; + return iter; + } +} + +void +cmark_iter_free(cmark_iter *iter) +{ + free(iter); +} + +cmark_event_type +cmark_iter_next(cmark_iter *iter) +{ + return iter->event_type; +} + +int S_is_leaf(cmark_node *node) +{ + switch (cmark_node_get_type(node)) { + case CMARK_NODE_HTML: + case CMARK_NODE_HRULE: + case CMARK_NODE_CODE_BLOCK: + 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; + } +} + +cmark_node* +cmark_iter_get_node(cmark_iter *iter) +{ + /* we'll return current */ + cmark_node *cur = iter->current; + + if (cur == NULL || iter->event_type == CMARK_EVENT_DONE) { + return NULL; + } + + /* roll forward to next item, setting both fields */ + if (iter->event_type == CMARK_EVENT_ENTER && !S_is_leaf(cur)) { + if (cur->first_child == NULL) { + /* stay on this node but exit */ + iter->event_type = CMARK_EVENT_EXIT; + } else { + iter->current = cur->first_child; + iter->event_type = CMARK_EVENT_ENTER; + } + } else if (cur == iter->root) { + /* don't move past root */ + iter->event_type = CMARK_EVENT_DONE; + iter->current = NULL; + } else if (cur->next) { + iter->event_type = CMARK_EVENT_ENTER; + iter->current = cur->next; + } else if (cur->parent) { + iter->event_type = CMARK_EVENT_EXIT; + iter->current = cur->parent; + } else { + iter->event_type = CMARK_EVENT_DONE; + iter->current = NULL; + } + + return cur; +} -- cgit v1.2.3