summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chunk.h39
-rw-r--r--src/cmark.h32
-rw-r--r--src/html/html.c14
-rw-r--r--src/node.c85
-rw-r--r--src/node.h2
5 files changed, 147 insertions, 25 deletions
diff --git a/src/chunk.h b/src/chunk.h
index 9dd56b6..7a1dbc3 100644
--- a/src/chunk.h
+++ b/src/chunk.h
@@ -8,15 +8,15 @@
#include "buffer.h"
typedef struct {
- const unsigned char *data;
+ unsigned char *data;
int len;
- int alloc;
+ int alloc; // also implies a NULL-terminated string
} cmark_chunk;
static inline void cmark_chunk_free(cmark_chunk *c)
{
if (c->alloc)
- free((char *)c->data);
+ free(c->data);
c->data = NULL;
c->alloc = 0;
@@ -55,21 +55,38 @@ static inline int cmark_chunk_strchr(cmark_chunk *ch, int c, int offset)
return p ? (int)(p - ch->data) : ch->len;
}
-static inline unsigned char *cmark_chunk_to_cstr(cmark_chunk *c)
+static inline const char *cmark_chunk_to_cstr(cmark_chunk *c)
{
unsigned char *str;
- str = (unsigned char *)calloc(c->len + 1, sizeof(*str));
- if(str != NULL) {
- memcpy(str, c->data, c->len);
- str[c->len] = 0;
- }
- return str;
+ if (c->alloc) {
+ return (char *)c->data;
+ }
+ str = (unsigned char *)malloc(c->len + 1);
+ if(str != NULL) {
+ memcpy(str, c->data, c->len);
+ str[c->len] = 0;
+ }
+ c->data = str;
+ c->alloc = 1;
+
+ return (char *)str;
+}
+
+static inline void cmark_chunk_set_cstr(cmark_chunk *c, const char *str)
+{
+ if (c->alloc) {
+ free(c->data);
+ }
+ c->len = strlen(str);
+ c->data = (unsigned char *)malloc(c->len + 1);
+ c->alloc = 1;
+ memcpy(c->data, str, c->len + 1);
}
static inline cmark_chunk cmark_chunk_literal(const char *data)
{
- cmark_chunk c = {(const unsigned char *)data, data ? strlen(data) : 0, 0};
+ cmark_chunk c = {(unsigned char *)data, data ? strlen(data) : 0, 0};
return c;
}
diff --git a/src/cmark.h b/src/cmark.h
index c5ddd5b..522e77e 100644
--- a/src/cmark.h
+++ b/src/cmark.h
@@ -56,8 +56,16 @@ typedef enum {
typedef struct cmark_node cmark_node;
typedef struct cmark_doc_parser cmark_doc_parser;
-CMARK_EXPORT cmark_node_type
-cmark_node_get_type(cmark_node *node);
+// Construction and destruction
+
+CMARK_EXPORT cmark_node*
+cmark_node_new(cmark_node_type type);
+
+CMARK_EXPORT void
+cmark_node_destroy(cmark_node *node);
+
+CMARK_EXPORT void
+cmark_free_nodes(cmark_node *e);
// Tree traversal
@@ -76,6 +84,23 @@ cmark_node_first_child(cmark_node *node);
CMARK_EXPORT cmark_node*
cmark_node_last_child(cmark_node *node);
+// Accessors
+
+CMARK_EXPORT cmark_node_type
+cmark_node_get_type(cmark_node *node);
+
+CMARK_EXPORT const char*
+cmark_node_get_content(cmark_node *node);
+
+CMARK_EXPORT int
+cmark_node_set_content(cmark_node *node, const char *content);
+
+CMARK_EXPORT const char*
+cmark_node_get_url(cmark_node *node);
+
+CMARK_EXPORT int
+cmark_node_set_url(cmark_node *node, const char *url);
+
// Tree manipulation
CMARK_EXPORT void
@@ -124,9 +149,6 @@ unsigned char *cmark_render_html(cmark_node *root);
CMARK_EXPORT
unsigned char *cmark_markdown_to_html(unsigned char *text, int len);
-CMARK_EXPORT
-void cmark_free_nodes(cmark_node *e);
-
#ifndef CMARK_NO_SHORT_NAMES
#define NODE_DOCUMENT CMARK_NODE_DOCUMENT
#define NODE_BQUOTE CMARK_NODE_BQUOTE
diff --git a/src/html/html.c b/src/html/html.c
index 11db0de..8110f87 100644
--- a/src/html/html.c
+++ b/src/html/html.c
@@ -152,11 +152,11 @@ static void inlines_to_plain_html(strbuf *html, cmark_node* ils)
// Convert an inline list to HTML. Returns 0 on success, and sets result.
static void inlines_to_html(strbuf *html, cmark_node* ils)
{
- cmark_node* children;
+ bool visit_children;
render_stack* rstack = NULL;
while(ils != NULL) {
- children = NULL;
+ visit_children = false;
switch(ils->type) {
case NODE_STRING:
escape_html(html, ils->as.literal.data, ils->as.literal.len);
@@ -193,7 +193,7 @@ static void inlines_to_html(strbuf *html, cmark_node* ils)
}
strbuf_puts(html, "\">");
- children = ils->first_child;
+ visit_children = true;
rstack = push_inline(rstack, ils->next, "</a>");
break;
@@ -215,20 +215,20 @@ static void inlines_to_html(strbuf *html, cmark_node* ils)
case NODE_STRONG:
strbuf_puts(html, "<strong>");
- children = ils->first_child;
+ visit_children = true;
rstack = push_inline(rstack, ils->next, "</strong>");
break;
case NODE_EMPH:
strbuf_puts(html, "<em>");
- children = ils->first_child;
+ visit_children = true;
rstack = push_inline(rstack, ils->next, "</em>");
break;
default:
break;
}
- if (children) {
- ils = children;
+ if (visit_children) {
+ ils = ils->first_child;
} else {
ils = ils->next;
}
diff --git a/src/node.c b/src/node.c
index 489ac7c..c5ce642 100644
--- a/src/node.c
+++ b/src/node.c
@@ -1,8 +1,26 @@
-#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
#include "config.h"
#include "node.h"
+static void
+S_node_unlink(cmark_node *node);
+
+cmark_node*
+cmark_node_new(cmark_node_type type) {
+ cmark_node *node = (cmark_node *)calloc(1, sizeof(*node));
+ node->type = type;
+ return node;
+}
+
+void
+cmark_node_destroy(cmark_node *node) {
+ S_node_unlink(node);
+ node->next = NULL;
+ cmark_free_nodes(node);
+}
+
cmark_node_type
cmark_node_get_type(cmark_node *node)
{
@@ -69,6 +87,71 @@ cmark_node_last_child(cmark_node *node)
return node->last_child;
}
+static char*
+S_strdup(const char *str) {
+ size_t size = strlen(str) + 1;
+ char *dup = (char *)malloc(size);
+ memcpy(dup, str, size);
+ return dup;
+}
+
+const char*
+cmark_node_get_content(cmark_node *node) {
+ switch (node->type) {
+ case NODE_STRING:
+ case NODE_INLINE_HTML:
+ case NODE_INLINE_CODE:
+ return cmark_chunk_to_cstr(&node->as.literal);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int
+cmark_node_set_content(cmark_node *node, const char *content) {
+ switch (node->type) {
+ case NODE_STRING:
+ case NODE_INLINE_HTML:
+ case NODE_INLINE_CODE:
+ cmark_chunk_set_cstr(&node->as.literal, content);
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+const char*
+cmark_node_get_url(cmark_node *node) {
+ switch (node->type) {
+ case NODE_LINK:
+ case NODE_IMAGE:
+ return (char *)node->as.link.url;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int
+cmark_node_set_url(cmark_node *node, const char *url) {
+ switch (node->type) {
+ case NODE_LINK:
+ case NODE_IMAGE:
+ free(node->as.link.url);
+ node->as.link.url = (unsigned char *)S_strdup(url);
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static inline bool
S_is_block(cmark_node *node) {
return node->type >= CMARK_NODE_FIRST_BLOCK
diff --git a/src/node.h b/src/node.h
index 533406b..2d7f0a1 100644
--- a/src/node.h
+++ b/src/node.h
@@ -61,7 +61,7 @@ struct cmark_node {
} as;
};
-int
+CMARK_EXPORT int
cmark_node_check(cmark_node *node);
#ifdef __cplusplus