GCC Code Coverage Report


Directory: ./
File: include/pinocchio/serialization/archive.hpp
Date: 2025-02-12 21:03:38
Exec Total Coverage
Lines: 91 97 93.8%
Branches: 68 146 46.6%

Line Branch Exec Source
1 //
2 // Copyright (c) 2017-2022 CNRS INRIA
3 //
4
5 #ifndef __pinocchio_serialization_archive_hpp__
6 #define __pinocchio_serialization_archive_hpp__
7
8 #include "pinocchio/serialization/fwd.hpp"
9 #include "pinocchio/serialization/static-buffer.hpp"
10
11 #include <fstream>
12 #include <string>
13 #include <sstream>
14 #include <stdexcept>
15 #include <boost/archive/text_oarchive.hpp>
16 #include <boost/archive/text_iarchive.hpp>
17 #include <boost/archive/xml_iarchive.hpp>
18 #include <boost/archive/xml_oarchive.hpp>
19 #include <boost/archive/binary_iarchive.hpp>
20 #include <boost/archive/binary_oarchive.hpp>
21
22 #if BOOST_VERSION / 100 % 1000 == 78 && __APPLE__
23 // See https://github.com/qcscine/utilities/issues/5#issuecomment-1246897049 for further details
24
25 #ifndef BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
26 #define DEFINE_BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
27 #define BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
28 #endif
29
30 #include <boost/asio/streambuf.hpp>
31
32 #ifdef DEFINE_BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
33 #undef BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
34 #endif
35
36 #else
37 #include <boost/asio/streambuf.hpp>
38 #endif
39
40 #include <boost/iostreams/device/array.hpp>
41 #include <boost/iostreams/stream.hpp>
42 #include <boost/iostreams/stream_buffer.hpp>
43
44 // Handle NAN inside TXT or XML archives
45 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
46
47 namespace pinocchio
48 {
49 namespace serialization
50 {
51
52 ///
53 /// \brief Loads an object from a TXT file.
54 ///
55 /// \tparam T Type of the object to deserialize.
56 ///
57 /// \param[out] object Object in which the loaded data are copied.
58 /// \param[in] filename Name of the file containing the serialized data.
59 ///
60 template<typename T>
61 351 inline void loadFromText(T & object, const std::string & filename)
62 {
63
1/2
✓ Branch 2 taken 176 times.
✗ Branch 3 not taken.
351 std::ifstream ifs(filename.c_str());
64
3/4
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
✓ Branch 4 taken 2 times.
351 if (ifs)
65 {
66
3/6
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 174 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 174 times.
✗ Branch 9 not taken.
347 std::locale const new_loc(ifs.getloc(), new boost::math::nonfinite_num_get<char>);
67
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 ifs.imbue(new_loc);
68
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 boost::archive::text_iarchive ia(ifs, boost::archive::no_codecvt);
69
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 ia >> object;
70 347 }
71 else
72 {
73
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 const std::string exception_message(filename + " does not seem to be a valid file.");
74
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 throw std::invalid_argument(exception_message);
75 }
76 351 }
77
78 ///
79 /// \brief Saves an object inside a TXT file.
80 ///
81 /// \tparam T Type of the object to deserialize.
82 ///
83 /// \param[in] object Object in which the loaded data are copied.
84 /// \param[in] filename Name of the file containing the serialized data.
85 ///
86 template<typename T>
87 349 inline void saveToText(const T & object, const std::string & filename)
88 {
89
1/2
✓ Branch 2 taken 175 times.
✗ Branch 3 not taken.
349 std::ofstream ofs(filename.c_str());
90
2/4
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 175 times.
✗ Branch 4 not taken.
349 if (ofs)
91 {
92
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
349 boost::archive::text_oarchive oa(ofs);
93
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
349 oa & object;
94 349 }
95 else
96 {
97 const std::string exception_message(filename + " does not seem to be a valid file.");
98 throw std::invalid_argument(exception_message);
99 }
100 349 }
101
102 ///
103 /// \brief Loads an object from a std::stringstream.
104 ///
105 /// \tparam T Type of the object to deserialize.
106 ///
107 /// \param[out] object Object in which the loaded data are copied.
108 /// \param[in] is string stream constaining the serialized content of the object.
109 ///
110 template<typename T>
111 695 inline void loadFromStringStream(T & object, std::istringstream & is)
112 {
113
1/2
✓ Branch 1 taken 349 times.
✗ Branch 2 not taken.
695 boost::archive::text_iarchive ia(is, boost::archive::no_codecvt);
114
1/2
✓ Branch 1 taken 349 times.
✗ Branch 2 not taken.
695 ia >> object;
115 695 }
116
117 ///
118 /// \brief Saves an object inside a std::stringstream.
119 ///
120 /// \tparam T Type of the object to deserialize.
121 ///
122 /// \param[in] object Object in which the loaded data are copied.
123 /// \param[out] ss String stream constaining the serialized content of the object.
124 ///
125 template<typename T>
126 695 inline void saveToStringStream(const T & object, std::stringstream & ss)
127 {
128
1/2
✓ Branch 1 taken 349 times.
✗ Branch 2 not taken.
695 boost::archive::text_oarchive oa(ss);
129
1/2
✓ Branch 1 taken 349 times.
✗ Branch 2 not taken.
695 oa & object;
130 695 }
131
132 ///
133 /// \brief Loads an object from a std::string
134 ///
135 /// \tparam T Type of the object to deserialize.
136 ///
137 /// \param[out] object Object in which the loaded data are copied.
138 /// \param[in] str string constaining the serialized content of the object.
139 ///
140 template<typename T>
141 349 inline void loadFromString(T & object, const std::string & str)
142 {
143
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
349 std::istringstream is(str);
144
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
349 loadFromStringStream(object, is);
145 349 }
146
147 ///
148 /// \brief Saves an object inside a std::string
149 ///
150 /// \tparam T Type of the object to deserialize.
151 ///
152 /// \param[in] object Object in which the loaded data are copied.
153 ///
154 /// \returns a string constaining the serialized content of the object.
155 ///
156 template<typename T>
157 349 inline std::string saveToString(const T & object)
158 {
159
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
349 std::stringstream ss;
160
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
349 saveToStringStream(object, ss);
161
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
698 return ss.str();
162 349 }
163
164 ///
165 /// \brief Loads an object from a XML file.
166 ///
167 /// \tparam T Type of the object to deserialize.
168 ///
169 /// \param[out] object Object in which the loaded data are copied.
170 /// \param[in] filename Name of the file containing the serialized data.
171 /// \param[in] tag_name XML Tag for the given object.
172 ///
173 template<typename T>
174 349 inline void loadFromXML(T & object, const std::string & filename, const std::string & tag_name)
175 {
176
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 175 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
349 PINOCCHIO_CHECK_INPUT_ARGUMENT(!tag_name.empty());
177
178
1/2
✓ Branch 2 taken 175 times.
✗ Branch 3 not taken.
349 std::ifstream ifs(filename.c_str());
179
3/4
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
✓ Branch 4 taken 1 times.
349 if (ifs)
180 {
181
3/6
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 174 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 174 times.
✗ Branch 9 not taken.
347 std::locale const new_loc(ifs.getloc(), new boost::math::nonfinite_num_get<char>);
182
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 ifs.imbue(new_loc);
183
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 boost::archive::xml_iarchive ia(ifs, boost::archive::no_codecvt);
184
1/2
✓ Branch 3 taken 174 times.
✗ Branch 4 not taken.
347 ia >> boost::serialization::make_nvp(tag_name.c_str(), object);
185 347 }
186 else
187 {
188
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 const std::string exception_message(filename + " does not seem to be a valid file.");
189
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 throw std::invalid_argument(exception_message);
190 }
191 349 }
192
193 ///
194 /// \brief Saves an object inside a XML file.
195 ///
196 /// \tparam T Type of the object to deserialize.
197 ///
198 /// \param[in] object Object in which the loaded data are copied.
199 /// \param[in] filename Name of the file containing the serialized data.
200 /// \param[in] tag_name XML Tag for the given object.
201 ///
202 template<typename T>
203 inline void
204 349 saveToXML(const T & object, const std::string & filename, const std::string & tag_name)
205 {
206
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 175 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
349 PINOCCHIO_CHECK_INPUT_ARGUMENT(!tag_name.empty());
207
208
1/2
✓ Branch 2 taken 175 times.
✗ Branch 3 not taken.
349 std::ofstream ofs(filename.c_str());
209
2/4
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 175 times.
✗ Branch 4 not taken.
349 if (ofs)
210 {
211
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
349 boost::archive::xml_oarchive oa(ofs);
212
1/2
✓ Branch 3 taken 175 times.
✗ Branch 4 not taken.
349 oa & boost::serialization::make_nvp(tag_name.c_str(), object);
213 349 }
214 else
215 {
216 const std::string exception_message(filename + " does not seem to be a valid file.");
217 throw std::invalid_argument(exception_message);
218 }
219 349 }
220
221 ///
222 /// \brief Loads an object from a binary file.
223 ///
224 /// \tparam T Type of the object to deserialize.
225 ///
226 /// \param[out] object Object in which the loaded data are copied.
227 /// \param[in] filename Name of the file containing the serialized data.
228 ///
229 template<typename T>
230 349 inline void loadFromBinary(T & object, const std::string & filename)
231 {
232
1/2
✓ Branch 2 taken 175 times.
✗ Branch 3 not taken.
349 std::ifstream ifs(filename.c_str(), std::ios::binary);
233
3/4
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
✓ Branch 4 taken 1 times.
349 if (ifs)
234 {
235
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 boost::archive::binary_iarchive ia(ifs);
236
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
347 ia >> object;
237 347 }
238 else
239 {
240
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 const std::string exception_message(filename + " does not seem to be a valid file.");
241
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 throw std::invalid_argument(exception_message);
242 }
243 349 }
244
245 ///
246 /// \brief Saves an object inside a binary file.
247 ///
248 /// \tparam T Type of the object to deserialize.
249 ///
250 /// \param[in] object Object in which the loaded data are copied.
251 /// \param[in] filename Name of the file containing the serialized data.
252 ///
253 template<typename T>
254 349 void saveToBinary(const T & object, const std::string & filename)
255 {
256
1/2
✓ Branch 2 taken 175 times.
✗ Branch 3 not taken.
349 std::ofstream ofs(filename.c_str(), std::ios::binary);
257
2/4
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 175 times.
✗ Branch 4 not taken.
349 if (ofs)
258 {
259
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
349 boost::archive::binary_oarchive oa(ofs);
260
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
349 oa & object;
261 349 }
262 else
263 {
264 const std::string exception_message(filename + " does not seem to be a valid file.");
265 throw std::invalid_argument(exception_message);
266 }
267 349 }
268
269 ///
270 /// \brief Loads an object from a binary buffer.
271 ///
272 /// \tparam T Type of the object to deserialize.
273 ///
274 /// \param[out] object Object in which the loaded data are copied.
275 /// \param[in] buffer Input buffer containing the serialized data.
276 ///
277 template<typename T>
278 346 inline void loadFromBinary(T & object, boost::asio::streambuf & buffer)
279 {
280
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 boost::archive::binary_iarchive ia(buffer);
281
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 ia >> object;
282 346 }
283
284 ///
285 /// \brief Saves an object to a binary buffer.
286 ///
287 /// \tparam T Type of the object to serialize.
288 ///
289 /// \param[in] object Object in which the loaded data are copied.
290 /// \param[out] buffer Output buffer containing the serialized data.
291 ///
292 template<typename T>
293 346 void saveToBinary(const T & object, boost::asio::streambuf & buffer)
294 {
295
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 boost::archive::binary_oarchive oa(buffer);
296
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 oa & object;
297 346 }
298
299 ///
300 /// \brief Loads an object from a static binary buffer.
301 /// The buffer should be of a sufficient size.
302 ///
303 /// \tparam T Type of the object to deserialize.
304 ///
305 /// \param[out] object Object in which the loaded data are copied.
306 /// \param[in] buffer Input buffer containing the serialized data.
307 ///
308 template<typename T>
309 346 inline void loadFromBinary(T & object, StaticBuffer & buffer)
310 {
311 346 boost::iostreams::stream_buffer<boost::iostreams::basic_array<char>> stream(
312
1/2
✓ Branch 3 taken 173 times.
✗ Branch 4 not taken.
346 buffer.data(), buffer.size());
313
314
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 boost::archive::binary_iarchive ia(stream);
315
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 ia >> object;
316 346 }
317
318 ///
319 /// \brief Saves an object to a static binary buffer.
320 /// The buffer should be of a sufficient size.
321 ///
322 /// \tparam T Type of the object to deserialize.
323 ///
324 /// \param[in] object Object in which the loaded data are copied.
325 /// \param[out] buffer Output buffer containing the serialized data.
326 ///
327 template<typename T>
328 346 inline void saveToBinary(const T & object, StaticBuffer & buffer)
329 {
330 346 boost::iostreams::stream_buffer<boost::iostreams::basic_array<char>> stream(
331
1/2
✓ Branch 3 taken 173 times.
✗ Branch 4 not taken.
346 buffer.data(), buffer.size());
332
333
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 boost::archive::binary_oarchive oa(stream);
334
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
346 oa & object;
335 346 }
336
337 } // namespace serialization
338 } // namespace pinocchio
339
340 #endif // ifndef __pinocchio_serialization_archive_hpp__
341