Blame utils/cmdline/options.hpp

Packit 209faa
// Copyright 2010 The Kyua Authors.
Packit 209faa
// All rights reserved.
Packit 209faa
//
Packit 209faa
// Redistribution and use in source and binary forms, with or without
Packit 209faa
// modification, are permitted provided that the following conditions are
Packit 209faa
// met:
Packit 209faa
//
Packit 209faa
// * Redistributions of source code must retain the above copyright
Packit 209faa
//   notice, this list of conditions and the following disclaimer.
Packit 209faa
// * Redistributions in binary form must reproduce the above copyright
Packit 209faa
//   notice, this list of conditions and the following disclaimer in the
Packit 209faa
//   documentation and/or other materials provided with the distribution.
Packit 209faa
// * Neither the name of Google Inc. nor the names of its contributors
Packit 209faa
//   may be used to endorse or promote products derived from this software
Packit 209faa
//   without specific prior written permission.
Packit 209faa
//
Packit 209faa
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 209faa
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 209faa
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 209faa
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 209faa
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 209faa
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 209faa
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 209faa
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 209faa
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 209faa
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 209faa
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 209faa
Packit 209faa
/// \file utils/cmdline/options.hpp
Packit 209faa
/// Definitions of command-line options.
Packit 209faa
Packit 209faa
#if !defined(UTILS_CMDLINE_OPTIONS_HPP)
Packit 209faa
#define UTILS_CMDLINE_OPTIONS_HPP
Packit 209faa
Packit 209faa
#include "utils/cmdline/options_fwd.hpp"
Packit 209faa
Packit 209faa
#include <string>
Packit 209faa
#include <utility>
Packit 209faa
#include <vector>
Packit 209faa
Packit 209faa
#include "utils/fs/path_fwd.hpp"
Packit 209faa
Packit 209faa
namespace utils {
Packit 209faa
namespace cmdline {
Packit 209faa
Packit 209faa
Packit 209faa
/// Type-less base option class.
Packit 209faa
///
Packit 209faa
/// This abstract class provides the most generic representation of options.  It
Packit 209faa
/// allows defining options with both short and long names, with and without
Packit 209faa
/// arguments and with and without optional values.  These are all the possible
Packit 209faa
/// combinations supported by the getopt_long(3) function, on which this is
Packit 209faa
/// built.
Packit 209faa
///
Packit 209faa
/// The internal values (e.g. the default value) of a generic option are all
Packit 209faa
/// represented as strings.  However, from the caller's perspective, this is
Packit 209faa
/// suboptimal.  Hence why this class must be specialized: the subclasses
Packit 209faa
/// provide type-specific accessors and provide automatic validation of the
Packit 209faa
/// types (e.g. a string '3foo' is not passed to an integer option).
Packit 209faa
///
Packit 209faa
/// Given that subclasses are used through templatized code, they must provide:
Packit 209faa
///
Packit 209faa
/// 
    Packit 209faa
    ///     
  • A public option_type typedef that defines the type of the
  • Packit 209faa
    ///     option.
    Packit 209faa
    ///
    Packit 209faa
    ///     
  • A convert() method that takes a string and converts it to
  • Packit 209faa
    ///     option_type.  The string can be assumed to be convertible to the
    Packit 209faa
    ///     destination type.  Should not raise exceptions.
    Packit 209faa
    ///
    Packit 209faa
    ///     
  • A validate() method that matches the implementation of convert().
  • Packit 209faa
    ///     This method can throw option_argument_value_error if the string cannot
    Packit 209faa
    ///     be converted appropriately.  If validate() does not throw, then
    Packit 209faa
    ///     convert() must execute successfully.
    Packit 209faa
    /// 
    Packit 209faa
    ///
    Packit 209faa
    /// TODO(jmmv): Many methods in this class are split into two parts: has_foo()
    Packit 209faa
    /// and foo(), the former to query if the foo is available and the latter to get
    Packit 209faa
    /// the foo.  It'd be very nice if we'd use something similar Boost.Optional to
    Packit 209faa
    /// simplify this interface altogether.
    Packit 209faa
    class base_option {
    Packit 209faa
        /// Short name of the option; 0 to indicate that none is available.
    Packit 209faa
        char _short_name;
    Packit 209faa
    Packit 209faa
        /// Long name of the option.
    Packit 209faa
        std::string _long_name;
    Packit 209faa
    Packit 209faa
        /// Textual description of the purpose of the option.
    Packit 209faa
        std::string _description;
    Packit 209faa
    Packit 209faa
        /// Descriptive name of the required argument; empty if not allowed.
    Packit 209faa
        std::string _arg_name;
    Packit 209faa
    Packit 209faa
        /// Whether the option has a default value or not.
    Packit 209faa
        ///
    Packit 209faa
        /// \todo We should probably be using the optional class here.
    Packit 209faa
        bool _has_default_value;
    Packit 209faa
    Packit 209faa
        /// If _has_default_value is true, the default value.
    Packit 209faa
        std::string _default_value;
    Packit 209faa
    Packit 209faa
    public:
    Packit 209faa
        base_option(const char, const char*, const char*, const char* = NULL,
    Packit 209faa
                    const char* = NULL);
    Packit 209faa
        base_option(const char*, const char*, const char* = NULL,
    Packit 209faa
                    const char* = NULL);
    Packit 209faa
        virtual ~base_option(void);
    Packit 209faa
    Packit 209faa
        bool has_short_name(void) const;
    Packit 209faa
        char short_name(void) const;
    Packit 209faa
        const std::string& long_name(void) const;
    Packit 209faa
        const std::string& description(void) const;
    Packit 209faa
    Packit 209faa
        bool needs_arg(void) const;
    Packit 209faa
        const std::string& arg_name(void) const;
    Packit 209faa
    Packit 209faa
        bool has_default_value(void) const;
    Packit 209faa
        const std::string& default_value(void) const;
    Packit 209faa
    Packit 209faa
        std::string format_short_name(void) const;
    Packit 209faa
        std::string format_long_name(void) const;
    Packit 209faa
    Packit 209faa
        virtual void validate(const std::string&) const;
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    /// Definition of a boolean option.
    Packit 209faa
    ///
    Packit 209faa
    /// A boolean option can be specified once in the command line, at which point
    Packit 209faa
    /// is set to true.  Such an option cannot carry optional arguments.
    Packit 209faa
    class bool_option : public base_option {
    Packit 209faa
    public:
    Packit 209faa
        bool_option(const char, const char*, const char*);
    Packit 209faa
        bool_option(const char*, const char*);
    Packit 209faa
        virtual ~bool_option(void) {}
    Packit 209faa
    Packit 209faa
        /// The data type of this option.
    Packit 209faa
        typedef bool option_type;
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    /// Definition of an integer option.
    Packit 209faa
    class int_option : public base_option {
    Packit 209faa
    public:
    Packit 209faa
        int_option(const char, const char*, const char*, const char*,
    Packit 209faa
                   const char* = NULL);
    Packit 209faa
        int_option(const char*, const char*, const char*, const char* = NULL);
    Packit 209faa
        virtual ~int_option(void) {}
    Packit 209faa
    Packit 209faa
        /// The data type of this option.
    Packit 209faa
        typedef int option_type;
    Packit 209faa
    Packit 209faa
        virtual void validate(const std::string& str) const;
    Packit 209faa
        static int convert(const std::string& str);
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    /// Definition of a comma-separated list of strings.
    Packit 209faa
    class list_option : public base_option {
    Packit 209faa
    public:
    Packit 209faa
        list_option(const char, const char*, const char*, const char*,
    Packit 209faa
                    const char* = NULL);
    Packit 209faa
        list_option(const char*, const char*, const char*, const char* = NULL);
    Packit 209faa
        virtual ~list_option(void) {}
    Packit 209faa
    Packit 209faa
        /// The data type of this option.
    Packit 209faa
        typedef std::vector< std::string > option_type;
    Packit 209faa
    Packit 209faa
        virtual void validate(const std::string&) const;
    Packit 209faa
        static option_type convert(const std::string&);
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    /// Definition of an option representing a path.
    Packit 209faa
    ///
    Packit 209faa
    /// The path pointed to by the option may not exist, but it must be
    Packit 209faa
    /// syntactically valid.
    Packit 209faa
    class path_option : public base_option {
    Packit 209faa
    public:
    Packit 209faa
        path_option(const char, const char*, const char*, const char*,
    Packit 209faa
                    const char* = NULL);
    Packit 209faa
        path_option(const char*, const char*, const char*, const char* = NULL);
    Packit 209faa
        virtual ~path_option(void) {}
    Packit 209faa
    Packit 209faa
        /// The data type of this option.
    Packit 209faa
        typedef utils::fs::path option_type;
    Packit 209faa
    Packit 209faa
        virtual void validate(const std::string&) const;
    Packit 209faa
        static utils::fs::path convert(const std::string&);
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    /// Definition of a property option.
    Packit 209faa
    ///
    Packit 209faa
    /// A property option is an option whose required arguments are of the form
    Packit 209faa
    /// 'name=value'.  Both components of the property are treated as free-form
    Packit 209faa
    /// non-empty strings; any other validation must happen on the caller side.
    Packit 209faa
    ///
    Packit 209faa
    /// \todo Would be nice if the delimiter was parametrizable.  With the current
    Packit 209faa
    ///     parser interface (convert() being a static method), the only way to do
    Packit 209faa
    ///     this would be to templatize this class.
    Packit 209faa
    class property_option : public base_option {
    Packit 209faa
    public:
    Packit 209faa
        property_option(const char, const char*, const char*, const char*);
    Packit 209faa
        property_option(const char*, const char*, const char*);
    Packit 209faa
        virtual ~property_option(void) {}
    Packit 209faa
    Packit 209faa
        /// The data type of this option.
    Packit 209faa
        typedef std::pair< std::string, std::string > option_type;
    Packit 209faa
    Packit 209faa
        virtual void validate(const std::string& str) const;
    Packit 209faa
        static option_type convert(const std::string& str);
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    /// Definition of a free-form string option.
    Packit 209faa
    ///
    Packit 209faa
    /// This class provides no restrictions on the argument passed to the option.
    Packit 209faa
    class string_option : public base_option {
    Packit 209faa
    public:
    Packit 209faa
        string_option(const char, const char*, const char*, const char*,
    Packit 209faa
                      const char* = NULL);
    Packit 209faa
        string_option(const char*, const char*, const char*, const char* = NULL);
    Packit 209faa
        virtual ~string_option(void) {}
    Packit 209faa
    Packit 209faa
        /// The data type of this option.
    Packit 209faa
        typedef std::string option_type;
    Packit 209faa
    Packit 209faa
        virtual void validate(const std::string& str) const;
    Packit 209faa
        static std::string convert(const std::string& str);
    Packit 209faa
    };
    Packit 209faa
    Packit 209faa
    Packit 209faa
    }  // namespace cmdline
    Packit 209faa
    }  // namespace utils
    Packit 209faa
    Packit 209faa
    #endif  // !defined(UTILS_CMDLINE_OPTIONS_HPP)