1 /* 2 * This file is part of the GROMACS molecular simulation package. 3 * 4 * Copyright (c) 2010-2018, The GROMACS development team. 5 * Copyright (c) 2019,2020, by the GROMACS development team, led by 6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, 7 * and including many others, as listed in the AUTHORS file in the 8 * top-level source directory and at http://www.gromacs.org. 9 * 10 * GROMACS is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public License 12 * as published by the Free Software Foundation; either version 2.1 13 * of the License, or (at your option) any later version. 14 * 15 * GROMACS is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with GROMACS; if not, see 22 * http://www.gnu.org/licenses, or write to the Free Software Foundation, 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 * 25 * If you want to redistribute modifications to GROMACS, please 26 * consider that scientific software is very special. Version 27 * control is crucial - bugs must be traceable. We will be happy to 28 * consider code for inclusion in the official distribution, but 29 * derived work must not be called official GROMACS. Details are found 30 * in the README & COPYING files - if they are missing, get the 31 * official version at http://www.gromacs.org. 32 * 33 * To help us fund GROMACS development, we humbly ask that you cite 34 * the research papers on the package. Check out http://www.gromacs.org. 35 */ 36 /*! \file 37 * \brief 38 * Declares option objects for basic option types. 39 * 40 * Together with options.h, this header forms the part of the public API 41 * that most classes will use to provide options. 42 * 43 * \author Teemu Murtola <teemu.murtola@gmail.com> 44 * \inpublicapi 45 * \ingroup module_options 46 */ 47 #ifndef GMX_OPTIONS_BASICOPTIONS_H 48 #define GMX_OPTIONS_BASICOPTIONS_H 49 50 #include <memory> 51 #include <string> 52 #include <vector> 53 54 #include "gromacs/options/abstractoption.h" 55 #include "gromacs/utility/arrayref.h" 56 #include "gromacs/utility/basedefinitions.h" 57 #include "gromacs/utility/enumerationhelpers.h" 58 #include "gromacs/utility/gmxassert.h" 59 60 #include "ivaluestore.h" 61 62 namespace gmx 63 { 64 65 class BooleanOptionInfo; 66 class BooleanOptionStorage; 67 class IntegerOptionInfo; 68 class IntegerOptionStorage; 69 class Int64OptionInfo; 70 class Int64OptionStorage; 71 class DoubleOptionInfo; 72 class DoubleOptionStorage; 73 class FloatOptionInfo; 74 class FloatOptionStorage; 75 class StringOptionInfo; 76 class StringOptionStorage; 77 class EnumOptionInfo; 78 class EnumOptionStorage; 79 80 //! \addtogroup module_options 81 //! \{ 82 83 /*! \brief 84 * Specifies an option that provides boolean values. 85 * 86 * Example: 87 * \code 88 bool bPBC; 89 using gmx::BooleanOption; 90 options.addOption(BooleanOption("pbc").store(&bPBC)); 91 * \endcode 92 * 93 * Public methods in this class do not throw. 94 * 95 * \inpublicapi 96 */ 97 class BooleanOption : public OptionTemplate<bool, BooleanOption> 98 { 99 public: 100 //! OptionInfo subclass corresponding to this option type. 101 typedef BooleanOptionInfo InfoType; 102 103 //! Initializes an option with the given name. BooleanOption(const char * name)104 explicit BooleanOption(const char* name) : MyBase(name) {} 105 106 private: 107 //! Creates a BooleanOptionStorage object. 108 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override; 109 }; 110 111 /*! \brief 112 * Specifies an option that provides integer values. 113 * 114 * Examples: 115 * \code 116 using gmx::IntegerOption; 117 // Simple option 118 int rcut = 0; 119 options.addOption(IntegerOption("rcut").store(&rcut)); 120 // Vector-valued option 121 int box[3] = {1, 1, 1}; // Default value 122 options.addOption(IntegerOption("box").store(box).vector()); 123 * \endcode 124 * 125 * Public methods in this class do not throw. 126 * 127 * \inpublicapi 128 */ 129 class IntegerOption : public OptionTemplate<int, IntegerOption> 130 { 131 public: 132 //! OptionInfo subclass corresponding to this option type. 133 typedef IntegerOptionInfo InfoType; 134 135 //! Initializes an option with the given name. IntegerOption(const char * name)136 explicit IntegerOption(const char* name) : MyBase(name) {} 137 138 /*! \brief 139 * Sets the option to return a vector value. 140 * 141 * A vector value returns a fixed number of values, the default being 142 * three (can be changed with valueCount()). However, it also accepts 143 * a single value, in which case the value is used to fill the whole 144 * vector. 145 */ vector()146 MyClass& vector() 147 { 148 setVector(); 149 return me(); 150 } 151 152 private: 153 //! Creates an IntegerOptionStorage object. 154 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override; 155 156 /*! \brief 157 * Needed to initialize IntegerOptionStorage from this class without 158 * otherwise unnecessary accessors. 159 */ 160 friend class IntegerOptionStorage; 161 }; 162 163 /*! \brief 164 * Specifies an option that provides 64-bit integer values. 165 * 166 * Public methods in this class do not throw. 167 * 168 * \see IntegerOption 169 * 170 * \inpublicapi 171 */ 172 class Int64Option : public OptionTemplate<int64_t, Int64Option> 173 { 174 public: 175 //! OptionInfo subclass corresponding to this option type. 176 typedef Int64OptionInfo InfoType; 177 178 //! Initializes an option with the given name. Int64Option(const char * name)179 explicit Int64Option(const char* name) : MyBase(name) {} 180 181 private: 182 //! Creates an Int64OptionStorage object. 183 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override; 184 185 /*! \brief 186 * Needed to initialize Int64OptionStorage from this class without 187 * otherwise unnecessary accessors. 188 */ 189 friend class Int64OptionStorage; 190 }; 191 192 /*! \brief 193 * Specifies an option that provides floating-point (double) values. 194 * 195 * Public methods in this class do not throw. 196 * 197 * \inpublicapi 198 */ 199 class DoubleOption : public OptionTemplate<double, DoubleOption> 200 { 201 public: 202 //! OptionInfo subclass corresponding to this option type. 203 typedef DoubleOptionInfo InfoType; 204 205 //! Initializes an option with the given name. DoubleOption(const char * name)206 explicit DoubleOption(const char* name) : MyBase(name), bTime_(false) {} 207 208 //! \copydoc IntegerOption::vector() vector()209 MyClass& vector() 210 { 211 setVector(); 212 return me(); 213 } 214 /*! \brief 215 * Marks this option as providing a time value whose unit can be changed. 216 * 217 * By itself, this option does nothing. It marks the option as a time 218 * value such that TimeUnitManager::scaleTimeOptions() can process it. 219 * In typical cases, \Gromacs scales the time options just before 220 * Options::finish() has been called, so the option value is only 221 * available after all option values have been processed. 222 * All values in the program are in ps (including any default value); 223 * user-provided values are scaled according to the time unit set in 224 * TimeUnitManager. 225 */ timeValue()226 MyClass& timeValue() 227 { 228 bTime_ = true; 229 return me(); 230 } 231 232 private: 233 //! Creates a DoubleOptionStorage object. 234 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override; 235 236 bool bTime_; 237 238 /*! \brief 239 * Needed to initialize DoubleOptionStorage from this class without 240 * otherwise unnecessary accessors. 241 */ 242 friend class DoubleOptionStorage; 243 }; 244 245 /*! \brief 246 * Specifies an option that provides floating-point (float) values. 247 * 248 * Public methods in this class do not throw. 249 * 250 * \see DoubleOption 251 * 252 * \inpublicapi 253 */ 254 class FloatOption : public OptionTemplate<float, FloatOption> 255 { 256 public: 257 //! OptionInfo subclass corresponding to this option type. 258 typedef FloatOptionInfo InfoType; 259 260 //! Initializes an option with the given name. FloatOption(const char * name)261 explicit FloatOption(const char* name) : MyBase(name), bTime_(false) {} 262 263 //! \copydoc IntegerOption::vector() vector()264 MyClass& vector() 265 { 266 setVector(); 267 return me(); 268 } 269 //! \copydoc DoubleOption::timeValue() timeValue()270 MyClass& timeValue() 271 { 272 bTime_ = true; 273 return me(); 274 } 275 276 private: 277 //! Creates a FloatOptionStorage object. 278 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override; 279 280 bool bTime_; 281 282 /*! \brief 283 * Needed to initialize FloatOptionStorage from this class without 284 * otherwise unnecessary accessors. 285 */ 286 friend class FloatOptionStorage; 287 }; 288 289 /*! \brief 290 * Specifies an option that provides string values. 291 * 292 * Examples: 293 * \code 294 using gmx::StringOption; 295 // Simple option 296 std::string str; 297 options.addOption(StringOption("str").store(&str)); 298 // Option that only accepts predefined values 299 const char * const allowed[] = { "atom", "residue", "molecule" }; 300 std::string str; 301 options.addOption(StringOption("type").enumValue(allowed).store(&str)); 302 * \endcode 303 * 304 * Public methods in this class do not throw. 305 * 306 * \inpublicapi 307 */ 308 class StringOption : public OptionTemplate<std::string, StringOption> 309 { 310 public: 311 //! OptionInfo subclass corresponding to this option type. 312 typedef StringOptionInfo InfoType; 313 314 //! Initializes an option with the given name. StringOption(const char * name)315 explicit StringOption(const char* name) : 316 MyBase(name), 317 enumValues_(nullptr), 318 enumValuesCount_(0), 319 defaultEnumIndex_(-1) 320 { 321 } 322 323 /*! \brief 324 * Sets the option to only accept one of a fixed set of strings. 325 * 326 * \param[in] values Array of strings to accept. 327 * 328 * Also accepts prefixes of the strings; if a prefix matches more than 329 * one of the possible strings, the shortest one is used (in a tie, the 330 * first one is). 331 * 332 * The strings are copied once the option is created. 333 */ 334 template<size_t count> enumValue(const char * const (& values)[count])335 MyClass& enumValue(const char* const (&values)[count]) 336 { 337 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified"); 338 enumValues_ = values; 339 enumValuesCount_ = count; 340 return me(); 341 } 342 /*! \brief 343 * Sets the option to only accept one of a fixed set of strings. 344 * 345 * \param[in] values Array of strings to accept, with a NULL pointer 346 * following the last string. 347 * 348 * Works otherwise as the array version, but accepts a pointer to 349 * an array of undetermined length. The end of the array is indicated 350 * by a NULL pointer in the array. 351 * 352 * \see enumValue() 353 */ enumValueFromNullTerminatedArray(const char * const * values)354 MyClass& enumValueFromNullTerminatedArray(const char* const* values) 355 { 356 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified"); 357 enumValues_ = values; 358 enumValuesCount_ = -1; 359 return me(); 360 } 361 /*! \brief 362 * Sets the default value using an index into the enumeration table. 363 * 364 * Cannot be specified without enumValue(). 365 */ defaultEnumIndex(int index)366 MyClass& defaultEnumIndex(int index) 367 { 368 GMX_ASSERT(index >= 0, "Invalid enumeration index"); 369 defaultEnumIndex_ = index; 370 return me(); 371 } 372 373 private: 374 //! Creates a StringOptionStorage object. 375 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override; 376 377 const char* const* enumValues_; 378 int enumValuesCount_; 379 int defaultEnumIndex_; 380 381 /*! \brief 382 * Needed to initialize StringOptionStorage from this class without 383 * otherwise unnecessary accessors. 384 */ 385 friend class StringOptionStorage; 386 }; 387 388 //! \} 389 390 namespace internal 391 { 392 393 /*! \internal 394 * \brief 395 * Type-specific implementation for IOptionValueStore for an enum option. 396 * 397 * This class is instantiated for each enum type for which EnumOption is used, 398 * and takes care of managing `int`-to-`enum` conversions. Having this part in 399 * the header allows the actual storage implementation to not be in the header, 400 * which would require exposing all the internals through this one header... 401 * 402 * \ingroup module_options 403 */ 404 template<typename EnumType> 405 class EnumIndexStore : public IOptionValueStore<int> 406 { 407 public: 408 //! Initializes the storage for the given actual enum variables. EnumIndexStore(EnumType * store,std::vector<EnumType> * storeVector)409 EnumIndexStore(EnumType* store, std::vector<EnumType>* storeVector) : 410 store_(store), 411 storeVector_(storeVector) 412 { 413 if (storeVector_ != nullptr) 414 { 415 for (EnumType value : *storeVector_) 416 { 417 intStore_.push_back(static_cast<int>(value)); 418 } 419 } 420 else if (store_ != nullptr) 421 { 422 // TODO: Copy more than one value if that would make sense. 423 intStore_.push_back(static_cast<int>(store_[0])); 424 } 425 } 426 valueCount()427 int valueCount() override { return ssize(intStore_); } values()428 ArrayRef<int> values() override { return intStore_; } clear()429 void clear() override 430 { 431 intStore_.clear(); 432 if (storeVector_ != nullptr) 433 { 434 storeVector_->clear(); 435 } 436 } reserve(size_t count)437 void reserve(size_t count) override 438 { 439 intStore_.reserve(intStore_.size() + count); 440 if (storeVector_ != nullptr) 441 { 442 storeVector_->reserve(storeVector_->size() + count); 443 } 444 } append(const int & value)445 void append(const int& value) override 446 { 447 const size_t count = intStore_.size(); 448 intStore_.push_back(value); 449 if (store_ != nullptr) 450 { 451 store_[count] = static_cast<EnumType>(value); 452 } 453 if (storeVector_ != nullptr) 454 { 455 storeVector_->push_back(static_cast<EnumType>(value)); 456 } 457 } 458 459 private: 460 //! Stores the integer values for values(). 461 std::vector<int> intStore_; 462 EnumType* store_; 463 std::vector<EnumType>* storeVector_; 464 }; 465 466 //! \cond internal 467 /*! \internal 468 * \brief 469 * Helper to create EnumOptionStorage instances. 470 * 471 * This function works as a proxy between EnumOption::createStorage() and the 472 * EnumOptionStorage constructor, such that the latter does not need to be 473 * exposed in the header. 474 * 475 * \ingroup module_options 476 */ 477 AbstractOptionStorage* createEnumOptionStorage(const AbstractOption& option, 478 const char* const* enumValues, 479 int count, 480 int defaultValue, 481 int defaultValueIfSet, 482 std::unique_ptr<IOptionValueStore<int>> store); 483 //! \endcond 484 485 } // namespace internal 486 487 //! \addtogroup module_options 488 //! \{ 489 490 /*! \brief 491 * Specifies an option that accepts an EnumerationArray of string values and writes the 492 * selected index into an `enum` variable. 493 * 494 * \tparam EnumType DataType of the variable that receives the values 495 * 496 * Examples: 497 * \code 498 enum class MyEnum { Atom, Res, Mol, Count } : int; 499 EnumerationArray<MyEnum, const char *> myEnumNames = { "atom", "residue", "molecule" }; 500 MyEnum value = MyEnum::Atom; // default value 501 options.addOption(EnumOption<MyEnum>("type").enumValue(myEnumNames).store(&value)); 502 * \endcode 503 * 504 * storeCount() is not currently implemented for this option type, and 505 * providing multiple default values through an array passed to store() does 506 * not work consistently in all cases. 507 * In the current implementation, the values of the enum type should correspond 508 * to indices in the array passed to enumValue(), i.e., be consecutive 509 * starting from zero. Only values corresponding to valid indices are accepted 510 * as parameters to, e.g., defaultValue(). However, other values can be used 511 * as the initial value of the variable (`value` in the above example), and 512 * those will be preserved if the option is not set. 513 * 514 * Public methods in this class do not throw. 515 * 516 * \inpublicapi 517 */ 518 template<typename EnumType> 519 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType>> 520 { 521 public: 522 //! OptionInfo subclass corresponding to this option type. 523 typedef EnumOptionInfo InfoType; 524 525 // This needs to be duplicated from OptionTemplate because this class 526 // is a template. 527 //! Short-hand for the base class. 528 typedef OptionTemplate<EnumType, EnumOption<EnumType>> MyBase; 529 530 //! Initializes an option with the given name. EnumOption(const char * name)531 explicit EnumOption(const char* name) : MyBase(name), enumValues_(nullptr), enumValuesCount_(0) 532 { 533 } 534 535 /*! \brief 536 * Sets the option to only accept one of a fixed set of strings. 537 * 538 539 * \param[in] values Array of strings to accept. 540 * 541 * Also accepts prefixes of the strings; if a prefix matches more than 542 * one of the possible strings, the shortest one is used (in a tie, the 543 * first one is). 544 * 545 * The strings are copied once the option is created. 546 */ enumValue(const EnumerationArray<EnumType,const char * > & values)547 EnumOption& enumValue(const EnumerationArray<EnumType, const char*>& values) 548 { 549 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified"); 550 enumValues_ = values.data(); 551 enumValuesCount_ = values.size(); 552 return MyBase::me(); 553 } 554 555 private: 556 //! Helper function to convert default values for storage initialization. convertToInt(const EnumType * defaultValue)557 static int convertToInt(const EnumType* defaultValue) 558 { 559 return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1; 560 } 561 562 //! Creates a EnumOptionStorage object. createStorage(const OptionManagerContainer &)563 AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override 564 { 565 // TODO: Implement storeCount() if necessary. 566 return internal::createEnumOptionStorage(*this, enumValues_, enumValuesCount_, 567 convertToInt(MyBase::defaultValue()), 568 convertToInt(MyBase::defaultValueIfSet()), 569 std::make_unique<internal::EnumIndexStore<EnumType>>( 570 MyBase::store(), MyBase::storeVector())); 571 } 572 573 const char* const* enumValues_; 574 int enumValuesCount_; 575 576 /*! \brief 577 * Needed to initialize EnumOptionStorage from this class without 578 * otherwise unnecessary accessors. 579 */ 580 friend class EnumOptionStorage; 581 }; 582 583 /*! \brief 584 * Specifies an option that accepts enumerated string values and writes the 585 * selected index into an `enum` variable. 586 * 587 * \tparam EnumType Type of the variable that receives the values 588 * (can also be `int`). 589 * 590 * Examples: 591 * \code 592 enum MyEnum { eAtom, eRes, eMol }; 593 using gmx::LegacyEnumOption; 594 const char * const allowed[] = { "atom", "residue", "molecule" }; 595 MyEnum value = eAtom; // default value 596 options.addOption(LegacyEnumOption<MyEnum>("type").enumValue(allowed).store(&value)); 597 * \endcode 598 * 599 * Works exactly as EnumOption. 600 * 601 * This is legacy support for pargsToOptions and can be removed when it 602 * is removed. No new uses of it should be made. 603 * 604 * Public methods in this class do not throw. 605 * 606 * \inpublicapi 607 */ 608 template<typename EnumType> 609 class LegacyEnumOption : public OptionTemplate<EnumType, LegacyEnumOption<EnumType>> 610 { 611 public: 612 //! OptionInfo subclass corresponding to this option type. 613 typedef EnumOptionInfo InfoType; 614 615 // This needs to be duplicated from OptionTemplate because this class 616 // is a template. 617 //! Short-hand for the base class. 618 typedef OptionTemplate<EnumType, LegacyEnumOption<EnumType>> MyBase; 619 620 //! Initializes an option with the given name. LegacyEnumOption(const char * name)621 explicit LegacyEnumOption(const char* name) : 622 MyBase(name), 623 enumValues_(nullptr), 624 enumValuesCount_(0) 625 { 626 } 627 628 /*! \brief 629 * Sets the option to only accept one of a fixed set of strings. 630 * 631 * \param[in] values Array of strings to accept. 632 * 633 * Also accepts prefixes of the strings; if a prefix matches more than 634 * one of the possible strings, the shortest one is used (in a tie, the 635 * first one is). 636 * 637 * The strings are copied once the option is created. 638 */ 639 template<size_t count> enumValue(const char * const (& values)[count])640 LegacyEnumOption& enumValue(const char* const (&values)[count]) 641 { 642 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified"); 643 enumValues_ = values; 644 enumValuesCount_ = count; 645 return MyBase::me(); 646 } 647 /*! \brief 648 * Sets the option to only accept one of a fixed set of strings. 649 * 650 * \param[in] values Array of strings to accept, with a NULL pointer 651 * following the last string. 652 * 653 * Works otherwise as the array version, but accepts a pointer to 654 * an array of undetermined length. The end of the array is indicated 655 * by a NULL pointer in the array. 656 * 657 * \see enumValue() 658 */ enumValueFromNullTerminatedArray(const char * const * values)659 LegacyEnumOption& enumValueFromNullTerminatedArray(const char* const* values) 660 { 661 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified"); 662 enumValues_ = values; 663 enumValuesCount_ = -1; 664 return MyBase::me(); 665 } 666 667 private: 668 //! Helper function to convert default values for storage initialization. convertToInt(const EnumType * defaultValue)669 static int convertToInt(const EnumType* defaultValue) 670 { 671 return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1; 672 } 673 674 //! Creates a EnumOptionStorage object. createStorage(const OptionManagerContainer &)675 AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override 676 { 677 // TODO: Implement storeCount() if necessary. 678 return internal::createEnumOptionStorage(*this, enumValues_, enumValuesCount_, 679 convertToInt(MyBase::defaultValue()), 680 convertToInt(MyBase::defaultValueIfSet()), 681 std::make_unique<internal::EnumIndexStore<EnumType>>( 682 MyBase::store(), MyBase::storeVector())); 683 } 684 685 const char* const* enumValues_; 686 int enumValuesCount_; 687 688 /*! \brief 689 * Needed to initialize EnumOptionStorage from this class without 690 * otherwise unnecessary accessors. 691 */ 692 friend class EnumOptionStorage; 693 }; 694 695 /*! \brief 696 * Wrapper class for accessing boolean option information. 697 * 698 * \inpublicapi 699 */ 700 class BooleanOptionInfo : public OptionInfo 701 { 702 public: 703 //! Creates an option info object for the given option. 704 explicit BooleanOptionInfo(BooleanOptionStorage* option); 705 706 //! Returns the default value for this option. 707 bool defaultValue() const; 708 709 private: 710 const BooleanOptionStorage& option() const; 711 }; 712 713 /*! \brief 714 * Wrapper class for accessing integer option information. 715 * 716 * \inpublicapi 717 */ 718 class IntegerOptionInfo : public OptionInfo 719 { 720 public: 721 //! Creates an option info object for the given option. 722 explicit IntegerOptionInfo(IntegerOptionStorage* option); 723 }; 724 725 /*! \brief 726 * Wrapper class for accessing 64-bit integer option information. 727 * 728 * \inpublicapi 729 */ 730 class Int64OptionInfo : public OptionInfo 731 { 732 public: 733 //! Creates an option info object for the given option. 734 explicit Int64OptionInfo(Int64OptionStorage* option); 735 }; 736 737 /*! \brief 738 * Wrapper class for accessing floating-point option information. 739 * 740 * \inpublicapi 741 */ 742 class DoubleOptionInfo : public OptionInfo 743 { 744 public: 745 //! Creates an option info object for the given option. 746 explicit DoubleOptionInfo(DoubleOptionStorage* option); 747 748 //! Whether the option specifies a time value. 749 bool isTime() const; 750 751 /*! \brief 752 * Sets a scale factor for user-provided values. 753 * 754 * Any user-provided value is scaled by the provided factor. 755 * Programmatically set default values are not scaled. 756 * If called multiple times, later calls override the previously set 757 * value. In other words, the scaling is not cumulative. 758 */ 759 void setScaleFactor(double factor); 760 761 private: 762 DoubleOptionStorage& option(); 763 const DoubleOptionStorage& option() const; 764 }; 765 766 /*! \brief 767 * Wrapper class for accessing floating-point option information. 768 * 769 * \inpublicapi 770 */ 771 class FloatOptionInfo : public OptionInfo 772 { 773 public: 774 //! Creates an option info object for the given option. 775 explicit FloatOptionInfo(FloatOptionStorage* option); 776 777 //! Whether the option specifies a time value. 778 bool isTime() const; 779 780 //! \copydoc DoubleOptionInfo::setScaleFactor() 781 void setScaleFactor(double factor); 782 783 private: 784 FloatOptionStorage& option(); 785 const FloatOptionStorage& option() const; 786 }; 787 788 /*! \brief 789 * Wrapper class for accessing string option information. 790 * 791 * \inpublicapi 792 */ 793 class StringOptionInfo : public OptionInfo 794 { 795 public: 796 //! Creates an option info object for the given option. 797 explicit StringOptionInfo(StringOptionStorage* option); 798 799 /*! \brief 800 * Whether this option accepts an enumerated set of values. 801 * 802 * Returns true if StringOption::enumValues() was used when creating 803 * this option. 804 */ 805 bool isEnumerated() const; 806 /*! \brief 807 * Returns the set of allowed values for this option. 808 * 809 * Returns an empty vector if isEnumerated() returns false. 810 */ 811 const std::vector<std::string>& allowedValues() const; 812 813 private: 814 const StringOptionStorage& option() const; 815 }; 816 817 /*! \brief 818 * Wrapper class for accessing enum option information. 819 * 820 * \inpublicapi 821 */ 822 class EnumOptionInfo : public OptionInfo 823 { 824 public: 825 //! Creates an option info object for the given option. 826 explicit EnumOptionInfo(EnumOptionStorage* option); 827 828 /*! \brief 829 * Returns the set of allowed values for this option. 830 */ 831 const std::vector<std::string>& allowedValues() const; 832 833 private: 834 const EnumOptionStorage& option() const; 835 }; 836 837 /*! \typedef RealOption 838 * \brief 839 * Typedef for either DoubleOption or FloatOption, depending on precision. 840 * 841 * Generally, new would be better using DoubleOption, but this is provided for 842 * cases where the output value needs to be of type `real` for some reason. 843 */ 844 /*! \typedef RealOptionInfo 845 * \brief 846 * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision. 847 * 848 * Generally, new would be better using DoubleOption, but this is provided for 849 * cases where the output value needs to be of type `real` for some reason. 850 */ 851 #if GMX_DOUBLE 852 typedef DoubleOption RealOption; 853 typedef DoubleOptionInfo RealOptionInfo; 854 #else 855 typedef FloatOption RealOption; 856 typedef FloatOptionInfo RealOptionInfo; 857 #endif 858 859 //! \} 860 861 } // namespace gmx 862 863 #endif 864