diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2022-08-14 18:03:18 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2022-08-14 18:14:21 +0200 |
commit | f545be725df9195a5b5897ad95a0220acf10f148 (patch) | |
tree | b30aab92bcf23e94ca2c74fca0c6f5573d5745c2 | |
parent | 7e8e085c97311b52db4d6739b6ef2a1b26a2319f (diff) | |
download | liberty-f545be725df9195a5b5897ad95a0220acf10f148.tar.gz liberty-f545be725df9195a5b5897ad95a0220acf10f148.tar.xz liberty-f545be725df9195a5b5897ad95a0220acf10f148.zip |
Extend string syntax in config
And actually test the results of string parsing.
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | liberty.c | 52 | ||||
-rw-r--r-- | tests/liberty.c | 7 |
3 files changed, 52 insertions, 9 deletions
@@ -1,4 +1,4 @@ -Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name> +Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. @@ -1,7 +1,7 @@ /* * liberty.c: the ultimate C unlibrary * - * Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name> + * Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted. @@ -4412,7 +4412,9 @@ socket_io_try_write (int socket_fd, struct str *wb) // object = lws '{' entries endobj // endobj = lws '}' // -// string = lws '"' ('\\' escape / ![\\"] char)* '"' +// quoted = lws '"' ('\\' escape / ![\\"] char)* '"' +// / lws '`' ![`]* '`' +// string = (quoted)+ // char = [\0-\177] # or any Unicode codepoint in the UTF-8 encoding // escape = [\\"abfnrtv] / [xX][0-9A-Fa-f][0-9A-Fa-f]? / [0-7][0-7]?[0-7]? // @@ -5039,10 +5041,10 @@ config_tokenizer_escape_sequence } static bool -config_tokenizer_string - (struct config_tokenizer *self, struct str *output, struct error **e) +config_tokenizer_dq_string (struct config_tokenizer *self, struct str *output, + struct error **e) { - unsigned char c; + unsigned char c = config_tokenizer_advance (self); while (self->len) { if ((c = config_tokenizer_advance (self)) == '"') @@ -5056,6 +5058,44 @@ config_tokenizer_string return false; } +static bool +config_tokenizer_bt_string (struct config_tokenizer *self, struct str *output, + struct error **e) +{ + unsigned char c = config_tokenizer_advance (self); + while (self->len) + { + if ((c = config_tokenizer_advance (self)) == '`') + return true; + str_append_c (output, c); + } + config_tokenizer_error (self, e, "premature end of string"); + return false; +} + +static bool +config_tokenizer_string (struct config_tokenizer *self, struct str *output, + struct error **e) +{ + // Go-like strings, with C/AWK-like automatic concatenation + while (self->len) + { + bool ok = true; + if (isspace_ascii (*self->p) && *self->p != '\n') + config_tokenizer_advance (self); + else if (*self->p == '"') + ok = config_tokenizer_dq_string (self, output, e); + else if (*self->p == '`') + ok = config_tokenizer_bt_string (self, output, e); + else + break; + + if (!ok) + return false; + } + return true; +} + static enum config_token config_tokenizer_next (struct config_tokenizer *self, struct error **e) { @@ -5080,7 +5120,7 @@ config_tokenizer_next (struct config_tokenizer *self, struct error **e) return CONFIG_T_ABORT; case '"': - config_tokenizer_advance (self); + case '`': str_reset (&self->string); if (!config_tokenizer_string (self, &self->string, e)) return CONFIG_T_ABORT; diff --git a/tests/liberty.c b/tests/liberty.c index dc445d8..3d932d5 100644 --- a/tests/liberty.c +++ b/tests/liberty.c @@ -1,7 +1,7 @@ /* * tests/liberty.c * - * Copyright (c) 2015 - 2016, Přemysl Eric Janouch <p@janouch.name> + * Copyright (c) 2015 - 2022, Přemysl Eric Janouch <p@janouch.name> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted. @@ -649,7 +649,7 @@ static struct config_schema g_config_test[] = .default_ = "1" }, { .name = "foobar", .type = CONFIG_ITEM_STRING, - .default_ = "\"qux\\x01\"" }, + .default_ = "\"qux\\x01`\" \"\"`a`" }, {} }; @@ -675,6 +675,9 @@ test_config (void) "top.bar", NULL), invalid, NULL)); config_item_destroy (invalid); + hard_assert (!strcmp ("qux\001`a", + config_item_get (config.root, "top.foobar", NULL)->value.string.str)); + struct str s = str_make (); config_item_write (config.root, true, &s); struct config_item *parsed = config_item_parse (s.str, s.len, false, NULL); |