Warn for type mismatch for gmx printf like functions 2/3
[gromacs.git] / src / gromacs / utility / keyvaluetreeserializer.cpp
blob2462857a2cf13e53ceba48bb2046cc6de61406c0
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2016,2017,2018, 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.
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.
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.
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.
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.
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.
35 #include "gmxpre.h"
37 #include "keyvaluetreeserializer.h"
39 #include "gromacs/utility/iserializer.h"
40 #include "gromacs/utility/keyvaluetree.h"
41 #include "gromacs/utility/keyvaluetreebuilder.h"
42 #include "gromacs/utility/mutex.h"
44 namespace gmx
47 namespace
50 class ValueSerializer
52 public:
53 static void initSerializers();
55 static void serialize(const KeyValueTreeValue &value, ISerializer *serializer);
56 static KeyValueTreeValue deserialize(ISerializer *serializer);
58 private:
59 ValueSerializer() = delete;
61 typedef void (*SerializerFunction)(const KeyValueTreeValue &value, ISerializer *serializer);
62 typedef void (*DeserializerFunction)(KeyValueTreeValueBuilder *builder, ISerializer *serializer);
64 struct Serializer
66 unsigned char typeTag;
67 SerializerFunction serialize;
68 DeserializerFunction deserialize;
71 static Mutex s_initMutex;
72 static std::map<std::type_index, Serializer> s_serializers;
73 static std::map<unsigned char, DeserializerFunction> s_deserializers;
76 Mutex ValueSerializer::s_initMutex;
77 std::map<std::type_index, ValueSerializer::Serializer> ValueSerializer::s_serializers;
78 std::map<unsigned char, ValueSerializer::DeserializerFunction> ValueSerializer::s_deserializers;
80 template <typename T>
81 struct SerializationTraits
85 template <>
86 struct SerializationTraits<KeyValueTreeObject>
88 static void serialize(const KeyValueTreeObject &value, ISerializer *serializer)
90 int count = value.properties().size();
91 serializer->doInt(&count);
92 for (const auto &prop : value.properties())
94 serializer->doString(const_cast<std::string *>(&prop.key()));
95 ValueSerializer::serialize(prop.value(), serializer);
98 static void deserialize(KeyValueTreeValueBuilder *value, ISerializer *serializer)
100 KeyValueTreeObjectBuilder builder(value->createObject());
101 deserializeObject(&builder, serializer);
103 static void deserializeObject(KeyValueTreeObjectBuilder *builder, ISerializer *serializer)
105 int count;
106 std::string key;
107 serializer->doInt(&count);
108 for (int i = 0; i < count; ++i)
110 serializer->doString(&key);
111 builder->addRawValue(key, ValueSerializer::deserialize(serializer));
116 template <>
117 struct SerializationTraits<KeyValueTreeArray>
119 static void serialize(const KeyValueTreeArray &array, ISerializer *serializer)
121 int count = array.values().size();
122 serializer->doInt(&count);
123 for (const auto &value : array.values())
125 ValueSerializer::serialize(value, serializer);
128 static void deserialize(KeyValueTreeValueBuilder *value, ISerializer *serializer)
130 KeyValueTreeArrayBuilder builder(value->createArray());
131 int count;
132 serializer->doInt(&count);
133 for (int i = 0; i < count; ++i)
135 builder.addRawValue(ValueSerializer::deserialize(serializer));
140 template <>
141 struct SerializationTraits<std::string>
143 static void serialize(const std::string &value, ISerializer *serializer)
145 serializer->doString(const_cast<std::string *>(&value));
147 static void deserialize(KeyValueTreeValueBuilder *builder, ISerializer *serializer)
149 std::string value;
150 serializer->doString(&value);
151 builder->setValue<std::string>(value);
155 template <>
156 struct SerializationTraits<bool>
158 static void serialize(bool value, ISerializer *serializer)
160 serializer->doBool(&value);
162 static void deserialize(KeyValueTreeValueBuilder *builder, ISerializer *serializer)
164 bool value;
165 serializer->doBool(&value);
166 builder->setValue<bool>(value);
170 template <>
171 struct SerializationTraits<int>
173 static void serialize(int value, ISerializer *serializer)
175 serializer->doInt(&value);
177 static void deserialize(KeyValueTreeValueBuilder *builder, ISerializer *serializer)
179 int value;
180 serializer->doInt(&value);
181 builder->setValue<int>(value);
185 template <>
186 struct SerializationTraits<int64_t>
188 static void serialize(int64_t value, ISerializer *serializer)
190 serializer->doInt64(&value);
192 static void deserialize(KeyValueTreeValueBuilder *builder, ISerializer *serializer)
194 int64_t value;
195 serializer->doInt64(&value);
196 builder->setValue<int64_t>(value);
200 template <>
201 struct SerializationTraits<float>
203 static void serialize(float value, ISerializer *serializer)
205 serializer->doFloat(&value);
207 static void deserialize(KeyValueTreeValueBuilder *builder, ISerializer *serializer)
209 float value;
210 serializer->doFloat(&value);
211 builder->setValue<float>(value);
215 template <>
216 struct SerializationTraits<double>
218 static void serialize(double value, ISerializer *serializer)
220 serializer->doDouble(&value);
222 static void deserialize(KeyValueTreeValueBuilder *builder, ISerializer *serializer)
224 double value;
225 serializer->doDouble(&value);
226 builder->setValue<double>(value);
230 //! Helper function for serializing values of a certain type.
231 template <typename T>
232 void serializeValueType(const KeyValueTreeValue &value, ISerializer *serializer)
234 SerializationTraits<T>::serialize(value.cast<T>(), serializer);
237 #define SERIALIZER(tag, type) \
238 { std::type_index(typeid(type)), \
239 { tag, &serializeValueType<type>, &SerializationTraits<type>::deserialize } \
242 // static
243 void ValueSerializer::initSerializers()
245 lock_guard<Mutex> lock(s_initMutex);
246 if (!s_serializers.empty())
248 return;
250 s_serializers = {
251 SERIALIZER('O', KeyValueTreeObject),
252 SERIALIZER('A', KeyValueTreeArray),
253 SERIALIZER('s', std::string),
254 SERIALIZER('b', bool),
255 SERIALIZER('i', int),
256 SERIALIZER('l', int64_t),
257 SERIALIZER('f', float),
258 SERIALIZER('d', double),
260 for (const auto &item : s_serializers)
262 s_deserializers[item.second.typeTag] = item.second.deserialize;
266 void ValueSerializer::serialize(const KeyValueTreeValue &value, ISerializer *serializer)
268 auto iter = s_serializers.find(value.type());
269 GMX_RELEASE_ASSERT(iter != s_serializers.end(),
270 "Unknown value type for serializization");
271 unsigned char typeTag = iter->second.typeTag;
272 serializer->doUChar(&typeTag);
273 iter->second.serialize(value, serializer);
276 KeyValueTreeValue ValueSerializer::deserialize(ISerializer *serializer)
278 unsigned char typeTag;
279 serializer->doUChar(&typeTag);
280 auto iter = s_deserializers.find(typeTag);
281 GMX_RELEASE_ASSERT(iter != s_deserializers.end(),
282 "Unknown type tag for deserializization");
283 KeyValueTreeValueBuilder builder;
284 iter->second(&builder, serializer);
285 return builder.build();
288 } // namespace
290 //! \cond libapi
291 void serializeKeyValueTree(const KeyValueTreeObject &root, ISerializer *serializer)
293 GMX_RELEASE_ASSERT(!serializer->reading(),
294 "Incorrect serializer direction");
295 ValueSerializer::initSerializers();
296 SerializationTraits<KeyValueTreeObject>::serialize(root, serializer);
299 KeyValueTreeObject deserializeKeyValueTree(ISerializer *serializer)
301 GMX_RELEASE_ASSERT(serializer->reading(),
302 "Incorrect serializer direction");
303 ValueSerializer::initSerializers();
304 KeyValueTreeBuilder builder;
305 KeyValueTreeObjectBuilder obj(builder.rootObject());
306 SerializationTraits<KeyValueTreeObject>::deserializeObject(&obj, serializer);
307 return builder.build();
309 //! \endcond
311 } // namespace gmx