aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am21
-rw-r--r--src/blogc/filelist-parser.c69
-rw-r--r--src/blogc/filelist-parser.h16
-rw-r--r--tests/blogc/check_filelist_parser.c131
5 files changed, 238 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e97005c..5336760 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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);
+}