1// Copyright 2010 The Kyua Authors.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "utils/cmdline/options.hpp"
30
31#include <stdexcept>
32#include <vector>
33
34#include "utils/cmdline/exceptions.hpp"
35#include "utils/defs.hpp"
36#include "utils/format/macros.hpp"
37#include "utils/fs/exceptions.hpp"
38#include "utils/fs/path.hpp"
39#include "utils/sanity.hpp"
40#include "utils/text/operations.ipp"
41
42namespace cmdline = utils::cmdline;
43namespace text = utils::text;
44
45
46/// Constructs a generic option with both a short and a long name.
47///
48/// \param short_name_ The short name for the option.
49/// \param long_name_ The long name for the option.
50/// \param description_ A user-friendly description for the option.
51/// \param arg_name_ If not NULL, specifies that the option must receive an
52///     argument and specifies the name of such argument for documentation
53///     purposes.
54/// \param default_value_ If not NULL, specifies that the option has a default
55///     value for the mandatory argument.
56cmdline::base_option::base_option(const char short_name_,
57                                  const char* long_name_,
58                                  const char* description_,
59                                  const char* arg_name_,
60                                  const char* default_value_) :
61    _short_name(short_name_),
62    _long_name(long_name_),
63    _description(description_),
64    _arg_name(arg_name_ == NULL ? "" : arg_name_),
65    _has_default_value(default_value_ != NULL),
66    _default_value(default_value_ == NULL ? "" : default_value_)
67{
68    INV(short_name_ != '\0');
69}
70
71
72/// Constructs a generic option with a long name only.
73///
74/// \param long_name_ The long name for the option.
75/// \param description_ A user-friendly description for the option.
76/// \param arg_name_ If not NULL, specifies that the option must receive an
77///     argument and specifies the name of such argument for documentation
78///     purposes.
79/// \param default_value_ If not NULL, specifies that the option has a default
80///     value for the mandatory argument.
81cmdline::base_option::base_option(const char* long_name_,
82                                  const char* description_,
83                                  const char* arg_name_,
84                                  const char* default_value_) :
85    _short_name('\0'),
86    _long_name(long_name_),
87    _description(description_),
88    _arg_name(arg_name_ == NULL ? "" : arg_name_),
89    _has_default_value(default_value_ != NULL),
90    _default_value(default_value_ == NULL ? "" : default_value_)
91{
92}
93
94
95/// Destructor for the option.
96cmdline::base_option::~base_option(void)
97{
98}
99
100
101/// Checks whether the option has a short name or not.
102///
103/// \return True if the option has a short name, false otherwise.
104bool
105cmdline::base_option::has_short_name(void) const
106{
107    return _short_name != '\0';
108}
109
110
111/// Returns the short name of the option.
112///
113/// \pre has_short_name() must be true.
114///
115/// \return The short name.
116char
117cmdline::base_option::short_name(void) const
118{
119    PRE(has_short_name());
120    return _short_name;
121}
122
123
124/// Returns the long name of the option.
125///
126/// \return The long name.
127const std::string&
128cmdline::base_option::long_name(void) const
129{
130    return _long_name;
131}
132
133
134/// Returns the description of the option.
135///
136/// \return The description.
137const std::string&
138cmdline::base_option::description(void) const
139{
140    return _description;
141}
142
143
144/// Checks whether the option needs an argument or not.
145///
146/// \return True if the option needs an argument, false otherwise.
147bool
148cmdline::base_option::needs_arg(void) const
149{
150    return !_arg_name.empty();
151}
152
153
154/// Returns the argument name of the option for documentation purposes.
155///
156/// \pre needs_arg() must be true.
157///
158/// \return The argument name.
159const std::string&
160cmdline::base_option::arg_name(void) const
161{
162    INV(needs_arg());
163    return _arg_name;
164}
165
166
167/// Checks whether the option has a default value for its argument.
168///
169/// \pre needs_arg() must be true.
170///
171/// \return True if the option has a default value, false otherwise.
172bool
173cmdline::base_option::has_default_value(void) const
174{
175    PRE(needs_arg());
176    return _has_default_value;
177}
178
179
180/// Returns the default value for the argument to the option.
181///
182/// \pre has_default_value() must be true.
183///
184/// \return The default value.
185const std::string&
186cmdline::base_option::default_value(void) const
187{
188    INV(has_default_value());
189    return _default_value;;
190}
191
192
193/// Formats the short name of the option for documentation purposes.
194///
195/// \return A string describing the option's short name.
196std::string
197cmdline::base_option::format_short_name(void) const
198{
199    PRE(has_short_name());
200
201    if (needs_arg()) {
202        return F("-%s %s") % short_name() % arg_name();
203    } else {
204        return F("-%s") % short_name();
205    }
206}
207
208
209/// Formats the long name of the option for documentation purposes.
210///
211/// \return A string describing the option's long name.
212std::string
213cmdline::base_option::format_long_name(void) const
214{
215    if (needs_arg()) {
216        return F("--%s=%s") % long_name() % arg_name();
217    } else {
218        return F("--%s") % long_name();
219    }
220}
221
222
223
224/// Ensures that an argument passed to the option is valid.
225///
226/// This must be reimplemented by subclasses that describe options with
227/// arguments.
228///
229/// \throw cmdline::option_argument_value_error Subclasses must raise this
230///     exception to indicate the cases in which str is invalid.
231void
232cmdline::base_option::validate(const std::string& /* str */) const
233{
234    UNREACHABLE_MSG("Option does not support an argument");
235}
236
237
238/// Constructs a boolean option with both a short and a long name.
239///
240/// \param short_name_ The short name for the option.
241/// \param long_name_ The long name for the option.
242/// \param description_ A user-friendly description for the option.
243cmdline::bool_option::bool_option(const char short_name_,
244                                  const char* long_name_,
245                                  const char* description_) :
246    base_option(short_name_, long_name_, description_)
247{
248}
249
250
251/// Constructs a boolean option with a long name only.
252///
253/// \param long_name_ The long name for the option.
254/// \param description_ A user-friendly description for the option.
255cmdline::bool_option::bool_option(const char* long_name_,
256                                  const char* description_) :
257    base_option(long_name_, description_)
258{
259}
260
261
262/// Constructs an integer option with both a short and a long name.
263///
264/// \param short_name_ The short name for the option.
265/// \param long_name_ The long name for the option.
266/// \param description_ A user-friendly description for the option.
267/// \param arg_name_ The name of the mandatory argument, for documentation
268///     purposes.
269/// \param default_value_ If not NULL, the default value for the mandatory
270///     argument.
271cmdline::int_option::int_option(const char short_name_,
272                                const char* long_name_,
273                                const char* description_,
274                                const char* arg_name_,
275                                const char* default_value_) :
276    base_option(short_name_, long_name_, description_, arg_name_,
277                default_value_)
278{
279}
280
281
282/// Constructs an integer option with a long name only.
283///
284/// \param long_name_ The long name for the option.
285/// \param description_ A user-friendly description for the option.
286/// \param arg_name_ The name of the mandatory argument, for documentation
287///     purposes.
288/// \param default_value_ If not NULL, the default value for the mandatory
289///     argument.
290cmdline::int_option::int_option(const char* long_name_,
291                                const char* description_,
292                                const char* arg_name_,
293                                const char* default_value_) :
294    base_option(long_name_, description_, arg_name_, default_value_)
295{
296}
297
298
299/// Ensures that an integer argument passed to the int_option is valid.
300///
301/// \param raw_value The argument representing an integer as provided by the
302///     user.
303///
304/// \throw cmdline::option_argument_value_error If the integer provided in
305///     raw_value is invalid.
306void
307cmdline::int_option::validate(const std::string& raw_value) const
308{
309    try {
310        (void)text::to_type< int >(raw_value);
311    } catch (const std::runtime_error& e) {
312        throw cmdline::option_argument_value_error(
313            F("--%s") % long_name(), raw_value, "Not a valid integer");
314    }
315}
316
317
318/// Converts an integer argument to a native integer.
319///
320/// \param raw_value The argument representing an integer as provided by the
321///     user.
322///
323/// \return The integer.
324///
325/// \pre validate(raw_value) must be true.
326int
327cmdline::int_option::convert(const std::string& raw_value)
328{
329    try {
330        return text::to_type< int >(raw_value);
331    } catch (const std::runtime_error& e) {
332        PRE_MSG(false, F("Raw value '%s' for int option not properly "
333                         "validated: %s") % raw_value % e.what());
334    }
335}
336
337
338/// Constructs a list option with both a short and a long name.
339///
340/// \param short_name_ The short name for the option.
341/// \param long_name_ The long name for the option.
342/// \param description_ A user-friendly description for the option.
343/// \param arg_name_ The name of the mandatory argument, for documentation
344///     purposes.
345/// \param default_value_ If not NULL, the default value for the mandatory
346///     argument.
347cmdline::list_option::list_option(const char short_name_,
348                                  const char* long_name_,
349                                  const char* description_,
350                                  const char* arg_name_,
351                                  const char* default_value_) :
352    base_option(short_name_, long_name_, description_, arg_name_,
353                default_value_)
354{
355}
356
357
358/// Constructs a list option with a long name only.
359///
360/// \param long_name_ The long name for the option.
361/// \param description_ A user-friendly description for the option.
362/// \param arg_name_ The name of the mandatory argument, for documentation
363///     purposes.
364/// \param default_value_ If not NULL, the default value for the mandatory
365///     argument.
366cmdline::list_option::list_option(const char* long_name_,
367                                  const char* description_,
368                                  const char* arg_name_,
369                                  const char* default_value_) :
370    base_option(long_name_, description_, arg_name_, default_value_)
371{
372}
373
374
375/// Ensures that a lisstring argument passed to the list_option is valid.
376void
377cmdline::list_option::validate(
378    const std::string& /* raw_value */) const
379{
380    // Any list is potentially valid; the caller must check for semantics.
381}
382
383
384/// Converts a string argument to a vector.
385///
386/// \param raw_value The argument representing a list as provided by the user.
387///
388/// \return The list.
389///
390/// \pre validate(raw_value) must be true.
391cmdline::list_option::option_type
392cmdline::list_option::convert(const std::string& raw_value)
393{
394    try {
395        return text::split(raw_value, ',');
396    } catch (const std::runtime_error& e) {
397        PRE_MSG(false, F("Raw value '%s' for list option not properly "
398                         "validated: %s") % raw_value % e.what());
399    }
400}
401
402
403/// Constructs a path option with both a short and a long name.
404///
405/// \param short_name_ The short name for the option.
406/// \param long_name_ The long name for the option.
407/// \param description_ A user-friendly description for the option.
408/// \param arg_name_ The name of the mandatory argument, for documentation
409///     purposes.
410/// \param default_value_ If not NULL, the default value for the mandatory
411///     argument.
412cmdline::path_option::path_option(const char short_name_,
413                                  const char* long_name_,
414                                  const char* description_,
415                                  const char* arg_name_,
416                                  const char* default_value_) :
417    base_option(short_name_, long_name_, description_, arg_name_,
418                default_value_)
419{
420}
421
422
423/// Constructs a path option with a long name only.
424///
425/// \param long_name_ The long name for the option.
426/// \param description_ A user-friendly description for the option.
427/// \param arg_name_ The name of the mandatory argument, for documentation
428///     purposes.
429/// \param default_value_ If not NULL, the default value for the mandatory
430///     argument.
431cmdline::path_option::path_option(const char* long_name_,
432                                  const char* description_,
433                                  const char* arg_name_,
434                                  const char* default_value_) :
435    base_option(long_name_, description_, arg_name_, default_value_)
436{
437}
438
439
440/// Ensures that a path argument passed to the path_option is valid.
441///
442/// \param raw_value The argument representing a path as provided by the user.
443///
444/// \throw cmdline::option_argument_value_error If the path provided in
445///     raw_value is invalid.
446void
447cmdline::path_option::validate(const std::string& raw_value) const
448{
449    try {
450        (void)utils::fs::path(raw_value);
451    } catch (const utils::fs::error& e) {
452        throw cmdline::option_argument_value_error(F("--%s") % long_name(),
453                                                   raw_value, e.what());
454    }
455}
456
457
458/// Converts a path argument to a utils::fs::path.
459///
460/// \param raw_value The argument representing a path as provided by the user.
461///
462/// \return The path.
463///
464/// \pre validate(raw_value) must be true.
465utils::fs::path
466cmdline::path_option::convert(const std::string& raw_value)
467{
468    try {
469        return utils::fs::path(raw_value);
470    } catch (const std::runtime_error& e) {
471        PRE_MSG(false, F("Raw value '%s' for path option not properly "
472                         "validated: %s") % raw_value % e.what());
473    }
474}
475
476
477/// Constructs a property option with both a short and a long name.
478///
479/// \param short_name_ The short name for the option.
480/// \param long_name_ The long name for the option.
481/// \param description_ A user-friendly description for the option.
482/// \param arg_name_ The name of the mandatory argument, for documentation
483///     purposes.  Must include the '=' delimiter.
484cmdline::property_option::property_option(const char short_name_,
485                                          const char* long_name_,
486                                          const char* description_,
487                                          const char* arg_name_) :
488    base_option(short_name_, long_name_, description_, arg_name_)
489{
490    PRE(arg_name().find('=') != std::string::npos);
491}
492
493
494/// Constructs a property option with a long name only.
495///
496/// \param long_name_ The long name for the option.
497/// \param description_ A user-friendly description for the option.
498/// \param arg_name_ The name of the mandatory argument, for documentation
499///     purposes.  Must include the '=' delimiter.
500cmdline::property_option::property_option(const char* long_name_,
501                                          const char* description_,
502                                          const char* arg_name_) :
503    base_option(long_name_, description_, arg_name_)
504{
505    PRE(arg_name().find('=') != std::string::npos);
506}
507
508
509/// Validates the argument to a property option.
510///
511/// \param raw_value The argument provided by the user.
512void
513cmdline::property_option::validate(const std::string& raw_value) const
514{
515    const std::string::size_type pos = raw_value.find('=');
516    if (pos == std::string::npos)
517        throw cmdline::option_argument_value_error(
518            F("--%s") % long_name(), raw_value,
519            F("Argument does not have the form '%s'") % arg_name());
520
521    const std::string key = raw_value.substr(0, pos);
522    if (key.empty())
523        throw cmdline::option_argument_value_error(
524            F("--%s") % long_name(), raw_value, "Empty property name");
525
526    const std::string value = raw_value.substr(pos + 1);
527    if (value.empty())
528        throw cmdline::option_argument_value_error(
529            F("--%s") % long_name(), raw_value, "Empty value");
530}
531
532
533/// Returns the property option in a key/value pair form.
534///
535/// \param raw_value The argument provided by the user.
536///
537/// \return raw_value The key/value pair representation of the property.
538///
539/// \pre validate(raw_value) must be true.
540cmdline::property_option::option_type
541cmdline::property_option::convert(const std::string& raw_value)
542{
543    const std::string::size_type pos = raw_value.find('=');
544    return std::make_pair(raw_value.substr(0, pos), raw_value.substr(pos + 1));
545}
546
547
548/// Constructs a string option with both a short and a long name.
549///
550/// \param short_name_ The short name for the option.
551/// \param long_name_ The long name for the option.
552/// \param description_ A user-friendly description for the option.
553/// \param arg_name_ The name of the mandatory argument, for documentation
554///     purposes.
555/// \param default_value_ If not NULL, the default value for the mandatory
556///     argument.
557cmdline::string_option::string_option(const char short_name_,
558                                      const char* long_name_,
559                                      const char* description_,
560                                      const char* arg_name_,
561                                      const char* default_value_) :
562    base_option(short_name_, long_name_, description_, arg_name_,
563                default_value_)
564{
565}
566
567
568/// Constructs a string option with a long name only.
569///
570/// \param long_name_ The long name for the option.
571/// \param description_ A user-friendly description for the option.
572/// \param arg_name_ The name of the mandatory argument, for documentation
573///     purposes.
574/// \param default_value_ If not NULL, the default value for the mandatory
575///     argument.
576cmdline::string_option::string_option(const char* long_name_,
577                                      const char* description_,
578                                      const char* arg_name_,
579                                      const char* default_value_) :
580    base_option(long_name_, description_, arg_name_, default_value_)
581{
582}
583
584
585/// Does nothing; all string values are valid arguments to a string_option.
586void
587cmdline::string_option::validate(
588    const std::string& /* raw_value */) const
589{
590    // Nothing to do.
591}
592
593
594/// Returns the string unmodified.
595///
596/// \param raw_value The argument provided by the user.
597///
598/// \return raw_value
599///
600/// \pre validate(raw_value) must be true.
601std::string
602cmdline::string_option::convert(const std::string& raw_value)
603{
604    return raw_value;
605}
606