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