1 // Copyright 2010 Google Inc.
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/sanity.hpp"
39 #include "utils/text/operations.ipp"
40
41 namespace cmdline = utils::cmdline;
42 namespace text = utils::text;
43
44
45 /// Constructs a generic option with both a short and a long name.
46 ///
47 /// \param short_name_ The short name for the option.
48 /// \param long_name_ The long name for the option.
49 /// \param description_ A user-friendly description for the option.
50 /// \param arg_name_ If not NULL, specifies that the option must receive an
51 /// argument and specifies the name of such argument for documentation
52 /// purposes.
53 /// \param default_value_ If not NULL, specifies that the option has a default
54 /// value for the mandatory argument.
base_option(const char short_name_,const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)55 cmdline::base_option::base_option(const char short_name_,
56 const char* long_name_,
57 const char* description_,
58 const char* arg_name_,
59 const char* default_value_) :
60 _short_name(short_name_),
61 _long_name(long_name_),
62 _description(description_),
63 _arg_name(arg_name_ == NULL ? "" : arg_name_),
64 _has_default_value(default_value_ != NULL),
65 _default_value(default_value_ == NULL ? "" : default_value_)
66 {
67 INV(short_name_ != '\0');
68 }
69
70
71 /// Constructs a generic option with a long name only.
72 ///
73 /// \param long_name_ The long name for the option.
74 /// \param description_ A user-friendly description for the option.
75 /// \param arg_name_ If not NULL, specifies that the option must receive an
76 /// argument and specifies the name of such argument for documentation
77 /// purposes.
78 /// \param default_value_ If not NULL, specifies that the option has a default
79 /// value for the mandatory argument.
base_option(const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)80 cmdline::base_option::base_option(const char* long_name_,
81 const char* description_,
82 const char* arg_name_,
83 const char* default_value_) :
84 _short_name('\0'),
85 _long_name(long_name_),
86 _description(description_),
87 _arg_name(arg_name_ == NULL ? "" : arg_name_),
88 _has_default_value(default_value_ != NULL),
89 _default_value(default_value_ == NULL ? "" : default_value_)
90 {
91 }
92
93
94 /// Destructor for the option.
~base_option(void)95 cmdline::base_option::~base_option(void)
96 {
97 }
98
99
100 /// Checks whether the option has a short name or not.
101 ///
102 /// \return True if the option has a short name, false otherwise.
103 bool
has_short_name(void) const104 cmdline::base_option::has_short_name(void) const
105 {
106 return _short_name != '\0';
107 }
108
109
110 /// Returns the short name of the option.
111 ///
112 /// \pre has_short_name() must be true.
113 ///
114 /// \return The short name.
115 char
short_name(void) const116 cmdline::base_option::short_name(void) const
117 {
118 PRE(has_short_name());
119 return _short_name;
120 }
121
122
123 /// Returns the long name of the option.
124 ///
125 /// \return The long name.
126 const std::string&
long_name(void) const127 cmdline::base_option::long_name(void) const
128 {
129 return _long_name;
130 }
131
132
133 /// Returns the description of the option.
134 ///
135 /// \return The description.
136 const std::string&
description(void) const137 cmdline::base_option::description(void) const
138 {
139 return _description;
140 }
141
142
143 /// Checks whether the option needs an argument or not.
144 ///
145 /// \return True if the option needs an argument, false otherwise.
146 bool
needs_arg(void) const147 cmdline::base_option::needs_arg(void) const
148 {
149 return !_arg_name.empty();
150 }
151
152
153 /// Returns the argument name of the option for documentation purposes.
154 ///
155 /// \pre needs_arg() must be true.
156 ///
157 /// \return The argument name.
158 const std::string&
arg_name(void) const159 cmdline::base_option::arg_name(void) const
160 {
161 INV(needs_arg());
162 return _arg_name;
163 }
164
165
166 /// Checks whether the option has a default value for its argument.
167 ///
168 /// \pre needs_arg() must be true.
169 ///
170 /// \return True if the option has a default value, false otherwise.
171 bool
has_default_value(void) const172 cmdline::base_option::has_default_value(void) const
173 {
174 PRE(needs_arg());
175 return _has_default_value;
176 }
177
178
179 /// Returns the default value for the argument to the option.
180 ///
181 /// \pre has_default_value() must be true.
182 ///
183 /// \return The default value.
184 const std::string&
default_value(void) const185 cmdline::base_option::default_value(void) const
186 {
187 INV(has_default_value());
188 return _default_value;;
189 }
190
191
192 /// Formats the short name of the option for documentation purposes.
193 ///
194 /// \return A string describing the option's short name.
195 std::string
format_short_name(void) const196 cmdline::base_option::format_short_name(void) const
197 {
198 PRE(has_short_name());
199
200 if (needs_arg()) {
201 return F("-%s %s") % short_name() % arg_name();
202 } else {
203 return F("-%s") % short_name();
204 }
205 }
206
207
208 /// Formats the long name of the option for documentation purposes.
209 ///
210 /// \return A string describing the option's long name.
211 std::string
format_long_name(void) const212 cmdline::base_option::format_long_name(void) const
213 {
214 if (needs_arg()) {
215 return F("--%s=%s") % long_name() % arg_name();
216 } else {
217 return F("--%s") % long_name();
218 }
219 }
220
221
222
223 /// Ensures that an argument passed to the option is valid.
224 ///
225 /// This must be reimplemented by subclasses that describe options with
226 /// arguments.
227 ///
228 /// \param unused_str The argument to validate as provided by the user in the
229 /// command line.
230 ///
231 /// \throw cmdline::option_argument_value_error Subclasses must raise this
232 /// exception to indicate the cases in which str is invalid.
233 void
validate(const std::string & UTILS_UNUSED_PARAM (str)) const234 cmdline::base_option::validate(const std::string& UTILS_UNUSED_PARAM(str)) const
235 {
236 UNREACHABLE_MSG("Option does not support an argument");
237 }
238
239
240 /// Constructs a boolean option with both a short and a long name.
241 ///
242 /// \param short_name_ The short name for the option.
243 /// \param long_name_ The long name for the option.
244 /// \param description_ A user-friendly description for the option.
bool_option(const char short_name_,const char * long_name_,const char * description_)245 cmdline::bool_option::bool_option(const char short_name_,
246 const char* long_name_,
247 const char* description_) :
248 base_option(short_name_, long_name_, description_)
249 {
250 }
251
252
253 /// Constructs a boolean option with a long name only.
254 ///
255 /// \param long_name_ The long name for the option.
256 /// \param description_ A user-friendly description for the option.
bool_option(const char * long_name_,const char * description_)257 cmdline::bool_option::bool_option(const char* long_name_,
258 const char* description_) :
259 base_option(long_name_, description_)
260 {
261 }
262
263
264 /// Constructs an integer option with both a short and a long name.
265 ///
266 /// \param short_name_ The short name for the option.
267 /// \param long_name_ The long name for the option.
268 /// \param description_ A user-friendly description for the option.
269 /// \param arg_name_ The name of the mandatory argument, for documentation
270 /// purposes.
271 /// \param default_value_ If not NULL, the default value for the mandatory
272 /// argument.
int_option(const char short_name_,const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)273 cmdline::int_option::int_option(const char short_name_,
274 const char* long_name_,
275 const char* description_,
276 const char* arg_name_,
277 const char* default_value_) :
278 base_option(short_name_, long_name_, description_, arg_name_,
279 default_value_)
280 {
281 }
282
283
284 /// Constructs an integer option with a long name only.
285 ///
286 /// \param long_name_ The long name for the option.
287 /// \param description_ A user-friendly description for the option.
288 /// \param arg_name_ The name of the mandatory argument, for documentation
289 /// purposes.
290 /// \param default_value_ If not NULL, the default value for the mandatory
291 /// argument.
int_option(const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)292 cmdline::int_option::int_option(const char* long_name_,
293 const char* description_,
294 const char* arg_name_,
295 const char* default_value_) :
296 base_option(long_name_, description_, arg_name_, default_value_)
297 {
298 }
299
300
301 /// Ensures that an integer argument passed to the int_option is valid.
302 ///
303 /// \param raw_value The argument representing an integer as provided by the
304 /// user.
305 ///
306 /// \throw cmdline::option_argument_value_error If the integer provided in
307 /// raw_value is invalid.
308 void
validate(const std::string & raw_value) const309 cmdline::int_option::validate(const std::string& raw_value) const
310 {
311 try {
312 (void)text::to_type< int >(raw_value);
313 } catch (const std::runtime_error& e) {
314 throw cmdline::option_argument_value_error(
315 F("--%s") % long_name(), raw_value, "Not a valid integer");
316 }
317 }
318
319
320 /// Converts an integer argument to a native integer.
321 ///
322 /// \param raw_value The argument representing an integer as provided by the
323 /// user.
324 ///
325 /// \return The integer.
326 ///
327 /// \pre validate(raw_value) must be true.
328 int
convert(const std::string & raw_value)329 cmdline::int_option::convert(const std::string& raw_value)
330 {
331 try {
332 return text::to_type< int >(raw_value);
333 } catch (const std::runtime_error& e) {
334 PRE_MSG(false, F("Raw value '%s' for int option not properly "
335 "validated: %s") % raw_value % e.what());
336 }
337 }
338
339
340 /// Constructs a list option with both a short and a long name.
341 ///
342 /// \param short_name_ The short name for the option.
343 /// \param long_name_ The long name for the option.
344 /// \param description_ A user-friendly description for the option.
345 /// \param arg_name_ The name of the mandatory argument, for documentation
346 /// purposes.
347 /// \param default_value_ If not NULL, the default value for the mandatory
348 /// argument.
list_option(const char short_name_,const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)349 cmdline::list_option::list_option(const char short_name_,
350 const char* long_name_,
351 const char* description_,
352 const char* arg_name_,
353 const char* default_value_) :
354 base_option(short_name_, long_name_, description_, arg_name_,
355 default_value_)
356 {
357 }
358
359
360 /// Constructs a list option with a long name only.
361 ///
362 /// \param long_name_ The long name for the option.
363 /// \param description_ A user-friendly description for the option.
364 /// \param arg_name_ The name of the mandatory argument, for documentation
365 /// purposes.
366 /// \param default_value_ If not NULL, the default value for the mandatory
367 /// argument.
list_option(const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)368 cmdline::list_option::list_option(const char* long_name_,
369 const char* description_,
370 const char* arg_name_,
371 const char* default_value_) :
372 base_option(long_name_, description_, arg_name_, default_value_)
373 {
374 }
375
376
377 /// Ensures that a lisstring argument passed to the list_option is valid.
378 ///
379 /// \param unused_raw_value The argument representing a list as provided by the
380 /// user.
381 void
validate(const std::string & UTILS_UNUSED_PARAM (raw_value)) const382 cmdline::list_option::validate(
383 const std::string& UTILS_UNUSED_PARAM(raw_value)) const
384 {
385 // Any list is potentially valid; the caller must check for semantics.
386 }
387
388
389 /// Converts a string argument to a vector.
390 ///
391 /// \param raw_value The argument representing a list as provided by the user.
392 ///
393 /// \return The list.
394 ///
395 /// \pre validate(raw_value) must be true.
396 cmdline::list_option::option_type
convert(const std::string & raw_value)397 cmdline::list_option::convert(const std::string& raw_value)
398 {
399 try {
400 return text::split(raw_value, ',');
401 } catch (const std::runtime_error& e) {
402 PRE_MSG(false, F("Raw value '%s' for list option not properly "
403 "validated: %s") % raw_value % e.what());
404 }
405 }
406
407
408 /// Constructs a path option with both a short and a long name.
409 ///
410 /// \param short_name_ The short name for the option.
411 /// \param long_name_ The long name for the option.
412 /// \param description_ A user-friendly description for the option.
413 /// \param arg_name_ The name of the mandatory argument, for documentation
414 /// purposes.
415 /// \param default_value_ If not NULL, the default value for the mandatory
416 /// argument.
path_option(const char short_name_,const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)417 cmdline::path_option::path_option(const char short_name_,
418 const char* long_name_,
419 const char* description_,
420 const char* arg_name_,
421 const char* default_value_) :
422 base_option(short_name_, long_name_, description_, arg_name_,
423 default_value_)
424 {
425 }
426
427
428 /// Constructs a path option with a long name only.
429 ///
430 /// \param long_name_ The long name for the option.
431 /// \param description_ A user-friendly description for the option.
432 /// \param arg_name_ The name of the mandatory argument, for documentation
433 /// purposes.
434 /// \param default_value_ If not NULL, the default value for the mandatory
435 /// argument.
path_option(const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)436 cmdline::path_option::path_option(const char* long_name_,
437 const char* description_,
438 const char* arg_name_,
439 const char* default_value_) :
440 base_option(long_name_, description_, arg_name_, default_value_)
441 {
442 }
443
444
445 /// Ensures that a path argument passed to the path_option is valid.
446 ///
447 /// \param raw_value The argument representing a path as provided by the user.
448 ///
449 /// \throw cmdline::option_argument_value_error If the path provided in
450 /// raw_value is invalid.
451 void
validate(const std::string & raw_value) const452 cmdline::path_option::validate(const std::string& raw_value) const
453 {
454 try {
455 (void)utils::fs::path(raw_value);
456 } catch (const utils::fs::error& e) {
457 throw cmdline::option_argument_value_error(F("--%s") % long_name(),
458 raw_value, e.what());
459 }
460 }
461
462
463 /// Converts a path argument to a utils::fs::path.
464 ///
465 /// \param raw_value The argument representing a path as provided by the user.
466 ///
467 /// \return The path.
468 ///
469 /// \pre validate(raw_value) must be true.
470 utils::fs::path
convert(const std::string & raw_value)471 cmdline::path_option::convert(const std::string& raw_value)
472 {
473 try {
474 return utils::fs::path(raw_value);
475 } catch (const std::runtime_error& e) {
476 PRE_MSG(false, F("Raw value '%s' for path option not properly "
477 "validated: %s") % raw_value % e.what());
478 }
479 }
480
481
482 /// Constructs a property option with both a short and a long name.
483 ///
484 /// \param short_name_ The short name for the option.
485 /// \param long_name_ The long name for the option.
486 /// \param description_ A user-friendly description for the option.
487 /// \param arg_name_ The name of the mandatory argument, for documentation
488 /// purposes. Must include the '=' delimiter.
property_option(const char short_name_,const char * long_name_,const char * description_,const char * arg_name_)489 cmdline::property_option::property_option(const char short_name_,
490 const char* long_name_,
491 const char* description_,
492 const char* arg_name_) :
493 base_option(short_name_, long_name_, description_, arg_name_)
494 {
495 PRE(arg_name().find('=') != std::string::npos);
496 }
497
498
499 /// Constructs a property option with a long name only.
500 ///
501 /// \param long_name_ The long name for the option.
502 /// \param description_ A user-friendly description for the option.
503 /// \param arg_name_ The name of the mandatory argument, for documentation
504 /// purposes. Must include the '=' delimiter.
property_option(const char * long_name_,const char * description_,const char * arg_name_)505 cmdline::property_option::property_option(const char* long_name_,
506 const char* description_,
507 const char* arg_name_) :
508 base_option(long_name_, description_, arg_name_)
509 {
510 PRE(arg_name().find('=') != std::string::npos);
511 }
512
513
514 /// Validates the argument to a property option.
515 ///
516 /// \param raw_value The argument provided by the user.
517 void
validate(const std::string & raw_value) const518 cmdline::property_option::validate(const std::string& raw_value) const
519 {
520 const std::string::size_type pos = raw_value.find('=');
521 if (pos == std::string::npos)
522 throw cmdline::option_argument_value_error(
523 F("--%s") % long_name(), raw_value,
524 F("Argument does not have the form '%s'") % arg_name());
525
526 const std::string key = raw_value.substr(0, pos);
527 if (key.empty())
528 throw cmdline::option_argument_value_error(
529 F("--%s") % long_name(), raw_value, "Empty property name");
530
531 const std::string value = raw_value.substr(pos + 1);
532 if (value.empty())
533 throw cmdline::option_argument_value_error(
534 F("--%s") % long_name(), raw_value, "Empty value");
535 }
536
537
538 /// Returns the property option in a key/value pair form.
539 ///
540 /// \param raw_value The argument provided by the user.
541 ///
542 /// \return raw_value The key/value pair representation of the property.
543 ///
544 /// \pre validate(raw_value) must be true.
545 cmdline::property_option::option_type
convert(const std::string & raw_value)546 cmdline::property_option::convert(const std::string& raw_value)
547 {
548 const std::string::size_type pos = raw_value.find('=');
549 return std::make_pair(raw_value.substr(0, pos), raw_value.substr(pos + 1));
550 }
551
552
553 /// Constructs a string option with both a short and a long name.
554 ///
555 /// \param short_name_ The short name for the option.
556 /// \param long_name_ The long name for the option.
557 /// \param description_ A user-friendly description for the option.
558 /// \param arg_name_ The name of the mandatory argument, for documentation
559 /// purposes.
560 /// \param default_value_ If not NULL, the default value for the mandatory
561 /// argument.
string_option(const char short_name_,const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)562 cmdline::string_option::string_option(const char short_name_,
563 const char* long_name_,
564 const char* description_,
565 const char* arg_name_,
566 const char* default_value_) :
567 base_option(short_name_, long_name_, description_, arg_name_,
568 default_value_)
569 {
570 }
571
572
573 /// Constructs a string option with a long name only.
574 ///
575 /// \param long_name_ The long name for the option.
576 /// \param description_ A user-friendly description for the option.
577 /// \param arg_name_ The name of the mandatory argument, for documentation
578 /// purposes.
579 /// \param default_value_ If not NULL, the default value for the mandatory
580 /// argument.
string_option(const char * long_name_,const char * description_,const char * arg_name_,const char * default_value_)581 cmdline::string_option::string_option(const char* long_name_,
582 const char* description_,
583 const char* arg_name_,
584 const char* default_value_) :
585 base_option(long_name_, description_, arg_name_, default_value_)
586 {
587 }
588
589
590 /// Does nothing; all string values are valid arguments to a string_option.
591 ///
592 /// \param unused_raw_value The argument provided by the user.
593 void
validate(const std::string & UTILS_UNUSED_PARAM (raw_value)) const594 cmdline::string_option::validate(
595 const std::string& UTILS_UNUSED_PARAM(raw_value)) const
596 {
597 // Nothing to do.
598 }
599
600
601 /// Returns the string unmodified.
602 ///
603 /// \param raw_value The argument provided by the user.
604 ///
605 /// \return raw_value
606 ///
607 /// \pre validate(raw_value) must be true.
608 std::string
convert(const std::string & raw_value)609 cmdline::string_option::convert(const std::string& raw_value)
610 {
611 return raw_value;
612 }
613