summaryrefslogtreecommitdiff
path: root/src/inlines.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2016-05-27 16:55:16 +0200
committerJohn MacFarlane <jgm@berkeley.edu>2016-06-06 15:39:05 -0700
commit25429c96f6554ffac415f9d865934b1183f3398e (patch)
tree84d4eef404e99ff9e88d96a86d348a863d7c466f /src/inlines.c
parentab6c81b960e86b26c7fda366f51ff29d1683a555 (diff)
cmark: Implement support for custom allocators
Diffstat (limited to 'src/inlines.c')
-rw-r--r--src/inlines.c158
1 files changed, 81 insertions, 77 deletions
diff --git a/src/inlines.c b/src/inlines.c
index f2e7cf1..8f18e6c 100644
--- a/src/inlines.c
+++ b/src/inlines.c
@@ -22,13 +22,13 @@ static const char *LEFTSINGLEQUOTE = "\xE2\x80\x98";
static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99";
// Macros for creating various kinds of simple.
-#define make_str(s) make_literal(CMARK_NODE_TEXT, s)
-#define make_code(s) make_literal(CMARK_NODE_CODE, s)
-#define make_raw_html(s) make_literal(CMARK_NODE_HTML_INLINE, s)
-#define make_linebreak() make_simple(CMARK_NODE_LINEBREAK)
-#define make_softbreak() make_simple(CMARK_NODE_SOFTBREAK)
-#define make_emph() make_simple(CMARK_NODE_EMPH)
-#define make_strong() make_simple(CMARK_NODE_STRONG)
+#define make_str(mem, s) make_literal(mem, CMARK_NODE_TEXT, s)
+#define make_code(mem, s) make_literal(mem, CMARK_NODE_CODE, s)
+#define make_raw_html(mem, s) make_literal(mem, CMARK_NODE_HTML_INLINE, s)
+#define make_linebreak(mem) make_simple(mem, CMARK_NODE_LINEBREAK)
+#define make_softbreak(mem) make_simple(mem, CMARK_NODE_SOFTBREAK)
+#define make_emph(mem) make_simple(mem, CMARK_NODE_EMPH)
+#define make_strong(mem) make_simple(mem, CMARK_NODE_STRONG)
typedef struct delimiter {
struct delimiter *previous;
@@ -42,6 +42,7 @@ typedef struct delimiter {
} delimiter;
typedef struct {
+ cmark_mem *mem;
cmark_chunk input;
bufsize_t pos;
cmark_reference_map *refmap;
@@ -57,44 +58,46 @@ static delimiter *S_insert_emph(subject *subj, delimiter *opener,
static int parse_inline(subject *subj, cmark_node *parent, int options);
-static void subject_from_buf(subject *e, cmark_strbuf *buffer,
+static void subject_from_buf(cmark_mem *mem, subject *e, cmark_strbuf *buffer,
cmark_reference_map *refmap);
static bufsize_t subject_find_special_char(subject *subj, int options);
// Create an inline with a literal string value.
-static CMARK_INLINE cmark_node *make_literal(cmark_node_type t, cmark_chunk s) {
- cmark_node *e = (cmark_node *)cmark_calloc(1, sizeof(*e));
+static CMARK_INLINE cmark_node *make_literal(cmark_mem *mem, cmark_node_type t, cmark_chunk s) {
+ cmark_node *e = (cmark_node *)mem->calloc(1, sizeof(*e));
+ cmark_strbuf_init(mem, &e->content, 0);
e->type = t;
e->as.literal = s;
return e;
}
// Create an inline with no value.
-static CMARK_INLINE cmark_node *make_simple(cmark_node_type t) {
- cmark_node *e = (cmark_node *)cmark_calloc(1, sizeof(*e));
+static CMARK_INLINE cmark_node *make_simple(cmark_mem *mem, cmark_node_type t) {
+ cmark_node *e = (cmark_node *)mem->calloc(1, sizeof(*e));
+ cmark_strbuf_init(mem, &e->content, 0);
e->type = t;
return e;
}
// Like make_str, but parses entities.
-static cmark_node *make_str_with_entities(cmark_chunk *content) {
- cmark_strbuf unescaped = GH_BUF_INIT;
+static cmark_node *make_str_with_entities(cmark_mem *mem, cmark_chunk *content) {
+ cmark_strbuf unescaped = CMARK_BUF_INIT(mem);
if (houdini_unescape_html(&unescaped, content->data, content->len)) {
- return make_str(cmark_chunk_buf_detach(&unescaped));
+ return make_str(mem, cmark_chunk_buf_detach(&unescaped));
} else {
- return make_str(*content);
+ return make_str(mem, *content);
}
}
// 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) {
+static cmark_chunk chunk_clone(cmark_mem *mem, cmark_chunk *src) {
cmark_chunk c;
bufsize_t len = src->len;
c.len = len;
- c.data = (unsigned char *)cmark_calloc(len + 1, 1);
+ c.data = (unsigned char *)mem->calloc(len + 1, 1);
c.alloc = 1;
memcpy(c.data, src->data, len);
c.data[len] = '\0';
@@ -102,8 +105,8 @@ static cmark_chunk chunk_clone(cmark_chunk *src) {
return c;
}
-static cmark_chunk cmark_clean_autolink(cmark_chunk *url, int is_email) {
- cmark_strbuf buf = GH_BUF_INIT;
+static cmark_chunk cmark_clean_autolink(cmark_mem *mem, cmark_chunk *url, int is_email) {
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
cmark_chunk_trim(url);
@@ -119,16 +122,17 @@ static cmark_chunk cmark_clean_autolink(cmark_chunk *url, int is_email) {
return cmark_chunk_buf_detach(&buf);
}
-static CMARK_INLINE cmark_node *make_autolink(cmark_chunk url, int is_email) {
- cmark_node *link = make_simple(CMARK_NODE_LINK);
- link->as.link.url = cmark_clean_autolink(&url, is_email);
+static CMARK_INLINE cmark_node *make_autolink(cmark_mem *mem, cmark_chunk url, int is_email) {
+ cmark_node *link = make_simple(mem, CMARK_NODE_LINK);
+ link->as.link.url = cmark_clean_autolink(mem, &url, is_email);
link->as.link.title = cmark_chunk_literal("");
- cmark_node_append_child(link, make_str_with_entities(&url));
+ cmark_node_append_child(link, make_str_with_entities(mem, &url));
return link;
}
-static void subject_from_buf(subject *e, cmark_strbuf *buffer,
+static void subject_from_buf(cmark_mem *mem, subject *e, cmark_strbuf *buffer,
cmark_reference_map *refmap) {
+ e->mem = mem;
e->input.data = buffer->ptr;
e->input.len = buffer->size;
e->input.alloc = 0;
@@ -229,16 +233,16 @@ static cmark_node *handle_backticks(subject *subj) {
if (endpos == 0) { // not found
subj->pos = startpos; // rewind
- return make_str(openticks);
+ return make_str(subj->mem, openticks);
} else {
- cmark_strbuf buf = GH_BUF_INIT;
+ cmark_strbuf buf = CMARK_BUF_INIT(subj->mem);
cmark_strbuf_set(&buf, subj->input.data + startpos,
endpos - startpos - openticks.len);
cmark_strbuf_trim(&buf);
cmark_strbuf_normalize_whitespace(&buf);
- return make_code(cmark_chunk_buf_detach(&buf));
+ return make_code(subj->mem, cmark_chunk_buf_detach(&buf));
}
}
@@ -340,7 +344,7 @@ static void remove_delimiter(subject *subj, delimiter *delim) {
static void push_delimiter(subject *subj, unsigned char c, bool can_open,
bool can_close, cmark_node *inl_text) {
- delimiter *delim = (delimiter *)cmark_calloc(1, sizeof(delimiter));
+ delimiter *delim = (delimiter *)subj->mem->calloc(1, sizeof(delimiter));
delim->delim_char = c;
delim->can_open = can_open;
delim->can_close = can_close;
@@ -373,7 +377,7 @@ static cmark_node *handle_delim(subject *subj, unsigned char c, bool smart) {
contents = cmark_chunk_dup(&subj->input, subj->pos - numdelims, numdelims);
}
- inl_text = make_str(contents);
+ inl_text = make_str(subj->mem, contents);
if ((can_open || can_close) && (!(c == '\'' || c == '"') || smart)) {
push_delimiter(subj, c, can_open, can_close, inl_text);
@@ -389,7 +393,7 @@ static cmark_node *handle_hyphen(subject *subj, bool smart) {
advance(subj);
if (!smart || peek_char(subj) != '-') {
- return make_str(cmark_chunk_literal("-"));
+ return make_str(subj->mem, cmark_chunk_literal("-"));
}
while (smart && peek_char(subj) == '-') {
@@ -400,7 +404,7 @@ static cmark_node *handle_hyphen(subject *subj, bool smart) {
int en_count = 0;
int em_count = 0;
int i;
- cmark_strbuf buf = GH_BUF_INIT;
+ cmark_strbuf buf = CMARK_BUF_INIT(subj->mem);
if (numhyphens % 3 == 0) { // if divisible by 3, use all em dashes
em_count = numhyphens / 3;
@@ -422,7 +426,7 @@ static cmark_node *handle_hyphen(subject *subj, bool smart) {
cmark_strbuf_puts(&buf, ENDASH);
}
- return make_str(cmark_chunk_buf_detach(&buf));
+ return make_str(subj->mem, cmark_chunk_buf_detach(&buf));
}
// Assumes we have a period at the current position.
@@ -432,12 +436,12 @@ static cmark_node *handle_period(subject *subj, bool smart) {
advance(subj);
if (peek_char(subj) == '.') {
advance(subj);
- return make_str(cmark_chunk_literal(ELLIPSES));
+ return make_str(subj->mem, cmark_chunk_literal(ELLIPSES));
} else {
- return make_str(cmark_chunk_literal(".."));
+ return make_str(subj->mem, cmark_chunk_literal(".."));
}
} else {
- return make_str(cmark_chunk_literal("."));
+ return make_str(subj->mem, cmark_chunk_literal("."));
}
}
@@ -483,18 +487,18 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) {
closer = closer->next;
}
} else if (closer->delim_char == '\'') {
- cmark_chunk_free(&closer->inl_text->as.literal);
+ cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE);
if (opener_found) {
- cmark_chunk_free(&opener->inl_text->as.literal);
+ cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE);
}
closer = closer->next;
} else if (closer->delim_char == '"') {
- cmark_chunk_free(&closer->inl_text->as.literal);
+ cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE);
if (opener_found) {
- cmark_chunk_free(&opener->inl_text->as.literal);
+ cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE);
}
closer = closer->next;
@@ -553,7 +557,7 @@ static delimiter *S_insert_emph(subject *subj, delimiter *opener,
// create new emph or strong, and splice it in to our inlines
// between the opener and closer
- emph = use_delims == 1 ? make_emph() : make_strong();
+ emph = use_delims == 1 ? make_emph(subj->mem) : make_strong(subj->mem);
tmp = opener_inl->next;
while (tmp && tmp != closer_inl) {
@@ -589,18 +593,18 @@ static cmark_node *handle_backslash(subject *subj) {
if (cmark_ispunct(
nextchar)) { // only ascii symbols and newline can be escaped
advance(subj);
- return make_str(cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
+ return make_str(subj->mem, cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
} else if (!is_eof(subj) && skip_line_end(subj)) {
- return make_linebreak();
+ return make_linebreak(subj->mem);
} else {
- return make_str(cmark_chunk_literal("\\"));
+ return make_str(subj->mem, cmark_chunk_literal("\\"));
}
}
// Parse an entity or a regular "&" string.
// Assumes the subject has an '&' character at the current position.
static cmark_node *handle_entity(subject *subj) {
- cmark_strbuf ent = GH_BUF_INIT;
+ cmark_strbuf ent = CMARK_BUF_INIT(subj->mem);
bufsize_t len;
advance(subj);
@@ -609,16 +613,16 @@ static cmark_node *handle_entity(subject *subj) {
subj->input.len - subj->pos);
if (len == 0)
- return make_str(cmark_chunk_literal("&"));
+ return make_str(subj->mem, cmark_chunk_literal("&"));
subj->pos += len;
- return make_str(cmark_chunk_buf_detach(&ent));
+ return make_str(subj->mem, cmark_chunk_buf_detach(&ent));
}
// Clean a URL: remove surrounding whitespace and surrounding <>,
// and remove \ that escape punctuation.
-cmark_chunk cmark_clean_url(cmark_chunk *url) {
- cmark_strbuf buf = GH_BUF_INIT;
+cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url) {
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
cmark_chunk_trim(url);
@@ -637,8 +641,8 @@ cmark_chunk cmark_clean_url(cmark_chunk *url) {
return cmark_chunk_buf_detach(&buf);
}
-cmark_chunk cmark_clean_title(cmark_chunk *title) {
- cmark_strbuf buf = GH_BUF_INIT;
+cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title) {
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
unsigned char first, last;
if (title->len == 0) {
@@ -675,7 +679,7 @@ static cmark_node *handle_pointy_brace(subject *subj) {
contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1);
subj->pos += matchlen;
- return make_autolink(contents, 0);
+ return make_autolink(subj->mem, contents, 0);
}
// next try to match an email autolink
@@ -684,7 +688,7 @@ static cmark_node *handle_pointy_brace(subject *subj) {
contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1);
subj->pos += matchlen;
- return make_autolink(contents, 1);
+ return make_autolink(subj->mem, contents, 1);
}
// finally, try to match an html tag
@@ -692,11 +696,11 @@ static cmark_node *handle_pointy_brace(subject *subj) {
if (matchlen > 0) {
contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1);
subj->pos += matchlen;
- return make_raw_html(contents);
+ return make_raw_html(subj->mem, contents);
}
// if nothing matches, just return the opening <:
- return make_str(cmark_chunk_literal("<"));
+ return make_str(subj->mem, cmark_chunk_literal("<"));
}
// Parse a link label. Returns 1 if successful.
@@ -774,13 +778,13 @@ static cmark_node *handle_close_bracket(subject *subj) {
}
if (opener == NULL) {
- return make_str(cmark_chunk_literal("]"));
+ return make_str(subj->mem, cmark_chunk_literal("]"));
}
if (!opener->active) {
// take delimiter off stack
remove_delimiter(subj, opener);
- return make_str(cmark_chunk_literal("]"));
+ return make_str(subj->mem, cmark_chunk_literal("]"));
}
// If we got here, we matched a potential link/image text.
@@ -811,10 +815,10 @@ static cmark_node *handle_close_bracket(subject *subj) {
url_chunk = cmark_chunk_dup(&subj->input, starturl, endurl - starturl);
title_chunk =
cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
- url = cmark_clean_url(&url_chunk);
- title = cmark_clean_title(&title_chunk);
- cmark_chunk_free(&url_chunk);
- cmark_chunk_free(&title_chunk);
+ url = cmark_clean_url(subj->mem, &url_chunk);
+ title = cmark_clean_title(subj->mem, &title_chunk);
+ cmark_chunk_free(subj->mem, &url_chunk);
+ cmark_chunk_free(subj->mem, &title_chunk);
goto match;
} else {
@@ -827,7 +831,7 @@ static cmark_node *handle_close_bracket(subject *subj) {
raw_label = cmark_chunk_literal("");
found_label = link_label(subj, &raw_label);
if (!found_label || raw_label.len == 0) {
- cmark_chunk_free(&raw_label);
+ cmark_chunk_free(subj->mem, &raw_label);
raw_label = cmark_chunk_dup(&subj->input, opener->position,
initial_pos - opener->position - 1);
}
@@ -839,11 +843,11 @@ static cmark_node *handle_close_bracket(subject *subj) {
}
ref = cmark_reference_lookup(subj->refmap, &raw_label);
- cmark_chunk_free(&raw_label);
+ cmark_chunk_free(subj->mem, &raw_label);
if (ref != NULL) { // found
- url = chunk_clone(&ref->url);
- title = chunk_clone(&ref->title);
+ url = chunk_clone(subj->mem, &ref->url);
+ title = chunk_clone(subj->mem, &ref->title);
goto match;
} else {
goto noMatch;
@@ -853,10 +857,10 @@ noMatch:
// If we fall through to here, it means we didn't match a link:
remove_delimiter(subj, opener); // remove this opener from delimiter list
subj->pos = initial_pos;
- return make_str(cmark_chunk_literal("]"));
+ return make_str(subj->mem, cmark_chunk_literal("]"));
match:
- inl = make_simple(is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK);
+ inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK);
inl->as.link.url = url;
inl->as.link.title = title;
cmark_node_insert_before(opener->inl_text, inl);
@@ -909,9 +913,9 @@ static cmark_node *handle_newline(subject *subj) {
skip_spaces(subj);
if (nlpos > 1 && peek_at(subj, nlpos - 1) == ' ' &&
peek_at(subj, nlpos - 2) == ' ') {
- return make_linebreak();
+ return make_linebreak(subj->mem);
} else {
- return make_softbreak();
+ return make_softbreak(subj->mem);
}
}
@@ -1000,7 +1004,7 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
break;
case '[':
advance(subj);
- new_inl = make_str(cmark_chunk_literal("["));
+ new_inl = make_str(subj->mem, cmark_chunk_literal("["));
push_delimiter(subj, '[', true, false, new_inl);
break;
case ']':
@@ -1010,10 +1014,10 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
advance(subj);
if (peek_char(subj) == '[') {
advance(subj);
- new_inl = make_str(cmark_chunk_literal("!["));
+ new_inl = make_str(subj->mem, cmark_chunk_literal("!["));
push_delimiter(subj, '!', false, true, new_inl);
} else {
- new_inl = make_str(cmark_chunk_literal("!"));
+ new_inl = make_str(subj->mem, cmark_chunk_literal("!"));
}
break;
default:
@@ -1026,7 +1030,7 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
cmark_chunk_rtrim(&contents);
}
- new_inl = make_str(contents);
+ new_inl = make_str(subj->mem, contents);
}
if (new_inl != NULL) {
cmark_node_append_child(parent, new_inl);
@@ -1036,10 +1040,10 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
}
// Parse inlines from parent's string_content, adding as children of parent.
-extern void cmark_parse_inlines(cmark_node *parent, cmark_reference_map *refmap,
+extern void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent, cmark_reference_map *refmap,
int options) {
subject subj;
- subject_from_buf(&subj, &parent->string_content, refmap);
+ subject_from_buf(mem, &subj, &parent->content, refmap);
cmark_chunk_rtrim(&subj.input);
while (!is_eof(&subj) && parse_inline(&subj, parent, options))
@@ -1060,7 +1064,7 @@ static void spnl(subject *subj) {
// Modify refmap if a reference is encountered.
// Return 0 if no reference found, otherwise position of subject
// after reference is parsed.
-bufsize_t cmark_parse_reference_inline(cmark_strbuf *input,
+bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_strbuf *input,
cmark_reference_map *refmap) {
subject subj;
@@ -1071,7 +1075,7 @@ bufsize_t cmark_parse_reference_inline(cmark_strbuf *input,
bufsize_t matchlen = 0;
bufsize_t beforetitle;
- subject_from_buf(&subj, input, NULL);
+ subject_from_buf(mem, &subj, input, NULL);
// parse label:
if (!link_label(&subj, &lab) || lab.len == 0)