Commit Graph

29 Commits

Author SHA1 Message Date
Laurent Pinchart 3c63675560 cam: options: Avoid copies of OptionvValue and KeyValueParser::Options
The OptionValue toKeyValues() and toArray() functions return a copy of
the values. This is unnecessary, and can cause use-after-free issues
when taking references to the return values. Return references instead
to optimize the implementation and avoid issues.

The behaviour of the two functions is now undefined in case of an option
type mismatch. The current implementation catches this with an
assertion.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2021-07-22 17:13:32 +03:00
Laurent Pinchart 812e5a946f cam: options: Add empty() function to OptionValue class
Add a convenience helper to check if an option value is empty, based on
the value type. This is useful as a shortcut syntax to check if an
option has been set.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2021-07-22 17:13:30 +03:00
Laurent Pinchart 668c87732a cam: options: Drop some OptionValue cast operators
While OptionValue cast operators to int and std::string allow useful
shortcut syntaxes, the cast operators to KeyValueParser::Options and
std::vector<OptionValue> are less useful. A an explicit static_cast call
would be more cumbersome to write than an explicit .toKeyValues() or
toArray(), and implicit cast hide too much of what's going on.

Drop those two cast operators, and replace the only implicit cast
occurrence with .toKeyValues(). While at it, drop the local opts
variable in StreamKeyValueParser::roles() as it isn't used.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:28 +03:00
Laurent Pinchart bb682d2585 cam: options: Support parent-child relationship between options
Add support for creating a tree-based hieararchy of options instead of a
flat list. This is useful to support options that need to be interpreted
in the context of a particular occurrence of an array option.

The usage text automatically documents the options in their
corresponding context:

Options:
  -c, --camera camera ...                               Specify which camera to operate on, by id or by index
  -h, --help                                            Display this help message
  -I, --info                                            Display information about stream(s)
  -l, --list                                            List all cameras
      --list-controls                                   List cameras controls
  -p, --list-properties                                 List cameras properties
  -m, --monitor                                         Monitor for hotplug and unplug camera events

Options valid in the context of --camera:
  -C, --capture[=count]                                 Capture until interrupted by user or until <count> frames captured
  -F, --file[=filename]                                 Write captured frames to disk
                                                        If the file name ends with a '/', it sets the directory in which
                                                        to write files, using the default file name. Otherwise it sets the
                                                        full file path and name. The first '#' character in the file name
                                                        is expanded to the camera index, stream name and frame sequence number.
                                                        The default file name is 'frame-#.bin'.
  -s, --stream key=value[,key=value,...] ...            Set configuration of a camera stream
          height=integer                                Height in pixels
          pixelformat=string                            Pixel format name
          role=string                                   Role for the stream (viewfinder, video, still, raw)
          width=integer                                 Width in pixels
      --strict-formats                                  Do not allow requested stream format(s) to be adjusted
      --metadata                                        Print the metadata for completed requests

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:23 +03:00
Laurent Pinchart b53f68e66c cam: options: Move key string left in usage() for key-value parser
When printing usage information for a key-value parser, the
documentation of the keys and values is printed in the second column of
the usage text:

  -s, --stream key=value[,key=value,...] ...            Set configuration of a camera stream
                                                        height=integer          Height in pixels
                                                        pixelformat=string      Pixel format name
                                                        role=string             Role for the stream (viewfinder, video, still, raw)
                                                        width=integer           Width in pixels
  -h, --help                                            Display this help message

This results in long lines. Improve this by moving the key description
to the first column, and aligning the value description as other option
description text:

  -s, --stream key=value[,key=value,...] ...            Set configuration of a camera stream
          height=integer                                Height in pixels
          pixelformat=string                            Pixel format name
          role=string                                   Role for the stream (viewfinder, video, still, raw)
          width=integer                                 Width in pixels
  -h, --help                                            Display this help message

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:22 +03:00
Laurent Pinchart c71691e66c cam: options: Disable copy for parsers
Copying the OptionsParser class would result in the optionsMap_ entries
pointing to Option entries of the original instance. As there's no use
case for copying the class, disable copying.

Disable copying of KeyValueParser as well for consistency as there's no
use case either.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:21 +03:00
Laurent Pinchart a8f3a68ec9 cam: options: Slit OptionsParser::usage() in two functions
To prepare for code reuse, split the printing of options out of
OptionsParser::usage() to a separate function.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:20 +03:00
Laurent Pinchart 7c205c79d9 cam: options: Add optionName() function to Option structure
Add an Option::optionName() function that returns a string describing
the option name, with leading dashes. As a result,
OptionsParser::parseValueError() function becomes a single-line function
and can be inlined in its caller.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:18 +03:00
Laurent Pinchart 539820f5d6 cam: options: Move OptionValue class after OptionsParser
To prepare for usage of the OptionsParser::Options class in OptionValue,
move the definition of the OptionValue class after OptionsParser. There
is no functional change.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:16 +03:00
Laurent Pinchart aeb6390418 cam: options: Move Option struct to options.cpp
The Option structure is an internal implementation detail and shouldn't
be exposed in the API. Move it to options.cpp. This requires moving the
inline constructors and destructors for the KeyValueParser and
OptionsParser classes to options.cpp as well, as they need a full
definition of the Option structure.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:11 +03:00
Laurent Pinchart 12cb9293fa cam: options: Make KeyValueParser::usage() private
The KeyValueParser::usage() function is meant to be called from an
OptionsParser or another KeyValueParser only. Make it private, and set
the OptionsParser class as a friend of the KeyValueParser class.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-22 17:13:07 +03:00
Laurent Pinchart c77d894a8b libcamera: Declare empty virtual destructors as defaulted
The base class of polymorphic classes is required to declare a
destructor. Several of these are empty, and can thus be declared as
defaulted.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <email@uajain.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-10-23 22:53:13 +03:00
Niklas Söderlund cdf7fbe35e cam: options: Add public method to invalidate options
Extend OptionsBase<T> with a public invalidate() method. This allows for
further examination of the options and if found unsuitable be
invalidated. The intended user for this new interface are subclasses of
KeyValueParser.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-05-01 12:24:07 +02:00
Niklas Söderlund e66d4f3823 cam: options: Make KeyValueParser::parse() virtual
Prepare for sub-classing of the KeyValueParser by making the parse()
method virtual.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-05-01 12:24:07 +02:00
Laurent Pinchart f8386836df cam: Separate options valid() and empty()
An empty option list is not necessarily an error. Add a new empty()
function to test the option list for emptiness, and modify the valid()
function to only notify parsing errors. As a side effect this allows
accessing partially parsed options, which may be useful in the future.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-03-27 18:26:15 +02:00
Niklas Söderlund 3f906920e4 cam: options: Add support for repeatable options
Add a flag to indicate if an option can be repeatable. If an option is
repeatable it must be accessed thru the array interface, even if it's
only specified once by the user.

Also update the usage generator to indicate which options are
repeatable.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-03-27 15:06:14 +01:00
Niklas Söderlund 2a608965f8 cam: options: Add an array data type to OptionValue
To allow specifying the same argument option multiple times a new type
of OptionValue is needed. As parsing of options is an iterative process
there is a need to append options as they are parsed so instead of
setting values using the constructor a new addValue() method is used.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-03-27 15:06:02 +01:00
Niklas Söderlund af45435014 cam: options: Create separate enum for OptionValue types
In preparation for support of multiple instances of the same option,
create a separate enum for the OptionValue types as it will diverge from
enum OptionType.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-03-25 21:56:30 +01:00
Laurent Pinchart 0c0b1e4dbe cam: options: Fix coding style issue related to templates
Our coding style doesn't add a space after the template keyword. Fix the
source code accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-02-13 13:23:36 +02:00
Laurent Pinchart 3fd5ade00c cam: options: Add explicit conversion methods to OptionValue
The OptionValue class defines operators to convert the variant to all
the supported option types. As a convenience, add explicit methods to
perform the same operations, avoiding the need to write long
static_cast<>() statements in the caller.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-02-01 11:42:10 +02:00
Niklas Söderlund 270eb0acc7 cam: options: Add a key=value parser
Some options passed to the cam utility need to be complex and specify a
list of key=value pairs. Add a new parser to deal with these options,
usable on its own to parse key=value pairs from any string.

Integrate the KeyValueParser into the existing OptionsParser. The cam
application can fully describe all its options in one location and
perform full parsing of all arguments in one go. The KeyValueParser also
integrates itself with the usage() printing of the OptionsParser.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-02-01 11:42:03 +02:00
Laurent Pinchart c8c546fe99 cam: options: Add option type handling to options parser
Extend the options parser with support for option types. All options
must now specify the type of their argument, and the parser
automatically parses the argument and handles errors internally.
Available types are none, integer or string.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-02-01 11:42:02 +02:00
Laurent Pinchart 6f3503981a cam: options: Store options in a list instead of a vector
When option are added to the parser, they are stored in the
OptionsParser::options_ vector, and a pointer to the option referencing
the vector entry is indexed in the OptionsParser::optionsMap_ map. When
the next option is added the vector may be resized, which invalidates
the pointers stored in the map.

Fix this by storing the options in an std::list<> instead of
std::vector<>.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-02-01 11:42:00 +02:00
Niklas Söderlund 69be770715 cam: options: Return whether addOption() succeeds or not
To later extend the options handling to cover subparsing of arguments it
will be needed to know if the addition of the option itself was
successful or not. The information is already present in addOption()
this change just makes it available.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-02-01 11:41:59 +02:00
Niklas Söderlund c6468e45d1 cam: options: Create a template class for options
In preparation to adding more parsers create a template class to hold
the parsed information. The rational for making it a template are that
different parsers can index the options using different data types.

The OptionsParser index its options using an int while the upcoming
KeyValyeParser will index its options using strings for example.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-02-01 11:41:55 +02:00
Laurent Pinchart 377516a084 cam: options: Move struct Option
The Option structure is declared within the OptionsParser, but will
later be needed by other parsers. Move it outside the OptionsParser
class.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-02-01 11:41:54 +02:00
Niklas Söderlund 0b2822749e cam: options: Move enum OptionArgument
The enumeration of the different possibilities for arguments can be used
by other parser then OptionsParser. Move it outside the class to make it
ready to be used by other parsers.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-02-01 11:41:53 +02:00
Laurent Pinchart a22dcaaa78 cam: options: Don't implement move semantics for OptionsParser::Options
The compiler creates a move constructor automatically when none is
supplied, and it does the right thing by default in this case. Using
std::move() inside the function prevents the compiler from doing
return value optimization and actually hinders performances. Using
std::move() in the caller is unnecessary, the move constructor is used
automatically by the compiler.

For all these reasons remove the tentative optimization that resulted in
worse performances and worse code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-01-22 20:44:04 +02:00
Laurent Pinchart f5e48ebf44 cam: Extract option parser to separate file
And turn it into an OptionsParser object.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2019-01-22 14:04:09 +01:00