From 91b872bc6ae83c6b46c441455e46781a3cab6fca Mon Sep 17 00:00:00 2001 From: Patrick McCarty Date: Wed, 14 Jun 2017 16:37:48 -0700 Subject: [PATCH 1/3] Add new nc_string_append_printf function As a slight modification to nc_string_cat(), add a new function to permit appending of formatted strings. Signed-off-by: Patrick McCarty --- src/include/nica/nc-string.h | 4 ++++ src/nc-string.c | 28 ++++++++++++++++++++++++++++ tests/check-core.c | 8 ++++++++ 3 files changed, 40 insertions(+) diff --git a/src/include/nica/nc-string.h b/src/include/nica/nc-string.h index a79e925..1ff3669 100644 --- a/src/include/nica/nc-string.h +++ b/src/include/nica/nc-string.h @@ -38,6 +38,10 @@ typedef struct nc_string_t { _nica_public_ nc_string *nc_string_dup_printf(const char *format, ...) __attribute__((format(printf, 1, 2))); + +_nica_public_ nc_string *nc_string_append_printf(nc_string *st, const char *ptn, ...) + __attribute__((format(printf, 2, 3))); + /** * Duplicate a string into a new NUL-terminated nc_string * diff --git a/src/nc-string.c b/src/nc-string.c index 3596255..f3975a4 100644 --- a/src/nc-string.c +++ b/src/nc-string.c @@ -61,6 +61,34 @@ nc_string *nc_string_dup_printf(const char *ptn, ...) return st; } +nc_string *nc_string_append_printf(nc_string *st, const char *ptn, ...) +{ + char *newstr; + char *newstr2; + int ret; + + if (!ptn) { + return NULL; + } + + va_list va; + va_start(va, ptn); + + ret = vasprintf(&newstr, ptn, va); + if (ret <= 0) { + newstr = strdup(""); + } + + st->len = asprintf(&newstr2, "%s%s", st->str, newstr); + free(st->str); + st->str = newstr2; + free(newstr); + va_end(va); + + return st; +} + + bool nc_string_cat(nc_string *s, const char *append) { char *p = NULL; diff --git a/tests/check-core.c b/tests/check-core.c index 41bc595..9db6256 100644 --- a/tests/check-core.c +++ b/tests/check-core.c @@ -103,6 +103,14 @@ START_TEST(nc_string_test) nc_string st = { .len = 0 }; fail_if(nc_string_equal(&st, &st), "equal on NULL ->str"); fail_if(nc_string_const_equal(&st, "TEST"), "const_equal on NULL ->str"); + + str = nc_string_dup_printf("Test String #%d", 3); + fail_if(!str, "Failed to allocate string"); + fail_if(ncstrlen(str) != 14, "Incorrect string length"); + fail_if(!nc_string_append_printf(str, "append"), "Failed to append formatted string"); + fail_if(ncstrlen(str) != 20, "Incorrect string length after formatted append"); + + nc_string_free(str); } END_TEST From d1bd0a947a58095d6a48c6a708058e73a3f0a49e Mon Sep 17 00:00:00 2001 From: Patrick McCarty Date: Wed, 14 Jun 2017 16:39:01 -0700 Subject: [PATCH 2/3] Add new nc_string_prepend function A prepend string function was missing, and I needed it for use in another project. Signed-off-by: Patrick McCarty --- src/include/nica/nc-string.h | 3 +++ src/nc-string.c | 21 +++++++++++++++++++++ tests/check-core.c | 3 +++ 3 files changed, 27 insertions(+) diff --git a/src/include/nica/nc-string.h b/src/include/nica/nc-string.h index 1ff3669..dc27ec4 100644 --- a/src/include/nica/nc-string.h +++ b/src/include/nica/nc-string.h @@ -76,6 +76,9 @@ static inline void nc_string_free(nc_string *str) */ _nica_public_ bool nc_string_cat(nc_string *str, const char *append); +_nica_public_ bool nc_string_prepend(nc_string *s, const char *prepend); + + /** * Determine if string A is equal to string B * diff --git a/src/nc-string.c b/src/nc-string.c index f3975a4..a1259a2 100644 --- a/src/nc-string.c +++ b/src/nc-string.c @@ -110,6 +110,27 @@ bool nc_string_cat(nc_string *s, const char *append) return true; } +bool nc_string_prepend(nc_string *s, const char *prepend) +{ + char *p = NULL; + int len = 0; + + if (!s || !prepend) { + return false; + } + if (!s->str) { + return false; + } + len = asprintf(&p, "%s%s", prepend, s->str); + if (!p || len < s->len) { + return false; + } + free(s->str); + s->str = p; + s->len = len; + return true; +} + /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * diff --git a/tests/check-core.c b/tests/check-core.c index 9db6256..6466028 100644 --- a/tests/check-core.c +++ b/tests/check-core.c @@ -110,6 +110,9 @@ START_TEST(nc_string_test) fail_if(!nc_string_append_printf(str, "append"), "Failed to append formatted string"); fail_if(ncstrlen(str) != 20, "Incorrect string length after formatted append"); + fail_if(!nc_string_prepend(str, "prepend"), "Failed to prepend string"); + fail_if(ncstrlen(str) != 27, "Incorrect string length after prepend"); + nc_string_free(str); } END_TEST From 9eda5b99feb23798f146b92f43885b9de0b2251f Mon Sep 17 00:00:00 2001 From: Patrick McCarty Date: Wed, 14 Jun 2017 16:39:53 -0700 Subject: [PATCH 3/3] Escape the \s sequence in INI files For telemetrics-client, we expected INI files to support "\s", indicating a whitespace character. Support it here by sending the values through an unescape function, which only supports the \s escape at the moment. Signed-off-by: Patrick McCarty --- src/inifile.c | 35 +++++++++++++++++++++++++++++++++++ tests/check-inifile.c | 7 ++++++- tests/ini/escaped_chars.ini | 10 ++++++++++ tests/ini/valid_padding.ini | 3 +++ tests/ini/wellformed.ini | 3 +++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/ini/escaped_chars.ini diff --git a/src/inifile.c b/src/inifile.c index 144e820..2d6cbd4 100644 --- a/src/inifile.c +++ b/src/inifile.c @@ -149,6 +149,40 @@ static char *string_strip(char *str, ssize_t len, ssize_t *out_len) return c; } +/* eat \s */ +static char *string_unescape(char *str) +{ + char *c, *c1, *c2, *c3;; + + if (!str) { + return NULL; + } + + c = calloc(strlen(str) + 1, 1); + c1 = c; + + c2 = str; + while (c2 && *c2 != 0) { + c3 = c2 + 1; + if (*c2 == '\\') { + if (*c3 == 's') { + *c = ' '; + c++; + c2 += 2; + } else { + c2++; + } + } else { + *c = *c2; + c++; + c2++; + } + } + + free(str); + return c1; +} + NcHashmap *nc_ini_file_parse(const char *path) { NcHashmap *ret = NULL; @@ -268,6 +302,7 @@ int nc_ini_file_parse_full(const char *path, NcHashmap **out_map, int *error_lin key = strdup(buf); key = string_chew_terminated(key); value = string_chew_terminated(value); + value = string_unescape(value); if (streq(key, "")) { err_ret = NC_INI_ERROR_EMPTY_KEY; diff --git a/tests/check-inifile.c b/tests/check-inifile.c index 5001f3a..de9feb5 100644 --- a/tests/check-inifile.c +++ b/tests/check-inifile.c @@ -31,7 +31,8 @@ END_TEST START_TEST(nc_inifile_good_test) { const char *wellformed[] = { TOP_DIR "/tests/ini/wellformed.ini", - TOP_DIR "/tests/ini/valid_padding.ini" }; + TOP_DIR "/tests/ini/valid_padding.ini", + TOP_DIR "/tests/ini/escaped_chars.ini" }; for (size_t i = 0; i < sizeof(wellformed) / sizeof(wellformed[0]); i++) { autofree(NcHashmap) *f = NULL; @@ -56,6 +57,10 @@ START_TEST(nc_inifile_good_test) ret = nc_hashmap_get(nc_hashmap_get(f, "Bob"), "Random"); fail_if(ret, "Got unexpected section"); + + ret = nc_hashmap_get(nc_hashmap_get(f, "Barry"), "slogan"); + fail_if(!ret, "Failed to get known value from INI file"); + fail_if(!streq(ret, "Hello World"), "Incorrect value in INI file #3"); } } END_TEST diff --git a/tests/ini/escaped_chars.ini b/tests/ini/escaped_chars.ini new file mode 100644 index 0000000..709f5c0 --- /dev/null +++ b/tests/ini/escaped_chars.ini @@ -0,0 +1,10 @@ +[John] +alive=true + +[Alice] +# Various comment types +; Sorry, Alice! +alive = false + +[Barry] +slogan=Hello\sWorld diff --git a/tests/ini/valid_padding.ini b/tests/ini/valid_padding.ini index 4ac24ca..f8f8f0a 100644 --- a/tests/ini/valid_padding.ini +++ b/tests/ini/valid_padding.ini @@ -8,3 +8,6 @@ # Various comment types ; Sorry, Alice! alive = false + +[Barry] +slogan=Hello World diff --git a/tests/ini/wellformed.ini b/tests/ini/wellformed.ini index 565e430..c20ce3e 100644 --- a/tests/ini/wellformed.ini +++ b/tests/ini/wellformed.ini @@ -5,3 +5,6 @@ alive=true # Various comment types ; Sorry, Alice! alive = false + +[Barry] +slogan=Hello World