3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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.
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.
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.
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.
29 * For more info, check our website at http://www.gromacs.org
33 * Implements gmx::Options.
35 * \author Teemu Murtola <teemu.murtola@gmail.com>
36 * \ingroup module_options
38 #include "gromacs/options/options.h"
40 #include "gromacs/options/abstractoption.h"
41 #include "gromacs/options/abstractoptionstorage.h"
42 #include "gromacs/utility/exceptions.h"
43 #include "gromacs/utility/gmxassert.h"
44 #include "gromacs/utility/messagestringcollector.h"
45 #include "gromacs/utility/stringutil.h"
47 #include "options-impl.h"
52 /********************************************************************
56 Options::Impl::Impl(const char *name, const char *title)
57 : name_(name != NULL ? name : ""), title_(title != NULL ? title : ""),
62 Options::Impl::~Impl()
66 Options *Options::Impl::findSubSection(const char *name) const
68 SubSectionList::const_iterator i;
69 for (i = subSections_.begin(); i != subSections_.end(); ++i)
71 if ((*i)->name() == name)
79 AbstractOptionStorage *Options::Impl::findOption(const char *name) const
81 OptionList::const_iterator i;
82 for (i = options_.begin(); i != options_.end(); ++i)
84 if ((*i)->name() == name)
92 void Options::Impl::startSource()
94 OptionList::const_iterator i;
95 for (i = options_.begin(); i != options_.end(); ++i)
97 AbstractOptionStorage &option = **i;
100 SubSectionList::const_iterator j;
101 for (j = subSections_.begin(); j != subSections_.end(); ++j)
103 Options §ion = **j;
104 section.impl_->startSource();
108 /********************************************************************
112 Options::Options(const char *name, const char *title)
113 : impl_(new Impl(name, title))
121 const std::string &Options::name() const
126 const std::string &Options::title() const
128 return impl_->title_;
131 const std::string &Options::description() const
133 return impl_->description_;
136 void Options::setDescription(const std::string &desc)
138 impl_->description_ = desc;
141 void Options::addSubSection(Options *section)
143 // Make sure that section is not already inserted somewhere.
144 GMX_RELEASE_ASSERT(section->impl_->parent_ == NULL,
145 "Cannot add as subsection twice");
146 // Make sure that there are no duplicate sections.
147 GMX_RELEASE_ASSERT(impl_->findSubSection(section->name().c_str()) == NULL,
148 "Duplicate subsection name");
149 impl_->subSections_.push_back(section);
150 section->impl_->parent_ = this;
153 OptionInfo *Options::addOption(const AbstractOption &settings)
155 AbstractOptionStoragePointer option(settings.createStorage());
156 if (impl_->findOption(option->name().c_str()) != NULL)
158 GMX_THROW(APIError("Duplicate option: " + option->name()));
160 impl_->options_.push_back(move(option));
161 return &impl_->options_.back()->optionInfo();
164 bool Options::isSet(const char *name) const
166 AbstractOptionStorage *option = impl_->findOption(name);
167 return (option != NULL ? option->isSet() : false);
170 void Options::finish()
172 // TODO: Consider how to customize these error messages based on context.
173 ExceptionInitializer errors("Invalid input values");
174 Impl::OptionList::const_iterator i;
175 for (i = impl_->options_.begin(); i != impl_->options_.end(); ++i)
177 AbstractOptionStorage &option = **i;
182 catch (UserInputError &ex)
184 ex.prependContext("In option " + option.name());
185 errors.addCurrentExceptionAsNested();
188 Impl::SubSectionList::const_iterator j;
189 for (j = impl_->subSections_.begin(); j != impl_->subSections_.end(); ++j)
191 Options §ion = **j;
196 catch (const UserInputError &)
198 errors.addCurrentExceptionAsNested();
201 if (errors.hasNestedExceptions())
203 // TODO: This exception type may not always be appropriate.
204 GMX_THROW(InvalidInputError(errors));