2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2016,2017,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.
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.
37 #include "keyvaluetreeserializer.h"
41 #include "gromacs/utility/iserializer.h"
42 #include "gromacs/utility/keyvaluetree.h"
43 #include "gromacs/utility/keyvaluetreebuilder.h"
54 static void initSerializers();
56 static void serialize(const KeyValueTreeValue& value, ISerializer* serializer);
57 static KeyValueTreeValue deserialize(ISerializer* serializer);
60 ValueSerializer() = delete;
62 typedef void (*SerializerFunction)(const KeyValueTreeValue& value, ISerializer* serializer);
63 typedef void (*DeserializerFunction)(KeyValueTreeValueBuilder* builder, ISerializer* serializer);
67 unsigned char typeTag;
68 SerializerFunction serialize;
69 DeserializerFunction deserialize;
71 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
72 static std::mutex s_initMutex;
73 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
74 static std::map<std::type_index, Serializer> s_serializers;
75 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
76 static std::map<unsigned char, DeserializerFunction> s_deserializers;
79 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
80 std::mutex ValueSerializer::s_initMutex;
81 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
82 std::map<std::type_index, ValueSerializer::Serializer> ValueSerializer::s_serializers;
83 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
84 std::map<unsigned char, ValueSerializer::DeserializerFunction> ValueSerializer::s_deserializers;
87 struct SerializationTraits
92 struct SerializationTraits<KeyValueTreeObject>
94 static void serialize(const KeyValueTreeObject& value, ISerializer* serializer)
96 int count = value.properties().size();
97 serializer->doInt(&count);
98 for (const auto& prop : value.properties())
100 serializer->doString(const_cast<std::string*>(&prop.key()));
101 ValueSerializer::serialize(prop.value(), serializer);
104 static void deserialize(KeyValueTreeValueBuilder* value, ISerializer* serializer)
106 KeyValueTreeObjectBuilder builder(value->createObject());
107 deserializeObject(&builder, serializer);
109 static void deserializeObject(KeyValueTreeObjectBuilder* builder, ISerializer* serializer)
113 serializer->doInt(&count);
114 for (int i = 0; i < count; ++i)
116 serializer->doString(&key);
117 builder->addRawValue(key, ValueSerializer::deserialize(serializer));
123 struct SerializationTraits<KeyValueTreeArray>
125 static void serialize(const KeyValueTreeArray& array, ISerializer* serializer)
127 int count = array.values().size();
128 serializer->doInt(&count);
129 for (const auto& value : array.values())
131 ValueSerializer::serialize(value, serializer);
134 static void deserialize(KeyValueTreeValueBuilder* value, ISerializer* serializer)
136 KeyValueTreeArrayBuilder builder(value->createArray());
138 serializer->doInt(&count);
139 for (int i = 0; i < count; ++i)
141 builder.addRawValue(ValueSerializer::deserialize(serializer));
147 struct SerializationTraits<std::string>
149 static void serialize(const std::string& value, ISerializer* serializer)
151 serializer->doString(const_cast<std::string*>(&value));
153 static void deserialize(KeyValueTreeValueBuilder* builder, ISerializer* serializer)
156 serializer->doString(&value);
157 builder->setValue<std::string>(value);
162 struct SerializationTraits<bool>
164 static void serialize(bool value, ISerializer* serializer) { serializer->doBool(&value); }
165 static void deserialize(KeyValueTreeValueBuilder* builder, ISerializer* serializer)
168 serializer->doBool(&value);
169 builder->setValue<bool>(value);
174 struct SerializationTraits<int>
176 static void serialize(int value, ISerializer* serializer) { serializer->doInt(&value); }
177 static void deserialize(KeyValueTreeValueBuilder* builder, ISerializer* serializer)
180 serializer->doInt(&value);
181 builder->setValue<int>(value);
186 struct SerializationTraits<int64_t>
188 static void serialize(int64_t value, ISerializer* serializer) { serializer->doInt64(&value); }
189 static void deserialize(KeyValueTreeValueBuilder* builder, ISerializer* serializer)
192 serializer->doInt64(&value);
193 builder->setValue<int64_t>(value);
198 struct SerializationTraits<float>
200 static void serialize(float value, ISerializer* serializer) { serializer->doFloat(&value); }
201 static void deserialize(KeyValueTreeValueBuilder* builder, ISerializer* serializer)
204 serializer->doFloat(&value);
205 builder->setValue<float>(value);
210 struct SerializationTraits<double>
212 static void serialize(double value, ISerializer* serializer) { serializer->doDouble(&value); }
213 static void deserialize(KeyValueTreeValueBuilder* builder, ISerializer* serializer)
216 serializer->doDouble(&value);
217 builder->setValue<double>(value);
221 //! Helper function for serializing values of a certain type.
223 void serializeValueType(const KeyValueTreeValue& value, ISerializer* serializer)
225 SerializationTraits<T>::serialize(value.cast<T>(), serializer);
228 #define SERIALIZER(tag, type) \
230 std::type_index(typeid(type)), \
232 tag, &serializeValueType<type>, &SerializationTraits<type>::deserialize \
237 void ValueSerializer::initSerializers()
239 std::lock_guard<std::mutex> lock(s_initMutex);
240 if (!s_serializers.empty())
245 SERIALIZER('O', KeyValueTreeObject),
246 SERIALIZER('A', KeyValueTreeArray),
247 SERIALIZER('s', std::string),
248 SERIALIZER('b', bool),
249 SERIALIZER('i', int),
250 SERIALIZER('l', int64_t),
251 SERIALIZER('f', float),
252 SERIALIZER('d', double),
254 for (const auto& item : s_serializers)
256 s_deserializers[item.second.typeTag] = item.second.deserialize;
260 void ValueSerializer::serialize(const KeyValueTreeValue& value, ISerializer* serializer)
262 auto iter = s_serializers.find(value.type());
263 GMX_RELEASE_ASSERT(iter != s_serializers.end(), "Unknown value type for serializization");
264 unsigned char typeTag = iter->second.typeTag;
265 serializer->doUChar(&typeTag);
266 iter->second.serialize(value, serializer);
269 KeyValueTreeValue ValueSerializer::deserialize(ISerializer* serializer)
271 unsigned char typeTag = 0;
272 serializer->doUChar(&typeTag);
273 auto iter = s_deserializers.find(typeTag);
274 GMX_RELEASE_ASSERT(iter != s_deserializers.end(), "Unknown type tag for deserializization");
275 KeyValueTreeValueBuilder builder;
276 iter->second(&builder, serializer);
277 return builder.build();
283 void serializeKeyValueTree(const KeyValueTreeObject& root, ISerializer* serializer)
285 GMX_RELEASE_ASSERT(!serializer->reading(), "Incorrect serializer direction");
286 ValueSerializer::initSerializers();
287 SerializationTraits<KeyValueTreeObject>::serialize(root, serializer);
290 KeyValueTreeObject deserializeKeyValueTree(ISerializer* serializer)
292 GMX_RELEASE_ASSERT(serializer->reading(), "Incorrect serializer direction");
293 ValueSerializer::initSerializers();
294 KeyValueTreeBuilder builder;
295 KeyValueTreeObjectBuilder obj(builder.rootObject());
296 SerializationTraits<KeyValueTreeObject>::deserializeObject(&obj, serializer);
297 return builder.build();