GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/serialization/archive.hpp Lines: 82 88 93.2 %
Date: 2024-01-23 21:41:47 Branches: 70 150 46.7 %

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
274
    inline void loadFromText(T & object,
62
                             const std::string & filename)
63
    {
64
548
      std::ifstream ifs(filename.c_str());
65

274
      if(ifs)
66
      {
67

540
        std::locale const new_loc(ifs.getloc(), new boost::math::nonfinite_num_get<char>);
68
270
        ifs.imbue(new_loc);
69
540
        boost::archive::text_iarchive ia(ifs,boost::archive::no_codecvt);
70
270
        ia >> object;
71
      }
72
      else
73
      {
74
8
        const std::string exception_message(filename + " does not seem to be a valid file.");
75
4
        throw std::invalid_argument(exception_message);
76
      }
77
270
    }
78
79
    ///
80
    /// \brief Saves an object inside a TXT file.
81
    ///
82
    /// \tparam T Type of the object to deserialize.
83
    ///
84
    /// \param[in]  object Object in which the loaded data are copied.
85
    /// \param[in]  filename Name of the file containing the serialized data.
86
    ///
87
    template<typename T>
88
272
    inline void saveToText(const T & object,
89
                           const std::string & filename)
90
    {
91
544
      std::ofstream ofs(filename.c_str());
92

272
      if(ofs)
93
      {
94
544
        boost::archive::text_oarchive oa(ofs);
95
272
        oa & object;
96
      }
97
      else
98
      {
99
        const std::string exception_message(filename + " does not seem to be a valid file.");
100
        throw std::invalid_argument(exception_message);
101
      }
102
272
    }
103
104
    ///
105
    /// \brief Loads an object from a std::stringstream.
106
    ///
107
    /// \tparam T Type of the object to deserialize.
108
    ///
109
    /// \param[out] object Object in which the loaded data are copied.
110
    /// \param[in]  is  string stream constaining the serialized content of the object.
111
    ///
112
    template<typename T>
113
540
    inline void loadFromStringStream(T & object,
114
                                     std::istringstream & is)
115
    {
116
1080
      boost::archive::text_iarchive ia(is,boost::archive::no_codecvt);
117
540
      ia >> object;
118
540
    }
119
120
    ///
121
    /// \brief Saves an object inside a std::stringstream.
122
    ///
123
    /// \tparam T Type of the object to deserialize.
124
    ///
125
    /// \param[in]   object Object in which the loaded data are copied.
126
    /// \param[out]  ss String stream constaining the serialized content of the object.
127
    ///
128
    template<typename T>
129
540
    inline void saveToStringStream(const T & object,
130
                                   std::stringstream & ss)
131
    {
132
1080
      boost::archive::text_oarchive oa(ss);
133
540
      oa & object;
134
540
    }
135
136
    ///
137
    /// \brief Loads an object from a std::string
138
    ///
139
    /// \tparam T Type of the object to deserialize.
140
    ///
141
    /// \param[out] object Object in which the loaded data are copied.
142
    /// \param[in]  str  string constaining the serialized content of the object.
143
    ///
144
    template<typename T>
145
270
    inline void loadFromString(T & object,
146
                               const std::string & str)
147
    {
148
540
      std::istringstream is(str);
149
270
      loadFromStringStream(object,is);
150
270
    }
151
152
    ///
153
    /// \brief Saves an object inside a std::string
154
    ///
155
    /// \tparam T Type of the object to deserialize.
156
    ///
157
    /// \param[in] object Object in which the loaded data are copied.
158
    ///
159
    /// \returns a string  constaining the serialized content of the object.
160
    ///
161
    template<typename T>
162
270
    inline std::string saveToString(const T & object)
163
    {
164
540
      std::stringstream ss;
165
270
      saveToStringStream(object,ss);
166
540
      return ss.str();
167
    }
168
169
    ///
170
    /// \brief Loads an object from a XML file.
171
    ///
172
    /// \tparam T Type of the object to deserialize.
173
    ///
174
    /// \param[out] object Object in which the loaded data are copied.
175
    /// \param[in] filename Name of the file containing the serialized data.
176
    /// \param[in] tag_name XML Tag for the given object.
177
    ///
178
    template<typename T>
179
272
    inline void loadFromXML(T & object,
180
                            const std::string & filename,
181
                            const std::string & tag_name)
182
    {
183

272
      PINOCCHIO_CHECK_INPUT_ARGUMENT(!tag_name.empty());
184
185
544
      std::ifstream ifs(filename.c_str());
186

272
      if(ifs)
187
      {
188

540
        std::locale const new_loc(ifs.getloc(), new boost::math::nonfinite_num_get<char>);
189
270
        ifs.imbue(new_loc);
190
270
        boost::archive::xml_iarchive ia(ifs,boost::archive::no_codecvt);
191

270
        ia >> boost::serialization::make_nvp(tag_name.c_str(),object);
192
      }
193
      else
194
      {
195
4
        const std::string exception_message(filename + " does not seem to be a valid file.");
196
2
        throw std::invalid_argument(exception_message);
197
      }
198
270
    }
199
200
    ///
201
    /// \brief Saves an object inside a XML file.
202
    ///
203
    /// \tparam T Type of the object to deserialize.
204
    ///
205
    /// \param[in] object Object in which the loaded data are copied.
206
    /// \param[in] filename Name of the file containing the serialized data.
207
    /// \param[in] tag_name XML Tag for the given object.
208
    ///
209
    template<typename T>
210
272
    inline void saveToXML(const T & object,
211
                          const std::string & filename,
212
                          const std::string & tag_name)
213
    {
214

272
      PINOCCHIO_CHECK_INPUT_ARGUMENT(!tag_name.empty());
215
216
544
      std::ofstream ofs(filename.c_str());
217

272
      if(ofs)
218
      {
219
272
        boost::archive::xml_oarchive oa(ofs);
220

272
        oa & boost::serialization::make_nvp(tag_name.c_str(),object);
221
      }
222
      else
223
      {
224
        const std::string exception_message(filename + " does not seem to be a valid file.");
225
        throw std::invalid_argument(exception_message);
226
      }
227
272
    }
228
229
    ///
230
    /// \brief Loads an object from a binary file.
231
    ///
232
    /// \tparam T Type of the object to deserialize.
233
    ///
234
    /// \param[out] object Object in which the loaded data are copied.
235
    /// \param[in] filename Name of the file containing the serialized data.
236
    ///
237
    template<typename T>
238
272
    inline void loadFromBinary(T & object,
239
                               const std::string & filename)
240
    {
241
544
      std::ifstream ifs(filename.c_str(), std::ios::binary);
242

272
      if(ifs)
243
      {
244
540
        boost::archive::binary_iarchive ia(ifs);
245
270
        ia >> object;
246
      }
247
      else
248
      {
249
4
        const std::string exception_message(filename + " does not seem to be a valid file.");
250
2
        throw std::invalid_argument(exception_message);
251
      }
252
270
    }
253
254
    ///
255
    /// \brief Saves an object inside a binary file.
256
    ///
257
    /// \tparam T Type of the object to deserialize.
258
    ///
259
    /// \param[in] object Object in which the loaded data are copied.
260
    /// \param[in] filename Name of the file containing the serialized data.
261
    ///
262
    template<typename T>
263
272
    void saveToBinary(const T & object,
264
                      const std::string & filename)
265
    {
266
544
      std::ofstream ofs(filename.c_str(), std::ios::binary);
267

272
      if(ofs)
268
      {
269
544
        boost::archive::binary_oarchive oa(ofs);
270
272
        oa & object;
271
      }
272
      else
273
      {
274
        const std::string exception_message(filename + " does not seem to be a valid file.");
275
        throw std::invalid_argument(exception_message);
276
      }
277
272
    }
278
279
    ///
280
    /// \brief Loads an object from a binary buffer.
281
    ///
282
    /// \tparam T Type of the object to deserialize.
283
    ///
284
    /// \param[out] object Object in which the loaded data are copied.
285
    /// \param[in] buffer Input buffer containing the serialized data.
286
    ///
287
    template<typename T>
288
270
    inline void loadFromBinary(T & object,
289
                               boost::asio::streambuf & buffer)
290
    {
291
540
      boost::archive::binary_iarchive ia(buffer);
292
270
      ia >> object;
293
270
    }
294
295
    ///
296
    /// \brief Saves an object to a binary buffer.
297
    ///
298
    /// \tparam T Type of the object to serialize.
299
    ///
300
    /// \param[in]  object Object in which the loaded data are copied.
301
    /// \param[out] buffer Output buffer containing the serialized data.
302
    ///
303
    template<typename T>
304
270
    void saveToBinary(const T & object,
305
                      boost::asio::streambuf & buffer)
306
    {
307
540
      boost::archive::binary_oarchive oa(buffer);
308
270
      oa & object;
309
270
    }
310
311
    ///
312
    /// \brief Loads an object from a static binary buffer.
313
    ///        The buffer should be of a sufficient size.
314
    ///
315
    /// \tparam T Type of the object to deserialize.
316
    ///
317
    /// \param[out] object Object in which the loaded data are copied.
318
    /// \param[in] buffer Input buffer containing the serialized data.
319
    ///
320
    template<typename T>
321
270
    inline void loadFromBinary(T & object,
322
                               StaticBuffer & buffer)
323
    {
324
540
      boost::iostreams::stream_buffer< boost::iostreams::basic_array<char> > stream(buffer.data(), buffer.size());
325
326
540
      boost::archive::binary_iarchive ia(stream);
327
270
      ia >> object;
328
270
    }
329
330
    ///
331
    /// \brief Saves an object to a static binary buffer.
332
    ///        The buffer should be of a sufficient size.
333
    ///
334
    /// \tparam T Type of the object to deserialize.
335
    ///
336
    /// \param[in]  object Object in which the loaded data are copied.
337
    /// \param[out] buffer Output buffer containing the serialized data.
338
    ///
339
    template<typename T>
340
270
    inline void saveToBinary(const T & object,
341
                             StaticBuffer & buffer)
342
    {
343
540
      boost::iostreams::stream_buffer< boost::iostreams::basic_array<char> > stream(buffer.data(), buffer.size());
344
345
540
      boost::archive::binary_oarchive oa(stream);
346
270
      oa & object;
347
270
    }
348
349
  } // namespace serialization
350
} // namespace pinocchio
351
352
#endif // ifndef __pinocchio_serialization_archive_hpp__