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