Merge remote-tracking branch 'gerrit/release-4-6'
[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 "optionflags.h"
45
46 namespace gmx
47 {
48
49 class AbstractOption;
50 class Options;
51
52 /*! \libinternal \brief
53  * Abstract base class for converting, validating, and storing option values.
54  *
55  * This class should normally not be subclassed directly, but the
56  * OptionStorageTemplate should be used instead.  The templated class provides
57  * basic functionality for most of the pure virtual methods, and also
58  * integrates well with option setting objects derived from OptionTemplate.
59  *
60  * \inlibraryapi
61  * \ingroup module_options
62  *
63  * \internal
64  * This class really consists of two parts: the public interface that is
65  * used by the internal implementation of the options module, and the
66  * interface that derived classes use to provide type-dependent functionality.
67  * The latter consists of a few pure virtual methods, of which a few simple
68  * query methods are also part of the module-internal interface, others are
69  * protected and called by the non-virtual methods when needed.
70  * The reason why these two roles are in one class is twofold:
71  *  -# Both the derived classes and the internal module implementation may need
72  *     access to the same information like the allowed number of values and the
73  *     name of the option.
74  *  -# Having only one class is consistent with the structure used for options
75  *     settings objects: there is very direct correspondence between
76  *     AbstractOption and AbstractOptionStorage and between OptionTemplate and
77  *     OptionStorageTemplate.
78  */
79 class AbstractOptionStorage
80 {
81     public:
82         virtual ~AbstractOptionStorage();
83
84         //! Returns true if the option has been set.
85         bool isSet() const { return hasFlag(efSet); }
86         //! Returns true if the option is a boolean option.
87         bool isBoolean() const { return hasFlag(efBoolean); }
88         //! Returns true if the option is a file option.
89         bool isFile() const { return hasFlag(efFile); }
90         //! Returns true if the option is a hidden option.
91         bool isHidden() const { return hasFlag(efHidden); }
92         //! Returns the name of the option.
93         const std::string &name() const { return _name; }
94         //! Returns the description of the option.
95         const std::string &description() const { return _descr; }
96         /*! \brief
97          * Returns a short string describing the type of the option.
98          *
99          * The caller is free to discard the returned string.
100          */
101         virtual const char *typeString() const = 0;
102         /*! \brief
103          * Returns the number of option values added so far.
104          */
105         virtual int valueCount() const = 0;
106         /*! \brief
107          * Returns the i'th value formatted as a string.
108          */
109         virtual std::string formatValue(int i) const = 0;
110
111         /*! \brief
112          * Starts adding values from a new source for the option.
113          *
114          * This marks the vurrent value of the option as a default value,
115          * causing next call to startSet() to clear it.  This allows values
116          * from the new source to overwrite old values.
117          *
118          * This method does not throw.
119          */
120         void startSource();
121         /*! \brief
122          * Starts adding a new set of values for the option.
123          *
124          * \throws  InvalidInputError if option is specified multiple times,
125          *      but is not specified to accept it.
126          *
127          * If the parameter is specified multiple times, startSet() should be
128          * called before the values for each instance.
129          *
130          * Strong exception safety guarantee.
131          */
132         void startSet();
133         /*! \brief
134          * Adds a new value for the option, converting it from a string.
135          *
136          * \param[in] value  String value to convert.
137          * \throws  InvalidInputError if value cannot be converted, or
138          *      if there are too many values.
139          *
140          * This method should only be called between startSet() and
141          * finishSet().
142          */
143         void appendValue(const std::string &value);
144         /*! \brief
145          * Performs validation and/or actions once a set of values has been
146          * added.
147          *
148          * \throws  InvalidInputError if too few values have been provided, or
149          *      if the valid values since previous startSet() are invalid as a
150          *      set.
151          *
152          * If the parameter is specified multiple times, finishSet() should be
153          * called after the values for each instance.
154          */
155         void finishSet();
156         /*! \brief
157          * Performs validation and/or actions once all values have been added.
158          *
159          * \throws InvalidInputError if the option is required but not set, or
160          *      if all valid values together are invalid as a set.
161          *
162          * This method should be called after all values have been provided
163          * with appendValue().
164          */
165         void finish();
166
167     protected:
168         /*! \brief
169          * Initializes the storage object from the settings object.
170          *
171          * \param[in] settings  Option settings.
172          * \param[in] options   Option collection that will contain the
173          *      option.
174          * \param[in] staticFlags Option flags that are always set and specify
175          *      generic behavior of the option.
176          * \throws  APIError if invalid settings have been provided.
177          */
178         AbstractOptionStorage(const AbstractOption &settings, Options *options,
179                               OptionFlags staticFlags);
180
181         //! Returns true if the given flag is set.
182         bool hasFlag(OptionFlag flag) const { return _flags.test(flag); }
183         //! Sets the given flag.
184         void setFlag(OptionFlag flag) { return _flags.set(flag); }
185         //! Clears the given flag.
186         void clearFlag(OptionFlag flag) { return _flags.clear(flag); }
187
188         //! Returns the minimum number of values required in one set.
189         int minValueCount() const { return _minValueCount; }
190         //! Returns the maximum allowed number of values in one set (-1 = no limit).
191         int maxValueCount() const { return _maxValueCount; }
192         /*! \brief
193          * Sets a new minimum number of values required in one set.
194          *
195          * \param[in] count  New minimum number of values (must be > 0).
196          * \throws InvalidInputError if already provided values violate the limit.
197          *
198          * If values have already been provided, it is checked that there are
199          * enough.
200          *
201          * Cannot be called for options with ::efMulti set, because it is
202          * impossible to check the requirement after the values have been set.
203          * If attempted, will assert.
204          */
205         void setMinValueCount(int count);
206         /*! \brief
207          * Sets a new maximum number of values required in one set.
208          *
209          * \param[in] count  New maximum number of values
210          *                   (must be > 0, or -1 for no limit).
211          * \throws InvalidInputError if already provided values violate the limit.
212          *
213          * If values have already been provided, it is checked that there are
214          * not too many.
215          *
216          * Cannot be called for options with ::efMulti set, because it is
217          * impossible to check the requirement after the values have been set.
218          * If attempted, will assert.
219          */
220         void setMaxValueCount(int count);
221
222         //! Returns the Options object that houses the option.
223         Options &hostOptions() { return *_options; }
224         //! \copydoc hostOptions()
225         const Options &hostOptions() const { return *_options; }
226
227         /*! \brief
228          * Removes all values from temporary storage for a set.
229          *
230          * This function is always called before starting to add values to
231          * a set, allowing the storage to clear its internal buffers.
232          *
233          * Should not throw.
234          */
235         virtual void clearSet() = 0;
236         /*! \brief
237          * Adds a new value, converting it from a string.
238          *
239          * \param[in] value  String value to convert.
240          * \throws  InvalidInputError if \p value is not valid for this option
241          *      or if there have been too many values in the set.
242          *
243          * This method may be called multiple times if the underlying
244          * option is defined to accept multiple values.
245          *
246          * \see OptionStorageTemplate::convertValue()
247          */
248         virtual void convertValue(const std::string &value) = 0;
249         /*! \brief
250          * Performs validation and/or actions once a set of values has been
251          * added.
252          *
253          * \throws  InvalidInputError if the values in the set are not valid
254          *      as a whole.
255          *
256          * This method may be called multiple times if the underlying option
257          * can be specified multiple times.
258          *
259          * \see OptionStorageTemplate::processSetValues()
260          */
261         virtual void processSet() = 0;
262         /*! \brief
263          * Performs validation and/or actions once all values have been added.
264          *
265          * \throws  InvalidInputError if all provided values are not valid as
266          *      a set.
267          *
268          * This method is always called once.
269          *
270          * If the method throws, implementation should take care to leave the
271          * option in a consistent, meaningful state.  However, currently none
272          * of the implementations actually throw in any situation where the
273          * option may be left in an inconsistent state.
274          */
275         virtual void processAll() = 0;
276
277     private:
278         std::string             _name;
279         std::string             _descr;
280         //! Flags for the option.
281         OptionFlags             _flags;
282         //! Minimum number of values required (in one set).
283         int                     _minValueCount;
284         //! Maximum allowed number of values (in one set), or -1 if no limit.
285         int                     _maxValueCount;
286         //! Whether we are currently assigning values to a set.
287         bool                    _inSet;
288         //! Parent Options object.
289         Options                *_options;
290
291         // Disallow copy and assign.
292         AbstractOptionStorage(const AbstractOptionStorage &);
293         void operator =(const AbstractOptionStorage &);
294 };
295
296 } // namespace gmx
297
298 #endif