Merge release-4-6 (commit 'Ic142a690')
[alexxy/gromacs.git] / src / gromacs / options / abstractoptionstorage.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \libinternal \file
32  * \brief
33  * Declares gmx::AbstractOptionStorage.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inlibraryapi
37  * \ingroup module_options
38  */
39 #ifndef GMX_OPTIONS_ABSTRACTOPTIONSTORAGE_H
40 #define GMX_OPTIONS_ABSTRACTOPTIONSTORAGE_H
41
42 #include <string>
43
44 #include "../utility/common.h"
45
46 #include "optionflags.h"
47
48 namespace gmx
49 {
50
51 class AbstractOption;
52 class OptionInfo;
53 class Options;
54
55 /*! \libinternal \brief
56  * Abstract base class for converting, validating, and storing option values.
57  *
58  * This class should normally not be subclassed directly, but the
59  * OptionStorageTemplate should be used instead.  The templated class provides
60  * basic functionality for most of the pure virtual methods, and also
61  * integrates well with option setting objects derived from OptionTemplate.
62  *
63  * \inlibraryapi
64  * \ingroup module_options
65  *
66  * \internal
67  * This class really consists of two parts: the public interface that is
68  * used by the internal implementation of the options module, and the
69  * interface that derived classes use to provide type-dependent functionality.
70  * The latter consists of a few pure virtual methods, of which a few simple
71  * query methods are also part of the module-internal interface, others are
72  * protected and called by the non-virtual methods when needed.
73  * The reason why these two roles are in one class is twofold:
74  *  -# Both the derived classes and the internal module implementation may need
75  *     access to the same information like the allowed number of values and the
76  *     name of the option.
77  *  -# Having only one class is consistent with the structure used for options
78  *     settings objects: there is very direct correspondence between
79  *     AbstractOption and AbstractOptionStorage and between OptionTemplate and
80  *     OptionStorageTemplate.
81  */
82 class AbstractOptionStorage
83 {
84     public:
85         virtual ~AbstractOptionStorage();
86
87         //! Returns true if the option has been set.
88         bool isSet() const { return hasFlag(efSet); }
89         /*! \brief
90          * Returns true if the option is a boolean option.
91          *
92          * This is used to optionally support an alternative syntax where an
93          * option provided with no value sets the value to true and an
94          * option prefixed with "no" clears the value.
95          */
96         bool isBoolean() const;
97         //! Returns true if the option is a hidden option.
98         bool isHidden() const { return hasFlag(efHidden); }
99         //! Returns true if the option is required.
100         bool isRequired() const { return hasFlag(efRequired); }
101         //! Returns the name of the option.
102         const std::string &name() const { return _name; }
103         //! Returns the description of the option.
104         const std::string &description() const { return _descr; }
105
106         /*! \brief
107          * Returns an option info object corresponding to this option.
108          */
109         virtual OptionInfo &optionInfo() = 0;
110         /*! \brief
111          * Returns a short string describing the type of the option.
112          *
113          * The caller is free to discard the returned string.
114          */
115         virtual const char *typeString() const = 0;
116         /*! \brief
117          * Returns the number of option values added so far.
118          */
119         virtual int valueCount() const = 0;
120         /*! \brief
121          * Returns the i'th value formatted as a string.
122          *
123          * If \p i is DefaultValueIfSetIndex, should format the default value
124          * if set (see OptionTemplate::defaultValueIfSet()).
125          */
126         virtual std::string formatValue(int i) const = 0;
127         //! \copydoc OptionInfo::formatDefaultValueIfSet()
128         std::string formatDefaultValueIfSet() const
129         { return formatValue(DefaultValueIfSetIndex); }
130
131         /*! \brief
132          * Starts adding values from a new source for the option.
133          *
134          * This marks the vurrent value of the option as a default value,
135          * causing next call to startSet() to clear it.  This allows values
136          * from the new source to overwrite old values.
137          *
138          * This method does not throw.
139          */
140         void startSource();
141         /*! \brief
142          * Starts adding a new set of values for the option.
143          *
144          * \throws  InvalidInputError if option is specified multiple times,
145          *      but is not specified to accept it.
146          *
147          * If the parameter is specified multiple times, startSet() should be
148          * called before the values for each instance.
149          *
150          * Strong exception safety guarantee.
151          */
152         void startSet();
153         /*! \brief
154          * Adds a new value for the option, converting it from a string.
155          *
156          * \param[in] value  String value to convert.
157          * \throws  InvalidInputError if value cannot be converted, or
158          *      if there are too many values.
159          *
160          * This method should only be called between startSet() and
161          * finishSet().
162          */
163         void appendValue(const std::string &value);
164         /*! \brief
165          * Performs validation and/or actions once a set of values has been
166          * added.
167          *
168          * \throws  InvalidInputError if too few values have been provided, or
169          *      if the valid values since previous startSet() are invalid as a
170          *      set.
171          *
172          * If the parameter is specified multiple times, finishSet() should be
173          * called after the values for each instance.
174          */
175         void finishSet();
176         /*! \brief
177          * Performs validation and/or actions once all values have been added.
178          *
179          * \throws InvalidInputError if the option is required but not set, or
180          *      if all valid values together are invalid as a set.
181          *
182          * This method should be called after all values have been provided
183          * with appendValue().
184          */
185         void finish();
186
187     protected:
188         //! Index used with formatValue() for formatting default value if set.
189         static const int DefaultValueIfSetIndex = -1;
190
191         /*! \brief
192          * Initializes the storage object from the settings object.
193          *
194          * \param[in] settings  Option settings.
195          * \param[in] staticFlags Option flags that are always set and specify
196          *      generic behavior of the option.
197          * \throws  APIError if invalid settings have been provided.
198          */
199         AbstractOptionStorage(const AbstractOption &settings,
200                               OptionFlags staticFlags);
201
202         //! Returns true if the given flag is set.
203         bool hasFlag(OptionFlag flag) const { return _flags.test(flag); }
204         //! Sets the given flag.
205         void setFlag(OptionFlag flag) { return _flags.set(flag); }
206         //! Clears the given flag.
207         void clearFlag(OptionFlag flag) { return _flags.clear(flag); }
208
209         //! Returns the minimum number of values required in one set.
210         int minValueCount() const { return _minValueCount; }
211         //! Returns the maximum allowed number of values in one set (-1 = no limit).
212         int maxValueCount() const { return _maxValueCount; }
213         /*! \brief
214          * Sets a new minimum number of values required in one set.
215          *
216          * \param[in] count  New minimum number of values (must be > 0).
217          * \throws InvalidInputError if already provided values violate the limit.
218          *
219          * If values have already been provided, it is checked that there are
220          * enough.
221          *
222          * Cannot be called for options with ::efMulti set, because it is
223          * impossible to check the requirement after the values have been set.
224          * If attempted, will assert.
225          */
226         void setMinValueCount(int count);
227         /*! \brief
228          * Sets a new maximum number of values required in one set.
229          *
230          * \param[in] count  New maximum number of values
231          *                   (must be > 0, or -1 for no limit).
232          * \throws InvalidInputError if already provided values violate the limit.
233          *
234          * If values have already been provided, it is checked that there are
235          * not too many.
236          *
237          * Cannot be called for options with ::efMulti set, because it is
238          * impossible to check the requirement after the values have been set.
239          * If attempted, will assert.
240          */
241         void setMaxValueCount(int count);
242
243         /*! \brief
244          * Removes all values from temporary storage for a set.
245          *
246          * This function is always called before starting to add values to
247          * a set, allowing the storage to clear its internal buffers.
248          *
249          * Should not throw.
250          */
251         virtual void clearSet() = 0;
252         /*! \brief
253          * Adds a new value, converting it from a string.
254          *
255          * \param[in] value  String value to convert.
256          * \throws  InvalidInputError if \p value is not valid for this option
257          *      or if there have been too many values in the set.
258          *
259          * This method may be called multiple times if the underlying
260          * option is defined to accept multiple values.
261          *
262          * \see OptionStorageTemplate::convertValue()
263          */
264         virtual void convertValue(const std::string &value) = 0;
265         /*! \brief
266          * Performs validation and/or actions once a set of values has been
267          * added.
268          *
269          * \throws  InvalidInputError if the values in the set are not valid
270          *      as a whole.
271          *
272          * This method may be called multiple times if the underlying option
273          * can be specified multiple times.
274          *
275          * \see OptionStorageTemplate::processSetValues()
276          */
277         virtual void processSet() = 0;
278         /*! \brief
279          * Performs validation and/or actions once all values have been added.
280          *
281          * \throws  InvalidInputError if all provided values are not valid as
282          *      a set.
283          *
284          * This method is always called once.
285          *
286          * If the method throws, implementation should take care to leave the
287          * option in a consistent, meaningful state.  However, currently none
288          * of the implementations actually throw in any situation where the
289          * option may be left in an inconsistent state.
290          */
291         virtual void processAll() = 0;
292
293     private:
294         std::string             _name;
295         std::string             _descr;
296         //! Flags for the option.
297         OptionFlags             _flags;
298         //! Minimum number of values required (in one set).
299         int                     _minValueCount;
300         //! Maximum allowed number of values (in one set), or -1 if no limit.
301         int                     _maxValueCount;
302         //! Whether we are currently assigning values to a set.
303         bool                    _inSet;
304
305         GMX_DISALLOW_COPY_AND_ASSIGN(AbstractOptionStorage);
306 };
307
308 } // namespace gmx
309
310 #endif