From bc51e0ad2f18a45e45da9c3ac8521ad8d9c86de1 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Tue, 9 Jun 2020 21:40:46 +0100 Subject: [PATCH] src/config/rcxml.c: parse xml from buffer Avoid unit tests writing to/from files by using xmlParseMemory() instead of xmlReadFile(). --- data/rc.xml | 3 +-- include/buf.h | 23 ++++++++++++++++++++++ include/rcxml.h | 3 +++ src/common/buf.c | 23 ++++++++++++++++++++++ src/common/meson.build | 3 +++ src/config/rcxml.c | 33 +++++++++++++++++++++++++++----- src/meson.build | 1 + tests/meson.build | 2 +- tests/t1000-rcxml-simple-parse.c | 2 ++ tools/rcxml/Makefile | 2 +- 10 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 include/buf.h create mode 100644 src/common/buf.c create mode 100644 src/common/meson.build diff --git a/data/rc.xml b/data/rc.xml index 49975ca2..da9244bf 100644 --- a/data/rc.xml +++ b/data/rc.xml @@ -1,8 +1,7 @@ - + diff --git a/include/buf.h b/include/buf.h new file mode 100644 index 00000000..c7184888 --- /dev/null +++ b/include/buf.h @@ -0,0 +1,23 @@ +/* + * Very simple C buffer implementation + * + * Copyright Johan Malm 2020 + */ + +#ifndef BUF_H +#define BUF_H + +#include +#include +#include + +struct buf { + char *buf; + int alloc; + int len; +}; + +void buf_init(struct buf *s); +void buf_add(struct buf *s, const char *data); + +#endif /* BUF_H */ diff --git a/include/rcxml.h b/include/rcxml.h index 4e0c643e..5370a796 100644 --- a/include/rcxml.h +++ b/include/rcxml.h @@ -4,6 +4,8 @@ #include #include +#include "buf.h" + struct rcxml { bool client_side_decorations; }; @@ -11,6 +13,7 @@ struct rcxml { extern struct rcxml rc; void rcxml_init(struct rcxml *rc); +void rcxml_parse_xml(struct buf *b); void rcxml_read(const char *filename); void rcxml_set_verbose(void); diff --git a/src/common/buf.c b/src/common/buf.c new file mode 100644 index 00000000..87c0d30f --- /dev/null +++ b/src/common/buf.c @@ -0,0 +1,23 @@ +#include "buf.h" + +void buf_init(struct buf *s) +{ + s->alloc = 256; + s->buf = malloc(s->alloc); + s->buf[0] = '\0'; + s->len = 0; +} + +void buf_add(struct buf *s, const char *data) +{ + if (!data || data[0] == '\0') + return; + int len = strlen(data); + if (s->alloc <= s->len + len + 1) { + s->alloc = s->alloc + len; + s->buf = realloc(s->buf, s->alloc); + } + memcpy(s->buf + s->len, data, len); + s->len += len; + s->buf[s->len] = 0; +} diff --git a/src/common/meson.build b/src/common/meson.build new file mode 100644 index 00000000..d14bba6c --- /dev/null +++ b/src/common/meson.build @@ -0,0 +1,3 @@ +labwc_sources += files( + 'buf.c', +) diff --git a/src/config/rcxml.c b/src/config/rcxml.c index fc7b677e..7caab18c 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 200112L +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -143,11 +143,12 @@ static void xml_tree_walk(xmlNode *node) } } -static void parse_xml(const char *filename) +/* Exposed in header file to allow unit tests to parse buffers */ +void rcxml_parse_xml(struct buf *b) { - xmlDoc *d = xmlReadFile(filename, NULL, 0); + xmlDoc *d = xmlParseMemory(b->buf, b->len); if (!d) { - fprintf(stderr, "fatal: error reading file '%s'\n", filename); + fprintf(stderr, "fatal: xmlParseMemory()\n"); exit(EXIT_FAILURE); } xml_tree_walk(xmlDocGetRootElement(d)); @@ -162,7 +163,29 @@ void rcxml_init(struct rcxml *rc) void rcxml_read(const char *filename) { - parse_xml(filename); + FILE *stream; + char *line = NULL; + size_t len = 0; + ssize_t n_read; + struct buf b; + + /* Read into buffer and then call rcxml_parse_xml() */ + stream = fopen(filename, "r"); + if (!stream) { + fprintf(stderr, "warn: cannot read '%s'\n", filename); + return; + } + buf_init(&b); + while ((n_read = getline(&line, &len, stream) != -1)) { + char *p = strrchr(line, '\n'); + if (p) + *p = '\0'; + buf_add(&b, line); + } + free(line); + fclose(stream); + rcxml_parse_xml(&b); + free(b.buf); } void rcxml_set_verbose(void) diff --git a/src/meson.build b/src/meson.build index 478f34ff..e76b4fb4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,5 +11,6 @@ labwc_sources = files( 'xwl.c', ) +subdir('common') subdir('config') subdir('debug') diff --git a/tests/meson.build b/tests/meson.build index aa0c5a36..3d438375 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,6 +1,6 @@ rcxml_lib = static_library( 'rcxml', - sources: ['../src/config/rcxml.c'], + sources: files('../src/config/rcxml.c', '../src/common/buf.c'), dependencies: xml2, include_directories: [labwc_inc], link_with: library('libxml-2.0'), diff --git a/tests/t1000-rcxml-simple-parse.c b/tests/t1000-rcxml-simple-parse.c index d3f98c0f..c57cb74c 100644 --- a/tests/t1000-rcxml-simple-parse.c +++ b/tests/t1000-rcxml-simple-parse.c @@ -33,4 +33,6 @@ int main(int argc, char **argv) diag("Simple parse rc.xml"); ok1(rc.client_side_decorations); + + return exit_status(); } diff --git a/tools/rcxml/Makefile b/tools/rcxml/Makefile index 40940aa2..d8a9da5f 100644 --- a/tools/rcxml/Makefile +++ b/tools/rcxml/Makefile @@ -11,7 +11,7 @@ PROGS = rcxml-print-nodenames all: $(PROGS) rcxml-print-nodenames: rcxml-print-nodenames.c - $(CC) $(CFLAGS) -o $@ $^ ../../src/config/rcxml.c $(LDFLAGS) + $(CC) $(CFLAGS) -o $@ $^ ../../src/config/rcxml.c ../../src/common/buf.c $(LDFLAGS) clean: rm -f $(PROGS) -- 2.52.0