Skip to content
Snippets Groups Projects
  1. Apr 21, 2022
  2. Feb 28, 2022
  3. Jul 06, 2021
  4. Dec 19, 2020
    • Markus Armbruster's avatar
      keyval: Use GString to accumulate value strings · 7ece4211
      Markus Armbruster authored
      
      QString supports modifying its string, but it's quite limited: you can
      only append.  The remaining callers use it for building an initial
      string, never for modifying it later.
      
      Change keyval_parse_one() to do build the initial string with GString.
      This is another step towards making QString immutable.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <20201211171152.146877-19-armbru@redhat.com>
      7ece4211
  5. Oct 15, 2020
    • Kevin Wolf's avatar
      keyval: Parse help options · 8bf12c4f
      Kevin Wolf authored
      
      This adds a special meaning for 'help' and '?' as options to the keyval
      parser. Instead of being an error (because of a missing value) or a
      value for an implied key, they now request help, which is a new boolean
      output of the parser in addition to the QDict.
      
      A new parameter 'p_help' is added to keyval_parse() that contains on
      return whether help was requested. If NULL is passed, requesting help
      results in an error and all other cases work like before.
      
      Turning previous error cases into help is a compatible extension. The
      behaviour potentially changes for implied keys: They could previously
      get 'help' as their value, which is now interpreted as requesting help.
      
      This is not a problem in practice because 'help' and '?' are not a valid
      values for the implied key of any option parsed with keyval_parse():
      
      * audiodev: union Audiodev, implied key "driver" is enum AudiodevDriver,
        "help" and "?" are not among its values
      
      * display: union DisplayOptions, implied key "type" is enum
        DisplayType, "help" and "?" are not among its values
      
      * blockdev: union BlockdevOptions, implied key "driver is enum
        BlockdevDriver, "help" and "?" are not among its values
      
      * export: union BlockExport, implied key "type" is enum BlockExportType,
        "help" and "?" are not among its values
      
      * monitor: struct MonitorOptions, implied key "mode" is enum MonitorMode,
        "help" and "?" are not among its values
      
      * nbd-server: struct NbdServerOptions, no implied key.
      
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <20201011073505.1185335-5-armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      8bf12c4f
    • Markus Armbruster's avatar
      keyval: Fix parsing of ',' in value of implied key · 7051ae6c
      Markus Armbruster authored
      
      The previous commit demonstrated documentation and code disagree on
      parsing of ',' in the value of an implied key.  Fix the code to match
      the documentation.
      
      This breaks uses of keyval_parse() that pass an implied key and accept
      a value containing ','.  None of the existing uses does:
      
      * audiodev: implied key "driver" is enum AudiodevDriver, none of the
        values contains ','
      
      * display: implied key "type" is enum DisplayType, none of the values
        contains ','
      
      * blockdev: implied key "driver is enum BlockdevDriver, none of the
        values contains ','
      
      * export: implied key "type" is enum BlockExportType, none of the
        values contains ','
      
      * monitor: implied key "mode" is enum MonitorMode, none of the values
        contains ','
      
      * nbd-server: no implied key.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <20201011073505.1185335-4-armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      7051ae6c
    • Markus Armbruster's avatar
      keyval: Fix and clarify grammar · fec33318
      Markus Armbruster authored
      
      The grammar has a few issues:
      
      * key-fragment = / [^=,.]* /
      
        Prose restricts key fragments: they "must be valid QAPI names or
        consist only of decimal digits".  Technically, '' consists only of
        decimal digits.  The code rejects that.  Fix the grammar.
      
      * val          = { / [^,]* / | ',,' }
      
        Use + instead of *.  Accepts the same language.
      
      * val-no-key   = / [^=,]* /
      
        The code rejects an empty value.  Fix the grammar.
      
      * Section "Additional syntax for use with an implied key" is
        confusing.  Rewrite it.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <20201011073505.1185335-2-armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      fec33318
  6. May 04, 2018
  7. Mar 19, 2018
    • Hanna Reitz's avatar
      qapi: Replace qobject_to_X(o) by qobject_to(X, o) · 7dc847eb
      Hanna Reitz authored
      
      This patch was generated using the following Coccinelle script:
      
      @@
      expression Obj;
      @@
      (
      - qobject_to_qnum(Obj)
      + qobject_to(QNum, Obj)
      |
      - qobject_to_qstring(Obj)
      + qobject_to(QString, Obj)
      |
      - qobject_to_qdict(Obj)
      + qobject_to(QDict, Obj)
      |
      - qobject_to_qlist(Obj)
      + qobject_to(QList, Obj)
      |
      - qobject_to_qbool(Obj)
      + qobject_to(QBool, Obj)
      )
      
      and a bit of manual fix-up for overly long lines and three places in
      tests/check-qjson.c that Coccinelle did not find.
      
      Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
      Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
      Message-Id: <20180224154033.29559-4-mreitz@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      [eblake: swap order from qobject_to(o, X), rebase to master, also a fix
      to latent false-positive compiler complaint about hw/i386/acpi-build.c]
      Signed-off-by: default avatarEric Blake <eblake@redhat.com>
      7dc847eb
  8. Feb 09, 2018
  9. Sep 04, 2017
  10. May 31, 2017
    • Markus Armbruster's avatar
      qapi: Reject alternates that can't work with keyval_parse() · c0644771
      Markus Armbruster authored
      
      Alternates are sum types like unions, but use the JSON type on the
      wire / QType in QObject instead of an explicit tag.  That's why we
      require alternate members to have distinct QTypes.
      
      The recently introduced keyval_parse() (commit d454dbe0) can only
      produce string scalars.  The qobject_input_visitor_new_keyval() input
      visitor mostly hides the difference, so code using a QObject input
      visitor doesn't have to care whether its input was parsed from JSON or
      KEY=VALUE,...  The difference leaks for alternates, as noted in commit
      0ee9ae7c: a non-string, non-enum scalar alternate value can't currently
      be expressed.
      
      In part, this is just our insufficiently sophisticated implementation.
      Consider alternate type 'GuestFileWhence'.  It has an integer member
      and a 'QGASeek' member.  The latter is an enumeration with values
      'set', 'cur', 'end'.  The meaning of b=set, b=cur, b=end, b=0, b=1 and
      so forth is perfectly obvious.  However, our current implementation
      falls apart at run time for b=0, b=1, and so forth.  Fixable, but not
      today; add a test case and a TODO comment.
      
      Now consider an alternate type with a string and an integer member.
      What's the meaning of a=42?  Is it the string "42" or the integer 42?
      Whichever meaning you pick makes the other inexpressible.  This isn't
      just an implementation problem, it's fundamental.  Our current
      implementation will pick string.
      
      So far, we haven't needed such alternates.  To make sure we stop and
      think before we add one that cannot sanely work with keyval_parse(),
      let's require alternate members to have sufficiently distinct
      representation in KEY=VALUE,... syntax:
      
      * A string member clashes with any other scalar member
      
      * An enumeration member clashes with bool members when it has value
        'on' or 'off'.
      
      * An enumeration member clashes with numeric members when it has a
        value that starts with '-', '+', or a decimal digit.  This is a
        rather lazy approximation of the actual number syntax accepted by
        the visitor.
      
        Note that enumeration values starting with '-' and '+' are rejected
        elsewhere already, but better safe than sorry.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1495471335-23707-5-git-send-email-armbru@redhat.com>
      Reviewed-by: default avatarEric Blake <eblake@redhat.com>
      Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
      c0644771
  11. Mar 21, 2017
  12. Mar 07, 2017
    • Markus Armbruster's avatar
      keyval: Support lists · 0b2c1bee
      Markus Armbruster authored
      
      Additionally permit non-negative integers as key components.  A
      dictionary's keys must either be all integers or none.  If all keys
      are integers, convert the dictionary to a list.  The set of keys must
      be [0,N].
      
      Examples:
      
      * list.1=goner,list.0=null,list.1=eins,list.2=zwei
        is equivalent to JSON [ "null", "eins", "zwei" ]
      
      * a.b.c=1,a.b.0=2
        is inconsistent: a.b.c clashes with a.b.0
      
      * list.0=null,list.2=eins,list.2=zwei
        has a hole: list.1 is missing
      
      Similar design flaw as for objects: there is no way to denote an empty
      list.  While interpreting "key absent" as empty list seems natural
      (removing a list member from the input string works when there are
      multiple ones, so why not when there's just one), it doesn't work:
      "key absent" already means "optional list absent", which isn't the
      same as "empty list present".
      
      Update the keyval object visitor to use this a.0 syntax in error
      messages rather than the usual a[0].
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1488317230-26248-25-git-send-email-armbru@redhat.com>
      [Off-by-one fix squashed in, as per Kevin's review]
      Reviewed-by: default avatarKevin Wolf <kwolf@redhat.com>
      0b2c1bee
    • Markus Armbruster's avatar
      keyval: Restrict key components to valid QAPI names · f7400483
      Markus Armbruster authored
      
      Until now, key components are separated by '.'.  This leaves little
      room for evolving the syntax, and is incompatible with the __RFQDN_
      prefix convention for downstream extensions.
      
      Since key components will be commonly used as QAPI member names by the
      QObject input visitor, we can just as well borrow the QAPI naming
      rules here: letters, digits, hyphen and period starting with a letter,
      with an optional __RFQDN_ prefix for downstream extensions.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: default avatarKevin Wolf <kwolf@redhat.com>
      Message-Id: <1488317230-26248-20-git-send-email-armbru@redhat.com>
      f7400483
    • Markus Armbruster's avatar
      keyval: New keyval_parse() · d454dbe0
      Markus Armbruster authored
      
      keyval_parse() parses KEY=VALUE,... into a QDict.  Works like
      qemu_opts_parse(), except:
      
      * Returns a QDict instead of a QemuOpts (d'oh).
      
      * Supports nesting, unlike QemuOpts: a KEY is split into key
        fragments at '.' (dotted key convention; the block layer does
        something similar on top of QemuOpts).  The key fragments are QDict
        keys, and the last one's value is updated to VALUE.
      
      * Each key fragment may be up to 127 bytes long.  qemu_opts_parse()
        limits the entire key to 127 bytes.
      
      * Overlong key fragments are rejected.  qemu_opts_parse() silently
        truncates them.
      
      * Empty key fragments are rejected.  qemu_opts_parse() happily
        accepts empty keys.
      
      * It does not store the returned value.  qemu_opts_parse() stores it
        in the QemuOptsList.
      
      * It does not treat parameter "id" specially.  qemu_opts_parse()
        ignores all but the first "id", and fails when its value isn't
        id_wellformed(), or duplicate (a QemuOpts with the same ID is
        already stored).  It also screws up when a value contains ",id=".
      
      * Implied value is not supported.  qemu_opts_parse() desugars "foo" to
        "foo=on", and "nofoo" to "foo=off".
      
      * An implied key's value can't be empty, and can't contain ','.
      
      I intend to grow this into a saner replacement for QemuOpts.  It'll
      take time, though.
      
      Note: keyval_parse() provides no way to do lists, and its key syntax
      is incompatible with the __RFQDN_ prefix convention for downstream
      extensions, because it blindly splits at '.', even in __RFQDN_.  Both
      issues will be addressed later in the series.
      
      Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1488317230-26248-4-git-send-email-armbru@redhat.com>
      d454dbe0
Loading