From 790a6ea843ce6db074fded21cb085b22cb319158 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Sun, 3 Apr 2016 00:59:45 +0200 Subject: [PATCH] cmark_parser: implement and expose reentrant feed function. This can be useful for transclusion extensions for example, http://talk.commonmark.org/t/transclusion-or-including-sub-documents-for-reuse/270 --- src/blocks.c | 21 ++++++++++++++++++++- src/cmark_extension_api.h | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/blocks.c b/src/blocks.c index ddc5b3d21..becfad391 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -566,6 +566,18 @@ void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len) { S_parser_feed(parser, (const unsigned char *)buffer, len, false); } +void cmark_parser_feed_reentrant(cmark_parser *parser, const char *buffer, size_t len) { + cmark_strbuf *saved_linebuf = parser->linebuf; + cmark_strbuf *buf = (cmark_strbuf *)malloc(sizeof(cmark_strbuf)); + cmark_strbuf_init(buf, 0); + + parser->linebuf = buf; + S_parser_feed(parser, (const unsigned char *)buffer, len, true); + cmark_strbuf_free(buf); + + parser->linebuf = saved_linebuf; +} + static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer, size_t len, bool eof) { const unsigned char *end = buffer + len; @@ -1216,6 +1228,9 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer, bool all_matched = true; cmark_node *container; cmark_chunk input; + cmark_node *current; + + cmark_strbuf_clear(parser->curline); if (parser->options & CMARK_OPT_VALIDATE_UTF8) cmark_utf8proc_check(parser->curline, buffer, bytes); @@ -1248,9 +1263,13 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer, if (parser->blank && container->last_line_blank) break_out_of_lists(parser, &container); + current = parser->current; + open_new_blocks(parser, &container, &input, all_matched); - add_text_to_container(parser, container, last_matched_container, &input); + /* parser->current might have changed if feed_reentrant was called */ + if (current == parser->current) + add_text_to_container(parser, container, last_matched_container, &input); finished: parser->last_line_length = input.len; diff --git a/src/cmark_extension_api.h b/src/cmark_extension_api.h index 941d82e78..b12477f1b 100644 --- a/src/cmark_extension_api.h +++ b/src/cmark_extension_api.h @@ -414,6 +414,10 @@ void cmark_parser_advance_offset(cmark_parser *parser, int count, int columns); + +CMARK_EXPORT +void cmark_parser_feed_reentrant(cmark_parser *parser, const char *buffer, size_t len); + /** Attach the syntax 'extension' to the 'parser', to provide extra syntax * rules. * See the documentation for cmark_syntax_extension for more information.