// // MessagePack for C++ static resolution routine // // Copyright (C) 2008-2014 FURUHASHI Sadayuki and KONDO Takatoshi // // Licensed under the Apache License, Version 2.0 (the “License”); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an “AS IS” BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ifndef MSGPACK_OBJECT_HPP define MSGPACK_OBJECT_HPP
include “msgpack/versioning.hpp” include “msgpack/pack.hpp” include “msgpack/zone.hpp” include “msgpack/adaptor/adaptor_base.hpp”
include <cstring> include <stdexcept> include <typeinfo> include <limits> include <ostream> include <typeinfo>
namespace msgpack {
/// @cond MSGPACK_API_VERSION_NAMESPACE(v1) { /// @endcond
struct object::implicit_type {
implicit_type(object const& o) : obj(o) { } ~implicit_type() { } template <typename T> operator T() { return obj.as<T>(); }
private:
msgpack::object const& obj;
};
namespace detail { template <typename Stream, typename T> struct packer_serializer {
static msgpack::packer<Stream>& pack(msgpack::packer<Stream>& o, const T& v) { v.msgpack_pack(o); return o; }
}; } // namespace detail
// Adaptor functors' member functions definitions. template <typename T> inline msgpack::object const& msgpack::adaptor::convert<T>::operator()(msgpack::object const& o, T& v) const {
v.msgpack_unpack(o.convert()); return o;
}
template <typename T> template <typename Stream> inline msgpack::packer<Stream>& msgpack::adaptor::pack<T>::operator()(msgpack::packer<Stream>& o, T const& v) const {
return detail::packer_serializer<Stream, T>::pack(o, v);
}
template <typename T> inline void msgpack::adaptor::object_with_zone<T>::operator()(msgpack::object::with_zone& o, T const& v) const {
v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
}
// Adaptor functor specialization to object namespace adaptor {
template <> struct convert<msgpack::object> {
msgpack::object const& operator()(msgpack::object const& o, msgpack::object& v) const { v = o; return o; }
};
template <> struct pack<msgpack::object> {
template <typename Stream> msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, msgpack::object const& v) const { switch(v.type) { case msgpack::type::NIL: o.pack_nil(); return o; case msgpack::type::BOOLEAN: if(v.via.boolean) { o.pack_true(); } else { o.pack_false(); } return o; case msgpack::type::POSITIVE_INTEGER: o.pack_uint64(v.via.u64); return o; case msgpack::type::NEGATIVE_INTEGER: o.pack_int64(v.via.i64); return o; case msgpack::type::FLOAT: o.pack_double(v.via.f64); return o; case msgpack::type::STR: o.pack_str(v.via.str.size); o.pack_str_body(v.via.str.ptr, v.via.str.size); return o; case msgpack::type::BIN: o.pack_bin(v.via.bin.size); o.pack_bin_body(v.via.bin.ptr, v.via.bin.size); return o; case msgpack::type::EXT: o.pack_ext(v.via.ext.size, v.via.ext.type()); o.pack_ext_body(v.via.ext.data(), v.via.ext.size); return o; case msgpack::type::ARRAY: o.pack_array(v.via.array.size); for(msgpack::object* p(v.via.array.ptr), * const pend(v.via.array.ptr + v.via.array.size); p < pend; ++p) { msgpack::operator<<(o, *p); } return o; case msgpack::type::MAP: o.pack_map(v.via.map.size); for(msgpack::object_kv* p(v.via.map.ptr), * const pend(v.via.map.ptr + v.via.map.size); p < pend; ++p) { msgpack::operator<<(o, p->key); msgpack::operator<<(o, p->val); } return o; default: throw msgpack::type_error(); } }
};
template <> struct object_with_zone<msgpack::object> {
void operator()(msgpack::object::with_zone& o, msgpack::object const& v) const { o.type = v.type; switch(v.type) { case msgpack::type::NIL: case msgpack::type::BOOLEAN: case msgpack::type::POSITIVE_INTEGER: case msgpack::type::NEGATIVE_INTEGER: case msgpack::type::FLOAT: std::memcpy(&o.via, &v.via, sizeof(v.via)); return; case msgpack::type::STR: { char* ptr = static_cast<char*>(o.zone.allocate_align(v.via.str.size)); o.via.str.ptr = ptr; o.via.str.size = v.via.str.size; std::memcpy(ptr, v.via.str.ptr, v.via.str.size); return; } case msgpack::type::BIN: { char* ptr = static_cast<char*>(o.zone.allocate_align(v.via.bin.size)); o.via.bin.ptr = ptr; o.via.bin.size = v.via.bin.size; std::memcpy(ptr, v.via.bin.ptr, v.via.bin.size); return; } case msgpack::type::EXT: { char* ptr = static_cast<char*>(o.zone.allocate_align(v.via.ext.size + 1)); o.via.ext.ptr = ptr; o.via.ext.size = v.via.ext.size; std::memcpy(ptr, v.via.ext.ptr, v.via.ext.size + 1); return; } case msgpack::type::ARRAY: o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object) * v.via.array.size)); o.via.array.size = v.via.array.size; for (msgpack::object * po(o.via.array.ptr), * pv(v.via.array.ptr), * const pvend(v.via.array.ptr + v.via.array.size); pv < pvend; ++po, ++pv) { new (po) msgpack::object(*pv, o.zone); } return; case msgpack::type::MAP: o.via.map.ptr = (msgpack::object_kv*)o.zone.allocate_align(sizeof(msgpack::object_kv) * v.via.map.size); o.via.map.size = v.via.map.size; for(msgpack::object_kv * po(o.via.map.ptr), * pv(v.via.map.ptr), * const pvend(v.via.map.ptr + v.via.map.size); pv < pvend; ++po, ++pv) { msgpack::object_kv* kv = new (po) msgpack::object_kv; new (&kv->key) msgpack::object(pv->key, o.zone); new (&kv->val) msgpack::object(pv->val, o.zone); } return; default: throw msgpack::type_error(); } }
};
// Adaptor functor specialization to object::with_zone
template <> struct object_with_zone<msgpack::object::with_zone> {
void operator()( msgpack::object::with_zone& o, msgpack::object::with_zone const& v) const { o << static_cast<msgpack::object const&>(v); }
};
} // namespace adaptor
// obsolete template <typename Type> class define : public Type { public:
typedef Type msgpack_type; typedef define<Type> define_type; define() {} define(const msgpack_type& v) : msgpack_type(v) {} template <typename Packer> void msgpack_pack(Packer& o) const { msgpack::operator<<(o, static_cast<const msgpack_type&>(*this)); } void msgpack_unpack(object const& o) { msgpack::operator>>(o, static_cast<msgpack_type&>(*this)); }
};
// deconvert operator
template <typename Stream> template <typename T> inline msgpack::packer<Stream>& packer<Stream>::pack(const T& v) {
msgpack::operator<<(*this, v); return *this;
}
inline bool operator==(const msgpack::object& x, const msgpack::object& y) {
if(x.type != y.type) { return false; } switch(x.type) { case msgpack::type::NIL: return true; case msgpack::type::BOOLEAN: return x.via.boolean == y.via.boolean; case msgpack::type::POSITIVE_INTEGER: return x.via.u64 == y.via.u64; case msgpack::type::NEGATIVE_INTEGER: return x.via.i64 == y.via.i64; case msgpack::type::FLOAT: return x.via.f64 == y.via.f64; case msgpack::type::STR: return x.via.str.size == y.via.str.size && std::memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0; case msgpack::type::BIN: return x.via.bin.size == y.via.bin.size && std::memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0; case msgpack::type::EXT: return x.via.ext.size == y.via.ext.size && std::memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0; case msgpack::type::ARRAY: if(x.via.array.size != y.via.array.size) { return false; } else if(x.via.array.size == 0) { return true; } else { msgpack::object* px = x.via.array.ptr; msgpack::object* const pxend = x.via.array.ptr + x.via.array.size; msgpack::object* py = y.via.array.ptr; do { if(!(*px == *py)) { return false; } ++px; ++py; } while(px < pxend); return true; } case msgpack::type::MAP: if(x.via.map.size != y.via.map.size) { return false; } else if(x.via.map.size == 0) { return true; } else { msgpack::object_kv* px = x.via.map.ptr; msgpack::object_kv* const pxend = x.via.map.ptr + x.via.map.size; msgpack::object_kv* py = y.via.map.ptr; do { if(!(px->key == py->key) || !(px->val == py->val)) { return false; } ++px; ++py; } while(px < pxend); return true; } default: return false; }
}
template <typename T> inline bool operator==(const msgpack::object& x, const T& y) try {
return x == msgpack::object(y);
} catch (msgpack::type_error&) {
return false;
}
inline bool operator!=(const msgpack::object& x, const msgpack::object& y) { return !(x == y); }
template <typename T> inline bool operator==(const T& y, const msgpack::object x) { return x == y; }
template <typename T> inline bool operator!=(const msgpack::object& x, const T& y) { return !(x == y); }
template <typename T> inline bool operator!=(const T& y, const msgpack::object& x) { return x != y; }
inline msgpack::object::implicit_type object::convert() const {
return msgpack::object::implicit_type(*this);
}
template <typename T> inline void object::convert(T& v) const {
msgpack::operator>>(*this, v);
}
template <typename T> inline void object::convert(T* v) const {
convert(*v);
}
template <typename T> inline T object::as() const {
T v; convert(v); return v;
}
inline object::object() {
type = msgpack::type::NIL;
}
template <typename T> inline object::object(const T& v) {
msgpack::operator<<(*this, v);
}
template <typename T> inline object& object::operator=(const T& v) {
*this = object(v); return *this;
}
template <typename T> object::object(const T& v, msgpack::zone& z) {
with_zone oz(z); msgpack::operator<<(oz, v); type = oz.type; via = oz.via;
}
template <typename T> object::object(const T& v, msgpack::zone* z) {
with_zone oz(*z); msgpack::operator<<(oz, v); type = oz.type; via = oz.via;
}
inline object::object(const msgpack_object& o) {
// FIXME beter way? std::memcpy(this, &o, sizeof(o));
}
inline void operator<< (msgpack::object& o, const msgpack_object& v) {
// FIXME beter way? std::memcpy(&o, &v, sizeof(v));
}
inline object::operator msgpack_object() const {
// FIXME beter way? msgpack_object obj; std::memcpy(&obj, this, sizeof(obj)); return obj;
}
// obsolete template <typename T> inline void convert(T& v, msgpack::object const& o) {
o.convert(v);
}
// obsolete template <typename Stream, typename T> inline void pack(msgpack::packer<Stream>& o, const T& v) {
o.pack(v);
}
// obsolete template <typename Stream, typename T> inline void pack_copy(msgpack::packer<Stream>& o, T v) {
pack(o, v);
}
template <typename Stream> inline msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const msgpack::object& v) {
switch(v.type) { case msgpack::type::NIL: o.pack_nil(); return o; case msgpack::type::BOOLEAN: if(v.via.boolean) { o.pack_true(); } else { o.pack_false(); } return o; case msgpack::type::POSITIVE_INTEGER: o.pack_uint64(v.via.u64); return o; case msgpack::type::NEGATIVE_INTEGER: o.pack_int64(v.via.i64); return o; case msgpack::type::FLOAT: o.pack_double(v.via.f64); return o; case msgpack::type::STR: o.pack_str(v.via.str.size); o.pack_str_body(v.via.str.ptr, v.via.str.size); return o; case msgpack::type::BIN: o.pack_bin(v.via.bin.size); o.pack_bin_body(v.via.bin.ptr, v.via.bin.size); return o; case msgpack::type::EXT: o.pack_ext(v.via.ext.size, v.via.ext.type()); o.pack_ext_body(v.via.ext.data(), v.via.ext.size); return o; case msgpack::type::ARRAY: o.pack_array(v.via.array.size); for(msgpack::object* p(v.via.array.ptr), * const pend(v.via.array.ptr + v.via.array.size); p < pend; ++p) { msgpack::operator<<(o, *p); } return o; case msgpack::type::MAP: o.pack_map(v.via.map.size); for(msgpack::object_kv* p(v.via.map.ptr), * const pend(v.via.map.ptr + v.via.map.size); p < pend; ++p) { msgpack::operator<<(o, p->key); msgpack::operator<<(o, p->val); } return o; default: throw msgpack::type_error(); }
}
template <typename Stream> msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const msgpack::object::with_zone& v) {
return o << static_cast<msgpack::object>(v);
}
inline std::ostream& operator<< (std::ostream& s, const msgpack::object& o) {
switch(o.type) { case msgpack::type::NIL: s << "nil"; break; case msgpack::type::BOOLEAN: s << (o.via.boolean ? "true" : "false"); break; case msgpack::type::POSITIVE_INTEGER: s << o.via.u64; break; case msgpack::type::NEGATIVE_INTEGER: s << o.via.i64; break; case msgpack::type::FLOAT: s << o.via.f64; break; case msgpack::type::STR: (s << '"').write(o.via.str.ptr, o.via.str.size) << '"'; break; case msgpack::type::BIN: (s << '"').write(o.via.bin.ptr, o.via.bin.size) << '"'; break; case msgpack::type::EXT: s << "EXT"; break; case msgpack::type::ARRAY: s << "["; if(o.via.array.size != 0) { msgpack::object* p(o.via.array.ptr); s << *p; ++p; for(msgpack::object* const pend(o.via.array.ptr + o.via.array.size); p < pend; ++p) { s << ", " << *p; } } s << "]"; break; case msgpack::type::MAP: s << "{"; if(o.via.map.size != 0) { msgpack::object_kv* p(o.via.map.ptr); s << p->key << "=>" << p->val; ++p; for(msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); p < pend; ++p) { s << ", " << p->key << "=>" << p->val; } } s << "}"; break; default: // FIXME s << "#<UNKNOWN " << static_cast<uint16_t>(o.type) << ">"; } return s;
}
/// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond
} // namespace msgpack
include “msgpack/type.hpp”
endif /* msgpack/object.hpp */