1*b0d29bc4SBrooks Davis // Copyright 2010 The Kyua Authors. 2*b0d29bc4SBrooks Davis // All rights reserved. 3*b0d29bc4SBrooks Davis // 4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without 5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are 6*b0d29bc4SBrooks Davis // met: 7*b0d29bc4SBrooks Davis // 8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright 9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer. 10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright 11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the 12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution. 13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors 14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software 15*b0d29bc4SBrooks Davis // without specific prior written permission. 16*b0d29bc4SBrooks Davis // 17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*b0d29bc4SBrooks Davis 29*b0d29bc4SBrooks Davis /// \file utils/cmdline/options.hpp 30*b0d29bc4SBrooks Davis /// Definitions of command-line options. 31*b0d29bc4SBrooks Davis 32*b0d29bc4SBrooks Davis #if !defined(UTILS_CMDLINE_OPTIONS_HPP) 33*b0d29bc4SBrooks Davis #define UTILS_CMDLINE_OPTIONS_HPP 34*b0d29bc4SBrooks Davis 35*b0d29bc4SBrooks Davis #include "utils/cmdline/options_fwd.hpp" 36*b0d29bc4SBrooks Davis 37*b0d29bc4SBrooks Davis #include <string> 38*b0d29bc4SBrooks Davis #include <utility> 39*b0d29bc4SBrooks Davis #include <vector> 40*b0d29bc4SBrooks Davis 41*b0d29bc4SBrooks Davis #include "utils/fs/path_fwd.hpp" 42*b0d29bc4SBrooks Davis 43*b0d29bc4SBrooks Davis namespace utils { 44*b0d29bc4SBrooks Davis namespace cmdline { 45*b0d29bc4SBrooks Davis 46*b0d29bc4SBrooks Davis 47*b0d29bc4SBrooks Davis /// Type-less base option class. 48*b0d29bc4SBrooks Davis /// 49*b0d29bc4SBrooks Davis /// This abstract class provides the most generic representation of options. It 50*b0d29bc4SBrooks Davis /// allows defining options with both short and long names, with and without 51*b0d29bc4SBrooks Davis /// arguments and with and without optional values. These are all the possible 52*b0d29bc4SBrooks Davis /// combinations supported by the getopt_long(3) function, on which this is 53*b0d29bc4SBrooks Davis /// built. 54*b0d29bc4SBrooks Davis /// 55*b0d29bc4SBrooks Davis /// The internal values (e.g. the default value) of a generic option are all 56*b0d29bc4SBrooks Davis /// represented as strings. However, from the caller's perspective, this is 57*b0d29bc4SBrooks Davis /// suboptimal. Hence why this class must be specialized: the subclasses 58*b0d29bc4SBrooks Davis /// provide type-specific accessors and provide automatic validation of the 59*b0d29bc4SBrooks Davis /// types (e.g. a string '3foo' is not passed to an integer option). 60*b0d29bc4SBrooks Davis /// 61*b0d29bc4SBrooks Davis /// Given that subclasses are used through templatized code, they must provide: 62*b0d29bc4SBrooks Davis /// 63*b0d29bc4SBrooks Davis /// <ul> 64*b0d29bc4SBrooks Davis /// <li>A public option_type typedef that defines the type of the 65*b0d29bc4SBrooks Davis /// option.</li> 66*b0d29bc4SBrooks Davis /// 67*b0d29bc4SBrooks Davis /// <li>A convert() method that takes a string and converts it to 68*b0d29bc4SBrooks Davis /// option_type. The string can be assumed to be convertible to the 69*b0d29bc4SBrooks Davis /// destination type. Should not raise exceptions.</li> 70*b0d29bc4SBrooks Davis /// 71*b0d29bc4SBrooks Davis /// <li>A validate() method that matches the implementation of convert(). 72*b0d29bc4SBrooks Davis /// This method can throw option_argument_value_error if the string cannot 73*b0d29bc4SBrooks Davis /// be converted appropriately. If validate() does not throw, then 74*b0d29bc4SBrooks Davis /// convert() must execute successfully.</li> 75*b0d29bc4SBrooks Davis /// </ul> 76*b0d29bc4SBrooks Davis /// 77*b0d29bc4SBrooks Davis /// TODO(jmmv): Many methods in this class are split into two parts: has_foo() 78*b0d29bc4SBrooks Davis /// and foo(), the former to query if the foo is available and the latter to get 79*b0d29bc4SBrooks Davis /// the foo. It'd be very nice if we'd use something similar Boost.Optional to 80*b0d29bc4SBrooks Davis /// simplify this interface altogether. 81*b0d29bc4SBrooks Davis class base_option { 82*b0d29bc4SBrooks Davis /// Short name of the option; 0 to indicate that none is available. 83*b0d29bc4SBrooks Davis char _short_name; 84*b0d29bc4SBrooks Davis 85*b0d29bc4SBrooks Davis /// Long name of the option. 86*b0d29bc4SBrooks Davis std::string _long_name; 87*b0d29bc4SBrooks Davis 88*b0d29bc4SBrooks Davis /// Textual description of the purpose of the option. 89*b0d29bc4SBrooks Davis std::string _description; 90*b0d29bc4SBrooks Davis 91*b0d29bc4SBrooks Davis /// Descriptive name of the required argument; empty if not allowed. 92*b0d29bc4SBrooks Davis std::string _arg_name; 93*b0d29bc4SBrooks Davis 94*b0d29bc4SBrooks Davis /// Whether the option has a default value or not. 95*b0d29bc4SBrooks Davis /// 96*b0d29bc4SBrooks Davis /// \todo We should probably be using the optional class here. 97*b0d29bc4SBrooks Davis bool _has_default_value; 98*b0d29bc4SBrooks Davis 99*b0d29bc4SBrooks Davis /// If _has_default_value is true, the default value. 100*b0d29bc4SBrooks Davis std::string _default_value; 101*b0d29bc4SBrooks Davis 102*b0d29bc4SBrooks Davis public: 103*b0d29bc4SBrooks Davis base_option(const char, const char*, const char*, const char* = NULL, 104*b0d29bc4SBrooks Davis const char* = NULL); 105*b0d29bc4SBrooks Davis base_option(const char*, const char*, const char* = NULL, 106*b0d29bc4SBrooks Davis const char* = NULL); 107*b0d29bc4SBrooks Davis virtual ~base_option(void); 108*b0d29bc4SBrooks Davis 109*b0d29bc4SBrooks Davis bool has_short_name(void) const; 110*b0d29bc4SBrooks Davis char short_name(void) const; 111*b0d29bc4SBrooks Davis const std::string& long_name(void) const; 112*b0d29bc4SBrooks Davis const std::string& description(void) const; 113*b0d29bc4SBrooks Davis 114*b0d29bc4SBrooks Davis bool needs_arg(void) const; 115*b0d29bc4SBrooks Davis const std::string& arg_name(void) const; 116*b0d29bc4SBrooks Davis 117*b0d29bc4SBrooks Davis bool has_default_value(void) const; 118*b0d29bc4SBrooks Davis const std::string& default_value(void) const; 119*b0d29bc4SBrooks Davis 120*b0d29bc4SBrooks Davis std::string format_short_name(void) const; 121*b0d29bc4SBrooks Davis std::string format_long_name(void) const; 122*b0d29bc4SBrooks Davis 123*b0d29bc4SBrooks Davis virtual void validate(const std::string&) const; 124*b0d29bc4SBrooks Davis }; 125*b0d29bc4SBrooks Davis 126*b0d29bc4SBrooks Davis 127*b0d29bc4SBrooks Davis /// Definition of a boolean option. 128*b0d29bc4SBrooks Davis /// 129*b0d29bc4SBrooks Davis /// A boolean option can be specified once in the command line, at which point 130*b0d29bc4SBrooks Davis /// is set to true. Such an option cannot carry optional arguments. 131*b0d29bc4SBrooks Davis class bool_option : public base_option { 132*b0d29bc4SBrooks Davis public: 133*b0d29bc4SBrooks Davis bool_option(const char, const char*, const char*); 134*b0d29bc4SBrooks Davis bool_option(const char*, const char*); ~bool_option(void)135*b0d29bc4SBrooks Davis virtual ~bool_option(void) {} 136*b0d29bc4SBrooks Davis 137*b0d29bc4SBrooks Davis /// The data type of this option. 138*b0d29bc4SBrooks Davis typedef bool option_type; 139*b0d29bc4SBrooks Davis }; 140*b0d29bc4SBrooks Davis 141*b0d29bc4SBrooks Davis 142*b0d29bc4SBrooks Davis /// Definition of an integer option. 143*b0d29bc4SBrooks Davis class int_option : public base_option { 144*b0d29bc4SBrooks Davis public: 145*b0d29bc4SBrooks Davis int_option(const char, const char*, const char*, const char*, 146*b0d29bc4SBrooks Davis const char* = NULL); 147*b0d29bc4SBrooks Davis int_option(const char*, const char*, const char*, const char* = NULL); ~int_option(void)148*b0d29bc4SBrooks Davis virtual ~int_option(void) {} 149*b0d29bc4SBrooks Davis 150*b0d29bc4SBrooks Davis /// The data type of this option. 151*b0d29bc4SBrooks Davis typedef int option_type; 152*b0d29bc4SBrooks Davis 153*b0d29bc4SBrooks Davis virtual void validate(const std::string& str) const; 154*b0d29bc4SBrooks Davis static int convert(const std::string& str); 155*b0d29bc4SBrooks Davis }; 156*b0d29bc4SBrooks Davis 157*b0d29bc4SBrooks Davis 158*b0d29bc4SBrooks Davis /// Definition of a comma-separated list of strings. 159*b0d29bc4SBrooks Davis class list_option : public base_option { 160*b0d29bc4SBrooks Davis public: 161*b0d29bc4SBrooks Davis list_option(const char, const char*, const char*, const char*, 162*b0d29bc4SBrooks Davis const char* = NULL); 163*b0d29bc4SBrooks Davis list_option(const char*, const char*, const char*, const char* = NULL); ~list_option(void)164*b0d29bc4SBrooks Davis virtual ~list_option(void) {} 165*b0d29bc4SBrooks Davis 166*b0d29bc4SBrooks Davis /// The data type of this option. 167*b0d29bc4SBrooks Davis typedef std::vector< std::string > option_type; 168*b0d29bc4SBrooks Davis 169*b0d29bc4SBrooks Davis virtual void validate(const std::string&) const; 170*b0d29bc4SBrooks Davis static option_type convert(const std::string&); 171*b0d29bc4SBrooks Davis }; 172*b0d29bc4SBrooks Davis 173*b0d29bc4SBrooks Davis 174*b0d29bc4SBrooks Davis /// Definition of an option representing a path. 175*b0d29bc4SBrooks Davis /// 176*b0d29bc4SBrooks Davis /// The path pointed to by the option may not exist, but it must be 177*b0d29bc4SBrooks Davis /// syntactically valid. 178*b0d29bc4SBrooks Davis class path_option : public base_option { 179*b0d29bc4SBrooks Davis public: 180*b0d29bc4SBrooks Davis path_option(const char, const char*, const char*, const char*, 181*b0d29bc4SBrooks Davis const char* = NULL); 182*b0d29bc4SBrooks Davis path_option(const char*, const char*, const char*, const char* = NULL); ~path_option(void)183*b0d29bc4SBrooks Davis virtual ~path_option(void) {} 184*b0d29bc4SBrooks Davis 185*b0d29bc4SBrooks Davis /// The data type of this option. 186*b0d29bc4SBrooks Davis typedef utils::fs::path option_type; 187*b0d29bc4SBrooks Davis 188*b0d29bc4SBrooks Davis virtual void validate(const std::string&) const; 189*b0d29bc4SBrooks Davis static utils::fs::path convert(const std::string&); 190*b0d29bc4SBrooks Davis }; 191*b0d29bc4SBrooks Davis 192*b0d29bc4SBrooks Davis 193*b0d29bc4SBrooks Davis /// Definition of a property option. 194*b0d29bc4SBrooks Davis /// 195*b0d29bc4SBrooks Davis /// A property option is an option whose required arguments are of the form 196*b0d29bc4SBrooks Davis /// 'name=value'. Both components of the property are treated as free-form 197*b0d29bc4SBrooks Davis /// non-empty strings; any other validation must happen on the caller side. 198*b0d29bc4SBrooks Davis /// 199*b0d29bc4SBrooks Davis /// \todo Would be nice if the delimiter was parametrizable. With the current 200*b0d29bc4SBrooks Davis /// parser interface (convert() being a static method), the only way to do 201*b0d29bc4SBrooks Davis /// this would be to templatize this class. 202*b0d29bc4SBrooks Davis class property_option : public base_option { 203*b0d29bc4SBrooks Davis public: 204*b0d29bc4SBrooks Davis property_option(const char, const char*, const char*, const char*); 205*b0d29bc4SBrooks Davis property_option(const char*, const char*, const char*); ~property_option(void)206*b0d29bc4SBrooks Davis virtual ~property_option(void) {} 207*b0d29bc4SBrooks Davis 208*b0d29bc4SBrooks Davis /// The data type of this option. 209*b0d29bc4SBrooks Davis typedef std::pair< std::string, std::string > option_type; 210*b0d29bc4SBrooks Davis 211*b0d29bc4SBrooks Davis virtual void validate(const std::string& str) const; 212*b0d29bc4SBrooks Davis static option_type convert(const std::string& str); 213*b0d29bc4SBrooks Davis }; 214*b0d29bc4SBrooks Davis 215*b0d29bc4SBrooks Davis 216*b0d29bc4SBrooks Davis /// Definition of a free-form string option. 217*b0d29bc4SBrooks Davis /// 218*b0d29bc4SBrooks Davis /// This class provides no restrictions on the argument passed to the option. 219*b0d29bc4SBrooks Davis class string_option : public base_option { 220*b0d29bc4SBrooks Davis public: 221*b0d29bc4SBrooks Davis string_option(const char, const char*, const char*, const char*, 222*b0d29bc4SBrooks Davis const char* = NULL); 223*b0d29bc4SBrooks Davis string_option(const char*, const char*, const char*, const char* = NULL); ~string_option(void)224*b0d29bc4SBrooks Davis virtual ~string_option(void) {} 225*b0d29bc4SBrooks Davis 226*b0d29bc4SBrooks Davis /// The data type of this option. 227*b0d29bc4SBrooks Davis typedef std::string option_type; 228*b0d29bc4SBrooks Davis 229*b0d29bc4SBrooks Davis virtual void validate(const std::string& str) const; 230*b0d29bc4SBrooks Davis static std::string convert(const std::string& str); 231*b0d29bc4SBrooks Davis }; 232*b0d29bc4SBrooks Davis 233*b0d29bc4SBrooks Davis 234*b0d29bc4SBrooks Davis } // namespace cmdline 235*b0d29bc4SBrooks Davis } // namespace utils 236*b0d29bc4SBrooks Davis 237*b0d29bc4SBrooks Davis #endif // !defined(UTILS_CMDLINE_OPTIONS_HPP) 238