summaryrefslogtreecommitdiff
path: root/src/iterator.c
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2014-12-13 14:13:58 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2014-12-13 19:40:21 -0800
commita3030f985a973b3b835645313fdad1a8a72ff432 (patch)
treee1b1b43b16102b106bc43f4dd5eee32bb11b2a73 /src/iterator.c
parent8d6efe632aaeb1831c86b27e120a344c5e3ee7d4 (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.c86
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;
+}