diff options
author | John MacFarlane <jgm@berkeley.edu> | 2014-12-13 14:13:58 -0800 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2014-12-13 19:40:21 -0800 |
commit | a3030f985a973b3b835645313fdad1a8a72ff432 (patch) | |
tree | e1b1b43b16102b106bc43f4dd5eee32bb11b2a73 /src/iterator.c | |
parent | 8d6efe632aaeb1831c86b27e120a344c5e3ee7d4 (diff) |
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.
Diffstat (limited to 'src/iterator.c')
-rw-r--r-- | src/iterator.c | 86 |
1 files changed, 86 insertions, 0 deletions
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 <stdlib.h> + +#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; +} |