Fix copyright notices for new C++ code.
[alexxy/gromacs.git] / src / gromacs / options / abstractoption.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * 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 /*! \internal \file
36  * \brief
37  * Implements classes in abstractoption.h and abstractoptionstorage.h.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_options
41  */
42 #include "gromacs/options/abstractoption.h"
43
44 #include "gromacs/options/abstractoptionstorage.h"
45 #include "gromacs/options/optionflags.h"
46 #include "gromacs/utility/exceptions.h"
47 #include "gromacs/utility/gmxassert.h"
48
49 #include "basicoptionstorage.h"
50
51 namespace gmx
52 {
53
54 /********************************************************************
55  * AbstractOptionStorage
56  */
57
58 AbstractOptionStorage::AbstractOptionStorage(const AbstractOption &settings,
59                                              OptionFlags           staticFlags)
60     : flags_(settings.flags_ | staticFlags),
61       minValueCount_(settings.minValueCount_),
62       maxValueCount_(settings.maxValueCount_),
63       bInSet_(false), bSetValuesHadErrors_(false)
64 {
65     // Check that user has not provided incorrect values for vectors.
66     if (hasFlag(efOption_Vector) && (minValueCount_ > 1 || maxValueCount_ < 1))
67     {
68         GMX_THROW(APIError("Inconsistent value counts for vector values"));
69     }
70
71     if (settings.name_ != NULL)
72     {
73         name_  = settings.name_;
74     }
75     descr_ = settings.createDescription();
76     setFlag(efOption_ClearOnNextSet);
77 }
78
79 AbstractOptionStorage::~AbstractOptionStorage()
80 {
81 }
82
83 bool AbstractOptionStorage::isBoolean() const
84 {
85     return dynamic_cast<const BooleanOptionStorage *>(this) != NULL;
86 }
87
88 void AbstractOptionStorage::startSource()
89 {
90     setFlag(efOption_ClearOnNextSet);
91 }
92
93 void AbstractOptionStorage::startSet()
94 {
95     GMX_RELEASE_ASSERT(!bInSet_, "finishSet() not called");
96     // The last condition takes care of the situation where multiple
97     // sources are used, and a later source should be able to reassign
98     // the value even though the option is already set.
99     if (isSet() && !hasFlag(efOption_MultipleTimes)
100         && !hasFlag(efOption_ClearOnNextSet))
101     {
102         GMX_THROW(InvalidInputError("Option specified multiple times"));
103     }
104     clearSet();
105     bInSet_              = true;
106     bSetValuesHadErrors_ = false;
107 }
108
109 void AbstractOptionStorage::appendValue(const std::string &value)
110 {
111     GMX_RELEASE_ASSERT(bInSet_, "startSet() not called");
112     try
113     {
114         convertValue(value);
115     }
116     catch (...)
117     {
118         bSetValuesHadErrors_ = true;
119         throw;
120     }
121 }
122
123 void AbstractOptionStorage::finishSet()
124 {
125     GMX_RELEASE_ASSERT(bInSet_, "startSet() not called");
126     bInSet_ = false;
127     // We mark the option as set even when there are errors to avoid additional
128     // errors from required options not set.
129     // TODO: There could be a separate flag for this purpose.
130     setFlag(efOption_Set);
131     if (!bSetValuesHadErrors_)
132     {
133         // TODO: Correct handling of the efOption_ClearOnNextSet requires
134         // processSet() and/or convertValue() to check it internally.
135         // OptionStorageTemplate takes care of it, but it's error-prone if
136         // a custom option is implemented that doesn't use it.
137         processSet();
138     }
139     bSetValuesHadErrors_ = false;
140     clearFlag(efOption_ClearOnNextSet);
141     clearSet();
142 }
143
144 void AbstractOptionStorage::finish()
145 {
146     GMX_RELEASE_ASSERT(!bInSet_, "finishSet() not called");
147     processAll();
148     if (isRequired() && !(isSet() || hasFlag(efOption_ExplicitDefaultValue)))
149     {
150         GMX_THROW(InvalidInputError("Option is required, but not set"));
151     }
152 }
153
154 void AbstractOptionStorage::setMinValueCount(int count)
155 {
156     GMX_RELEASE_ASSERT(!hasFlag(efOption_MultipleTimes),
157                        "setMinValueCount() not supported with efOption_MultipleTimes");
158     GMX_RELEASE_ASSERT(count >= 0, "Invalid value count");
159     minValueCount_ = count;
160     if (isSet() && !hasFlag(efOption_DontCheckMinimumCount)
161         && valueCount() < minValueCount_)
162     {
163         GMX_THROW(InvalidInputError("Too few values"));
164     }
165 }
166
167 void AbstractOptionStorage::setMaxValueCount(int count)
168 {
169     GMX_RELEASE_ASSERT(!hasFlag(efOption_MultipleTimes),
170                        "setMaxValueCount() not supported with efOption_MultipleTimes");
171     GMX_RELEASE_ASSERT(count >= -1, "Invalid value count");
172     maxValueCount_ = count;
173     if (isSet() && maxValueCount_ >= 0 && valueCount() > maxValueCount_)
174     {
175         GMX_THROW(InvalidInputError("Too many values"));
176     }
177 }
178
179 /********************************************************************
180  * OptionInfo
181  */
182
183 /*! \cond libapi */
184 OptionInfo::OptionInfo(AbstractOptionStorage *option)
185     : option_(*option)
186 {
187 }
188 //! \endcond
189
190 OptionInfo::~OptionInfo()
191 {
192 }
193
194 bool OptionInfo::isSet() const
195 {
196     return option().isSet();
197 }
198
199 bool OptionInfo::isHidden() const
200 {
201     return option().isHidden();
202 }
203
204 bool OptionInfo::isRequired() const
205 {
206     return option().isRequired();
207 }
208
209 const std::string &OptionInfo::name() const
210 {
211     return option().name();
212 }
213
214 const std::string &OptionInfo::description() const
215 {
216     return option().description();
217 }
218
219 const char *OptionInfo::type() const
220 {
221     return option().typeString();
222 }
223
224 int OptionInfo::valueCount() const
225 {
226     return option().valueCount();
227 }
228
229 std::string OptionInfo::formatValue(int i) const
230 {
231     return option().formatValue(i);
232 }
233
234 std::string OptionInfo::formatDefaultValueIfSet() const
235 {
236     return option().formatDefaultValueIfSet();
237 }
238
239 } // namespace gmx