From f3f50b29d615d2678d8047dc277b108cc5143167 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 19 Jan 2020 13:46:10 +0100 Subject: 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. --- src/blocks.c | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'src/blocks.c') 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++; -- cgit v1.2.3