diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 21 | ||||
-rw-r--r-- | src/blogc/filelist-parser.c | 69 | ||||
-rw-r--r-- | src/blogc/filelist-parser.h | 16 | ||||
-rw-r--r-- | tests/blogc/check_filelist_parser.c | 131 |
5 files changed, 238 insertions, 0 deletions
@@ -57,6 +57,7 @@ blogc*.html /tests/blogc/check_blogc.sh /tests/blogc/check_content_parser /tests/blogc/check_datetime_parser +/tests/blogc/check_filelist_parser /tests/blogc/check_funcvars /tests/blogc/check_loader /tests/blogc/check_renderer diff --git a/Makefile.am b/Makefile.am index 040f291..3f00119 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,6 +40,7 @@ noinst_HEADERS = \ src/blogc/content-parser.h \ src/blogc/datetime-parser.h \ src/blogc/debug.h \ + src/blogc/filelist-parser.h \ src/blogc/funcvars.h \ src/blogc/loader.h \ src/blogc/renderer.h \ @@ -128,6 +129,7 @@ libblogc_la_SOURCES = \ src/blogc/content-parser.c \ src/blogc/datetime-parser.c \ src/blogc/debug.c \ + src/blogc/filelist-parser.c \ src/blogc/funcvars.c \ src/blogc/loader.c \ src/blogc/renderer.c \ @@ -468,6 +470,7 @@ if USE_CMOCKA check_PROGRAMS += \ tests/blogc/check_content_parser \ tests/blogc/check_datetime_parser \ + tests/blogc/check_filelist_parser \ tests/blogc/check_renderer \ tests/blogc/check_source_parser \ tests/blogc/check_template_parser \ @@ -660,6 +663,24 @@ tests_blogc_check_datetime_parser_LDADD = \ libblogc_common.la \ $(NULL) +tests_blogc_check_filelist_parser_SOURCES = \ + tests/blogc/check_filelist_parser.c \ + $(NULL) + +tests_blogc_check_filelist_parser_CFLAGS = \ + $(CMOCKA_CFLAGS) \ + $(NULL) + +tests_blogc_check_filelist_parser_LDFLAGS = \ + -no-install \ + $(NULL) + +tests_blogc_check_filelist_parser_LDADD = \ + $(CMOCKA_LIBS) \ + libblogc.la \ + libblogc_common.la \ + $(NULL) + tests_blogc_check_renderer_SOURCES = \ tests/blogc/check_renderer.c \ $(NULL) diff --git a/src/blogc/filelist-parser.c b/src/blogc/filelist-parser.c new file mode 100644 index 0000000..ac9c50a --- /dev/null +++ b/src/blogc/filelist-parser.c @@ -0,0 +1,69 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include "../common/utils.h" + + +typedef enum { + LINE_START = 1, + LINE, +} blogc_filelist_parser_state_t; + + +bc_slist_t* +blogc_filelist_parse(const char *src, size_t src_len) +{ + size_t current = 0; + size_t start = 0; + bc_slist_t *rv = NULL; + bc_string_t *line = bc_string_new(); + blogc_filelist_parser_state_t state = LINE_START; + + while (current < src_len) { + char c = src[current]; + bool is_last = current == src_len - 1; + + switch (state) { + + case LINE_START: + if (c == '#') { + while (current < src_len) { + if (src[current] == '\r' || src[current] == '\n') + break; + current++; + } + break; + } + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + break; + start = current; + state = LINE; + continue; + + case LINE: + if (c == '\r' || c == '\n' || is_last) { + if (is_last && c != '\r' && c != '\n') + bc_string_append_c(line, c); + rv = bc_slist_append(rv, bc_str_strip(line->str)); + bc_string_free(line, false); + line = bc_string_new(); + state = LINE_START; + break; + } + bc_string_append_c(line, c); + break; + + } + + current++; + } + + bc_string_free(line, true); + + return rv; +} diff --git a/src/blogc/filelist-parser.h b/src/blogc/filelist-parser.h new file mode 100644 index 0000000..5c65ee0 --- /dev/null +++ b/src/blogc/filelist-parser.h @@ -0,0 +1,16 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _FILELIST_PARSER_H +#define _FILELIST_PARSER_H + +#include "../common/utils.h" + +bc_slist_t* blogc_filelist_parse(const char *src, size_t src_len); + +#endif /* _FILELIST_PARSER_H */ diff --git a/tests/blogc/check_filelist_parser.c b/tests/blogc/check_filelist_parser.c new file mode 100644 index 0000000..0db50ec --- /dev/null +++ b/tests/blogc/check_filelist_parser.c @@ -0,0 +1,131 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <string.h> +#include <stdlib.h> +#include "../../src/common/utils.h" +#include "../../src/blogc/filelist-parser.h" + + +static void +test_filelist_parse_empty(void **state) +{ + bc_slist_t *l = blogc_filelist_parse("", 0); + assert_null(l); +} + + +static void +test_filelist_parse(void **state) +{ + const char *a = + "content/post/post1.txt"; + bc_slist_t *l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_null(l->next); + bc_slist_free_full(l, free); + a = + "content/post/post1.txt\n"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_null(l->next); + bc_slist_free_full(l, free); + a = + "content/post/post1.txt\n" + "content/post/post2.txt\n"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_string_equal(l->next->data, "content/post/post2.txt"); + assert_null(l->next->next); + bc_slist_free_full(l, free); + a = + "content/post/post1.txt\n" + "content/post/post2.txt\n" + "content/post/post3.txt"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_string_equal(l->next->data, "content/post/post2.txt"); + assert_string_equal(l->next->next->data, "content/post/post3.txt"); + assert_null(l->next->next->next); + bc_slist_free_full(l, free); + a = + " content/post/post1.txt\n" + "content/post/post2.txt\t\n" + "\tcontent/post/post3.txt"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_string_equal(l->next->data, "content/post/post2.txt"); + assert_string_equal(l->next->next->data, "content/post/post3.txt"); + assert_null(l->next->next->next); + bc_slist_free_full(l, free); +} + + +static void +test_filelist_parse_crlf(void **state) +{ + const char *a = + "content/post/post1.txt\r\n"; + bc_slist_t *l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_null(l->next); + bc_slist_free_full(l, free); + a = + "content/post/post1.txt\r\n" + "content/post/post2.txt\r\n"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_string_equal(l->next->data, "content/post/post2.txt"); + assert_null(l->next->next); + bc_slist_free_full(l, free); + a = + "content/post/post1.txt\r\n" + "content/post/post2.txt\r\n" + "content/post/post3.txt"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_string_equal(l->next->data, "content/post/post2.txt"); + assert_string_equal(l->next->next->data, "content/post/post3.txt"); + assert_null(l->next->next->next); + bc_slist_free_full(l, free); + a = + " content/post/post1.txt\r\n" + "content/post/post2.txt\t\r\n" + "\tcontent/post/post3.txt"; + l = blogc_filelist_parse(a, strlen(a)); + assert_non_null(l); + assert_string_equal(l->data, "content/post/post1.txt"); + assert_string_equal(l->next->data, "content/post/post2.txt"); + assert_string_equal(l->next->next->data, "content/post/post3.txt"); + assert_null(l->next->next->next); + bc_slist_free_full(l, free); +} + + +int +main(void) +{ + const UnitTest tests[] = { + unit_test(test_filelist_parse_empty), + unit_test(test_filelist_parse), + unit_test(test_filelist_parse_crlf), + }; + return run_tests(tests); +} |