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.
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"
53 static void initSerializers();
55 static void serialize(const KeyValueTreeValue
&value
, ISerializer
*serializer
);
56 static KeyValueTreeValue
deserialize(ISerializer
*serializer
);
59 ValueSerializer() = delete;
61 typedef void (*SerializerFunction
)(const KeyValueTreeValue
&value
, ISerializer
*serializer
);
62 typedef void (*DeserializerFunction
)(KeyValueTreeValueBuilder
*builder
, ISerializer
*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
;
81 struct SerializationTraits
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
)
107 serializer
->doInt(&count
);
108 for (int i
= 0; i
< count
; ++i
)
110 serializer
->doString(&key
);
111 builder
->addRawValue(key
, ValueSerializer::deserialize(serializer
));
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());
132 serializer
->doInt(&count
);
133 for (int i
= 0; i
< count
; ++i
)
135 builder
.addRawValue(ValueSerializer::deserialize(serializer
));
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
)
150 serializer
->doString(&value
);
151 builder
->setValue
<std::string
>(value
);
156 struct SerializationTraits
<bool>
158 static void serialize(bool value
, ISerializer
*serializer
)
160 serializer
->doBool(&value
);
162 static void deserialize(KeyValueTreeValueBuilder
*builder
, ISerializer
*serializer
)
165 serializer
->doBool(&value
);
166 builder
->setValue
<bool>(value
);
171 struct SerializationTraits
<int>
173 static void serialize(int value
, ISerializer
*serializer
)
175 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
)
190 serializer
->doInt64(&value
);
192 static void deserialize(KeyValueTreeValueBuilder
*builder
, ISerializer
*serializer
)
195 serializer
->doInt64(&value
);
196 builder
->setValue
<int64_t>(value
);
201 struct SerializationTraits
<float>
203 static void serialize(float value
, ISerializer
*serializer
)
205 serializer
->doFloat(&value
);
207 static void deserialize(KeyValueTreeValueBuilder
*builder
, ISerializer
*serializer
)
210 serializer
->doFloat(&value
);
211 builder
->setValue
<float>(value
);
216 struct SerializationTraits
<double>
218 static void serialize(double value
, ISerializer
*serializer
)
220 serializer
->doDouble(&value
);
222 static void deserialize(KeyValueTreeValueBuilder
*builder
, ISerializer
*serializer
)
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 } \
243 void ValueSerializer::initSerializers()
245 lock_guard
<Mutex
> lock(s_initMutex
);
246 if (!s_serializers
.empty())
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();
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();