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 42 namespace cmdline = utils::cmdline; 43 namespace 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. 56 cmdline::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. 81 cmdline::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. 96 cmdline::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. 104 bool 105 cmdline::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. 116 char 117 cmdline::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. 127 const std::string& 128 cmdline::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. 137 const std::string& 138 cmdline::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. 147 bool 148 cmdline::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. 159 const std::string& 160 cmdline::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. 172 bool 173 cmdline::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. 185 const std::string& 186 cmdline::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. 196 std::string 197 cmdline::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. 212 std::string 213 cmdline::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. 231 void 232 cmdline::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. 243 cmdline::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. 255 cmdline::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. 271 cmdline::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. 290 cmdline::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. 306 void 307 cmdline::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. 326 int 327 cmdline::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. 347 cmdline::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. 366 cmdline::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. 376 void 377 cmdline::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. 391 cmdline::list_option::option_type 392 cmdline::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. 412 cmdline::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. 431 cmdline::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. 446 void 447 cmdline::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. 465 utils::fs::path 466 cmdline::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. 484 cmdline::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. 500 cmdline::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. 512 void 513 cmdline::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. 540 cmdline::property_option::option_type 541 cmdline::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. 557 cmdline::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. 576 cmdline::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. 586 void 587 cmdline::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. 601 std::string 602 cmdline::string_option::convert(const std::string& raw_value) 603 { 604 return raw_value; 605 } 606