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