serializer.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi 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.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #include "function.hpp"
27 #include "serializer.hpp"
28 #include "serializing_stream.hpp"
29 #include "slice.hpp"
30 #include "linsol.hpp"
31 #include "importer.hpp"
32 #include "generic_type.hpp"
33 #include "filesystem_impl.hpp"
34 #include <iomanip>
35 
36 namespace casadi {
37 
39  SerializerBase(std::unique_ptr<std::ostream>(new std::stringstream()), opts) {
40  }
41 
42  FileSerializer::FileSerializer(const std::string& fname, const Dict& opts) :
44  std::unique_ptr<std::ostream>(
45  Filesystem::ofstream_ptr(fname, std::ios_base::binary | std::ios::out)),
46  opts) {
47  }
48 
49  SerializerBase::SerializerBase(std::unique_ptr<std::ostream> stream, const Dict& opts) :
50  sstream_(std::move(stream)),
51  serializer_(new SerializingStream(*sstream_, opts)) {
52  }
53 
55  switch (type) {
56  case SERIALIZED_SPARSITY: return "sparsity";
57  case SERIALIZED_MX: return "mx";
58  case SERIALIZED_MX_v1: return "mx_v1";
59  case SERIALIZED_DM: return "dm";
60  case SERIALIZED_SX: return "sx";
61  case SERIALIZED_SX_v1: return "sx_v1";
62  case SERIALIZED_LINSOL: return "linsol";
63  case SERIALIZED_FUNCTION: return "function";
64  case SERIALIZED_GENERICTYPE: return "generictype";
65  case SERIALIZED_INT: return "int";
66  case SERIALIZED_DOUBLE: return "double";
67  case SERIALIZED_STRING: return "string";
68  case SERIALIZED_SPARSITY_VECTOR: return "sparsity_vector";
69  case SERIALIZED_MX_VECTOR: return "mx_vector";
70  case SERIALIZED_MX_VECTOR_v1: return "mx_vector_v1";
71  case SERIALIZED_DM_VECTOR: return "dm_vector";
72  case SERIALIZED_SX_VECTOR: return "sx_vector";
73  case SERIALIZED_SX_VECTOR_v1: return "sx_vector_v1";
74  case SERIALIZED_LINSOL_VECTOR: return "linsol_vector";
75  case SERIALIZED_FUNCTION_VECTOR: return "function_vector";
76  case SERIALIZED_GENERICTYPE_VECTOR: return "generictype_vector";
77  case SERIALIZED_INT_VECTOR: return "int_vector";
78  case SERIALIZED_DOUBLE_VECTOR: return "double_vector";
79  case SERIALIZED_STRING_VECTOR: return "string_vector";
80  default: casadi_error("Unknown type" + str(type));
81  }
82  }
83 
85  }
86 
87  std::string StringSerializer::encode() {
88  std::string ret = static_cast<std::stringstream*>(sstream_.get())->str();
89  static_cast<std::stringstream*>(sstream_.get())->str("");
90  sstream_->clear();
91  return ret;
92  }
93  void StringDeserializer::decode(const std::string& string) {
94  casadi_assert(dstream_->peek() == std::char_traits<char>::eof(),
95  "StringDeserializer::decode does not apply: current string not fully consumed yet.");
96  static_cast<std::stringstream*>(dstream_.get())->str(string);
97  dstream_->clear(); // reset error flags
98  }
99 
102 
103  DeserializerBase::DeserializerBase(std::unique_ptr<std::istream> stream) :
104  dstream_(std::move(stream)),
105  deserializer_(new DeserializingStream(*dstream_)) {
106  }
107 
108  FileDeserializer::FileDeserializer(const std::string& fname) :
109  DeserializerBase(std::unique_ptr<std::istream>(
110  new std::ifstream(fname, std::ios_base::binary | std::ios::in))) {
111  if ((dstream_->rdstate() & std::ifstream::failbit) != 0) {
112  casadi_error("Could not open file '" + fname + "' for reading.");
113  }
114  }
115 
116  StringDeserializer::StringDeserializer(const std::string& string) :
117  DeserializerBase(std::unique_ptr<std::istream>(
118  new std::stringstream(string))) {
119  }
120 
124 
126  return *serializer_;
127  }
128 
130  casadi_assert(dstream_->peek() != std::char_traits<char>::eof(),
131  "Deserializer reached end of stream. Nothing left to unpack.");
132  return *deserializer_;
133  }
134 
136  char type;
137  deserializer().unpack(type);
138  return static_cast<SerializerBase::SerializationType>(type);
139  }
140 
141  void SerializerBase::pack(const MX& e) {
142  serializer().pack(static_cast<char>(SERIALIZED_MX));
144  serializer().pack(e);
145  }
146  void SerializerBase::pack(const std::vector<MX>& e) {
147  serializer().pack(static_cast<char>(SERIALIZED_MX_VECTOR));
149  serializer().pack(e);
150  }
151  void SerializerBase::pack(const SX& e) {
152  serializer().pack(static_cast<char>(SERIALIZED_SX));
154  serializer().pack(e);
155  }
156  void SerializerBase::pack(const std::vector<SX>& e) {
157  serializer().pack(static_cast<char>(SERIALIZED_SX_VECTOR));
159  serializer().pack(e);
160  }
162  std::vector<MX> sorted;
163  deserializer().unpack(sorted);
164  MX ret;
165  deserializer().unpack(ret);
166  return ret;
167  }
169  std::vector<SX> sorted;
170  deserializer().unpack(sorted);
171  SX ret;
172  deserializer().unpack(ret);
173  return ret;
174  }
176  std::vector<MX> sorted;
177  deserializer().unpack(sorted);
178  std::vector<MX> ret;
179  deserializer().unpack(ret);
180  return ret;
181  }
183  std::vector<SX> sorted;
184  deserializer().unpack(sorted);
185  std::vector<SX> ret;
186  deserializer().unpack(ret);
187  return ret;
188  }
190  Function f;
191  deserializer().unpack(f);
192  MX ret;
193  deserializer().unpack(ret);
194  return ret;
195  }
197  Function f;
198  deserializer().unpack(f);
199  SX ret;
200  deserializer().unpack(ret);
201  return ret;
202  }
204  Function f;
205  deserializer().unpack(f);
206  std::vector<MX> ret;
207  deserializer().unpack(ret);
208  return ret;
209  }
211  Function f;
212  deserializer().unpack(f);
213  std::vector<SX> ret;
214  deserializer().unpack(ret);
215  return ret;
216  }
219  if (t==SerializerBase::SerializationType::SERIALIZED_MX_v1) {
220  return blind_unpack_mx_v1();
221  }
222  casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_MX,
223  "Expected to find a '" + SerializerBase::type_to_string(
224  SerializerBase::SerializationType::SERIALIZED_MX)+
225  "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");
226  return blind_unpack_mx();
227  }
230  if (t==SerializerBase::SerializationType::SERIALIZED_SX_v1) {
231  return blind_unpack_sx_v1();
232  }
233  casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_SX,
234  "Expected to find a '" + SerializerBase::type_to_string(
235  SerializerBase::SerializationType::SERIALIZED_SX)+
236  "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");
237  return blind_unpack_sx();
238  }
241  if (t==SerializerBase::SerializationType::SERIALIZED_MX_VECTOR_v1) {
242  return blind_unpack_mx_vector_v1();
243  }
244  casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_MX_VECTOR, \
245  "Expected to find a '" + SerializerBase::type_to_string(
246  SerializerBase::SerializationType::SERIALIZED_MX_VECTOR)+
247  "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");
248  return blind_unpack_mx_vector();
249  }
252  if (t==SerializerBase::SerializationType::SERIALIZED_SX_VECTOR_v1) {
253  return blind_unpack_sx_vector_v1();
254  }
255  casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_SX_VECTOR, \
256  "Expected to find a '" + SerializerBase::type_to_string(\
257  SerializerBase::SerializationType::SERIALIZED_SX_VECTOR)+
258  "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");
259  return blind_unpack_sx_vector();
260  }
261 
262 #define SERIALIZE(TYPE, Type, type) \
263  void SerializerBase::pack(const Type& e) { \
264  serializer().pack(static_cast<char>(SERIALIZED_ ## TYPE));\
265  serializer().pack(e); \
266  } \
267  \
268  Type DeserializerBase::blind_unpack_ ## type() { \
269  Type ret;\
270  deserializer().unpack(ret);\
271  return ret;\
272  }\
273  Type DeserializerBase::unpack_ ## type() { \
274  SerializerBase::SerializationType t = pop_type();\
275  casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_ ## TYPE, \
276  "Expected to find a '" + SerializerBase::type_to_string(\
277  SerializerBase::SerializationType::SERIALIZED_ ## TYPE) +\
278  "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");\
279  return blind_unpack_ ## type();\
280  }
281 
282 #define SERIALIZE_ALL(TYPE, Type, type)\
283  SERIALIZE(TYPE, Type, type)\
284  SERIALIZE(TYPE ## _VECTOR, std::vector< Type >, type ## _vector)
285 
286 SERIALIZE_ALL(SPARSITY, Sparsity, sparsity)
287 SERIALIZE_ALL(DM, DM, dm)
288 SERIALIZE_ALL(LINSOL, Linsol, linsol)
289 SERIALIZE_ALL(FUNCTION, Function, function)
290 SERIALIZE_ALL(GENERICTYPE, GenericType, generictype)
291 SERIALIZE_ALL(INT, casadi_int, int)
292 SERIALIZE_ALL(DOUBLE, double, double)
293 SERIALIZE_ALL(STRING, std::string , string)
294 
295  void SerializerBase::connect(DeserializerBase & s) {
296  serializer_->connect(*s.deserializer_);
297  }
299  serializer_->reset();
300  }
302  deserializer_->connect(*s.serializer_);
303  }
305  deserializer_->reset();
306  }
307 
308 } // namespace casadi
std::vector< MX > blind_unpack_mx_vector()
Definition: serializer.cpp:175
Matrix< SXElem > blind_unpack_sx_v1()
Definition: serializer.cpp:196
Matrix< SXElem > unpack_sx()
Definition: serializer.cpp:228
std::vector< Matrix< SXElem > > unpack_sx_vector()
Definition: serializer.cpp:250
std::unique_ptr< DeserializingStream > deserializer_
Definition: serializer.hpp:178
DeserializingStream & deserializer()
Definition: serializer.cpp:129
std::vector< MX > blind_unpack_mx_vector_v1()
Definition: serializer.cpp:203
Matrix< SXElem > blind_unpack_sx()
Definition: serializer.cpp:168
std::vector< Matrix< SXElem > > blind_unpack_sx_vector_v1()
Definition: serializer.cpp:210
std::unique_ptr< std::istream > dstream_
Definition: serializer.hpp:177
std::vector< Matrix< SXElem > > blind_unpack_sx_vector()
Definition: serializer.cpp:182
DeserializerBase(std::unique_ptr< std::istream > stream)
Definition: serializer.cpp:103
void connect(SerializerBase &s)
Definition: serializer.cpp:301
SerializerBase::SerializationType pop_type()
Definition: serializer.cpp:135
std::vector< MX > unpack_mx_vector()
Definition: serializer.cpp:239
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
FileDeserializer(const std::string &fname)
Advanced deserialization of CasADi objects.
Definition: serializer.cpp:108
FileSerializer(const std::string &fname, const Dict &opts=Dict())
Advanced serialization of CasADi objects.
Definition: serializer.cpp:42
Filesystem interface.
Function object.
Definition: function.hpp:60
static std::vector< SX > order(const std::vector< SX > &expr)
Definition: function.cpp:1938
Generic data type, can hold different types such as bool, casadi_int, std::string etc.
Linear solver.
Definition: linsol.hpp:55
MX - Matrix expression.
Definition: mx.hpp:92
Sparse matrix class. SX and DM are specializations.
Definition: matrix_decl.hpp:99
SerializerBase(std::unique_ptr< std::ostream > stream, const Dict &opts=Dict())
Definition: serializer.cpp:49
void connect(DeserializerBase &s)
Definition: serializer.cpp:295
std::unique_ptr< SerializingStream > serializer_
Definition: serializer.hpp:113
void pack(const Sparsity &e)
std::unique_ptr< std::ostream > sstream_
Definition: serializer.hpp:112
static std::string type_to_string(SerializationType type)
Definition: serializer.cpp:54
SerializingStream & serializer()
Definition: serializer.cpp:125
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
General sparsity class.
Definition: sparsity.hpp:106
StringDeserializer(const std::string &string)
Advanced deserialization of CasADi objects.
Definition: serializer.cpp:116
void decode(const std::string &string)
Sets the string to deserialize objects from.
Definition: serializer.cpp:93
std::string encode()
Returns a string that holds the serialized objects.
Definition: serializer.cpp:87
StringSerializer(const Dict &opts=Dict())
Advanced serialization of CasADi objects.
Definition: serializer.cpp:38
The casadi namespace.
Definition: archiver.cpp:28
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.