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. 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. 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. 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 104 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 116 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& 127 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& 137 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 147 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& 159 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 172 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& 185 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 196 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 212 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 234 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. 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. 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. 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. 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 309 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 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. 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. 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 382 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 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. 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. 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 452 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 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. 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. 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 518 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 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. 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. 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 594 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 609 cmdline::string_option::convert(const std::string& raw_value) 610 { 611 return raw_value; 612 } 613