Merge release-4-6 into master
[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(efOption_Set); }
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(efOption_Hidden); }
99         //! Returns true if the option is required.
100         bool isRequired() const { return hasFlag(efOption_Required); }
101         //! Returns true if the option is vector-valued.
102         bool isVector() const { return hasFlag(efOption_Vector); }
103         //! Returns the name of the option.
104         const std::string &name() const { return name_; }
105         //! Returns the description of the option.
106         const std::string &description() const { return descr_; }
107
108         /*! \brief
109          * Returns an option info object corresponding to this option.
110          */
111         virtual OptionInfo &optionInfo() = 0;
112         /*! \brief
113          * Returns a short string describing the type of the option.
114          *
115          * The caller is free to discard the returned string.
116          */
117         virtual const char *typeString() const = 0;
118         /*! \brief
119          * Returns the number of option values added so far.
120          */
121         virtual int valueCount() const = 0;
122         /*! \brief
123          * Returns the i'th value formatted as a string.
124          *
125          * If \p i is DefaultValueIfSetIndex, should format the default value
126          * if set (see OptionTemplate::defaultValueIfSet()).
127          */
128         virtual std::string formatValue(int i) const = 0;
129         //! \copydoc OptionInfo::formatDefaultValueIfSet()
130         std::string formatDefaultValueIfSet() const
131         { return formatValue(DefaultValueIfSetIndex); }
132
133         /*! \brief
134          * Starts adding values from a new source for the option.
135          *
136          * This marks the vurrent value of the option as a default value,
137          * causing next call to startSet() to clear it.  This allows values
138          * from the new source to overwrite old values.
139          *
140          * This method does not throw.
141          */
142         void startSource();
143         /*! \brief
144          * Starts adding a new set of values for the option.
145          *
146          * \throws  InvalidInputError if option is specified multiple times,
147          *      but is not specified to accept it.
148          *
149          * If the parameter is specified multiple times, startSet() should be
150          * called before the values for each instance.
151          *
152          * Strong exception safety guarantee.
153          */
154         void startSet();
155         /*! \brief
156          * Adds a new value for the option, converting it from a string.
157          *
158          * \param[in] value  String value to convert.
159          * \throws  InvalidInputError if value cannot be converted, or
160          *      if there are too many values.
161          *
162          * This method should only be called between startSet() and
163          * finishSet().
164          */
165         void appendValue(const std::string &value);
166         /*! \brief
167          * Performs validation and/or actions once a set of values has been
168          * added.
169          *
170          * \throws  InvalidInputError if too few values have been provided, or
171          *      if the valid values since previous startSet() are invalid as a
172          *      set.
173          *
174          * If the parameter is specified multiple times, finishSet() should be
175          * called after the values for each instance.
176          */
177         void finishSet();
178         /*! \brief
179          * Performs validation and/or actions once all values have been added.
180          *
181          * \throws InvalidInputError if the option is required but not set, or
182          *      if all valid values together are invalid as a set.
183          *
184          * This method should be called after all values have been provided
185          * with appendValue().
186          */
187         void finish();
188
189     protected:
190         //! Index used with formatValue() for formatting default value if set.
191         static const int DefaultValueIfSetIndex = -1;
192
193         /*! \brief
194          * Initializes the storage object from the settings object.
195          *
196          * \param[in] settings  Option settings.
197          * \param[in] staticFlags Option flags that are always set and specify
198          *      generic behavior of the option.
199          * \throws  APIError if invalid settings have been provided.
200          */
201         AbstractOptionStorage(const AbstractOption &settings,
202                               OptionFlags staticFlags);
203
204         //! Marks the option as set.
205         void markAsSet() { flags_.set(efOption_Set); }
206         //! Returns true if the given flag is set.
207         bool hasFlag(OptionFlag flag) const { return flags_.test(flag); }
208         //! Sets the given flag.
209         void setFlag(OptionFlag flag) { return flags_.set(flag); }
210         //! Clears the given flag.
211         void clearFlag(OptionFlag flag) { return flags_.clear(flag); }
212
213         //! Returns the minimum number of values required in one set.
214         int minValueCount() const { return minValueCount_; }
215         //! Returns the maximum allowed number of values in one set (-1 = no limit).
216         int maxValueCount() const { return maxValueCount_; }
217         /*! \brief
218          * Sets a new minimum number of values required in one set.
219          *
220          * \param[in] count  New minimum number of values (must be > 0).
221          * \throws InvalidInputError if already provided values violate the limit.
222          *
223          * If values have already been provided, it is checked that there are
224          * enough.
225          *
226          * Cannot be called for options with ::efOption_MultipleTimes set,
227          * because it is impossible to check the requirement after the values
228          * have been set.
229          * If attempted, will assert.
230          */
231         void setMinValueCount(int count);
232         /*! \brief
233          * Sets a new maximum number of values required in one set.
234          *
235          * \param[in] count  New maximum number of values
236          *                   (must be > 0, or -1 for no limit).
237          * \throws InvalidInputError if already provided values violate the limit.
238          *
239          * If values have already been provided, it is checked that there are
240          * not too many.
241          *
242          * Cannot be called for options with ::efOption_MultipleTimes set,
243          * because it is impossible to check the requirement after the values
244          * have been set.
245          * If attempted, will assert.
246          */
247         void setMaxValueCount(int count);
248
249         /*! \brief
250          * Removes all values from temporary storage for a set.
251          *
252          * This function is always called before starting to add values to
253          * a set, allowing the storage to clear its internal buffers.
254          *
255          * Should not throw.
256          */
257         virtual void clearSet() = 0;
258         /*! \brief
259          * Adds a new value, converting it from a string.
260          *
261          * \param[in] value  String value to convert.
262          * \throws  InvalidInputError if \p value is not valid for this option
263          *      or if there have been too many values in the set.
264          *
265          * This method may be called multiple times if the underlying
266          * option is defined to accept multiple values.
267          *
268          * \see OptionStorageTemplate::convertValue()
269          */
270         virtual void convertValue(const std::string &value) = 0;
271         /*! \brief
272          * Performs validation and/or actions once a set of values has been
273          * added.
274          *
275          * \throws  InvalidInputError if the values in the set are not valid
276          *      as a whole.
277          *
278          * This method may be called multiple times if the underlying option
279          * can be specified multiple times.
280          * This method is not currently called if one of the convertValue()
281          * calls throwed.
282          *
283          * \todo
284          * Improve the call semantics.
285          *
286          * \see OptionStorageTemplate::processSetValues()
287          */
288         virtual void processSet() = 0;
289         /*! \brief
290          * Performs validation and/or actions once all values have been added.
291          *
292          * \throws  InvalidInputError if all provided values are not valid as
293          *      a set.
294          *
295          * This method is always called once.
296          *
297          * If the method throws, implementation should take care to leave the
298          * option in a consistent, meaningful state.  However, currently none
299          * of the implementations actually throw in any situation where the
300          * option may be left in an inconsistent state.
301          */
302         virtual void processAll() = 0;
303
304     private:
305         std::string             name_;
306         std::string             descr_;
307         //! Flags for the option.
308         OptionFlags             flags_;
309         //! Minimum number of values required (in one set).
310         int                     minValueCount_;
311         //! Maximum allowed number of values (in one set), or -1 if no limit.
312         int                     maxValueCount_;
313         //! Whether we are currently assigning values to a set.
314         bool                    bInSet_;
315         //! Whether there were errors in set values.
316         bool                    bSetValuesHadErrors_;
317
318         GMX_DISALLOW_COPY_AND_ASSIGN(AbstractOptionStorage);
319 };
320
321 } // namespace gmx
322
323 #endif