Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / options / repeatingsection.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2016,2018,2019, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source 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 /*! \file
36  * \brief
37  * Declares gmx::RepeatingOptionSection and related classes.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_options
42  */
43 #ifndef GMX_OPTIONS_REPEATINGSECTION_H
44 #define GMX_OPTIONS_REPEATINGSECTION_H
45
46 #include <memory>
47 #include <vector>
48
49 #include "gromacs/options/ioptionscontainerwithsections.h"
50
51 #include "abstractsection.h"
52 #include "isectionstorage.h"
53 #include "valuestore.h"
54
55 namespace gmx
56 {
57
58 template<class T>
59 class RepeatingOptionSectionHandle;
60 template<class T>
61 class RepeatingOptionSectionStorage;
62
63 /*! \brief
64  * Declares an option section that creates a structure for each instance.
65  *
66  * \tparam  T  Structure that stores the values for an instance of the section.
67  *
68  * This class declares a section that can be specified multiple times, and
69  * creates an instance of `T` for each instance.  Options within the section
70  * can store their values in the created structure.
71  *
72  * \inpublicapi
73  * \ingroup module_options
74  */
75 template<class T>
76 class RepeatingOptionSection : public AbstractOptionSection
77 {
78 public:
79     //! AbstractOptionSectionHandle corresponding to this option type.
80     typedef RepeatingOptionSectionHandle<T> HandleType;
81
82     //! Creates a section with the given name.
83     explicit RepeatingOptionSection(const char* name) :
84         AbstractOptionSection(name),
85         values_(nullptr)
86     {
87     }
88
89     //! Specifies a vector to receive the section structures.
90     RepeatingOptionSection& storeVector(std::vector<T>* values)
91     {
92         values_ = values;
93         return *this;
94     }
95
96 private:
97     std::unique_ptr<IOptionSectionStorage> createStorage() const override;
98
99     std::vector<T>* values_;
100
101     //! Allows accessing the properties when initializing the storage.
102     friend class RepeatingOptionSectionStorage<T>;
103 };
104
105 /*! \internal
106  * \brief
107  * Implements handling of the structures that stores per-section values.
108  *
109  * \ingroup module_options
110  */
111 template<class T>
112 class RepeatingOptionSectionStorage : public IOptionSectionStorage
113 {
114 public:
115     //! Initializes the storage for given section properties.
116     explicit RepeatingOptionSectionStorage(const RepeatingOptionSection<T>& section) :
117         store_(new OptionValueStoreVector<T>(section.values_)),
118         currentData_()
119     {
120     }
121
122     void initStorage() override { defaultValues_ = currentData_; }
123     void startSection() override { resetSection(); }
124     void finishSection() override
125     {
126         store_->append(currentData_);
127         resetSection();
128     }
129
130 private:
131     void resetSection() { currentData_ = defaultValues_; }
132
133     //! Final storage location for the section structures.
134     const std::unique_ptr<IOptionValueStore<T>> store_;
135     T                                           defaultValues_;
136     /*! \brief
137      * Stores the values for the current in-process section.
138      *
139      * Options within the section store their values to this structure, and
140      * they are then copied to the final storage when the section finishes.
141      */
142     T currentData_;
143
144     //! Allows binding option storage to the current section data structure.
145     friend class RepeatingOptionSectionHandle<T>;
146 };
147
148 template<class T>
149 std::unique_ptr<IOptionSectionStorage> RepeatingOptionSection<T>::createStorage() const
150 {
151
152     return std::make_unique<RepeatingOptionSectionStorage<T>>(*this);
153 }
154
155 /*! \brief
156  * Allows adding options to an RepeatingOptionSection.
157  *
158  * An instance of this class is returned from
159  * IOptionsContainerWithSections::addSection(), and supports adding options and
160  * subsections to a section created with OptionSection.
161  *
162  * Example:
163  * \code
164    struct SectionData { int value; }
165    // as class attribute
166    std::vector<SectionData> values;
167
168    void MyClass::initOptions(gmx::IOptionsContainerWithSections *options)
169    {
170        auto sec = options->addSection(gmx::RepeatingOptionSection<SectionData>("sec").storeVector(&values));
171        sec->addOption(gmx::IntegerOption("arg").store(&sec.bind().value));
172    }
173    \endcode
174  *
175  * \inpublicapi
176  * \ingroup module_options
177  */
178 template<class T>
179 class RepeatingOptionSectionHandle : public AbstractOptionSectionHandle
180 {
181 public:
182     //! Wraps a given section storage object.
183     explicit RepeatingOptionSectionHandle(internal::OptionSectionImpl* section) :
184         AbstractOptionSectionHandle(section),
185         storage_(getStorage<RepeatingOptionSectionStorage<T>>(section))
186     {
187     }
188
189     /*! \brief
190      * Supports storing option values within the per-section data structure.
191      *
192      * See class documentation for an example.
193      */
194     T& bind() { return storage_->currentData_; }
195
196 private:
197     RepeatingOptionSectionStorage<T>* storage_;
198 };
199
200 } // namespace gmx
201
202 #endif