Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component balcl_optionvalue
[Package balcl]

Provide a variant type for command-line-option values. More...

Namespaces

namespace  balcl

Detailed Description

Outline
Purpose:
Provide a variant type for command-line-option values.
Classes:
balcl::OptionValue the value of a user supplied command-line option
See also:
Component balcl_optiontype, Component balcl_commandline
Description:
This component provides a value-semantic class, balcl::OptionValue, that can have a value of any of the types specified by balcl::OptionType -- i.e., any of the values that can be associated with a command-line option by balcl::CommandLine. The balcl::OptionValue class has two related states:
  1. A default-constructed balcl::OptionValue object is in the "unset state" -- meaning that no type has been defined for a value (its type is void). In this state, balcl::OptionType::e_VOID == type() and false == hasNonVoidType(). To have a value, a type must be specified for the value by using the setType method or using one of the constructors that define an initial value. Example 1 shows how this state can be set and reset.
  1. If a balcl::OptionValue object has a (non-'void') type it can have a value of that type or be in a "null state". Objects in the null state can be used to represent the value of command-line options that were not entered on the command line (assuming no default value was specified for the option). Example 2 shows how this feature can be used.
Usage:
This section illustrates intended use of this component.
Example 1: Basic Use of balcl::OptionValue:
The following snippets of code illustrate how to create and use a balcl::OptionValue object. Note that balcl::OptionValue objects are typically used in a description of a sequence of command-line options (see balcl_optiontype).
First, we create a default balcl::OptionValue, valueA, and observe that it is in the unset state:
  balcl::OptionValue valueA;

  assert(false                     == valueA.hasNonVoidType());
  assert(balcl::OptionType::e_VOID == valueA.type());
Next, we create a second balcl::OptionValue having the value 5, and then confirm its value and observe that it does not compare equal to the valueA:
  balcl::OptionValue valueB(5);

  assert(true                     == valueB.hasNonVoidType());
  assert(balcl::OptionType::e_INT == valueB.type());
  assert(5                        == valueB.the<int>());

  assert(valueA != valueB);
Then, we call the reset method of valueB resetting it to the unset state, and observe that valueA now compares equal to valueB:
  valueB.reset();

  assert(valueA == valueB);
Now, we change the type of valueA so that it can be hold a double value:
  valueA.setType(balcl::OptionType::e_DOUBLE);
  assert(true                        == valueA.hasNonVoidType());
  assert(balcl::OptionType::e_DOUBLE == valueA.type());
  assert(double()                    == valueA.the<double>());

  valueA.set(6.0);
  assert(6.0                         == valueA.the<double>());
Finally, we set the object to the null state. Notice that the type of that value is not changed:
  valueA.setNull();
  assert(true                        == valueA.isNull());
  assert(balcl::OptionType::e_DOUBLE == valueA.type());
Example 2: Interpreting Option Parser Results:
Command-line options have values of many different types (e.g., int, double, string, date) or their values may not be specified -- after all, some command-line options may be optional. The balcl::OptionValue class can be used to represent such values.
First, we define MyCommandLineParser, a simple command-line argument parser. This class accepts a description (e.g., option name, value type) of allowable options on construction and provides a parse method that accepts argc and argv, the values made available (by the operating system) to main:
                      // =========================
                      // class MyCommandLineParser
                      // =========================

  class MyCommandLineParser {
      // ...

    public:
      // CREATORS
      MyCommandLineParser(const MyOptionDescription *descriptions,
                          bsl::size_t                count);
          // Create an object that can parse command-line arguments that
          // satisfy the specified 'descriptions', an array containing the
          // specified 'count' elements.

      // ...

      // MANIPULATORS
      int parse(int argc, const char **argv);
          // Parse the command-line options in the specified 'argv', an array
          // having the specified 'argc' elements.  Return 0 on success --
          // i.e., the options were compatible with the option descriptions
          // specified on construction -- and a non-zero value otherwise.

      // ...
After a successful call to the parse method, the results are available by several accessors. Note that the index of a result corresponds to the index of that option in the description provided on construction:
      // ACCESSORS
      bool isParsed() const;
          // Return 'true' if the most recent call to 'parsed' was successful
          // and 'false' otherwise.

      const char *name (bsl::size_t index) const;
          // Return of the name of the parsed option at the specified 'index'
          // position.  The behavior is undefined unless
          // '0 <= index < numOptions()' and 'true == isParsed()'

      const balcl::OptionValue& value(bsl::size_t index) const;
          // Return a 'const' reference to the value (possibly in a null
          // state) of the parsed option at the specified 'index' position.
          // The behavior is undefined unless '0 <= index < numOptions()' and
          // 'true == isParsed()'.

      bsl::size_t numOptions() const;
          // Return the number of parsed options.  The behavior is undefined
          // unless 'true == isParsed()'.

      // ...
  };
Note that neither our option description nor our parser support the concept of default values for options that are not entered on the command line.
Then, we create a description having three allowable options (elided), a parser object, and invoke parse on the arguments available from main:
  int main(int argc, const char **argv)
  {
      MyOptionDescription optionDescriptions[NUM_OPTIONS] = {
          // ...
      };

      MyCommandLineParser parser(optionDescriptions, NUM_OPTIONS);

      int rc = parser.parse(argc, argv);
      assert(0    == rc);
      assert(true == parser.isParsed());
Now, we examine the value of each defined option:
      for (bsl::size_t i = 0; i < parser.numOptions(); ++i) {
          const char                *name  = parser.name(i);
          const balcl::OptionValue&  value = parser.value(i);
Since our (toy) parser has no feature for handling default values for options that are not specified on the command line, we must handle those explicitly.
If the option named "outputDir" was set, we use that value; otherwise, we set a default value, the current directory:
          if (0 == bsl::strcmp("outputDir", name)) {
              setOutputDir(value.isNull()
                           ? "."
                           : value.the<bsl::string>().c_str());
          }
If the option named "verbosityLevel" was set we use that value; otherwise, we set a default value, 1:
          if (0 == bsl::strcmp("verbosityLevel", name)) {
              setVerbosityLevel(value.isNull()
                                ? 1
                                : value.the<int>());
          }
The option named "caseInsensitive" has no associated value. If that option appeared on the command line, the value of the program flag is set to true, otherwise (false == isNull()) that flag is set to false:
          if (0 == bsl::strcmp("caseInsensitive", name)) {
              setCaseInsensitivityFlag(value.isNull()
                                       ? false
                                       : true);
          }
      }
Finally, we continue with the execution of our program using the values obtained from the command-line options:
      // ...

      return 0;
  }