fa34c5dae44f6794261ac5d043f13f9cb7b24fef
[alexxy/gromacs.git] / src / gromacs / options / abstractoption.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010-2017, The GROMACS development team.
5  * Copyright (c) 2019,2021, 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  * Defines gmx::AbstractOption, gmx::OptionTemplate and gmx::OptionInfo.
39  *
40  * This header defines base classes for option settings that are used with
41  * Options::addOption().  These classes implement the "named parameter"
42  * idiom for specifying option properties.
43  *
44  * These classes also take care of creating and setting up the actual option
45  * objects.
46  *
47  * This header is needed directly only when implementing new option types,
48  * but methods of OptionTemplate are visible even to the normal user through
49  * its subclasses.
50  *
51  * \author Teemu Murtola <teemu.murtola@gmail.com>
52  * \inlibraryapi
53  * \ingroup module_options
54  */
55 #ifndef GMX_OPTIONS_ABSTRACTOPTION_H
56 #define GMX_OPTIONS_ABSTRACTOPTION_H
57
58 #include <memory>
59 #include <string>
60 #include <vector>
61
62 #include "gromacs/utility/classhelpers.h"
63
64 #include "optionflags.h"
65
66 namespace gmx
67 {
68
69 class AbstractOptionStorage;
70 template<typename T>
71 class OptionStorageTemplate;
72 class OptionManagerContainer;
73 class Any;
74
75 namespace internal
76 {
77 class OptionSectionImpl;
78 }
79
80 /*! \brief
81  * Abstract base class for specifying option properties.
82  *
83  * Concrete classes should normally not derive directly from this class,
84  * but from OptionTemplate instead.  Classes derived from this class
85  * are mainly designed to implement the "named parameter" idiom.  For
86  * efficiency and clarity, these classes should only store values provided to
87  * them.  All error checking and memory management should be postponed to the
88  * point when the actual option is created.
89  *
90  * Subclasses should override createStorage() to create the correct type
91  * of storage object.  If they use their own info type derived from OptionInfo,
92  * they should also have a public typedef \c InfoType that specifies that
93  * info type.  This is required for Options::addOption() to return the correct
94  * info type.
95  *
96  * \ingroup module_options
97  */
98 class AbstractOption
99 {
100 public:
101     // Virtual only for completeness, in normal use should not be needed.
102     virtual ~AbstractOption() {}
103
104 protected:
105     /*! \cond libapi */
106     //! Initializes the name and default values for an option.
107     explicit AbstractOption(const char* name) :
108         minValueCount_(1),
109         maxValueCount_(1),
110         name_(name),
111         descr_(nullptr),
112         storeIsSet_(nullptr)
113     {
114     }
115
116     /*! \brief
117      * Creates a default storage object for the option.
118      *
119      * \param[in] managers  Manager container (unused if the option does
120      *     not use a manager).
121      * \returns   The created storage object.
122      * \throws    APIError if invalid option settings have been provided.
123      *
124      * This method is called by Options::addOption() when initializing an
125      * option from the settings.
126      *
127      * Derived classes should implement the method to create an actual
128      * storage object and populate it with correct values.
129      * They should also throw APIError if they detect problems.
130      *
131      * Should only be called by Options::addOption().
132      *
133      * The ownership of the return value is passed, but is not using a
134      * smart pointer to avoid introducing such a dependency in an installed
135      * header.  The implementation will always consist of a single `new`
136      * call and returning that value, and the caller always immediately
137      * wraps the pointer in a smart pointer, so there is not exception
138      * safety issue.
139      */
140     virtual AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const = 0;
141
142     //! Sets the description for the option.
143     void setDescription(const char* descr) { descr_ = descr; }
144     //! Sets the storage location for whether the option is set.
145     void setStoreIsSet(bool* store) { storeIsSet_ = store; }
146     //! Sets a flag for the option.
147     void setFlag(OptionFlag flag) { flags_.set(flag); }
148     //! Clears a flag for the option.
149     void clearFlag(OptionFlag flag) { flags_.clear(flag); }
150     //! Sets or clears a flag for the option.
151     void setFlag(OptionFlag flag, bool bSet) { flags_.set(flag, bSet); }
152     //! Returns true if the option is vector-valued.
153     bool isVector() const { return hasFlag(efOption_Vector); }
154     /*! \brief
155      * Sets the option to be vector-valued.
156      *
157      * This method is provided for convenience to make management of value
158      * counts easier.  In order to implement a vector-valued option, the
159      * class derived from AbstractOption should expose a method that calls
160      * this method, and the storage object derived from
161      * AbstractOptionStorage should check isVector().
162      * If only a single value is provided, the storage object should fill
163      * the whole vector with that value.
164      *
165      * The length of the vector (the value of maxValueCount_) must be
166      * fixed.  The default length is 3 elements.
167      */
168     void setVector()
169     {
170         setFlag(efOption_Vector);
171         minValueCount_ = 1;
172         if (maxValueCount_ == 1)
173         {
174             maxValueCount_ = 3;
175         }
176     }
177     //! Sets the required number of values for the option.
178     void setValueCount(int count)
179     {
180         if (!hasFlag(efOption_Vector))
181         {
182             minValueCount_ = count;
183         }
184         maxValueCount_ = count;
185     }
186
187     //! Minimum number of values required for the option.
188     int minValueCount_;
189     //! Maximum number of values allowed for the option.
190     int maxValueCount_;
191     //! \endcond
192
193 private:
194     //! Returns true if a flag has been set.
195     bool hasFlag(OptionFlag flag) const { return flags_.test(flag); }
196
197     const char* name_;
198     //! Pointer to description of the option.
199     const char* descr_;
200     OptionFlags flags_;
201     bool*       storeIsSet_;
202
203     /*! \brief
204      * Needed to initialize an AbstractOptionStorage object from this class
205      * without otherwise unnecessary accessors.
206      */
207     friend class AbstractOptionStorage;
208     //! Needed to be able to call createStorage().
209     friend class internal::OptionSectionImpl;
210 };
211
212 /*! \brief
213  * Templated base class for constructing concrete option settings classes.
214  *
215  * \tparam T Assignable type that stores a single option value.
216  * \tparam U Type of the derived class.
217  *
218  * This template is used as a base class like this:
219  * \code
220    class ConcreteOption : public OptionTemplate<int, ConcreteOption>
221    {
222  * \endcode
223  *
224  * All public functions in this class return \c *this casted to a reference to
225  * \p U.  They do not throw.
226  *
227  * For examples of how to use classes derived from this class, see the class
228  * documentation for Options.
229  *
230  * \inlibraryapi
231  * \ingroup module_options
232  */
233 template<typename T, class U>
234 class OptionTemplate : public AbstractOption
235 {
236 public:
237     //! Type that stores a single option value.
238     typedef T ValueType;
239     //! Alias for the derived class type.
240     typedef U MyClass;
241
242     /*! \brief
243      * Sets a description for the option.
244      *
245      * \param[in] descr Description to set.
246      *
247      * String in \p descr is copied when the option is created.
248      */
249     MyClass& description(const char* descr)
250     {
251         setDescription(descr);
252         return me();
253     }
254     //! Hides the option from normal help output.
255     MyClass& hidden(bool bHidden = true)
256     {
257         setFlag(efOption_Hidden, bHidden);
258         return me();
259     }
260     /*! \brief
261      * Requires the option to be specified explicitly.
262      *
263      * Note that if you specify defaultValue() together with required(),
264      * the user is not required to explicitly provide the option.
265      * In this case, required() only affects possible help output.
266      */
267     MyClass& required(bool bRequired = true)
268     {
269         setFlag(efOption_Required, bRequired);
270         return me();
271     }
272     //! Allows the option to be specified multiple times.
273     MyClass& allowMultiple(bool bMulti = true)
274     {
275         setFlag(efOption_MultipleTimes, bMulti);
276         return me();
277     }
278     //! Requires exactly \p count values for the option.
279     MyClass& valueCount(int count)
280     {
281         setValueCount(count);
282         return me();
283     }
284     //! Allows any number of values for the option.
285     MyClass& multiValue(bool bMulti = true)
286     {
287         if (bMulti)
288         {
289             maxValueCount_ = -1;
290         }
291         return me();
292     }
293
294     /*! \brief
295      * Sets a default value for the option.
296      *
297      * \param[in] defaultValue Default value.
298      *
299      * If the option is never set, the default value is copied to the
300      * assigned storage.  Note that if the option is not set and there
301      * is no default value, the storage is not altered, which can also be
302      * used to provide a default value.  The latter method has to be used
303      * if the option can take multiple values.
304      *
305      * \p defaultValue is copied when the option is created.
306      */
307     MyClass& defaultValue(const T& defaultValue)
308     {
309         defaultValue_ = &defaultValue;
310         return me();
311     }
312     /*! \brief
313      * Sets a default value for the option when it is set.
314      *
315      * \param[in] defaultValue Default value.
316      *
317      * This value is used if the option is set, but no value is provided.
318      * If the option is never set, the value set with defaultValue() is
319      * used.  Can only be used for options that accept a single value.
320      *
321      * \p defaultValue is copied when the option is created.
322      */
323     MyClass& defaultValueIfSet(const T& defaultValue)
324     {
325         defaultValueIfSet_ = &defaultValue;
326         return me();
327     }
328     /*! \brief
329      * Stores value(s) in memory pointed by \p store.
330      *
331      * \param[in] store  Storage for option value(s).
332      *
333      * The caller is responsible for allocating enough memory such that
334      * the any allowed number of values fits into the array pointed by
335      * \p store.  If there is no maximum allowed number or if the maximum
336      * is inconveniently large, storeVector() should be used.
337      *
338      * For information on when values are available in the storage, see
339      * storeVector().
340      *
341      * The pointer provided should remain valid as long as the associated
342      * Options object exists.
343      */
344     MyClass& store(T* store)
345     {
346         store_ = store;
347         return me();
348     }
349     /*! \brief
350      * Stores number of values in the value pointed by \p countptr.
351      *
352      * \param[in] countptr Storage for the number of values.
353      *
354      * For information on when values are available in the storage, see
355      * storeVector().
356      *
357      * The pointers provided should remain valid as long as the associated
358      * Options object exists.
359      */
360     MyClass& storeCount(int* countptr)
361     {
362         countptr_ = countptr;
363         return me();
364     }
365     /*! \brief
366      * Stores option values in the provided vector.
367      *
368      * \param[in] store  Vector to store option values in.
369      *
370      * Values are added to the vector after each successful set of values
371      * is parsed.  Note that for some options, the value may be changed
372      * later, and is only guaranteed to be correct after Options::finish()
373      * has been called.
374      *
375      * The pointer provided should remain valid as long as the associated
376      * Options object exists.
377      */
378     MyClass& storeVector(std::vector<T>* store)
379     {
380         storeVector_ = store;
381         return me();
382     }
383     /*! \brief
384      * Stores whether the option was explicitly set.
385      *
386      * \param[in] store  Variable to store the flag in.
387      *
388      * The value is set to `false` on creation of the option, and to `true`
389      * as soon as a value is assigned to the option.  A default value does
390      * not set the flag to `true`, but assignment that uses
391      * defaultValueIfSet() does.
392      *
393      * The pointer provided should remain valid as long as the associated
394      * Options object exists.
395      */
396     MyClass& storeIsSet(bool* store)
397     {
398         setStoreIsSet(store);
399         return me();
400     }
401
402 protected:
403     /*! \cond libapi */
404     //! Alias for the template class for use in base classes.
405     typedef OptionTemplate<T, U> MyBase;
406
407     //! Initializes the name and default values for an option.
408     explicit OptionTemplate(const char* name) :
409         AbstractOption(name),
410         defaultValue_(nullptr),
411         defaultValueIfSet_(nullptr),
412         store_(nullptr),
413         countptr_(nullptr),
414         storeVector_(nullptr)
415     {
416     }
417
418     /*! \brief
419      * Returns a pointer to user-specified default value, or NULL if there
420      * is none.
421      */
422     const T* defaultValue() const { return defaultValue_; }
423     /*! \brief
424      * Returns a pointer to user-specified default value, or NULL if there
425      * is none.
426      */
427     const T* defaultValueIfSet() const { return defaultValueIfSet_; }
428     /*! \brief
429      * Returns a pointer to the storage location, or NULL if none specified.
430      */
431     T* store() const { return store_; }
432     /*! \brief
433      * Returns a pointer to the storage vector, or NULL if none specified.
434      */
435     std::vector<T>* storeVector() const { return storeVector_; }
436     //! Returns \p *this casted into MyClass to reduce typing.
437     MyClass& me() { return static_cast<MyClass&>(*this); }
438     //! \endcond
439
440 private:
441     const T*        defaultValue_;
442     const T*        defaultValueIfSet_;
443     T*              store_;
444     int*            countptr_;
445     std::vector<T>* storeVector_;
446
447     /*! \brief
448      * Needed to initialize storage from this class without otherwise
449      * unnecessary accessors.
450      */
451     friend class OptionStorageTemplate<T>;
452 };
453
454 /*! \brief
455  * Gives information and allows modifications to an option after creation.
456  *
457  * When an option is added with Options::addOption(), an object of a subclass
458  * of OptionInfo is returned.  This object can be later used to access
459  * information about the option.  Non-const methods also allow later changing
460  * (some of) the option settings provided at initialization time.
461  * The properties accessible/modifiable through this interface are implemented
462  * based on need, and may not be implemented for all cases.
463  *
464  * \if libapi
465  * This class is also used by OptionsVisitor and OptionsModifyingVisitor as
466  * the interface that allows querying/modifying each visited option.
467  * \endif
468  *
469  * This class isolates the details of the internal option implementation from
470  * callers.  Although this class is a simple reference to the underlying
471  * implementation, it is implemented as non-copyable to allow const/non-const
472  * status of a reference to this class to indicate whether modifications are
473  * allowed.  Otherwise, separate classes would be needed for access and
474  * modification, complicating the implementation.  In the implementation,
475  * there is always a single OptionInfo instance referring to one option.
476  * The underlying implementation object always owns this instance, and only
477  * references are passed to callers.
478  *
479  * \see Options::addOption()
480  * \if libapi
481  * \see OptionsVisitor
482  * \see OptionsModifyingVisitor
483  * \endif
484  *
485  * \inpublicapi
486  * \ingroup module_options
487  */
488 class OptionInfo
489 {
490 public:
491     virtual ~OptionInfo();
492
493     /*! \brief
494      * Test whether the option is of a particular type.
495      *
496      * \tparam InfoType  Option type to test for. Should be a class derived
497      *      from OptionInfo.
498      */
499     template<class InfoType>
500     bool isType() const
501     {
502         return toType<InfoType>() != nullptr;
503     }
504     /*! \brief
505      * Convert the info object to a particular type if the type is correct.
506      *
507      * \tparam InfoType  Option type to convert to. Should be a class
508      *      derived from OptionInfo.
509      * \retval this converted to a pointer to \p InfoType, or NULL if the
510      *      conversion is not possible.
511      */
512     template<class InfoType>
513     InfoType* toType()
514     {
515         return dynamic_cast<InfoType*>(this);
516     }
517     //! \copydoc toType()
518     template<class InfoType>
519     const InfoType* toType() const
520     {
521         return dynamic_cast<const InfoType*>(this);
522     }
523
524     //! Returns true if the option has been set.
525     bool isSet() const;
526     //! Returns true if the option is a hidden option.
527     bool isHidden() const;
528     //! Returns true if the option is required.
529     bool isRequired() const;
530     //! Returns the minimum number of values that this option accepts.
531     int minValueCount() const;
532     //! Returns the maximum number of values that this option accepts.
533     int maxValueCount() const;
534     //! Returns the name of the option.
535     const std::string& name() const;
536     //! Returns the type of the option as a string.
537     std::string type() const;
538     //! Returns the description of the option.
539     std::string formatDescription() const;
540
541     /*! \brief
542      * Returns the default value(s) of the option.
543      *
544      * The returned values should all be of the same type, but returning
545      * each as a separate any is currently simpler.
546      *
547      * Currently, this can only be called before option values have been
548      * assigned.
549      */
550     std::vector<Any> defaultValues() const;
551     /*! \brief
552      * Returns the default value(s) of the option as strings.
553      *
554      * If there is no default value, but defaultValueIfSet() is set, that
555      * is returned instead.
556      *
557      * Currently, this can only be called before option values have been
558      * assigned.
559      */
560     std::vector<std::string> defaultValuesAsStrings() const;
561     /*! \brief
562      * Converts given values to native representation for this option.
563      *
564      * For example, strings are parsed to the type that is actually used to
565      * store the options.
566      *
567      * The return value only depends on the option type, not on the current
568      * value of the option, and the current value in the option is not
569      * changed.
570      */
571     std::vector<Any> normalizeValues(const std::vector<Any>& values) const;
572
573 protected:
574     /*! \cond libapi */
575     /*! \brief
576      * Wraps a given option object.
577      *
578      * Does not throw.
579      */
580     explicit OptionInfo(AbstractOptionStorage* option);
581
582     //! Returns the wrapped option storage object.
583     AbstractOptionStorage& option() { return option_; }
584     //! Returns the wrapped option storage object.
585     const AbstractOptionStorage& option() const { return option_; }
586     //! \endcond
587
588 private:
589     //! The wrapped option.
590     AbstractOptionStorage& option_;
591
592     GMX_DISALLOW_COPY_AND_ASSIGN(OptionInfo);
593 };
594
595 } // namespace gmx
596
597 #endif