1 /*
2 * This file is part of CasADi.
3 *
4 * CasADi -- A symbolic framework for dynamic optimization.
5 * Copyright (C) 2010-2014 Joel Andersson, Joris Gillis, Moritz Diehl,
6 * K.U. 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 <iomanip>
34
35 using namespace std;
36 namespace casadi {
37
StringSerializer(const Dict & opts)38 StringSerializer::StringSerializer(const Dict& opts) :
39 SerializerBase(std::unique_ptr<std::ostream>(new std::stringstream()), opts) {
40 }
41
FileSerializer(const std::string & fname,const Dict & opts)42 FileSerializer::FileSerializer(const std::string& fname, const Dict& opts) :
43 SerializerBase(
44 std::unique_ptr<std::ostream>(
45 new std::ofstream(fname, ios_base::binary | std::ios::out)),
46 opts) {
47 if ((sstream_->rdstate() & std::ifstream::failbit) != 0) {
48 casadi_error("Could not open file '" + fname + "' for writing.");
49 }
50 }
51
SerializerBase(std::unique_ptr<std::ostream> stream,const Dict & opts)52 SerializerBase::SerializerBase(std::unique_ptr<std::ostream> stream, const Dict& opts) :
53 sstream_(std::move(stream)),
54 serializer_(new SerializingStream(*sstream_, opts)) {
55 }
56
type_to_string(SerializationType type)57 std::string SerializerBase::type_to_string(SerializationType type) {
58 switch (type) {
59 case SERIALIZED_SPARSITY: return "sparsity";
60 case SERIALIZED_MX: return "mx";
61 case SERIALIZED_DM: return "dm";
62 case SERIALIZED_SX: return "sx";
63 case SERIALIZED_LINSOL: return "linsol";
64 case SERIALIZED_FUNCTION: return "function";
65 case SERIALIZED_GENERICTYPE: return "generictype";
66 case SERIALIZED_INT: return "int";
67 case SERIALIZED_DOUBLE: return "double";
68 case SERIALIZED_STRING: return "string";
69 case SERIALIZED_SPARSITY_VECTOR: return "sparsity_vector";
70 case SERIALIZED_MX_VECTOR: return "mx_vector";
71 case SERIALIZED_DM_VECTOR: return "dm_vector";
72 case SERIALIZED_SX_VECTOR: return "sx_vector";
73 case SERIALIZED_LINSOL_VECTOR: return "linsol_vector";
74 case SERIALIZED_FUNCTION_VECTOR: return "function_vector";
75 case SERIALIZED_GENERICTYPE_VECTOR: return "generictype_vector";
76 case SERIALIZED_INT_VECTOR: return "int_vector";
77 case SERIALIZED_DOUBLE_VECTOR: return "double_vector";
78 case SERIALIZED_STRING_VECTOR: return "string_vector";
79 default: casadi_error("Unknown type" + str(type));
80 }
81 }
82
~FileSerializer()83 FileSerializer::~FileSerializer() {
84 }
85
encode()86 std::string StringSerializer::encode() {
87 std::string ret = static_cast<std::stringstream*>(sstream_.get())->str();
88 static_cast<std::stringstream*>(sstream_.get())->str("");
89 sstream_->clear();
90 return ret;
91 }
decode(const std::string & string)92 void StringDeserializer::decode(const std::string& string) {
93 casadi_assert(dstream_->peek()==char_traits<char>::eof(),
94 "StringDeserializer::decode does not apply: current string not fully consumed yet.");
95 static_cast<std::stringstream*>(dstream_.get())->str(string);
96 dstream_->clear(); // reset error flags
97 }
98
~SerializerBase()99 SerializerBase::~SerializerBase() { }
~StringSerializer()100 StringSerializer::~StringSerializer() { }
101
DeserializerBase(std::unique_ptr<std::istream> stream)102 DeserializerBase::DeserializerBase(std::unique_ptr<std::istream> stream) :
103 dstream_(std::move(stream)),
104 deserializer_(new DeserializingStream(*dstream_)) {
105 }
106
FileDeserializer(const std::string & fname)107 FileDeserializer::FileDeserializer(const std::string& fname) :
108 DeserializerBase(std::unique_ptr<std::istream>(
109 new std::ifstream(fname, ios_base::binary | std::ios::in))) {
110 if ((dstream_->rdstate() & std::ifstream::failbit) != 0) {
111 casadi_error("Could not open file '" + fname + "' for reading.");
112 }
113 }
114
StringDeserializer(const std::string & string)115 StringDeserializer::StringDeserializer(const std::string& string) :
116 DeserializerBase(std::unique_ptr<std::istream>(
117 new std::stringstream(string))) {
118 }
119
~DeserializerBase()120 DeserializerBase::~DeserializerBase() { }
~StringDeserializer()121 StringDeserializer::~StringDeserializer() { }
~FileDeserializer()122 FileDeserializer::~FileDeserializer() { }
123
serializer()124 SerializingStream& SerializerBase::serializer() {
125 return *serializer_;
126 }
127
deserializer()128 DeserializingStream& DeserializerBase::deserializer() {
129 casadi_assert(dstream_->peek()!=char_traits<char>::eof(),
130 "Deserializer reached end of stream. Nothing left to unpack.");
131 return *deserializer_;
132 }
133
pop_type()134 SerializerBase::SerializationType DeserializerBase::pop_type() {
135 char type;
136 deserializer().unpack(type);
137 return static_cast<SerializerBase::SerializationType>(type);
138 }
139
140 #define SERIALIZEX(TYPE, BaseType, Type, type, arg) \
141 void SerializerBase::pack(const Type& e) { \
142 serializer().pack(static_cast<char>(SERIALIZED_ ## TYPE));\
143 serializer().pack(Function("temp", std::vector< BaseType >{}, arg)); \
144 serializer().pack(e); \
145 } \
146 \
147 Type DeserializerBase::blind_unpack_ ## type() { \
148 Function f; \
149 deserializer().unpack(f);\
150 Type ret;\
151 deserializer().unpack(ret);\
152 return ret;\
153 } \
154 Type DeserializerBase::unpack_ ## type() { \
155 SerializerBase::SerializationType t = pop_type();\
156 casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_ ## TYPE, \
157 "Expected to find a '" + SerializerBase::type_to_string(\
158 SerializerBase::SerializationType::SERIALIZED_ ## TYPE)+ \
159 "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");\
160 return blind_unpack_ ## type();\
161 }
162
163 #define SERIALIZEX_ALL(TYPE, Type, type)\
164 SERIALIZEX(TYPE, Type, Type, type, {e})\
165 SERIALIZEX(TYPE ## _VECTOR, Type, std::vector< Type >, type ## _vector, e)
166
SERIALIZEX_ALL(MX,MX,mx)167 SERIALIZEX_ALL(MX, MX, mx)
168 SERIALIZEX_ALL(SX, SX, sx)
169
170 #define SERIALIZE(TYPE, Type, type) \
171 void SerializerBase::pack(const Type& e) { \
172 serializer().pack(static_cast<char>(SERIALIZED_ ## TYPE));\
173 serializer().pack(e); \
174 } \
175 \
176 Type DeserializerBase::blind_unpack_ ## type() { \
177 Type ret;\
178 deserializer().unpack(ret);\
179 return ret;\
180 }\
181 Type DeserializerBase::unpack_ ## type() { \
182 SerializerBase::SerializationType t = pop_type();\
183 casadi_assert(t==SerializerBase::SerializationType::SERIALIZED_ ## TYPE, \
184 "Expected to find a '" + SerializerBase::type_to_string(\
185 SerializerBase::SerializationType::SERIALIZED_ ## TYPE) +\
186 "', but encountered a '" + SerializerBase::type_to_string(t) + "' instead.");\
187 return blind_unpack_ ## type();\
188 }
189
190 #define SERIALIZE_ALL(TYPE, Type, type)\
191 SERIALIZE(TYPE, Type, type)\
192 SERIALIZE(TYPE ## _VECTOR, std::vector< Type >, type ## _vector)
193
194 SERIALIZE_ALL(SPARSITY, Sparsity, sparsity)
195 SERIALIZE_ALL(DM, DM, dm)
196 SERIALIZE_ALL(LINSOL, Linsol, linsol)
197 SERIALIZE_ALL(FUNCTION, Function, function)
198 SERIALIZE_ALL(GENERICTYPE, GenericType, generictype)
199 SERIALIZE_ALL(INT, casadi_int, int)
200 SERIALIZE_ALL(DOUBLE, double, double)
201 SERIALIZE_ALL(STRING, std::string , string)
202
203 void SerializerBase::connect(DeserializerBase & s) {
204 serializer_->connect(*s.deserializer_);
205 }
reset()206 void SerializerBase::reset() {
207 serializer_->reset();
208 }
connect(SerializerBase & s)209 void DeserializerBase::connect(SerializerBase & s) {
210 deserializer_->connect(*s.serializer_);
211 }
reset()212 void DeserializerBase::reset() {
213 deserializer_->reset();
214 }
215
216 } // namespace casadi
217