summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xCMakeLists.txt2
-rw-r--r--api_test/main.c15
-rw-r--r--changelog.txt10
-rw-r--r--man/man3/cmark.32
-rw-r--r--src/blocks.c12
-rw-r--r--src/cmark.h2
-rw-r--r--src/main.c2
-rw-r--r--src/parser.h1
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)) {
diff --git a/src/main.c b/src/main.c
index a78c76a..fa18e03 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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