summaryrefslogtreecommitdiff
path: root/src/blocks.c
diff options
context:
space:
mode:
authorNick Wellnhofer <wellnhofer@aevum.de>2020-01-19 13:46:10 +0100
committerJohn MacFarlane <jgm@berkeley.edu>2020-01-23 08:25:54 -0800
commitf3f50b29d615d2678d8047dc277b108cc5143167 (patch)
treeca3f01f6352d2cc2dd7cfc9c96508b800b8cc510 /src/blocks.c
parent3ef0718f9f4c9dea5014a8a0e9a67e2366b9374f (diff)
Rearrange struct cmark_node
Introduce multi-purpose data/len members in struct cmark_node. This is mainly used to store literal text for inlines, code and HTML blocks. Move the content strbuf for blocks from cmark_node to cmark_parser. When finalizing nodes that allow inlines (paragraphs and headings), detach the strbuf and store the block content in the node's data/len members. Free the block content after processing inlines. Reduces size of struct cmark_node by 8 bytes.
Diffstat (limited to 'src/blocks.c')
-rw-r--r--src/blocks.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/src/blocks.c b/src/blocks.c
index 9970cc9..df19752 100644
--- a/src/blocks.c
+++ b/src/blocks.c
@@ -72,7 +72,7 @@ static cmark_node *make_block(cmark_mem *mem, cmark_node_type tag,
cmark_node *e;
e = (cmark_node *)mem->calloc(1, sizeof(*e));
- cmark_strbuf_init(mem, &e->content, 32);
+ e->mem = mem;
e->type = (uint16_t)tag;
e->flags = CMARK_NODE__OPEN;
e->start_line = start_line;
@@ -96,6 +96,7 @@ cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) {
cmark_strbuf_init(mem, &parser->curline, 256);
cmark_strbuf_init(mem, &parser->linebuf, 0);
+ cmark_strbuf_init(mem, &parser->content, 0);
parser->refmap = cmark_reference_map_new(mem);
parser->root = document;
@@ -171,19 +172,18 @@ static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) {
block_type == CMARK_NODE_HEADING);
}
-static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) {
+static void add_line(cmark_chunk *ch, cmark_parser *parser) {
int chars_to_tab;
int i;
- assert(node->flags & CMARK_NODE__OPEN);
if (parser->partially_consumed_tab) {
parser->offset += 1; // skip over tab
// add space characters:
chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
for (i = 0; i < chars_to_tab; i++) {
- cmark_strbuf_putc(&node->content, ' ');
+ cmark_strbuf_putc(&parser->content, ' ');
}
}
- cmark_strbuf_put(&node->content, ch->data + parser->offset,
+ cmark_strbuf_put(&parser->content, ch->data + parser->offset,
ch->len - parser->offset);
}
@@ -230,12 +230,10 @@ static bool S_ends_with_blank_line(cmark_node *node) {
}
// returns true if content remains after link defs are resolved.
-static bool resolve_reference_link_definitions(
- cmark_parser *parser,
- cmark_node *b) {
+static bool resolve_reference_link_definitions(cmark_parser *parser) {
bufsize_t pos;
- cmark_strbuf *node_content = &b->content;
- cmark_chunk chunk = {node_content->ptr, node_content->size, 0};
+ cmark_strbuf *node_content = &parser->content;
+ cmark_chunk chunk = {node_content->ptr, node_content->size};
while (chunk.len && chunk.data[0] == '[' &&
(pos = cmark_parse_reference_inline(parser->mem, &chunk,
parser->refmap))) {
@@ -244,7 +242,7 @@ static bool resolve_reference_link_definitions(
chunk.len -= pos;
}
cmark_strbuf_drop(node_content, (node_content->size - chunk.len));
- return !is_blank(&b->content, 0);
+ return !is_blank(node_content, 0);
}
static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
@@ -277,15 +275,18 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
b->end_column = parser->last_line_length;
}
- cmark_strbuf *node_content = &b->content;
+ cmark_strbuf *node_content = &parser->content;
switch (S_type(b)) {
case CMARK_NODE_PARAGRAPH:
{
- has_content = resolve_reference_link_definitions(parser, b);
+ has_content = resolve_reference_link_definitions(parser);
if (!has_content) {
// remove blank node (former reference def)
cmark_node_free(b);
+ } else {
+ b->len = node_content->size;
+ b->data = cmark_strbuf_detach(node_content);
}
break;
}
@@ -318,12 +319,14 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
pos += 1;
cmark_strbuf_drop(node_content, pos);
}
- b->as.code.literal = cmark_strbuf_detach(node_content);
+ b->len = node_content->size;
+ b->data = cmark_strbuf_detach(node_content);
break;
+ case CMARK_NODE_HEADING:
case CMARK_NODE_HTML_BLOCK:
- b->as.literal.len = node_content->size;
- b->as.literal.data = cmark_strbuf_detach(node_content);
+ b->len = node_content->size;
+ b->data = cmark_strbuf_detach(node_content);
break;
case CMARK_NODE_LIST: // determine tight/loose status
@@ -401,6 +404,9 @@ static void process_inlines(cmark_mem *mem, cmark_node *root,
if (ev_type == CMARK_EVENT_ENTER) {
if (contains_inlines(S_type(cur))) {
cmark_parse_inlines(mem, cur, refmap, options);
+ mem->free(cur->data);
+ cur->data = NULL;
+ cur->len = 0;
}
}
}
@@ -513,6 +519,8 @@ static cmark_node *finalize_document(cmark_parser *parser) {
finalize(parser, parser->root);
process_inlines(parser->mem, parser->root, parser->refmap, parser->options);
+ cmark_strbuf_free(&parser->content);
+
return parser->root;
}
@@ -996,7 +1004,7 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
(lev =
scan_setext_heading_line(input, parser->first_nonspace))) {
// finalize paragraph, resolving reference links
- has_content = resolve_reference_link_definitions(parser, *container);
+ has_content = resolve_reference_link_definitions(parser);
if (has_content) {
@@ -1136,7 +1144,7 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
if (parser->current != last_matched_container &&
container == last_matched_container && !parser->blank &&
S_type(parser->current) == CMARK_NODE_PARAGRAPH) {
- add_line(parser->current, input, parser);
+ add_line(input, parser);
} else { // not a lazy continuation
// Finalize any blocks that were not matched and set cur to container:
while (parser->current != last_matched_container) {
@@ -1145,9 +1153,9 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
}
if (S_type(container) == CMARK_NODE_CODE_BLOCK) {
- add_line(container, input, parser);
+ add_line(input, parser);
} else if (S_type(container) == CMARK_NODE_HTML_BLOCK) {
- add_line(container, input, parser);
+ add_line(input, parser);
int matches_end_condition;
switch (container->as.html_block_type) {
@@ -1194,14 +1202,14 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
}
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
false);
- add_line(container, input, parser);
+ add_line(input, parser);
} else {
// create paragraph container for line
container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
parser->first_nonspace + 1);
S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
false);
- add_line(container, input, parser);
+ add_line(input, parser);
}
parser->current = container;
@@ -1238,7 +1246,6 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
input.data = parser->curline.ptr;
input.len = parser->curline.size;
- input.alloc = 0;
parser->line_number++;