diff options
-rwxr-xr-x | CMakeLists.txt | 2 | ||||
-rw-r--r-- | api_test/main.c | 15 | ||||
-rw-r--r-- | changelog.txt | 10 | ||||
-rw-r--r-- | man/man3/cmark.3 | 2 | ||||
-rw-r--r-- | src/blocks.c | 12 | ||||
-rw-r--r-- | src/cmark.h | 2 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/parser.h | 1 |
8 files changed, 41 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d3f6232..2ab6a72 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set(PROJECT_NAME "cmark") set(PROJECT_VERSION_MAJOR 0) set(PROJECT_VERSION_MINOR 25) -set(PROJECT_VERSION_PATCH 1) +set(PROJECT_VERSION_PATCH 2) set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} ) option(CMARK_TESTS "Build cmark tests and enable testing" ON) diff --git a/api_test/main.c b/api_test/main.c index cd9ffb5..8af2e71 100644 --- a/api_test/main.c +++ b/api_test/main.c @@ -362,6 +362,9 @@ static void create_tree(test_batch_runner *runner) { cmark_node *str4 = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(str4, "brzz"); OK(runner, cmark_node_replace(str1, str4), "replace"); + // The replaced node is not freed + cmark_node_free(str1); + INT_EQ(runner, cmark_node_check(doc, NULL), 0, "replace consistent"); OK(runner, cmark_node_previous(emph) == str4, "replace works"); INT_EQ(runner, cmark_node_replace(p, str4), 0, "replace str for p fails"); @@ -852,6 +855,17 @@ static void test_md_to_html(test_batch_runner *runner, const char *markdown, free(html); } +static void test_feed_across_line_ending(test_batch_runner *runner) { + // See #117 + cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); + cmark_parser_feed(parser, "line1\r", 6); + cmark_parser_feed(parser, "\nline2\r\n", 8); + cmark_node *document = cmark_parser_finish(parser); + OK(runner, document->first_child->next == NULL, "document has one paragraph"); + cmark_parser_free(parser); + cmark_node_free(document); +} + int main() { int retval; test_batch_runner *runner = test_batch_runner_new(); @@ -876,6 +890,7 @@ int main() { numeric_entities(runner); test_cplusplus(runner); test_safe(runner); + test_feed_across_line_ending(runner); test_print_summary(runner); retval = test_ok(runner) ? 0 : 1; diff --git a/changelog.txt b/changelog.txt index 98645a9..77341b5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,13 @@ +[0.25.2] + + * Open files in binary mode (#113, Nick Wellnhofer). Now that cmark + supports different line endings, files must be openend in binary mode + on Windows. + * Reset `partially_consumed_tab` on every new line (#114, Nick Wellnhofer). + * Handle buffer split across a CRLF line ending (#117). Adds an internal + field to the parser struct to keep track of `last_buffer_ended_with_cr`. + Added test. + [0.25.1] * Release with no code changes. cmark version was mistakenly set to diff --git a/man/man3/cmark.3 b/man/man3/cmark.3 index 523a3d4..283b9cc 100644 --- a/man/man3/cmark.3 +++ b/man/man3/cmark.3 @@ -543,7 +543,7 @@ Streaming interface: .nf \f[C] cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); -FILE *fp = fopen("myfile.md", "r"); +FILE *fp = fopen("myfile.md", "rb"); while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { cmark_parser_feed(parser, buffer, bytes); if (bytes < sizeof(buffer)) { diff --git a/src/blocks.c b/src/blocks.c index 00639cf..f49ad4e 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -90,6 +90,7 @@ cmark_parser *cmark_parser_new(int options) { parser->last_line_length = 0; parser->linebuf = buf; parser->options = options; + parser->last_buffer_ended_with_cr = false; return parser; } @@ -506,6 +507,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer, const unsigned char *end = buffer + len; static const uint8_t repl[] = {239, 191, 189}; + if (parser->last_buffer_ended_with_cr && *buffer == '\n') { + // skip NL if last buffer ended with CR ; see #117 + buffer++; + } + parser->last_buffer_ended_with_cr = false; while (buffer < end) { const unsigned char *eol; bufsize_t chunk_len; @@ -546,8 +552,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer, buffer += chunk_len; // skip over line ending characters: - if (buffer < end && *buffer == '\r') + if (buffer < end && *buffer == '\r') { buffer++; + if (buffer == end) + parser->last_buffer_ended_with_cr = true; + } if (buffer < end && *buffer == '\n') buffer++; } @@ -1124,6 +1133,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer, parser->offset = 0; parser->column = 0; parser->blank = false; + parser->partially_consumed_tab = false; input.data = parser->curline->ptr; input.len = parser->curline->size; diff --git a/src/cmark.h b/src/cmark.h index 31bbf01..3c5d6b6 100644 --- a/src/cmark.h +++ b/src/cmark.h @@ -418,7 +418,7 @@ CMARK_EXPORT void cmark_consolidate_text_nodes(cmark_node *root); * Streaming interface: * * cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); - * FILE *fp = fopen("myfile.md", "r"); + * FILE *fp = fopen("myfile.md", "rb"); * while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { * cmark_parser_feed(parser, buffer, bytes); * if (bytes < sizeof(buffer)) { @@ -146,7 +146,7 @@ int main(int argc, char *argv[]) { parser = cmark_parser_new(options); for (i = 0; i < numfps; i++) { - FILE *fp = fopen(argv[files[i]], "r"); + FILE *fp = fopen(argv[files[i]], "rb"); if (fp == NULL) { fprintf(stderr, "Error opening file %s: %s\n", argv[files[i]], strerror(errno)); diff --git a/src/parser.h b/src/parser.h index b3ff39b..ab21d0f 100644 --- a/src/parser.h +++ b/src/parser.h @@ -27,6 +27,7 @@ struct cmark_parser { bufsize_t last_line_length; cmark_strbuf *linebuf; int options; + bool last_buffer_ended_with_cr; }; #ifdef __cplusplus |