summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2017-09-07 08:06:11 -0700
committerAshe Connor <ashe@kivikakk.ee>2017-09-14 11:57:43 +1000
commit6c9b4d75cb9e98a7f225e9873045326dffd8b6c6 (patch)
tree405fdcdf0268a3b241661d93bbd0c91861d50b4e
parentb9c7a496ba7dd9c3495bae2ff2855899e47b245d (diff)
blocks: Fix quadratic behavior in `finalize`
-rw-r--r--src/blocks.c12
-rw-r--r--src/inlines.c49
-rw-r--r--src/inlines.h2
3 files changed, 33 insertions, 30 deletions
diff --git a/src/blocks.c b/src/blocks.c
index 5a293b2..3e810bc 100644
--- a/src/blocks.c
+++ b/src/blocks.c
@@ -255,17 +255,21 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
switch (S_type(b)) {
case CMARK_NODE_PARAGRAPH:
- while (cmark_strbuf_at(node_content, 0) == '[' &&
- (pos = cmark_parse_reference_inline(parser->mem, node_content,
- parser->refmap))) {
+ {
+ cmark_chunk chunk = {node_content->ptr, node_content->size, 0};
+ while (chunk.len && chunk.data[0] == '[' &&
+ (pos = cmark_parse_reference_inline(parser->mem, &chunk, parser->refmap))) {
- cmark_strbuf_drop(node_content, pos);
+ chunk.data += pos;
+ chunk.len -= pos;
}
+ cmark_strbuf_drop(node_content, (node_content->size - chunk.len));
if (is_blank(node_content, 0)) {
// remove blank node (former reference def)
cmark_node_free(b);
}
break;
+ }
case CMARK_NODE_CODE_BLOCK:
if (!b->as.code.fenced) { // indented code
diff --git a/src/inlines.c b/src/inlines.c
index 2d7f385..c445f2f 100644
--- a/src/inlines.c
+++ b/src/inlines.c
@@ -72,7 +72,7 @@ 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(cmark_mem *mem, subject *e, cmark_strbuf *buffer,
+static void subject_from_buf(cmark_mem *mem, subject *e, cmark_chunk *chunk,
cmark_reference_map *refmap);
static bufsize_t subject_find_special_char(subject *subj, int options);
@@ -149,13 +149,11 @@ static CMARK_INLINE cmark_node *make_autolink(cmark_mem *mem, cmark_chunk url,
return link;
}
-static void subject_from_buf(cmark_mem *mem, subject *e, cmark_strbuf *buffer,
+static void subject_from_buf(cmark_mem *mem, subject *e, cmark_chunk *chunk,
cmark_reference_map *refmap) {
int i;
e->mem = mem;
- e->input.data = buffer->ptr;
- e->input.len = buffer->size;
- e->input.alloc = 0;
+ e->input = *chunk;
e->pos = 0;
e->refmap = refmap;
e->last_delim = NULL;
@@ -708,7 +706,7 @@ cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url) {
return result;
}
- houdini_unescape_html_f(&buf, url->data, url->len);
+ houdini_unescape_html_f(&buf, url->data, url->len);
cmark_strbuf_unescape(&buf);
return cmark_chunk_buf_detach(&buf);
@@ -827,24 +825,24 @@ static bufsize_t manual_scan_link_url_2(cmark_chunk *input, bufsize_t offset,
bufsize_t i = offset;
size_t nb_p = 0;
- while (i < input->len) {
- if (input->data[i] == '\\' &&
- i + 1 < input-> len &&
- cmark_ispunct(input->data[i+1]))
- i += 2;
- else if (input->data[i] == '(') {
- ++nb_p;
- ++i;
- } else if (input->data[i] == ')') {
- if (nb_p == 0)
+ while (i < input->len) {
+ if (input->data[i] == '\\' &&
+ i + 1 < input-> len &&
+ cmark_ispunct(input->data[i+1]))
+ i += 2;
+ else if (input->data[i] == '(') {
+ ++nb_p;
+ ++i;
+ } else if (input->data[i] == ')') {
+ if (nb_p == 0)
+ break;
+ --nb_p;
+ ++i;
+ } else if (cmark_isspace(input->data[i]))
break;
- --nb_p;
- ++i;
- } else if (cmark_isspace(input->data[i]))
- break;
- else
- ++i;
- }
+ else
+ ++i;
+ }
if (i >= input->len)
return -1;
@@ -1178,7 +1176,8 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
extern void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
cmark_reference_map *refmap, int options) {
subject subj;
- subject_from_buf(mem, &subj, &parent->content, refmap);
+ cmark_chunk content = {parent->content.ptr, parent->content.size, 0};
+ subject_from_buf(mem, &subj, &content, refmap);
cmark_chunk_rtrim(&subj.input);
while (!is_eof(&subj) && parse_inline(&subj, parent, options))
@@ -1206,7 +1205,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_mem *mem, cmark_strbuf *input,
+bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
cmark_reference_map *refmap) {
subject subj;
diff --git a/src/inlines.h b/src/inlines.h
index 52be768..39d3363 100644
--- a/src/inlines.h
+++ b/src/inlines.h
@@ -11,7 +11,7 @@ cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title);
void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
cmark_reference_map *refmap, int options);
-bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_strbuf *input,
+bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
cmark_reference_map *refmap);
#ifdef __cplusplus