cmark

My personal build of CMark ✏️

Commit
8d6efe632aaeb1831c86b27e120a344c5e3ee7d4
Parent
a6a7d2f8f47df7144e636ae2875a8d2ffc0173ae
Author
John MacFarlane <jgm@berkeley.edu>
Date

API improvements: cmark_event_type parameter for walk handlers.

Added cmark_event_type enum, which is used as the second parameter of the handler passed to cmark_walk.

See #224.

Diffstat

5 files changed, 24 insertions, 13 deletions

Status File Name N° Changes Insertions Deletions
Modified api_test/main.c 4 2 2
Modified man/man3/cmark.3 4 2 2
Modified src/cmark.h 11 9 2
Modified src/html.c 4 3 1
Modified src/node.c 14 8 6
diff --git a/api_test/main.c b/api_test/main.c
@@ -294,10 +294,10 @@ node_check(test_batch_runner *runner) {
 }
 
 static int
-S_handler(cmark_node *node, int entering, void *state)
+S_handler(cmark_node *node, cmark_event_type ev_type, void *state)
 {
 	int *textnodes = state;
-	if (entering) {
+	if (ev_type == CMARK_EVENT_ENTER) {
 		if (node->type == CMARK_NODE_TEXT) {
 			*textnodes += 1;
 		}
diff --git a/man/man3/cmark.3 b/man/man3/cmark.3
@@ -1,4 +1,4 @@
-.TH cmark 3 "December 12, 2014" "LOCAL" "Library Functions Manual"
+.TH cmark 3 "December 13, 2014" "LOCAL" "Library Functions Manual"
 .SH NAME
 
 .B cmark
@@ -277,7 +277,7 @@ typedef enum {
 Walks the tree starting from root, applying handler to each node.
 Nodes that can have children are visited twice, once on the way in
 and once on the way out.  handler is a function that takes a node
-pointer, an integer direction (1 for entering, 0 for leaving),
+pointer, a cmark_event_type,
 and a pointer to a state structure that can be consulted and
 updated by the handler.  The handler should return 1 on success,
 0 on failure.  cmark_walk returns 1 if it traversed the entire
diff --git a/src/cmark.h b/src/cmark.h
@@ -85,7 +85,14 @@ typedef enum {
 typedef struct cmark_node cmark_node;
 typedef struct cmark_parser cmark_parser;
 
-typedef int (*cmark_node_handler)(cmark_node*, int, void*);
+typedef enum {
+	CMARK_EVENT_DONE,
+	CMARK_EVENT_ENTER,
+	CMARK_EVENT_EXIT
+} cmark_event_type;
+
+typedef int (*cmark_node_handler)(cmark_node *node, cmark_event_type ev_type,
+				  void *state);
 
 /**
  * .SH CREATING AND DESTROYING NODES
@@ -311,7 +318,7 @@ char *cmark_render_html(cmark_node *root);
 /** Walks the tree starting from root, applying handler to each node.
  * Nodes that can have children are visited twice, once on the way in
  * and once on the way out.  handler is a function that takes a node
- * pointer, an integer direction (1 for entering, 0 for leaving),
+ * pointer, a cmark_event_type,
  * and a pointer to a state structure that can be consulted and
  * updated by the handler.  The handler should return 1 on success,
  * 0 on failure.  cmark_walk returns 1 if it traversed the entire
diff --git a/src/html.c b/src/html.c
@@ -39,7 +39,7 @@ struct render_state {
 };
 
 static int
-S_render_node(cmark_node *node, int entering, void *vstate)
+S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
 {
 	struct render_state *state = vstate;
 	cmark_node *parent;
@@ -50,6 +50,8 @@ S_render_node(cmark_node *node, int entering, void *vstate)
 	strbuf *info;
 	bool tight;
 
+	bool entering = (ev_type == CMARK_EVENT_ENTER);
+
 	if (state->plain == node) { // back at original node
 		state->plain = NULL;
 	}
diff --git a/src/node.c b/src/node.c
@@ -786,7 +786,7 @@ int S_is_leaf_node(cmark_node *current_node)
 
 int cmark_walk(cmark_node *root, cmark_node_handler handler, void *state)
 {
-	int begin = 1;
+	int ev_type = CMARK_EVENT_ENTER;
 	cmark_node *current_node = root;
 	int depth = 0;
 	cmark_node *next, *parent, *first_child;
@@ -796,14 +796,15 @@ int cmark_walk(cmark_node *root, cmark_node_handler handler, void *state)
 		next = current_node->next;
 		parent = current_node->parent;
 
-		if (!handler(current_node, begin, state)) {
+		if (!handler(current_node, ev_type, state)) {
 			return 0;
 		}
 
-		if (begin && !S_is_leaf_node(current_node)) {
+		if (ev_type == CMARK_EVENT_ENTER &&
+		    !S_is_leaf_node(current_node)) {
 			first_child = current_node->first_child;
 			if (first_child == NULL) {
-				begin = 0; // stay on this node
+				ev_type = CMARK_EVENT_EXIT; // stay on this node
 			} else {
 				depth += 1;
 				current_node = first_child;
@@ -816,13 +817,14 @@ int cmark_walk(cmark_node *root, cmark_node_handler handler, void *state)
 			if (next) {
 				// don't go past root:
 				if (current_node == root) {
+					ev_type = CMARK_EVENT_DONE;
 					return 1;
 				} else {
-					begin = 1;
+					ev_type = CMARK_EVENT_ENTER;
 					current_node = next;
 				}
 			} else {
-				begin = 0;
+				ev_type = CMARK_EVENT_EXIT;
 				depth -= 1;
 				current_node = parent;
 			}