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