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