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