includefile(include/header)

COMMENT(manpage, section, releasedate, archive, short name)
manpage(FBB::ArgConfig)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_)
                    (Program Arguments)

manpagename(FBB::ArgConfig)(A singleton class processing program arguments)

manpagesynopsis()
    bf(#include <bobcat/argconfig>)nl()
    Linking option: tt(-lbobcat) 

manpagedescription()
    Singleton class (see Gamma em(et al.), 1995) built around
bf(getopt_long())(3). The class handles short- and long command-line options,
as well as configuration files.

    In addition to the standard command-line options the various tt(option)
members also recognize long options as keys, optionally followed by a colon
and an option value are also recognized. E.g., an option tt(--input filename)
can be specified in the configuration file like
        verb(
    input: filename
        )
or
        verb(
    input filename
        )
    Options without arguments should probably not use the colon, although it
is accepted by tt(ConfigArg). E.g., for the option tt(--verbose) both forms 
are accepted:
    verb(
verbose
verbose:
    )

includefile(include/namespace)

manpagesection(INHERITS FROM)
    bf(FBB::Arg),nl()
    bf(FBB::ConfigFile)

manpagesection(ENUMERATION)

    The bf(FBB::ArgConfig::Type) enumeration is inherited from the
bf(FBB::Arg) class. It is used to specify whether or not long options require
arguments. It defines the following values: bf(None, Required, Optional).
    itemization(
    it() bf(None): the long option does not use an argument;
    it() bf(Required): the long option requires an argument value;
    it() bf(Optional): the long option may optionally be provided with  an
        argument value; 
    )

These values are used when defining long options (like tt(--version)), which
are defined as objects of the (nested inherited) class
bf(FBB::Arg::LongOption) (in the context of tt(ArgConfig) this is identical to
bf(FBB::ArgConfig::LongOption).

manpagesection(THE NESTED INHERITED CLASS FBB::Arg::LongOption)
   Long options are defined using objects of the nested class
    bf(FBB::Arg::LongOption). This class provides the following constructors:
   itemization(
    itb(FBB::Arg::LongOption(char const *name, FBB::Arg::Type type =
        FBB::Arg::None)) 
       This constructor is used to define a long option for which no
        corresponding short option is defined. The parameter tt(name) is the
        name of the long option (without specifying the -- characters which
        are only required when specifying a long option when calling a
        program).

    itb(FBB::Arg::LongOption(char const *name, int optionChar))
       This constructor is used to define a long option for which a
        corresponding short option is defined. The parameter tt(name) is the
        name of the long option (without specifying the -- characters which
        are only required when specifying a long option when calling a
        program).
    )

    To define long options use the following procedure:
    itemization(
    it() First, construct an array 
        verb(
    FBB::Arg::LongOption longOptions[] = { c1, c2, ..., cn };
        )
    Where tt(c1, c2, ..., cn) are tt(n) constructor invocations of 
        bf(FBB::Arg::LongOption()) constructors

    it() Next, pass tt(longOptions, LongOptions + n) as arguments to an
        tt(Arg::initialize) member that supports long options.
    )

    Objects of the class tt(LongOptions) are normally used internally by the
tt(ArgConfig) object, but they can also be used outside of the tt(ArgConfig)
object. For that situation the following members are available:
    itemization(
    itb(std::string const &longName() const)
       returns the tt(LongOption's) long option name;
    itb(int optionChar() const)
       returns the tt(LongOption's) option character (or one of the
        tt(Arg::Type) enumeration values if there is no option character
        associated with the tt(LongOption)).
    )

manpagesection(CONSTRUCTORS)
    Since the class is a em(Singleton), no public constructors are
available. Instead, static members are offered to initialize and access the
single bf(ArgConfig) object.

manpagesection(STATIC MEMBERS)

    All tt(initialize) members initialize the bf(FBB::ArgConfig) singleton,
and can only be called once. An exception is thrown when called multiple
times. All tt(initialize) members return a reference to the initialized
tt(ArgConfig) singleton object.

    All tt(initialize) members define the parameters tt(argc) and tt(argv)
which are interpreted as tt(main's) tt(argc) and tt(argv) parameters.  When an
tt(argv) element points to two consecutive dashes (tt(--)) then that element
is ignored, and all of tt(argv's) subsequent elements are considered arguments
instead of options.

    itemization(
    itb(FBB::ArgConfig &ArgConfig::initialize(char const *optstring, int argc,
        char **argv, [std::string const &fname,] Comment cType = KeepComment,
        SearchCasing sType = SearchCaseSensitive, Indices iType =
        IgnoreIndices))
       The parameter tt(optstring) is a null-terminated byte string (NTBS)
        optionally starting with a + character, but otherwise containing
        option characters. One or two colons may be postfixed to option
        characters:
       quote(
       itemization(
        it() a single colon (:) indicates that the option requires an
            option value.
        it() a double colon (::) indicates that the option has an optional
            argument. With short options the option value is considered absent
            unless it is attached to the short option (e.g.,
            tt(-tvalue)). Long options optionally accepting arguments should
            always immediately be followed by an assignment character (=),
            immediately followed by the option's value (which must start with
            a non-blank character). E.g., tt(--value=) indicates an absent
            option value, tt(--value=text) indicates the option's value equals
            tt(text).  If an option value itself contains blanks, it must be
            surrounded by single or double quotes (e.g., tt(-t'this value'),
            or tt(--text='this value')). The surrounding quotes are not part
            of the option's value.
        ))

        When tt(optstring's) first character is + then all non-specified
        options are considered arguments, appearing in the final arguments
        list at their current argument positions. E.g., when tt(optstring)
        is tt(+ab) and no long options are defined, then calling 
    verb(
    prog -a -z -b -yvalue --long arg1 arg2
    ) 
       results in the member tt(argv) returning a vector containing the
        elements tt(-z, -yvalue, --long, arg1,) and tt(arg2). If
        tt(optstring's) first character isn't + and an undefined option is
        encountered then an exception is thrown.

       The tt(fname) argument is optional. If provided, a configuration file
        by the specified name is opened (and must exist); if omitted the
        tt(ArgConfig) is created without using a configuration file. In the
        latter case a configuration file may be specified later using the
        tt(open) member inherited from tt(ConfigFile). 

       The final three parameters are tt(ConfigFile) parameters, receiving the
        shown default values. This constructor returns a reference to the
        singleton object, allowing code initializing bf(ArgConfig) to use the
        initialized object immediately.

    itb(FBB::ArgConfig &ArgConfig::initialize(int accept. char const
        *optstring, int argc, char **argv, [std::string const &fname,] Comment
        cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices
        iType = IgnoreIndices))
       Acts like the previous member, but in addition defines the
        parameter tt(accept) specifying an option character from where all
        subsequent arguments and options are considered arguments. To ignore
        tt(accept) the value 0 (not the character '0') can be specified or an
        tt(initialize) members can be used that does not define an
        tt(accept) parameter.

        When arguments contain both an tt(accept) option and two consecutive
        dashes then the first one is interpreted, resulting in all remaining
        tt(argv) elements being interpreted as mere arguments. For example,
        when specifying tt(initialize('t', ...)) and calling
    verb(
    prog one -ttwo -c -- three
    )
       then the member tt(argv) returns a vector containing the elements
        tt(one, -tttwo, -c, --), and tt(three) (see also the member
        tt(beyondDashes) below).

    itb(FBB::ArgConfig &ArgConfig::initialize(char const *optstring,
        ArgConfig::LongOption const *const begin, ArgConfig::LongOption const
        *const end, int argc, char **argv, [std::string const &fname,] Comment
        cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices
        iType = IgnoreIndices))
      Acts like the first tt(ArgConfig::initialize) member, but in addition
        defines two parameters specifying the range of elements of an array of
        tt(ArgConfig::LongOption) objects specifying long options. The
        parameter tt(begin) points to the first element of the range, the
        parameter tt(end) points just beyond the last element of the
        range. E.g., after defining
    verb(
    FBB::ArgConfig::LongOption longOptions[] = { c1, c2, ..., cn };
    )
       the arguments passed to tt(begin) and tt(end) could be specified as
    verb(
    initialize(..., longOptions, longOptions + size(longOptions), ...);
    )

    itb(FBB::ArgConfig &ArgConfig::initialize(char accept, char const
        *optstring, LongOption const *const begin, LongOption const *const
        end, int argc, char **argv, [std::string const &fname,] Comment cType
        = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType
        = IgnoreIndices))

      Acts like the previous tt(ArgConfig::initialize) member, but in addition
        defines an tt(accept) parameter as defined by the second
        tt(ArgConfig::initialize) member.

    itb(FBB::ArgConfig &ArgConfig::instance()) 
       Once an tt(ArgConfig::initialize) member has been called this member
        can be called from anywhere in the program (and it can be called
        multiple times), returning a reference to the initialized
        bf(ArgConfig) object.

       If it is called before an tt(ArgConfig::initialize) member has been
        called an exception is thrown.
    )

    itb(FBB::ArgConfig &instance()) 
       Returns the instance of the bf(ArgConfig) object, available after
        calling one of the bf(ArgConfig::initialize) members.  If called
        before initialization, an tt(FBB::Exception) exception is thrown.
    )

manpagesection(NON-STATIC MEMBER FUNCTIONS)
    All public members of the tt(Arg) and tt(ConfigFile) classes are also
offered by the tt(ArgConfig) class. As several  tt(Arg::option) members were
reimplemented by tt(ArgConfig) all tt(option) members are discussed below. All
other members inherit straight from the classes tt(Arg) and
tt(ConfigFile). Consult their man pages for details.
    itemization(
    itb(size_t option(int option) const)
       Returns the number of times `option' (or its long option synonym, if
        defined) was specified as command line option or as as a configuration
        file option.
    itb(size_t option(std::string const &options) const)
       Returns the total number of times any of the characters specified in
        the `options' string (or their long option synonyms) was specified as
        command line option or as as a configuration file option.
    itb(size_t option(string *value, int option) const)
       Returns the number of times the provided option (or its long option
        synonym) was present as either a command line option or as a
        configuration file option. If the return value is non-zero then the
        value of the first occurrence of this option (first checking the
        command line options; then checking the configuration file) is stored
        in tt(*value), which is left untouched if `option' was not present. 0
        may be specified for bf(value) if the option does not have a value or
        if the value should not be stored.
    itb(size_t option(size_t idx, string *value, int option) const)
       This member acts identically to the tt(Arg::option) member having the
        identical prototype. It does not consider the configuration file but
        merely returns the number of times the provided option (or its long
        option synonym) was present. If the return value is non-zero then the
        value of the tt(idx)th occurrence (0-based offset) of this option is
        stored in tt(*value), which is left untouched if `option' was not
        present or if tt(idx) is or exceeds the number of specifications of
        the provided option. 0 may be specified for bf(value) if the option
        does not have a value or if the value should not be stored.
    itb(size_t option(size_t *idx, string *value, int option) const)
       This member acts identically to the tt(Arg::option) member having the
        identical prototype. It does not consider the configuration file but
        merely returns the number of times the provided option (or its long
        option synonym) was present. If the return value is non-zero then the
        offset (within the series of tt(option) specifications) of the first
        option having a non-empty option value is returned in tt(*idx), while
        its option value is stored in tt(*value). Both tt(*value) and tt(*idx)
        are left untouched if `option' was not present. 0 may be specified for
        bf(value) if the option does not have a value or if the value should
        not be stored.
    itb(size_t option(string *value, char const *longOption) const)
       Returns the number of times the specified long option (not having a
        single-character synonym) was present as either a command line option
        or in the configuration file. If found, then the value found at the
        first occurrence of the option (first considering the command line
        options, then the configuration file) is stored in tt(*value). The
        string pointed to by tt(value) is left untouched if the long option
        was not present. 0 may be specified for bf(value) if the option does
        not have a value or if the value should not be stored.
    itb(size_t option(size_t idx, string *value, 
                                        char const * longOption) const)
       This member acts identically to the tt(Arg::option) member having the
        identical prototype. It does not consider the configuration file but
        merely returns the number of times the provided long option (not
        having a single-character synonym) was present. If the return value is
        non-zero then the value of the tt(idx)th occurrence (0-based offset)
        of this long option is stored in tt(*value), which is left untouched
        if the long option was not present or if tt(idx) is or exceeds the
        number of specifications of the provided long option. 0 may be
        specified for bf(value) if the long option does not have a value or if
        the value should not be stored.
    itb(size_t option(size_t *idx, string *value, int longOption) const)
       This member acts identically to the tt(Arg::option) member having the
        identical prototype. It does not consider the configuration file but
        merely returns the number of times the provided long option (not
        having a single-character synonym) was present. If the return value is
        non-zero then the offset (within the series of this long option
        specifications) of the first long option having a non-empty option
        value is returned in tt(*idx), while its option value is stored in
        tt(*value). Both tt(*value) and tt(*idx) are left untouched if long
        option was not present. 0 may be specified for bf(value) if the long
        option does not have a value or if the value should not be stored.
    )

manpagesection(EXAMPLE)

    verb(
#include <iostream>
#include <string>

#include <bobcat/argconfig>
#include <bobcat/exception>

using namespace std;
using namespace FBB;

ArgConfig::LongOption lo[] =
{
    ArgConfig::LongOption{"option", 'o'},
    ArgConfig::LongOption{"value-option", 'v'}
};

class X
{
    ArgConfig &d_arg;

    public:
        X();
        void function();
};

X::X()
:
    d_arg(ArgConfig::instance())
{}

void X::function()
{
    if (d_arg.nArgs() == 0)
        throw Exception() << "Provide the name of a config file as 1st arg";

    cout << "Counting " << d_arg.option('o') << " instances of -o or "
                                                            "--option\n";

    d_arg.open(d_arg[0]);       // Now open the config file explicitly
                            // (alternatively: use a constructor expecting 
                            // a file name)

    cout << "Counting " << d_arg.option('o') << " instances of -o or "
                                                            "--option\n";

    string optval;
    size_t count = d_arg.option(&optval, 'v');

    cout << "Counting " << count << 
                        " instances of -v or --value-option\n";
    if (count)
        cout << "Option value = " << optval << endl;
}

int main(int argc, char **argv)
try
{
    ArgConfig::initialize("ov:", lo, lo + 2, argc, argv);

    X x;
    x.function();
}
catch (Exception const &err)
{
    cout << "Terminating " << err.what() << endl;
    return 1;
}
    )

manpagefiles()
    em(bobcat/argconfig) - defines the class interface

manpageseealso()
    bf(arg)(3bobcat), bf(configfile)(3obcat), bf(bobcat)(7)

manpagebugs()
    None Reported.

includefile(include/trailer)
