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