xref: /freebsd/contrib/kyua/utils/cmdline/options.hpp (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
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