Path: blob/main/contrib/kyua/utils/cmdline/options.hpp
101184 views
// Copyright 2010 The Kyua Authors.1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are5// met:6//7// * Redistributions of source code must retain the above copyright8// notice, this list of conditions and the following disclaimer.9// * Redistributions in binary form must reproduce the above copyright10// notice, this list of conditions and the following disclaimer in the11// documentation and/or other materials provided with the distribution.12// * Neither the name of Google Inc. nor the names of its contributors13// may be used to endorse or promote products derived from this software14// without specific prior written permission.15//16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2728/// \file utils/cmdline/options.hpp29/// Definitions of command-line options.3031#if !defined(UTILS_CMDLINE_OPTIONS_HPP)32#define UTILS_CMDLINE_OPTIONS_HPP3334#include "utils/cmdline/options_fwd.hpp"3536#include <string>37#include <utility>38#include <vector>3940#include "utils/fs/path_fwd.hpp"4142namespace utils {43namespace cmdline {444546/// Type-less base option class.47///48/// This abstract class provides the most generic representation of options. It49/// allows defining options with both short and long names, with and without50/// arguments and with and without optional values. These are all the possible51/// combinations supported by the getopt_long(3) function, on which this is52/// built.53///54/// The internal values (e.g. the default value) of a generic option are all55/// represented as strings. However, from the caller's perspective, this is56/// suboptimal. Hence why this class must be specialized: the subclasses57/// provide type-specific accessors and provide automatic validation of the58/// types (e.g. a string '3foo' is not passed to an integer option).59///60/// Given that subclasses are used through templatized code, they must provide:61///62/// <ul>63/// <li>A public option_type typedef that defines the type of the64/// option.</li>65///66/// <li>A convert() method that takes a string and converts it to67/// option_type. The string can be assumed to be convertible to the68/// destination type. Should not raise exceptions.</li>69///70/// <li>A validate() method that matches the implementation of convert().71/// This method can throw option_argument_value_error if the string cannot72/// be converted appropriately. If validate() does not throw, then73/// convert() must execute successfully.</li>74/// </ul>75///76/// TODO(jmmv): Many methods in this class are split into two parts: has_foo()77/// and foo(), the former to query if the foo is available and the latter to get78/// the foo. It'd be very nice if we'd use something similar Boost.Optional to79/// simplify this interface altogether.80class base_option {81/// Short name of the option; 0 to indicate that none is available.82char _short_name;8384/// Long name of the option.85std::string _long_name;8687/// Textual description of the purpose of the option.88std::string _description;8990/// Descriptive name of the required argument; empty if not allowed.91std::string _arg_name;9293/// If the option can be used without an explicit argument provided.94bool _arg_is_optional = false;9596/// Whether the option has a default value or not.97///98/// \todo We should probably be using the optional class here.99bool _has_default_value;100101/// If _has_default_value is true, the default value.102std::string _default_value;103104public:105base_option(const char, const char*, const char*, const char* = NULL,106const char* = NULL, bool = false);107base_option(const char*, const char*, const char* = NULL,108const char* = NULL);109virtual ~base_option(void);110111bool has_short_name(void) const;112char short_name(void) const;113const std::string& long_name(void) const;114const std::string& description(void) const;115116bool needs_arg(void) const;117const std::string& arg_name(void) const;118bool arg_is_optional(void) const;119120bool has_default_value(void) const;121const std::string& default_value(void) const;122123std::string format_short_name(void) const;124std::string format_long_name(void) const;125126virtual void validate(const std::string&) const;127};128129130/// Definition of a boolean option.131///132/// A boolean option can be specified once in the command line, at which point133/// is set to true. Such an option cannot carry optional arguments.134class bool_option : public base_option {135public:136bool_option(const char, const char*, const char*);137bool_option(const char*, const char*);138virtual ~bool_option(void) {}139140/// The data type of this option.141typedef bool option_type;142};143144145/// Definition of an integer option.146class int_option : public base_option {147public:148int_option(const char, const char*, const char*, const char*,149const char* = NULL);150int_option(const char*, const char*, const char*, const char* = NULL);151virtual ~int_option(void) {}152153/// The data type of this option.154typedef int option_type;155156virtual void validate(const std::string& str) const;157static int convert(const std::string& str);158};159160161/// Definition of a comma-separated list of strings.162class list_option : public base_option {163public:164list_option(const char, const char*, const char*, const char*,165const char* = NULL);166list_option(const char*, const char*, const char*, const char* = NULL);167virtual ~list_option(void) {}168169/// The data type of this option.170typedef std::vector< std::string > option_type;171172virtual void validate(const std::string&) const;173static option_type convert(const std::string&);174};175176177/// Definition of an option representing a path.178///179/// The path pointed to by the option may not exist, but it must be180/// syntactically valid.181class path_option : public base_option {182public:183path_option(const char, const char*, const char*, const char*,184const char* = NULL);185path_option(const char*, const char*, const char*, const char* = NULL);186virtual ~path_option(void) {}187188/// The data type of this option.189typedef utils::fs::path option_type;190191virtual void validate(const std::string&) const;192static utils::fs::path convert(const std::string&);193};194195196/// Definition of a property option.197///198/// A property option is an option whose required arguments are of the form199/// 'name=value'. Both components of the property are treated as free-form200/// non-empty strings; any other validation must happen on the caller side.201///202/// \todo Would be nice if the delimiter was parametrizable. With the current203/// parser interface (convert() being a static method), the only way to do204/// this would be to templatize this class.205class property_option : public base_option {206public:207property_option(const char, const char*, const char*, const char*);208property_option(const char*, const char*, const char*);209virtual ~property_option(void) {}210211/// The data type of this option.212typedef std::pair< std::string, std::string > option_type;213214virtual void validate(const std::string& str) const;215static option_type convert(const std::string& str);216};217218219/// Definition of a free-form string option.220///221/// This class provides no restrictions on the argument passed to the option.222class string_option : public base_option {223public:224string_option(const char, const char*, const char*, const char*,225const char* = NULL, bool = false);226string_option(const char*, const char*, const char*, const char* = NULL);227virtual ~string_option(void) {}228229/// The data type of this option.230typedef std::string option_type;231232virtual void validate(const std::string& str) const;233static std::string convert(const std::string& str);234};235236237} // namespace cmdline238} // namespace utils239240#endif // !defined(UTILS_CMDLINE_OPTIONS_HPP)241242243