Apply clang-format-11
[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,2021, 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), values_(nullptr)
85     {
86     }
87
88     //! Specifies a vector to receive the section structures.
89     RepeatingOptionSection& storeVector(std::vector<T>* values)
90     {
91         values_ = values;
92         return *this;
93     }
94
95 private:
96     std::unique_ptr<IOptionSectionStorage> createStorage() const override;
97
98     std::vector<T>* values_;
99
100     //! Allows accessing the properties when initializing the storage.
101     friend class RepeatingOptionSectionStorage<T>;
102 };
103
104 /*! \internal
105  * \brief
106  * Implements handling of the structures that stores per-section values.
107  *
108  * \ingroup module_options
109  */
110 template<class T>
111 class RepeatingOptionSectionStorage : public IOptionSectionStorage
112 {
113 public:
114     //! Initializes the storage for given section properties.
115     explicit RepeatingOptionSectionStorage(const RepeatingOptionSection<T>& section) :
116         store_(new OptionValueStoreVector<T>(section.values_)), currentData_()
117     {
118     }
119
120     void initStorage() override { defaultValues_ = currentData_; }
121     void startSection() override { resetSection(); }
122     void finishSection() override
123     {
124         store_->append(currentData_);
125         resetSection();
126     }
127
128 private:
129     void resetSection() { currentData_ = defaultValues_; }
130
131     //! Final storage location for the section structures.
132     const std::unique_ptr<IOptionValueStore<T>> store_;
133     T                                           defaultValues_;
134     /*! \brief
135      * Stores the values for the current in-process section.
136      *
137      * Options within the section store their values to this structure, and
138      * they are then copied to the final storage when the section finishes.
139      */
140     T currentData_;
141
142     //! Allows binding option storage to the current section data structure.
143     friend class RepeatingOptionSectionHandle<T>;
144 };
145
146 template<class T>
147 std::unique_ptr<IOptionSectionStorage> RepeatingOptionSection<T>::createStorage() const
148 {
149
150     return std::make_unique<RepeatingOptionSectionStorage<T>>(*this);
151 }
152
153 /*! \brief
154  * Allows adding options to an RepeatingOptionSection.
155  *
156  * An instance of this class is returned from
157  * IOptionsContainerWithSections::addSection(), and supports adding options and
158  * subsections to a section created with OptionSection.
159  *
160  * Example:
161  * \code
162    struct SectionData { int value; }
163    // as class attribute
164    std::vector<SectionData> values;
165
166    void MyClass::initOptions(gmx::IOptionsContainerWithSections *options)
167    {
168        auto sec = options->addSection(gmx::RepeatingOptionSection<SectionData>("sec").storeVector(&values));
169        sec->addOption(gmx::IntegerOption("arg").store(&sec.bind().value));
170    }
171    \endcode
172  *
173  * \inpublicapi
174  * \ingroup module_options
175  */
176 template<class T>
177 class RepeatingOptionSectionHandle : public AbstractOptionSectionHandle
178 {
179 public:
180     //! Wraps a given section storage object.
181     explicit RepeatingOptionSectionHandle(internal::OptionSectionImpl* section) :
182         AbstractOptionSectionHandle(section),
183         storage_(getStorage<RepeatingOptionSectionStorage<T>>(section))
184     {
185     }
186
187     /*! \brief
188      * Supports storing option values within the per-section data structure.
189      *
190      * See class documentation for an example.
191      */
192     T& bind() { return storage_->currentData_; }
193
194 private:
195     RepeatingOptionSectionStorage<T>* storage_;
196 };
197
198 } // namespace gmx
199
200 #endif