From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org,
Alexander Turenko <alexander.turenko@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH v2 2/3] lua-yaml: fix boolean/null representation in yaml
Date: Fri, 25 Jan 2019 00:26:56 +0300 [thread overview]
Message-ID: <3da6fc29-991d-e475-0777-49eacb764b94@tarantool.org> (raw)
In-Reply-To: <15b711cb55d34fff1f010fd6df1aa32248f65735.1548123025.git.alexander.turenko@tarantool.org>
Thanks for the patch!
On 22/01/2019 05:12, Alexander Turenko wrote:
> Encode changes:
>
> Wrap the following string literals into single quotes: 'false', 'no',
> 'true', 'yes', '~', 'null', 'Null', 'NULL'. The content of these strings
> is equals to null or boolean values representation in YAML.
>
> Reverted the a2d7643c commit to use single quotes instead of multiline
> encoding for 'true' and 'false' string literals.
>
> '~', 'null', 'Null', 'NULL', 'no' and 'yes' were encoded w/o quotes
> before, so '~', 'null', 'no', 'yes' were decoded with a wrong type then.
> Multiline encoding was used for 'true' and 'false'.
Unfortunately, I hardly understood what happened in this commit
by reading this message, sorry. Maybe I am confused by imperative
in the message body, or by too frequent repetition of this infinite
sequence of strings: "'~', 'null', 'Null', 'NULL', 'no' and 'yes'",
or by too mixed style of narration of what is the true and standard
way of these values encoding - with quotes or without.
Could you, please, make it simpler somehow?
>
> Decode changes:
>
> Treat 'Null', 'NULL' as null in addition to '~' and 'null'.
>
> Note: this commit leaves an empty document/value treatment as an empty
> string, which is not standard (should be treated as null). This is fixed
> in the following commit.
>
> Follows up #3476
> Closes #3662
> Closes #3583
> ---
> test/app-tap/console.test.lua | 23 +++++++---
> test/box/misc.result | 2 +-
> third_party/lua-yaml/lyaml.cc | 80 ++++++++++++++++++++++++++---------
> 3 files changed, 80 insertions(+), 25 deletions(-)
>
> diff --git a/test/app-tap/console.test.lua b/test/app-tap/console.test.lua
> index 4f915afd7..68f273234 100755
> --- a/test/app-tap/console.test.lua
> +++ b/test/app-tap/console.test.lua
> @@ -77,11 +77,24 @@ test:is(yaml.decode(client:read(EOL)), '', "clear delimiter")
>
> --
> -- gh-3476: yaml.encode encodes 'false' and 'true' incorrectly.
> +-- gh-3662: yaml.encode encodes booleans with multiline format.
> +-- gh-3583: yaml.encode encodes null incorrectly.
> --
> -test:is(type(yaml.decode(yaml.encode('false'))), 'string')
> -test:is(type(yaml.decode(yaml.encode('true'))), 'string')
> -test:is(type(yaml.decode(yaml.encode({a = 'false'})).a), 'string')
> -test:is(type(yaml.decode(yaml.encode({a = 'false'})).a), 'string')
1. Are you sure that this is the correct behaviour? So now it is
not true that decode(encode(obj)) == obj? Looks utterly confusing.
Or why else you removed these tests?
> +
> +test:is(yaml.encode(false), "--- false\n...\n")
> +test:is(yaml.encode(true), "--- true\n...\n")
> +test:is(yaml.encode('false'), "--- 'false'\n...\n")
> +test:is(yaml.encode('true'), "--- 'true'\n...\n")
> +test:is(yaml.encode(nil), "--- null\n...\n")
> +
> +test:is(yaml.decode('false'), false)
> +test:is(yaml.decode('no'), false)
> +test:is(yaml.decode('true'), true)
> +test:is(yaml.decode('yes'), true)
> +test:is(yaml.decode('~'), nil)
> +test:is(yaml.decode('null'), nil)
> +test:is(yaml.decode('Null'), nil)
> +test:is(yaml.decode('NULL'), nil)
>
> box.cfg{
> listen=IPROTO_SOCKET;
> diff --git a/third_party/lua-yaml/lyaml.cc b/third_party/lua-yaml/lyaml.cc
> index 9b07992d8..73e5d2c31 100644
> --- a/third_party/lua-yaml/lyaml.cc
> +++ b/third_party/lua-yaml/lyaml.cc
> @@ -94,6 +94,46 @@ struct lua_yaml_dumper {
> luaL_Buffer yamlbuf;
> };
>
> +enum yaml_type {
> + YAML_NO_MATCH = 0,
> + YAML_FALSE,
> + YAML_TRUE,
> + YAML_NULL
> +};
> +
> +/**
> + * Verify whether a string represents a boolean literal in YAML.
> + *
> + * Non-standard: only subset of YAML 1.1 boolean literals are
> + * treated as boolean values.
> + */
> +static yaml_type
> +yaml_get_bool(const char *str, const size_t len)
2. Usually in such cases we use int 0/-1 returned value
and return the result via an out-parameter. So it should be
static inline int
yaml_parse_bool(const char *str, size_t len, bool *value);
Yes, I've changed 'get' to 'parse' and inlined the function,
if you do not mind.
The same for the next function, parsing null. After that you
can remove enum yaml_type.
Which, btw, is not a type, strictly speaking, because it
does not have YAML_INT, YAML_DOUBLE ...
Also, I do not see any point in making 'len' be 'const'.
Scarcely it is a case when you need a parameter, passed by
value instead of pointer, be explicitly const. The compiler
can detect it easily.
> +{
> + if (len > 5)
> + return YAML_NO_MATCH;
> + if (strcmp(str, "false") == 0 || strcmp(str, "no") == 0)
> + return YAML_FALSE;
> + if (strcmp(str, "true") == 0 || strcmp(str, "yes") == 0)
3. I think, it is redundant to firstly check length and then
call strcmp, which also calculates length (by checking zero
byte). We need either use only strcmp(), or use length comparison
+ memcmp. The same below for the null parser.
> + return YAML_TRUE;
> + return YAML_NO_MATCH;
> +}
> +
> +/**
> + * Verify whether a string represents a null literal in YAML.
> + *
> + * Non-standard: don't match an empty string as null.
> + */
> +static yaml_type
> +yaml_get_null(const char *str, const size_t len){
4. ?
static inline int
yaml_parse_null(const char *str, size_t len, bool *is_null);
> + if (len == 1 && str[0] == '~')
> + return YAML_NULL;
> + if (len == 4 && (strcmp(str, "null") == 0 || strcmp(str, "Null") == 0 ||
5. Hmm. Length of "null" and "Null" is 3, not 4. As I understand,
len does not count terminating zero. And I can prove it - load_scalar()
in case if !strcmp(tag, "str") does lua_pushlstring(loader->L, str, length),
so length == strlen(str).
Even if I am mistaken about it, why two lines above you consider len
of "~" as 1, not 2?
> + strcmp(str, "NULL") == 0))
> + return YAML_NULL;
> + return YAML_NO_MATCH;
> +}
> +
> static void generate_error_message(struct lua_yaml_loader *loader) {
> char buf[256];
> luaL_Buffer b;
> @@ -597,8 +636,13 @@ static int dump_node(struct lua_yaml_dumper *dumper)
> return dump_table(dumper, &field);
> case MP_STR:
> str = lua_tolstring(dumper->L, -1, &len);
> - if (lua_isnumber(dumper->L, -1)) {
> - /* string is convertible to number, quote it to preserve type */
> + if ((yaml_get_null(str, len) == YAML_NULL)
> + || (yaml_get_bool(str, len) != YAML_NO_MATCH)
> + || (lua_isnumber(dumper->L, -1))) {
> + /*
> + * The string is convertible to a null, a boolean or
> + * a number, quote it to preserve its type.
> + */
6. I think, it is related to my first comment. So why did you
delete those tests?
> style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
> break;
> }
next prev parent reply other threads:[~2019-01-24 21:27 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-22 2:12 [tarantool-patches] [PATCH v2 0/3] lua-yaml null/boolean fixes Alexander Turenko
2019-01-22 2:12 ` [tarantool-patches] [PATCH v2 1/3] lua-yaml: verify arguments count Alexander Turenko
2019-01-24 21:26 ` [tarantool-patches] " Vladislav Shpilevoy
2019-02-05 3:29 ` Alexander Turenko
2019-02-05 19:36 ` Vladislav Shpilevoy
2019-02-11 13:32 ` Alexander Turenko
2019-02-15 21:28 ` Vladislav Shpilevoy
2019-01-22 2:12 ` [tarantool-patches] [PATCH v2 2/3] lua-yaml: fix boolean/null representation in yaml Alexander Turenko
2019-01-24 21:26 ` Vladislav Shpilevoy [this message]
2019-01-24 21:32 ` [tarantool-patches] " Vladislav Shpilevoy
2019-02-05 3:29 ` Alexander Turenko
2019-02-05 19:36 ` Vladislav Shpilevoy
2019-02-15 21:06 ` Vladislav Shpilevoy
2019-02-15 21:23 ` Alexander Turenko
2019-02-18 18:55 ` Alexander Turenko
2019-02-22 15:14 ` Vladislav Shpilevoy
2019-01-22 2:12 ` [tarantool-patches] [PATCH v2 3/3] lua-yaml: treat an empty document/value as null Alexander Turenko
2019-01-24 21:26 ` [tarantool-patches] " Vladislav Shpilevoy
2019-02-05 3:30 ` Alexander Turenko
2019-01-24 21:26 ` [tarantool-patches] Re: [PATCH v2 0/3] lua-yaml null/boolean fixes Vladislav Shpilevoy
2019-02-25 11:27 ` Kirill Yukhin
2019-03-05 16:40 ` Alexander Turenko
2019-03-06 7:21 ` Kirill Yukhin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3da6fc29-991d-e475-0777-49eacb764b94@tarantool.org \
--to=v.shpilevoy@tarantool.org \
--cc=alexander.turenko@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='[tarantool-patches] Re: [PATCH v2 2/3] lua-yaml: fix boolean/null representation in yaml' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox