From da23f80b53d47c76a85ba163cb0fb426050f3738 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sat, 9 May 2015 15:57:35 +0200 Subject: Store link URL and title as cmark_chunk --- src/chunk.h | 2 ++ src/html.c | 18 ++++++++------- src/inlines.c | 67 ++++++++++++++++++++++++++++++++------------------------ src/inlines.h | 4 ++-- src/node.c | 27 +++++------------------ src/node.h | 4 ++-- src/references.c | 4 ++-- src/references.h | 4 ++-- src/xml.c | 6 +++-- 9 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/chunk.h b/src/chunk.h index 54c4b16..8b4333a 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; 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, "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, "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: -- cgit v1.2.3 From eada41977a4dc6da389d3bdefe7116ac2b1d75bd Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sat, 9 May 2015 16:30:50 +0200 Subject: Allow NULL value in string setters Supersedes pull request #34. --- src/chunk.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/chunk.h b/src/chunk.h index 8b4333a..3d6743c 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -80,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) -- cgit v1.2.3