1 //
2 // MessagePack for C++ static resolution routine
3 //
4 // Copyright (C) 2008-2009 FURUHASHI Sadayuki
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 #ifndef MSGPACK_OBJECT_HPP__
19 #define MSGPACK_OBJECT_HPP__
20
21 #include "object.h"
22 #include "pack.hpp"
23 #include "zone.hpp"
24 #include <string.h>
25 #include <stdexcept>
26 #include <typeinfo>
27 #include <limits>
28 #include <ostream>
29
30 namespace msgpack {
31
32
33 class type_error : public std::bad_cast { };
34
35
36 namespace type {
37 enum object_type {
38 NIL = MSGPACK_OBJECT_NIL,
39 BOOLEAN = MSGPACK_OBJECT_BOOLEAN,
40 POSITIVE_INTEGER = MSGPACK_OBJECT_POSITIVE_INTEGER,
41 NEGATIVE_INTEGER = MSGPACK_OBJECT_NEGATIVE_INTEGER,
42 DOUBLE = MSGPACK_OBJECT_DOUBLE,
43 RAW = MSGPACK_OBJECT_RAW,
44 ARRAY = MSGPACK_OBJECT_ARRAY,
45 MAP = MSGPACK_OBJECT_MAP,
46 };
47 }
48
49
50 struct object;
51 struct object_kv;
52
53 struct object_array {
54 uint32_t size;
55 object* ptr;
56 };
57
58 struct object_map {
59 uint32_t size;
60 object_kv* ptr;
61 };
62
63 struct object_raw {
64 uint32_t size;
65 const char* ptr;
66 };
67
68 struct object {
69 union union_type {
70 bool boolean;
71 uint64_t u64;
72 int64_t i64;
73 double dec;
74 object_array array;
75 object_map map;
76 object_raw raw;
77 object_raw ref; // obsolete
78 };
79
80 type::object_type type;
81 union_type via;
82
is_nilmsgpack::object83 bool is_nil() const { return type == type::NIL; }
84
85 template <typename T>
86 T as() const;
87
88 template <typename T>
89 void convert(T* v) const;
90
91 object();
92
93 object(msgpack_object o);
94
95 template <typename T>
96 explicit object(const T& v);
97
98 template <typename T>
99 object(const T& v, zone* z);
100
101 template <typename T>
102 object& operator=(const T& v);
103
104 operator msgpack_object() const;
105
106 struct with_zone;
107
108 private:
109 struct implicit_type;
110
111 public:
112 implicit_type convert() const;
113 };
114
115 struct object_kv {
116 object key;
117 object val;
118 };
119
120 struct object::with_zone : object {
with_zonemsgpack::object::with_zone121 with_zone(msgpack::zone* zone) : zone(zone) { }
122 msgpack::zone* zone;
123 private:
124 with_zone();
125 };
126
127
128 bool operator==(const object x, const object y);
129 bool operator!=(const object x, const object y);
130
131 template <typename T>
132 bool operator==(const object x, const T& y);
133
134 template <typename T>
135 bool operator==(const T& y, const object x);
136
137 template <typename T>
138 bool operator!=(const object x, const T& y);
139
140 template <typename T>
141 bool operator!=(const T& y, const object x);
142
143 std::ostream& operator<< (std::ostream& s, const object o);
144
145
146 // serialize operator
147 template <typename Stream, typename T>
148 packer<Stream>& operator<< (packer<Stream>& o, const T& v);
149
150 // convert operator
151 template <typename T>
152 T& operator>> (object o, T& v);
153
154 // deconvert operator
155 template <typename T>
156 void operator<< (object::with_zone& o, const T& v);
157
158
159 struct object::implicit_type {
implicit_typemsgpack::object::implicit_type160 implicit_type(object o) : obj(o) { }
~implicit_typemsgpack::object::implicit_type161 ~implicit_type() { }
162
163 template <typename T>
operator Tmsgpack::object::implicit_type164 operator T() { return obj.as<T>(); }
165
166 private:
167 object obj;
168 };
169
170
171 // obsolete
172 template <typename Type>
173 class define : public Type {
174 public:
175 typedef Type msgpack_type;
176 typedef define<Type> define_type;
177
define()178 define() {}
define(const msgpack_type & v)179 define(const msgpack_type& v) : msgpack_type(v) {}
180
181 template <typename Packer>
msgpack_pack(Packer & o) const182 void msgpack_pack(Packer& o) const
183 {
184 o << static_cast<const msgpack_type&>(*this);
185 }
186
msgpack_unpack(object o)187 void msgpack_unpack(object o)
188 {
189 o >> static_cast<msgpack_type&>(*this);
190 }
191 };
192
193
194 template <typename Stream>
195 template <typename T>
pack(const T & v)196 inline packer<Stream>& packer<Stream>::pack(const T& v)
197 {
198 *this << v;
199 return *this;
200 }
201
operator >>(object o,object & v)202 inline object& operator>> (object o, object& v)
203 {
204 v = o;
205 return v;
206 }
207
208 template <typename T>
operator >>(object o,T & v)209 inline T& operator>> (object o, T& v)
210 {
211 v.msgpack_unpack(o.convert());
212 return v;
213 }
214
215 template <typename Stream, typename T>
operator <<(packer<Stream> & o,const T & v)216 inline packer<Stream>& operator<< (packer<Stream>& o, const T& v)
217 {
218 v.msgpack_pack(o);
219 return o;
220 }
221
222 template <typename T>
operator <<(object::with_zone & o,const T & v)223 void operator<< (object::with_zone& o, const T& v)
224 {
225 v.msgpack_object(static_cast<object*>(&o), o.zone);
226 }
227
228
operator ==(const object x,const object y)229 inline bool operator==(const object x, const object y)
230 {
231 return msgpack_object_equal(x, y);
232 }
233
234 template <typename T>
operator ==(const object x,const T & y)235 inline bool operator==(const object x, const T& y)
236 try {
237 return x == object(y);
238 } catch (msgpack::type_error&) {
239 return false;
240 }
241
operator !=(const object x,const object y)242 inline bool operator!=(const object x, const object y)
243 { return !(x == y); }
244
245 template <typename T>
operator ==(const T & y,const object x)246 inline bool operator==(const T& y, const object x)
247 { return x == y; }
248
249 template <typename T>
operator !=(const object x,const T & y)250 inline bool operator!=(const object x, const T& y)
251 { return !(x == y); }
252
253 template <typename T>
operator !=(const T & y,const object x)254 inline bool operator!=(const T& y, const object x)
255 { return x != y; }
256
257
convert() const258 inline object::implicit_type object::convert() const
259 {
260 return implicit_type(*this);
261 }
262
263 template <typename T>
convert(T * v) const264 inline void object::convert(T* v) const
265 {
266 *this >> *v;
267 }
268
269 template <typename T>
as() const270 inline T object::as() const
271 {
272 T v;
273 convert(&v);
274 return v;
275 }
276
277
object()278 inline object::object()
279 {
280 type = type::NIL;
281 }
282
283 template <typename T>
object(const T & v)284 inline object::object(const T& v)
285 {
286 *this << v;
287 }
288
289 template <typename T>
operator =(const T & v)290 inline object& object::operator=(const T& v)
291 {
292 *this = object(v);
293 return *this;
294 }
295
296 template <typename T>
object(const T & v,zone * z)297 object::object(const T& v, zone* z)
298 {
299 with_zone oz(z);
300 oz << v;
301 type = oz.type;
302 via = oz.via;
303 }
304
305
object(msgpack_object o)306 inline object::object(msgpack_object o)
307 {
308 // FIXME beter way?
309 ::memcpy(this, &o, sizeof(o));
310 }
311
operator <<(object & o,msgpack_object v)312 inline void operator<< (object& o, msgpack_object v)
313 {
314 // FIXME beter way?
315 ::memcpy(&o, &v, sizeof(v));
316 }
317
operator msgpack_object() const318 inline object::operator msgpack_object() const
319 {
320 // FIXME beter way?
321 msgpack_object obj;
322 ::memcpy(&obj, this, sizeof(obj));
323 return obj;
324 }
325
326
327 // obsolete
328 template <typename T>
convert(T & v,object o)329 inline void convert(T& v, object o)
330 {
331 o.convert(&v);
332 }
333
334 // obsolete
335 template <typename Stream, typename T>
pack(packer<Stream> & o,const T & v)336 inline void pack(packer<Stream>& o, const T& v)
337 {
338 o.pack(v);
339 }
340
341 // obsolete
342 template <typename Stream, typename T>
pack_copy(packer<Stream> & o,T v)343 inline void pack_copy(packer<Stream>& o, T v)
344 {
345 pack(o, v);
346 }
347
348
349 template <typename Stream>
operator <<(packer<Stream> & o,const object & v)350 packer<Stream>& operator<< (packer<Stream>& o, const object& v)
351 {
352 switch(v.type) {
353 case type::NIL:
354 o.pack_nil();
355 return o;
356
357 case type::BOOLEAN:
358 if(v.via.boolean) {
359 o.pack_true();
360 } else {
361 o.pack_false();
362 }
363 return o;
364
365 case type::POSITIVE_INTEGER:
366 o.pack_uint64(v.via.u64);
367 return o;
368
369 case type::NEGATIVE_INTEGER:
370 o.pack_int64(v.via.i64);
371 return o;
372
373 case type::DOUBLE:
374 o.pack_double(v.via.dec);
375 return o;
376
377 case type::RAW:
378 o.pack_raw(v.via.raw.size);
379 o.pack_raw_body(v.via.raw.ptr, v.via.raw.size);
380 return o;
381
382 case type::ARRAY:
383 o.pack_array(v.via.array.size);
384 for(object* p(v.via.array.ptr),
385 * const pend(v.via.array.ptr + v.via.array.size);
386 p < pend; ++p) {
387 o << *p;
388 }
389 return o;
390
391 case type::MAP:
392 o.pack_map(v.via.map.size);
393 for(object_kv* p(v.via.map.ptr),
394 * const pend(v.via.map.ptr + v.via.map.size);
395 p < pend; ++p) {
396 o << p->key;
397 o << p->val;
398 }
399 return o;
400
401 default:
402 throw type_error();
403 }
404 }
405
406
407 } // namespace msgpack
408
409 #include "msgpack/type.hpp"
410
411 #endif /* msgpack/object.hpp */
412
413