SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / utility / keyvaluetreebuilder.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2016,2017,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 /*! \libinternal \file
36  * \brief
37  * Declares classes for building the data structures in keyvaluetree.h.
38  *
39  * These are separate from the data structures to enforce clear separation of
40  * the APIs, and to make the data structure immutable after construction.
41  *
42  * For the main use case described in \ref page_mdmodules, they are mainly
43  * used internally, but currently gmx::KeyValueTreeObjectBuilder (and
44  * everything it references) is exposed for more complex transforms through
45  * gmx::IKeyValueTreeTransformRules.
46  *
47  * \author Teemu Murtola <teemu.murtola@gmail.com>
48  * \inlibraryapi
49  * \ingroup module_utility
50  */
51 #ifndef GMX_UTILITY_KEYVALUETREEBUILDER_H
52 #define GMX_UTILITY_KEYVALUETREEBUILDER_H
53
54 #include <initializer_list>
55 #include <string>
56 #include <utility>
57 #include <vector>
58
59 #include "gromacs/utility/any.h"
60 #include "gromacs/utility/gmxassert.h"
61 #include "gromacs/utility/keyvaluetree.h"
62
63 namespace gmx
64 {
65
66 class KeyValueTreeArrayBuilder;
67 class KeyValueTreeObjectBuilder;
68
69 /*! \libinternal \brief
70  * Root builder for creating trees that have an object at the root.
71  *
72  * \inlibraryapi
73  * \ingroup module_utility
74  */
75 class KeyValueTreeBuilder
76 {
77 public:
78     //! Returns a builder for the root object.
79     KeyValueTreeObjectBuilder rootObject();
80
81     /*! \brief
82      * Builds the final object.
83      *
84      * The builder should not be accessed after this call.
85      */
86     KeyValueTreeObject build() { return std::move(root_); }
87
88 private:
89     /*! \brief
90      * Helper function for other builders to create values of certain type.
91      */
92     template<typename T>
93     static KeyValueTreeValue createValue(const T& value)
94     {
95         return KeyValueTreeValue(Any::create<T>(value));
96     }
97     /*! \brief
98      * Helper function for other builders to create default-constructed
99      * values.
100      */
101     template<typename T>
102     static KeyValueTreeValue createValue()
103     {
104         return KeyValueTreeValue(Any::create<T>(T()));
105     }
106
107     KeyValueTreeObject root_;
108
109     //! For access to createValue() methods.
110     friend class KeyValueTreeObjectArrayBuilder;
111     //! For access to createValue() methods.
112     friend class KeyValueTreeObjectBuilder;
113     //! For access to createValue() methods.
114     template<typename T>
115     friend class KeyValueTreeUniformArrayBuilder;
116 };
117
118 /*! \libinternal \brief
119  * Builder for KeyValueTreeValue objects.
120  *
121  * This builder can be constructed directly and can create self-standing
122  * KeyValueTreeValue objects.
123  *
124  * \inlibraryapi
125  * \ingroup module_utility
126  */
127 class KeyValueTreeValueBuilder
128 {
129 public:
130     //! Assigns a scalar value of certain type.
131     template<typename T>
132     void setValue(const T& value)
133     {
134         value_ = Any::create<T>(value);
135     }
136     //! Assigns a Any value to the built value.
137     void setAnyValue(Any&& value) { value_ = std::move(value); }
138     /*! \brief
139      * Returns an object builder for building an object into this value.
140      *
141      * Any method call in this value builder invalidates the returned
142      * builder.
143      */
144     KeyValueTreeObjectBuilder createObject();
145     /*! \brief
146      * Returns an array builder for building an array into this value.
147      *
148      * Any method call in this value builder invalidates the returned
149      * builder.
150      */
151     KeyValueTreeArrayBuilder createArray();
152
153     /*! \brief
154      * Builds the final value.
155      *
156      * The builder should not be accessed after this call.
157      */
158     KeyValueTreeValue build() { return KeyValueTreeValue(std::move(value_)); }
159
160 private:
161     Any value_;
162 };
163
164 class KeyValueTreeArrayBuilderBase
165 {
166 protected:
167     //! Creates an array builder for populating given array object.
168     explicit KeyValueTreeArrayBuilderBase(KeyValueTreeArray* array) : array_(array) {}
169
170     //! Appends a raw Any value to the array.
171     KeyValueTreeValue& addRawValue(Any&& value)
172     {
173         KeyValueTreeValueBuilder builder;
174         builder.setAnyValue(std::move(value));
175         array_->values_.push_back(builder.build());
176         return array_->values_.back();
177     }
178     //! Appends a raw KeyValueTreeValue to the array.
179     KeyValueTreeValue& addRawValue(KeyValueTreeValue&& value)
180     {
181         array_->values_.push_back(std::move(value));
182         return array_->values_.back();
183     }
184
185 private:
186     KeyValueTreeArray* array_;
187 };
188
189 class KeyValueTreeArrayBuilder : public KeyValueTreeArrayBuilderBase
190 {
191 public:
192     using KeyValueTreeArrayBuilderBase::addRawValue;
193
194 private:
195     explicit KeyValueTreeArrayBuilder(KeyValueTreeArray* array) :
196         KeyValueTreeArrayBuilderBase(array)
197     {
198     }
199
200     friend class KeyValueTreeObjectBuilder;
201     friend class KeyValueTreeValueBuilder;
202 };
203
204 /*! \libinternal \brief
205  * Builder for KeyValueTreeArray objects where all elements are of type `T`.
206  *
207  * The builder does not own the array being constructed, but instead holds a
208  * reference to an object within a tree rooted in KeyValueTreeBuilder or
209  * KeyValueTreeValueBuilder.
210  *
211  * \inlibraryapi
212  * \ingroup module_utility
213  */
214 template<typename T>
215 class KeyValueTreeUniformArrayBuilder : public KeyValueTreeArrayBuilderBase
216 {
217 public:
218     //! Appends a value to the array.
219     void addValue(const T& value) { addRawValue(KeyValueTreeBuilder::createValue<T>(value)); }
220
221 private:
222     explicit KeyValueTreeUniformArrayBuilder(KeyValueTreeArray* array) :
223         KeyValueTreeArrayBuilderBase(array)
224     {
225     }
226
227     friend class KeyValueTreeObjectBuilder;
228 };
229
230 /*! \libinternal \brief
231  * Builder for KeyValueTreeArray objects where all elements are
232  * KeyValueTreeObject objects.
233  *
234  * The builder does not own the array being constructed, but instead holds a
235  * reference to an object within a tree rooted in KeyValueTreeBuilder or
236  * KeyValueTreeValueBuilder.
237  *
238  * \inlibraryapi
239  * \ingroup module_utility
240  */
241 class KeyValueTreeObjectArrayBuilder : public KeyValueTreeArrayBuilderBase
242 {
243 public:
244     /*! \brief
245      * Appends an object to the array.
246      *
247      * The object is created empty and can be built using the returned
248      * builder.
249      */
250     KeyValueTreeObjectBuilder addObject();
251
252 private:
253     explicit KeyValueTreeObjectArrayBuilder(KeyValueTreeArray* array) :
254         KeyValueTreeArrayBuilderBase(array)
255     {
256     }
257
258     friend class KeyValueTreeObjectBuilder;
259 };
260
261 /*! \libinternal \brief
262  * Builder for KeyValueTreeObject objects.
263  *
264  * The builder does not own the object being constructed, but instead holds a
265  * reference to an object within a tree rooted in KeyValueTreeBuilder or
266  * KeyValueTreeValueBuilder.
267  *
268  * \inlibraryapi
269  * \ingroup module_utility
270  */
271 class KeyValueTreeObjectBuilder
272 {
273 public:
274     //! Adds a property with given key from a KeyValueTreeValue.
275     void addRawValue(const std::string& key, KeyValueTreeValue&& value)
276     {
277         addProperty(key, std::move(value));
278     }
279     //! Adds a property with given key from a Any value.
280     void addRawValue(const std::string& key, Any&& value)
281     {
282         addProperty(key, KeyValueTreeValue(std::move(value)));
283     }
284     //! Adds a scalar property with given key, type, and value.
285     template<typename T>
286     void addValue(const std::string& key, const T& value)
287     {
288         addRawValue(key, KeyValueTreeBuilder::createValue<T>(value));
289     }
290     /*! \brief
291      * Adds an object-valued property with given key.
292      *
293      * The object is created empty and can be built using the returned
294      * builder.
295      */
296     KeyValueTreeObjectBuilder addObject(const std::string& key)
297     {
298         auto iter = addProperty(key, KeyValueTreeBuilder::createValue<KeyValueTreeObject>());
299         return KeyValueTreeObjectBuilder(&iter->second);
300     }
301     /*! \brief
302      * Adds a generic array-valued property with given key.
303      *
304      * The array is created empty and can be built using the returned
305      * builder.
306      */
307     KeyValueTreeArrayBuilder addArray(const std::string& key)
308     {
309         auto iter = addProperty(key, KeyValueTreeBuilder::createValue<KeyValueTreeArray>());
310         return KeyValueTreeArrayBuilder(&iter->second.asArray());
311     }
312     /*! \brief
313      * Adds an array-valued property with uniform value types with given
314      * key.
315      *
316      * \tparam T  Type for all values in the array.
317      *
318      * The array is created empty and can be built using the returned
319      * builder.
320      */
321     template<typename T>
322     KeyValueTreeUniformArrayBuilder<T> addUniformArray(const std::string& key)
323     {
324         auto iter = addProperty(key, KeyValueTreeBuilder::createValue<KeyValueTreeArray>());
325         return KeyValueTreeUniformArrayBuilder<T>(&iter->second.asArray());
326     }
327     /*! \brief
328      * Adds an array-valued property with uniform value types with given
329      * key and values.
330      *
331      * \tparam T  Type for all values in the array.
332      *
333      * The array is created to contain the values from `values`.
334      */
335     template<typename T>
336     void addUniformArray(const std::string& key, std::initializer_list<T> values)
337     {
338         auto builder = addUniformArray<T>(key);
339         for (const auto& value : values)
340         {
341             builder.addValue(value);
342         }
343     }
344     /*! \brief
345      * Adds an array-valued property with objects in the array with given
346      * key.
347      *
348      * The array is created empty and can be built using the returned
349      * builder.
350      */
351     KeyValueTreeObjectArrayBuilder addObjectArray(const std::string& key)
352     {
353         auto iter = addProperty(key, KeyValueTreeBuilder::createValue<KeyValueTreeArray>());
354         return KeyValueTreeObjectArrayBuilder(&iter->second.asArray());
355     }
356
357     //! Whether a property with given key exists.
358     bool keyExists(const std::string& key) const { return object_->keyExists(key); }
359     //! Returns value for a given key.
360     const KeyValueTreeValue& operator[](const std::string& key) const { return (*object_)[key]; }
361     //! Returns an object builder for an existing object.
362     KeyValueTreeObjectBuilder getObjectBuilder(const std::string& key)
363     {
364         GMX_ASSERT(keyExists(key), "Requested non-existent value");
365         GMX_ASSERT((*this)[key].isObject(), "Accessing non-object value as object");
366         return KeyValueTreeObjectBuilder(&object_->valueMap_.at(key).asObject());
367     }
368
369     /*! \brief
370      * Returns whether the given object shares any keys with \p this.
371      */
372     bool objectHasDistinctProperties(const KeyValueTreeObject& obj) const
373     {
374         return object_->hasDistinctProperties(obj);
375     }
376     /*! \brief
377      * Merges properties from a given object to `this`.
378      *
379      * The objects should not share any keys, i.e.,
380      * objectHasDistinctProperties() should return `true`.
381      */
382     void mergeObject(KeyValueTreeObject&& obj)
383     {
384         GMX_ASSERT(objectHasDistinctProperties(obj), "Trying to merge overlapping object");
385         for (auto& prop : obj.valueMap_)
386         {
387             addRawValue(prop.first, std::move(prop.second));
388         }
389     }
390
391 private:
392     explicit KeyValueTreeObjectBuilder(KeyValueTreeObject* object) : object_(object) {}
393     explicit KeyValueTreeObjectBuilder(KeyValueTreeValue* value) : object_(&value->asObject()) {}
394
395     std::map<std::string, KeyValueTreeValue>::iterator addProperty(const std::string&  key,
396                                                                    KeyValueTreeValue&& value)
397     {
398         GMX_RELEASE_ASSERT(!keyExists(key), "Duplicate key value");
399         object_->values_.reserve(object_->values_.size() + 1);
400         auto iter = object_->valueMap_.insert(std::make_pair(key, std::move(value))).first;
401         object_->values_.push_back(KeyValueTreeProperty(iter));
402         return iter;
403     }
404
405     KeyValueTreeObject* object_;
406
407     friend class KeyValueTreeBuilder;
408     friend class KeyValueTreeValueBuilder;
409     friend class KeyValueTreeObjectArrayBuilder;
410 };
411
412 /********************************************************************
413  * Inline functions that could not be declared within the classes
414  */
415
416 inline KeyValueTreeObjectBuilder KeyValueTreeBuilder::rootObject()
417 {
418     return KeyValueTreeObjectBuilder(&root_);
419 }
420
421 inline KeyValueTreeObjectBuilder KeyValueTreeValueBuilder::createObject()
422 {
423     value_ = Any::create<KeyValueTreeObject>(KeyValueTreeObject());
424     return KeyValueTreeObjectBuilder(&value_.castRef<KeyValueTreeObject>());
425 }
426
427 inline KeyValueTreeArrayBuilder KeyValueTreeValueBuilder::createArray()
428 {
429     value_ = Any::create<KeyValueTreeArray>(KeyValueTreeArray());
430     return KeyValueTreeArrayBuilder(&value_.castRef<KeyValueTreeArray>());
431 }
432
433 inline KeyValueTreeObjectBuilder KeyValueTreeObjectArrayBuilder::addObject()
434 {
435     auto& value = addRawValue(KeyValueTreeBuilder::createValue<KeyValueTreeObject>());
436     return KeyValueTreeObjectBuilder(&value);
437 }
438
439 } // namespace gmx
440
441 #endif