aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/content-parser.c35
-rw-r--r--tests/check_content_parser.c231
2 files changed, 252 insertions, 14 deletions
diff --git a/src/content-parser.c b/src/content-parser.c
index 75c0f34..8249322 100644
--- a/src/content-parser.c
+++ b/src/content-parser.c
@@ -87,7 +87,7 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
switch (state) {
case CONTENT_START_LINE:
- if (c == '\n' || c == '\r')
+ if (c == '\n' || c == '\r' || is_last)
break;
if (c == '#') {
header_level = 1;
@@ -140,18 +140,15 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
case CONTENT_HEADER_TITLE_START:
if (c == ' ' || c == '\t')
break;
- if (c != '\n' || c != '\r') {
- start = current;
+ start = current;
+ if (c != '\n' && c != '\r') {
state = CONTENT_HEADER_TITLE;
break;
}
- *err = blogc_error_parser(BLOGC_ERROR_CONTENT_PARSER, src, src_len,
- current, "Empty header");
- break;
case CONTENT_HEADER_TITLE:
if (c == '\n' || c == '\r' || is_last) {
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
tmp = b_strndup(src + start, end - start);
b_string_append_printf(rv, "<h%d>%s</h%d>\n", header_level,
tmp, header_level);
@@ -159,14 +156,13 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
tmp = NULL;
state = CONTENT_START_LINE;
start = current;
- break;
}
break;
case CONTENT_HTML:
if (c == '\n' || c == '\r' || is_last) {
state = CONTENT_HTML_END;
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
}
if (!is_last)
break;
@@ -189,10 +185,11 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
break;
prefix = b_strndup(src + start, current - start);
state = CONTENT_BLOCKQUOTE_START;
+ break;
case CONTENT_BLOCKQUOTE_START:
if (c == '\n' || c == '\r' || is_last) {
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
tmp = b_strndup(src + start, end - start);
if (b_str_starts_with(tmp, prefix)) {
lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix)));
@@ -202,6 +199,10 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
*err = blogc_error_parser(BLOGC_ERROR_CONTENT_PARSER, src, src_len,
current, "Malformed blockquote, must use same prefix "
"as previous line(s): %s", prefix);
+ free(prefix);
+ prefix = NULL;
+ b_slist_free_full(lines, free);
+ lines = NULL;
}
free(tmp);
tmp = NULL;
@@ -245,10 +246,11 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
break;
prefix = b_strndup(src + start, current - start);
state = CONTENT_CODE_START;
+ break;
case CONTENT_CODE_START:
if (c == '\n' || c == '\r' || is_last) {
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
tmp = b_strndup(src + start, end - start);
if (b_str_starts_with(tmp, prefix)) {
lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix)));
@@ -258,6 +260,10 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
*err = blogc_error_parser(BLOGC_ERROR_CONTENT_PARSER, src, src_len,
current, "Malformed code block, must use same prefix "
"as previous line(s): '%s'", prefix);
+ free(prefix);
+ prefix = NULL;
+ b_slist_free_full(lines, free);
+ lines = NULL;
}
free(tmp);
tmp = NULL;
@@ -316,7 +322,7 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
case CONTENT_UNORDERED_LIST_START:
if (c == '\n' || c == '\r' || is_last) {
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
tmp = b_strndup(src + start, end - start);
if (b_str_starts_with(tmp, prefix)) {
lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix)));
@@ -367,10 +373,11 @@ blogc_content_parse(const char *src, size_t src_len, blogc_error_t **err)
break;
prefix_len = current - start;
state = CONTENT_ORDERED_LIST_START;
+ break;
case CONTENT_ORDERED_LIST_START:
if (c == '\n' || c == '\r' || is_last) {
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
tmp = b_strndup(src + start, end - start);
if (strlen(tmp) >= prefix_len) {
tmp2 = b_strndup(tmp, prefix_len);
@@ -436,7 +443,7 @@ err_li:
case CONTENT_PARAGRAPH:
if (c == '\n' || c == '\r' || is_last) {
state = CONTENT_PARAGRAPH_END;
- end = is_last ? src_len : current;
+ end = is_last && c != '\n' && c != '\r' ? src_len : current;
}
if (!is_last)
break;
diff --git a/tests/check_content_parser.c b/tests/check_content_parser.c
index df14df3..b3e7092 100644
--- a/tests/check_content_parser.c
+++ b/tests/check_content_parser.c
@@ -96,11 +96,242 @@ test_content_parse(void **state)
}
+void
+test_content_parse_header(void **state)
+{
+ const char *a = "## bola";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html, "<h2>bola</h2>\n");
+ free(html);
+ a = "## bola\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html, "<h2>bola</h2>\n");
+ free(html);
+ a =
+ "bola\n"
+ "\n"
+ "## bola\n"
+ "\n"
+ "guda\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<p>bola</p>\n"
+ "<h2>bola</h2>\n"
+ "<p>guda</p>\n");
+ free(html);
+}
+
+
+void
+test_content_parse_html(void **state)
+{
+ const char *a = "<div>\n</div>";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html, "<div>\n</div>\n");
+ free(html);
+ a = "<div>\n</div>\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html, "<div>\n</div>\n");
+ free(html);
+ a =
+ "bola\n"
+ "\n"
+ "<div>\n"
+ "</div>\n"
+ "\n"
+ "chunda\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<p>bola</p>\n"
+ "<div>\n</div>\n"
+ "<p>chunda</p>\n");
+ free(html);
+}
+
+
+void
+test_content_parse_blockquote(void **state)
+{
+ const char *a = "> bola\n> guda";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<blockquote><p>bola\n"
+ "guda</p>\n"
+ "</blockquote>\n");
+ free(html);
+ a = "> bola\n> guda\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<blockquote><p>bola\n"
+ "guda</p>\n"
+ "</blockquote>\n");
+ free(html);
+ a =
+ "bola\n"
+ "\n"
+ "> bola\n"
+ "> guda\n"
+ "\n"
+ "chunda\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<p>bola</p>\n"
+ "<blockquote><p>bola\n"
+ "guda</p>\n"
+ "</blockquote>\n"
+ "<p>chunda</p>\n");
+ free(html);
+}
+
+
+void
+test_content_parse_code(void **state)
+{
+ const char *a = " bola\n guda";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<pre><code>bola\n"
+ "guda</code></pre>\n");
+ free(html);
+ a = " bola\n guda\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<pre><code>bola\n"
+ "guda</code></pre>\n");
+ free(html);
+ a =
+ "bola\n"
+ "\n"
+ " bola\n"
+ " guda\n"
+ "\n"
+ "chunda\n";
+ html = blogc_content_parse(a, strlen(a), &err);
+ assert_null(err);
+ assert_non_null(html);
+ assert_string_equal(html,
+ "<p>bola</p>\n"
+ "<pre><code>bola\n"
+ "guda</code></pre>\n"
+ "<p>chunda</p>\n");
+ free(html);
+}
+
+
+void
+test_content_parse_invalid_header(void **state)
+{
+ const char *a =
+ "asd\n"
+ "\n"
+ "##bola\n";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_non_null(err);
+ assert_null(html);
+ assert_int_equal(err->type, BLOGC_ERROR_CONTENT_PARSER);
+ assert_string_equal(err->msg,
+ "Malformed header, no space or tab after '#'\n"
+ "Error occurred near to 'bola'");
+ blogc_error_free(err);
+}
+
+
+void
+test_content_parse_invalid_header_empty(void **state)
+{
+ const char *a =
+ "asd\n"
+ "\n"
+ "##\n"
+ "\n"
+ "qwe\n";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_non_null(err);
+ assert_null(html);
+ assert_int_equal(err->type, BLOGC_ERROR_CONTENT_PARSER);
+ assert_string_equal(err->msg,
+ "Malformed header, no space or tab after '#'");
+ blogc_error_free(err);
+}
+
+
+void
+test_content_parse_invalid_blockquote(void **state)
+{
+ const char *a =
+ "> asd\n"
+ "> bola\n"
+ "> foo\n";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_non_null(err);
+ assert_null(html);
+ assert_int_equal(err->type, BLOGC_ERROR_CONTENT_PARSER);
+ assert_string_equal(err->msg,
+ "Malformed blockquote, must use same prefix as previous line(s): > ");
+ blogc_error_free(err);
+}
+
+
+void
+test_content_parse_invalid_code(void **state)
+{
+ const char *a =
+ " asd\n"
+ " bola\n"
+ " foo\n";
+ blogc_error_t *err = NULL;
+ char *html = blogc_content_parse(a, strlen(a), &err);
+ assert_non_null(err);
+ assert_null(html);
+ assert_int_equal(err->type, BLOGC_ERROR_CONTENT_PARSER);
+ assert_string_equal(err->msg,
+ "Malformed code block, must use same prefix as previous line(s): ' '");
+ blogc_error_free(err);
+}
+
+
int
main(void)
{
const UnitTest tests[] = {
unit_test(test_content_parse),
+ unit_test(test_content_parse_header),
+ unit_test(test_content_parse_html),
+ unit_test(test_content_parse_blockquote),
+ unit_test(test_content_parse_code),
+ unit_test(test_content_parse_invalid_header),
+ unit_test(test_content_parse_invalid_header_empty),
+ unit_test(test_content_parse_invalid_blockquote),
+ unit_test(test_content_parse_invalid_code),
};
return run_tests(tests);
}