summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2015-05-14 08:12:13 -0700
committerJohn MacFarlane <jgm@berkeley.edu>2015-05-14 08:12:13 -0700
commit0e4769d5c1e254fa1747701d2da708d0cb61d0c3 (patch)
tree4a7b13b50456cc57743a1bedbbb5285605817479
parent5ba5740f7e4404c0111a37f77db42c105740a6ff (diff)
parenteada41977a4dc6da389d3bdefe7116ac2b1d75bd (diff)
Merge pull request #38 from nwellnhof/chunks_for_links
Store link URL and title as cmark_chunk
-rw-r--r--src/chunk.h17
-rw-r--r--src/html.c18
-rw-r--r--src/inlines.c67
-rw-r--r--src/inlines.h4
-rw-r--r--src/node.c27
-rw-r--r--src/node.h4
-rw-r--r--src/references.c4
-rw-r--r--src/references.h4
-rw-r--r--src/xml.c6
9 files changed, 79 insertions, 72 deletions
diff --git a/src/chunk.h b/src/chunk.h
index 54c4b16..3d6743c 100644
--- a/src/chunk.h
+++ b/src/chunk.h
@@ -7,6 +7,8 @@
#include "cmark_ctype.h"
#include "buffer.h"
+#define CMARK_CHUNK_EMPTY { NULL, 0, 0 }
+
typedef struct {
unsigned char *data;
int len;
@@ -78,10 +80,17 @@ 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);
+ if (str == NULL) {
+ c->len = 0;
+ c->data = NULL;
+ c->alloc = 0;
+ }
+ else {
+ 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)
diff --git a/src/html.c b/src/html.c
index f1b88fa..c15f6f4 100644
--- a/src/html.c
+++ b/src/html.c
@@ -261,12 +261,13 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
case CMARK_NODE_LINK:
if (entering) {
cmark_strbuf_puts(html, "<a href=\"");
- if (node->as.link.url)
- escape_href(html, node->as.link.url, -1);
+ escape_href(html, node->as.link.url.data,
+ node->as.link.url.len);
- if (node->as.link.title) {
+ if (node->as.link.title.len) {
cmark_strbuf_puts(html, "\" title=\"");
- escape_html(html, node->as.link.title, -1);
+ escape_html(html, node->as.link.title.data,
+ node->as.link.title.len);
}
cmark_strbuf_puts(html, "\">");
@@ -278,15 +279,16 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
case CMARK_NODE_IMAGE:
if (entering) {
cmark_strbuf_puts(html, "<img src=\"");
- if (node->as.link.url)
- escape_href(html, node->as.link.url, -1);
+ escape_href(html, node->as.link.url.data,
+ node->as.link.url.len);
cmark_strbuf_puts(html, "\" alt=\"");
state->plain = node;
} else {
- if (node->as.link.title) {
+ if (node->as.link.title.len) {
cmark_strbuf_puts(html, "\" title=\"");
- escape_html(html, node->as.link.title, -1);
+ escape_html(html, node->as.link.title.data,
+ node->as.link.title.len);
}
cmark_strbuf_puts(html, "\" />");
diff --git a/src/inlines.c b/src/inlines.c
index afe564c..fc39a5f 100644
--- a/src/inlines.c
+++ b/src/inlines.c
@@ -59,31 +59,33 @@ static void subject_from_buf(subject *e, cmark_strbuf *buffer,
cmark_reference_map *refmap);
static int subject_find_special_char(subject *subj, int options);
-static unsigned char *cmark_clean_autolink(cmark_chunk *url, int is_email)
+static cmark_chunk cmark_clean_autolink(cmark_chunk *url, int is_email)
{
cmark_strbuf buf = GH_BUF_INIT;
cmark_chunk_trim(url);
- if (url->len == 0)
- return NULL;
+ if (url->len == 0) {
+ cmark_chunk result = CMARK_CHUNK_EMPTY;
+ return result;
+ }
if (is_email)
cmark_strbuf_puts(&buf, "mailto:");
houdini_unescape_html_f(&buf, url->data, url->len);
- return cmark_strbuf_detach(&buf);
+ return cmark_chunk_buf_detach(&buf);
}
-static inline cmark_node *make_link(cmark_node *label, unsigned char *url, unsigned char *title)
+static inline cmark_node *make_link(cmark_node *label, cmark_chunk *url, cmark_chunk *title)
{
cmark_node* e = (cmark_node *)calloc(1, sizeof(*e));
if(e != NULL) {
e->type = CMARK_NODE_LINK;
e->first_child = label;
e->last_child = label;
- e->as.link.url = url;
- e->as.link.title = title;
+ e->as.link.url = *url;
+ e->as.link.title = *title;
e->next = NULL;
label->parent = e;
}
@@ -92,7 +94,9 @@ static inline cmark_node *make_link(cmark_node *label, unsigned char *url, unsig
static inline cmark_node* make_autolink(cmark_node* label, cmark_chunk url, int is_email)
{
- return make_link(label, cmark_clean_autolink(&url, is_email), NULL);
+ cmark_chunk clean_url = cmark_clean_autolink(&url, is_email);
+ cmark_chunk title = CMARK_CHUNK_EMPTY;
+ return make_link(label, &clean_url, &title);
}
// Create an inline with a literal string value.
@@ -134,19 +138,20 @@ static inline cmark_node* make_simple(cmark_node_type t)
return e;
}
-static unsigned char *bufdup(const unsigned char *buf)
+// Duplicate a chunk by creating a copy of the buffer not by reusing the
+// buffer like cmark_chunk_dup does.
+static cmark_chunk chunk_clone(cmark_chunk *src)
{
- unsigned char *new_buf = NULL;
+ cmark_chunk c;
+ int len = src->len;
- if (buf) {
- int len = strlen((char *)buf);
- new_buf = (unsigned char *)calloc(len + 1, sizeof(*new_buf));
- if(new_buf != NULL) {
- memcpy(new_buf, buf, len + 1);
- }
- }
+ c.len = len;
+ c.data = (unsigned char *)malloc(len + 1);
+ c.alloc = 1;
+ memcpy(c.data, src->data, len);
+ c.data[len] = '\0';
- return new_buf;
+ return c;
}
static void subject_from_buf(subject *e, cmark_strbuf *buffer,
@@ -622,14 +627,16 @@ static cmark_node *make_str_with_entities(cmark_chunk *content)
// Clean a URL: remove surrounding whitespace and surrounding <>,
// and remove \ that escape punctuation.
-unsigned char *cmark_clean_url(cmark_chunk *url)
+cmark_chunk cmark_clean_url(cmark_chunk *url)
{
cmark_strbuf buf = GH_BUF_INIT;
cmark_chunk_trim(url);
- if (url->len == 0)
- return NULL;
+ if (url->len == 0) {
+ cmark_chunk result = CMARK_CHUNK_EMPTY;
+ return result;
+ }
if (url->data[0] == '<' && url->data[url->len - 1] == '>') {
houdini_unescape_html_f(&buf, url->data + 1, url->len - 2);
@@ -638,16 +645,18 @@ unsigned char *cmark_clean_url(cmark_chunk *url)
}
cmark_strbuf_unescape(&buf);
- return buf.size == 0 ? NULL : cmark_strbuf_detach(&buf);
+ return cmark_chunk_buf_detach(&buf);
}
-unsigned char *cmark_clean_title(cmark_chunk *title)
+cmark_chunk cmark_clean_title(cmark_chunk *title)
{
cmark_strbuf buf = GH_BUF_INIT;
unsigned char first, last;
- if (title->len == 0)
- return NULL;
+ if (title->len == 0) {
+ cmark_chunk result = CMARK_CHUNK_EMPTY;
+ return result;
+ }
first = title->data[0];
last = title->data[title->len - 1];
@@ -662,7 +671,7 @@ unsigned char *cmark_clean_title(cmark_chunk *title)
}
cmark_strbuf_unescape(&buf);
- return buf.size == 0 ? NULL : cmark_strbuf_detach(&buf);
+ return cmark_chunk_buf_detach(&buf);
}
// Parse an autolink or HTML tag.
@@ -766,7 +775,7 @@ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
cmark_reference *ref;
bool is_image = false;
cmark_chunk url_chunk, title_chunk;
- unsigned char *url, *title;
+ cmark_chunk url, title;
delimiter *opener;
cmark_node *link_text;
cmark_node *inl;
@@ -854,8 +863,8 @@ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
cmark_chunk_free(&raw_label);
if (ref != NULL) { // found
- url = bufdup(ref->url);
- title = bufdup(ref->title);
+ url = chunk_clone(&ref->url);
+ title = chunk_clone(&ref->title);
goto match;
} else {
goto noMatch;
diff --git a/src/inlines.h b/src/inlines.h
index 9e56790..534588e 100644
--- a/src/inlines.h
+++ b/src/inlines.h
@@ -5,8 +5,8 @@
extern "C" {
#endif
-unsigned char *cmark_clean_url(cmark_chunk *url);
-unsigned char *cmark_clean_title(cmark_chunk *title);
+cmark_chunk cmark_clean_url(cmark_chunk *url);
+cmark_chunk cmark_clean_title(cmark_chunk *title);
void cmark_parse_inlines(cmark_node* parent, cmark_reference_map *refmap, int options);
diff --git a/src/node.c b/src/node.c
index 466b0a1..7b1bb10 100644
--- a/src/node.c
+++ b/src/node.c
@@ -122,12 +122,8 @@ void S_free_nodes(cmark_node *e)
break;
case NODE_LINK:
case NODE_IMAGE:
- if (e->as.link.url) {
- free(e->as.link.url);
- }
- if (e->as.link.title) {
- free(e->as.link.title);
- }
+ cmark_chunk_free(&e->as.link.url);
+ cmark_chunk_free(&e->as.link.title);
break;
default:
break;
@@ -282,15 +278,6 @@ cmark_node_set_user_data(cmark_node *node, void *user_data)
return 1;
}
-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_literal(cmark_node *node)
{
@@ -541,7 +528,7 @@ cmark_node_get_url(cmark_node *node)
switch (node->type) {
case NODE_LINK:
case NODE_IMAGE:
- return (char *)node->as.link.url;
+ return cmark_chunk_to_cstr(&node->as.link.url);
default:
break;
}
@@ -559,8 +546,7 @@ 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);
+ cmark_chunk_set_cstr(&node->as.link.url, url);
return 1;
default:
break;
@@ -579,7 +565,7 @@ cmark_node_get_title(cmark_node *node)
switch (node->type) {
case NODE_LINK:
case NODE_IMAGE:
- return (char *)node->as.link.title;
+ return cmark_chunk_to_cstr(&node->as.link.title);
default:
break;
}
@@ -597,8 +583,7 @@ cmark_node_set_title(cmark_node *node, const char *title)
switch (node->type) {
case NODE_LINK:
case NODE_IMAGE:
- free(node->as.link.title);
- node->as.link.title = (unsigned char *)S_strdup(title);
+ cmark_chunk_set_cstr(&node->as.link.title, title);
return 1;
default:
break;
diff --git a/src/node.h b/src/node.h
index 7a45d42..911a18f 100644
--- a/src/node.h
+++ b/src/node.h
@@ -38,8 +38,8 @@ typedef struct {
} cmark_header;
typedef struct {
- unsigned char *url;
- unsigned char *title;
+ cmark_chunk url;
+ cmark_chunk title;
} cmark_link;
struct cmark_node {
diff --git a/src/references.c b/src/references.c
index 37bf4cb..1d3d56d 100644
--- a/src/references.c
+++ b/src/references.c
@@ -20,8 +20,8 @@ static void reference_free(cmark_reference *ref)
{
if(ref != NULL) {
free(ref->label);
- free(ref->url);
- free(ref->title);
+ cmark_chunk_free(&ref->url);
+ cmark_chunk_free(&ref->title);
free(ref);
}
}
diff --git a/src/references.h b/src/references.h
index 69325bb..a360cd5 100644
--- a/src/references.h
+++ b/src/references.h
@@ -12,8 +12,8 @@ extern "C" {
struct cmark_reference {
struct cmark_reference *next;
unsigned char *label;
- unsigned char *url;
- unsigned char *title;
+ cmark_chunk url;
+ cmark_chunk title;
unsigned int hash;
};
diff --git a/src/xml.c b/src/xml.c
index 845e553..acb2f3d 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -118,10 +118,12 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
case CMARK_NODE_LINK:
case CMARK_NODE_IMAGE:
cmark_strbuf_puts(xml, " destination=\"");
- escape_xml(xml, node->as.link.url, -1);
+ escape_xml(xml, node->as.link.url.data,
+ node->as.link.url.len);
cmark_strbuf_putc(xml, '"');
cmark_strbuf_puts(xml, " title=\"");
- escape_xml(xml, node->as.link.title, -1);
+ escape_xml(xml, node->as.link.title.data,
+ node->as.link.title.len);
cmark_strbuf_putc(xml, '"');
break;
default: