GCC Code Coverage Report


Directory: ./
File: include/coal/serialization/archive.h
Date: 2025-04-01 09:23:31
Exec Total Coverage
Lines: 78 92 84.8%
Branches: 57 198 28.8%

Line Branch Exec Source
1 //
2 // Copyright (c) 2017-2024 CNRS INRIA
3 // This file was borrowed from the Pinocchio library:
4 // https://github.com/stack-of-tasks/pinocchio
5 //
6
7 #ifndef COAL_SERIALIZATION_ARCHIVE_H
8 #define COAL_SERIALIZATION_ARCHIVE_H
9
10 #include "coal/fwd.hh"
11
12 #include <boost/serialization/nvp.hpp>
13 #include <boost/archive/text_iarchive.hpp>
14 #include <boost/archive/text_oarchive.hpp>
15 #include <boost/archive/xml_iarchive.hpp>
16 #include <boost/archive/xml_oarchive.hpp>
17 #include <boost/archive/binary_iarchive.hpp>
18 #include <boost/archive/binary_oarchive.hpp>
19
20 #include <fstream>
21 #include <string>
22 #include <sstream>
23 #include <stdexcept>
24
25 #if BOOST_VERSION / 100 % 1000 == 78 && __APPLE__
26 // See https://github.com/qcscine/utilities/issues/5#issuecomment-1246897049 for
27 // further details
28
29 #ifndef BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
30 #define DEFINE_BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
31 #define BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
32 #endif
33
34 #include <boost/asio/streambuf.hpp>
35
36 #ifdef DEFINE_BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
37 #undef BOOST_ASIO_DISABLE_STD_ALIGNED_ALLOC
38 #endif
39
40 #else
41 #include <boost/asio/streambuf.hpp>
42 #endif
43
44 #include <boost/iostreams/device/array.hpp>
45 #include <boost/iostreams/stream.hpp>
46 #include <boost/iostreams/stream_buffer.hpp>
47
48 // Handle NAN inside TXT or XML archives
49 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
50
51 namespace coal {
52 namespace serialization {
53
54 ///
55 /// \brief Loads an object from a TXT file.
56 ///
57 /// \tparam T Type of the object to deserialize.
58 ///
59 /// \param[out] object Object in which the loaded data are copied.
60 /// \param[in] filename Name of the file containing the serialized data.
61 ///
62 template <typename T>
63 92 inline void loadFromText(T& object, const std::string& filename) {
64
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
92 std::ifstream ifs(filename.c_str());
65
2/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
92 if (ifs) {
66
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
92 std::locale const new_loc(ifs.getloc(),
67
2/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
92 new boost::math::nonfinite_num_get<char>);
68
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
92 ifs.imbue(new_loc);
69
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
92 boost::archive::text_iarchive ia(ifs, boost::archive::no_codecvt);
70
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
92 ia >> object;
71 92 } else {
72 const std::string exception_message(filename +
73 " does not seem to be a valid file.");
74 throw std::invalid_argument(exception_message);
75 }
76 92 }
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 92 inline void saveToText(const T& object, const std::string& filename) {
88
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
92 std::ofstream ofs(filename.c_str());
89
2/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
92 if (ofs) {
90
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
92 boost::archive::text_oarchive oa(ofs);
91
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
92 oa & object;
92 92 } else {
93 const std::string exception_message(filename +
94 " does not seem to be a valid file.");
95 throw std::invalid_argument(exception_message);
96 }
97 92 }
98
99 ///
100 /// \brief Loads an object from a std::stringstream.
101 ///
102 /// \tparam T Type of the object to deserialize.
103 ///
104 /// \param[out] object Object in which the loaded data are copied.
105 /// \param[in] is string stream constaining the serialized content of the
106 /// object.
107 ///
108 template <typename T>
109 88 inline void loadFromStringStream(T& object, std::istringstream& is) {
110
1/2
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
88 std::locale const new_loc(is.getloc(),
111
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
88 new boost::math::nonfinite_num_get<char>);
112
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 is.imbue(new_loc);
113
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 boost::archive::text_iarchive ia(is, boost::archive::no_codecvt);
114
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 ia >> object;
115 88 }
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
124 /// object.
125 ///
126 template <typename T>
127 88 inline void saveToStringStream(const T& object, std::stringstream& ss) {
128
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 boost::archive::text_oarchive oa(ss);
129
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 oa & object;
130 88 }
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 44 inline void loadFromString(T& object, const std::string& str) {
142
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 std::istringstream is(str);
143
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 loadFromStringStream(object, is);
144 44 }
145
146 ///
147 /// \brief Saves an object inside a std::string
148 ///
149 /// \tparam T Type of the object to deserialize.
150 ///
151 /// \param[in] object Object in which the loaded data are copied.
152 ///
153 /// \returns a string constaining the serialized content of the object.
154 ///
155 template <typename T>
156 44 inline std::string saveToString(const T& object) {
157
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 std::stringstream ss;
158
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 saveToStringStream(object, ss);
159
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
88 return ss.str();
160 44 }
161
162 ///
163 /// \brief Loads an object from a XML file.
164 ///
165 /// \tparam T Type of the object to deserialize.
166 ///
167 /// \param[out] object Object in which the loaded data are copied.
168 /// \param[in] filename Name of the file containing the serialized data.
169 /// \param[in] tag_name XML Tag for the given object.
170 ///
171 template <typename T>
172 44 inline void loadFromXML(T& object, const std::string& filename,
173 const std::string& tag_name) {
174
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
44 if (filename.empty()) {
175 COAL_THROW_PRETTY("Tag name should not be empty.", std::invalid_argument);
176 }
177
178
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 std::ifstream ifs(filename.c_str());
179
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 if (ifs) {
180
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 std::locale const new_loc(ifs.getloc(),
181
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
44 new boost::math::nonfinite_num_get<char>);
182
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 ifs.imbue(new_loc);
183
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 boost::archive::xml_iarchive ia(ifs, boost::archive::no_codecvt);
184
1/2
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 ia >> boost::serialization::make_nvp(tag_name.c_str(), object);
185 44 } else {
186 const std::string exception_message(filename +
187 " does not seem to be a valid file.");
188 throw std::invalid_argument(exception_message);
189 }
190 44 }
191
192 ///
193 /// \brief Saves an object inside a XML file.
194 ///
195 /// \tparam T Type of the object to deserialize.
196 ///
197 /// \param[in] object Object in which the loaded data are copied.
198 /// \param[in] filename Name of the file containing the serialized data.
199 /// \param[in] tag_name XML Tag for the given object.
200 ///
201 template <typename T>
202 44 inline void saveToXML(const T& object, const std::string& filename,
203 const std::string& tag_name) {
204
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
44 if (filename.empty()) {
205 COAL_THROW_PRETTY("Tag name should not be empty.", std::invalid_argument);
206 }
207
208
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 std::ofstream ofs(filename.c_str());
209
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 if (ofs) {
210
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 boost::archive::xml_oarchive oa(ofs);
211
1/2
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 oa& boost::serialization::make_nvp(tag_name.c_str(), object);
212 44 } else {
213 const std::string exception_message(filename +
214 " does not seem to be a valid file.");
215 throw std::invalid_argument(exception_message);
216 }
217 44 }
218
219 ///
220 /// \brief Loads an object from a binary file.
221 ///
222 /// \tparam T Type of the object to deserialize.
223 ///
224 /// \param[out] object Object in which the loaded data are copied.
225 /// \param[in] filename Name of the file containing the serialized data.
226 ///
227 template <typename T>
228 44 inline void loadFromBinary(T& object, const std::string& filename) {
229
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 std::ifstream ifs(filename.c_str(), std::ios::binary);
230
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 if (ifs) {
231
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 boost::archive::binary_iarchive ia(ifs);
232
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 ia >> object;
233 44 } else {
234 const std::string exception_message(filename +
235 " does not seem to be a valid file.");
236 throw std::invalid_argument(exception_message);
237 }
238 44 }
239
240 ///
241 /// \brief Saves an object inside a binary file.
242 ///
243 /// \tparam T Type of the object to deserialize.
244 ///
245 /// \param[in] object Object in which the loaded data are copied.
246 /// \param[in] filename Name of the file containing the serialized data.
247 ///
248 template <typename T>
249 44 void saveToBinary(const T& object, const std::string& filename) {
250
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 std::ofstream ofs(filename.c_str(), std::ios::binary);
251
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 if (ofs) {
252
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 boost::archive::binary_oarchive oa(ofs);
253
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 oa & object;
254 44 } else {
255 const std::string exception_message(filename +
256 " does not seem to be a valid file.");
257 throw std::invalid_argument(exception_message);
258 }
259 44 }
260
261 ///
262 /// \brief Loads an object from a binary buffer.
263 ///
264 /// \tparam T Type of the object to deserialize.
265 ///
266 /// \param[out] object Object in which the loaded data are copied.
267 /// \param[in] buffer Input buffer containing the serialized data.
268 ///
269 template <typename T>
270 48 inline void loadFromBuffer(T& object, boost::asio::streambuf& buffer) {
271
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 boost::archive::binary_iarchive ia(buffer);
272
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 ia >> object;
273 48 }
274
275 ///
276 /// \brief Saves an object to a binary buffer.
277 ///
278 /// \tparam T Type of the object to serialize.
279 ///
280 /// \param[in] object Object in which the loaded data are copied.
281 /// \param[out] buffer Output buffer containing the serialized data.
282 ///
283 template <typename T>
284 48 void saveToBuffer(const T& object, boost::asio::streambuf& buffer) {
285
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 boost::archive::binary_oarchive oa(buffer);
286
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 oa & object;
287 48 }
288
289 } // namespace serialization
290 } // namespace coal
291
292 #endif // ifndef COAL_SERIALIZATION_ARCHIVE_H
293