All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>, qemu-block@nongnu.org
Cc: qemu-devel@nongnu.org, armbru@redhat.com, mreitz@redhat.com
Subject: Re: [PATCH v2 1/4] keyval: Parse help options
Date: Wed, 30 Sep 2020 08:35:38 -0500	[thread overview]
Message-ID: <001c321e-7400-f680-45ce-c920f078d5d8@redhat.com> (raw)
In-Reply-To: <20200930124557.51835-2-kwolf@redhat.com>


[-- Attachment #1.1: Type: text/plain, Size: 5957 bytes --]

On 9/30/20 7:45 AM, Kevin Wolf wrote:
> This adds a new parameter 'help' to keyval_parse() that enables parsing
> of help options. If NULL is passed, the function behaves the same as
> before. But if a bool pointer is given, it contains the information
> whether an option "help" without value was given (which would otherwise
> either result in an error or be interpreted as the value for an implied
> key).
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---

> +
> +    /* "help" is only a help option if it has no value */
> +    qdict = keyval_parse("help=on", NULL, &help, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 1);
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "help"), ==, "on");
> +    g_assert_false(help);
> +    qobject_unref(qdict);
> +
> +    /* Double comma after "help" in an implied key is not a help option */
> +    qdict = keyval_parse("help,,abc", "implied", &help, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 1);
> +    g_assert_false(help);
> +    qobject_unref(qdict);

Worth checking qdict_get_try_str(qdict, "implied") for "help,abc"?

> +
> +    /* Without implied key and without value, it's an error */
> +    qdict = keyval_parse("help,,abc", NULL, &help, &err);
> +    error_free_or_abort(&err);
> +    g_assert(!qdict);
> +
> +    /* "help" as the only option */
> +    qdict = keyval_parse("help", NULL, &help, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 0);
> +    g_assert_true(help);
> +    qobject_unref(qdict);
> +
> +    /* "help" as the first part of the key */
> +    qdict = keyval_parse("help.abc", NULL, &help, &err);
> +    error_free_or_abort(&err);
> +    g_assert(!qdict);

Worth checking qdict_get_try_str(qdict, "help.abc") for "on"? (at least,
that's my guess as what happened)

> +
> +    /* "help" as the last part of the key */
> +    qdict = keyval_parse("abc.help", NULL, &help, &err);
> +    error_free_or_abort(&err);
> +    g_assert(!qdict);

[1]

> +
> +    /* "help" is not a value for the implied key if &help is given */
> +    qdict = keyval_parse("help", "implied", &help, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 0);
> +    g_assert_true(help);
> +    qobject_unref(qdict);

Worth checking that the qdict does not contain "implied"?  Perhaps by
checking qdict_size() == 0?

> +
> +    /* "help" is a value for the implied key when passing NULL for help */
> +    qdict = keyval_parse("help", "implied", NULL, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 1);
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "help");
> +    qobject_unref(qdict);
> +
> +    /* "help.abc" is a value for the implied key */
> +    qdict = keyval_parse("help.abc", "implied", &help, &err);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 1);
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "help.abc");
> +    g_assert_false(help);
> +    qobject_unref(qdict);
> +
> +    /* "abc.help" is a value for the implied key */
> +    qdict = keyval_parse("abc.help", "implied", &help, &err);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 1);
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "abc.help");
> +    g_assert_false(help);
> +    qobject_unref(qdict);
> +
> +    /* "help" as the last part of the key */
> +    qdict = keyval_parse("abc.help", NULL, &help, &err);
> +    error_free_or_abort(&err);
> +    g_assert(!qdict);

duplicates [1]

> +
> +    /* Other keys before and after help are still parsed normally */
> +    qdict = keyval_parse("number=42,help,foo=bar", NULL, &help, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 2);
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "number"), ==, "42");
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar");
> +    g_assert_true(help);
> +    qobject_unref(qdict);
> +
> +    /* ...even with an implied key */
> +    qdict = keyval_parse("val,help,foo=bar", "implied", &help, &error_abort);
> +    g_assert_cmpuint(qdict_size(qdict), ==, 2);
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "val");
> +    g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar");
> +    g_assert_true(help);
> +    qobject_unref(qdict);
>  }
>  

Overall a nice set of additions.  You could tweak it further, but I'm no
longer seeing a hole like last time.

> +++ b/util/keyval.c
> @@ -166,7 +166,7 @@ static QObject *keyval_parse_put(QDict *cur,
>   * On failure, return NULL.
>   */
>  static const char *keyval_parse_one(QDict *qdict, const char *params,
> -                                    const char *implied_key,
> +                                    const char *implied_key, bool *help,
>                                      Error **errp)
>  {
>      const char *key, *key_end, *s, *end;
> @@ -238,13 +238,20 @@ static const char *keyval_parse_one(QDict *qdict, const char *params,
>      if (key == implied_key) {
>          assert(!*s);
>          s = params;
> +    } else if (*s == '=') {
> +        s++;
>      } else {
> -        if (*s != '=') {
> +        if (help && !strncmp(key, "help", s - key)) {

Should this use is_help_option() to also accept "?", or are we okay
demanding exactly "help"?

> +            *help = true;
> +            if (*s) {
> +                s++;
> +            }
> +            return s;
> +        } else {
>              error_setg(errp, "Expected '=' after parameter '%.*s'",
>                         (int)(s - key), key);
>              return NULL;
>          }
> -        s++;
>      }

Assuming you can touch up the testsuite before the pull request, and
assuming we don't care about "?",

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

  reply	other threads:[~2020-09-30 13:36 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-30 12:45 [PATCH v2 0/4] qemu-storage-daemon: Remove QemuOpts from --object parser Kevin Wolf
2020-09-30 12:45 ` [PATCH v2 1/4] keyval: Parse help options Kevin Wolf
2020-09-30 13:35   ` Eric Blake [this message]
2020-09-30 15:10     ` Kevin Wolf
2020-10-01 10:34       ` Markus Armbruster
2020-10-01 11:33         ` Kevin Wolf
2020-10-01 15:46   ` Markus Armbruster
2020-10-05 12:08     ` Markus Armbruster
2020-09-30 12:45 ` [PATCH v2 2/4] qom: Factor out helpers from user_creatable_print_help() Kevin Wolf
2020-09-30 13:46   ` Eric Blake
2020-10-02 12:13   ` Markus Armbruster
2020-09-30 12:45 ` [PATCH v2 3/4] qom: Add user_creatable_print_help_from_qdict() Kevin Wolf
2020-09-30 13:48   ` Eric Blake
2020-10-02 12:25   ` Markus Armbruster
2020-10-02 12:36     ` Markus Armbruster
2020-09-30 12:45 ` [PATCH v2 4/4] qemu-storage-daemon: Remove QemuOpts from --object parser Kevin Wolf
2020-09-30 13:49   ` Eric Blake
2020-10-02 12:26   ` Markus Armbruster

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=001c321e-7400-f680-45ce-c920f078d5d8@redhat.com \
    --to=eblake@redhat.com \
    --cc=armbru@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.