mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-21 23:56:55 +02:00
413 lines
7.2 KiB
C++
413 lines
7.2 KiB
C++
//
|
|
// MessagePack for C++ static resolution routine
|
|
//
|
|
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
|
//
|
|
// 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
|
|
//
|
|
// http://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/object.h"
|
|
#include "msgpack/pack.hpp"
|
|
#include "msgpack/zone.hpp"
|
|
#include <string.h>
|
|
#include <stdexcept>
|
|
#include <typeinfo>
|
|
#include <limits>
|
|
#include <ostream>
|
|
|
|
namespace msgpack {
|
|
|
|
|
|
class type_error : public std::bad_cast { };
|
|
|
|
|
|
namespace type {
|
|
enum object_type {
|
|
NIL = MSGPACK_OBJECT_NIL,
|
|
BOOLEAN = MSGPACK_OBJECT_BOOLEAN,
|
|
POSITIVE_INTEGER = MSGPACK_OBJECT_POSITIVE_INTEGER,
|
|
NEGATIVE_INTEGER = MSGPACK_OBJECT_NEGATIVE_INTEGER,
|
|
DOUBLE = MSGPACK_OBJECT_DOUBLE,
|
|
RAW = MSGPACK_OBJECT_RAW,
|
|
ARRAY = MSGPACK_OBJECT_ARRAY,
|
|
MAP = MSGPACK_OBJECT_MAP,
|
|
};
|
|
}
|
|
|
|
|
|
struct object;
|
|
struct object_kv;
|
|
|
|
struct object_array {
|
|
uint32_t size;
|
|
object* ptr;
|
|
};
|
|
|
|
struct object_map {
|
|
uint32_t size;
|
|
object_kv* ptr;
|
|
};
|
|
|
|
struct object_raw {
|
|
uint32_t size;
|
|
const char* ptr;
|
|
};
|
|
|
|
struct object {
|
|
union union_type {
|
|
bool boolean;
|
|
uint64_t u64;
|
|
int64_t i64;
|
|
double dec;
|
|
object_array array;
|
|
object_map map;
|
|
object_raw raw;
|
|
object_raw ref; // obsolete
|
|
};
|
|
|
|
type::object_type type;
|
|
union_type via;
|
|
|
|
bool is_nil() const { return type == type::NIL; }
|
|
|
|
template <typename T>
|
|
T as() const;
|
|
|
|
template <typename T>
|
|
void convert(T* v) const;
|
|
|
|
object();
|
|
|
|
object(msgpack_object o);
|
|
|
|
template <typename T>
|
|
explicit object(const T& v);
|
|
|
|
template <typename T>
|
|
object(const T& v, zone* z);
|
|
|
|
template <typename T>
|
|
object& operator=(const T& v);
|
|
|
|
operator msgpack_object() const;
|
|
|
|
struct with_zone;
|
|
|
|
private:
|
|
struct implicit_type;
|
|
|
|
public:
|
|
implicit_type convert() const;
|
|
};
|
|
|
|
struct object_kv {
|
|
object key;
|
|
object val;
|
|
};
|
|
|
|
struct object::with_zone : object {
|
|
with_zone(msgpack::zone* zone) : zone(zone) { }
|
|
msgpack::zone* zone;
|
|
private:
|
|
with_zone();
|
|
};
|
|
|
|
|
|
bool operator==(const object x, const object y);
|
|
bool operator!=(const object x, const object y);
|
|
|
|
template <typename T>
|
|
bool operator==(const object x, const T& y);
|
|
|
|
template <typename T>
|
|
bool operator==(const T& y, const object x);
|
|
|
|
template <typename T>
|
|
bool operator!=(const object x, const T& y);
|
|
|
|
template <typename T>
|
|
bool operator!=(const T& y, const object x);
|
|
|
|
std::ostream& operator<< (std::ostream& s, const object o);
|
|
|
|
|
|
// serialize operator
|
|
template <typename Stream, typename T>
|
|
packer<Stream>& operator<< (packer<Stream>& o, const T& v);
|
|
|
|
// convert operator
|
|
template <typename T>
|
|
T& operator>> (object o, T& v);
|
|
|
|
// deconvert operator
|
|
template <typename T>
|
|
void operator<< (object::with_zone& o, const T& v);
|
|
|
|
|
|
struct object::implicit_type {
|
|
implicit_type(object o) : obj(o) { }
|
|
~implicit_type() { }
|
|
|
|
template <typename T>
|
|
operator T() { return obj.as<T>(); }
|
|
|
|
private:
|
|
object obj;
|
|
};
|
|
|
|
|
|
// 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
|
|
{
|
|
o << static_cast<const msgpack_type&>(*this);
|
|
}
|
|
|
|
void msgpack_unpack(object o)
|
|
{
|
|
o >> static_cast<msgpack_type&>(*this);
|
|
}
|
|
};
|
|
|
|
|
|
template <typename Stream>
|
|
template <typename T>
|
|
inline packer<Stream>& packer<Stream>::pack(const T& v)
|
|
{
|
|
*this << v;
|
|
return *this;
|
|
}
|
|
|
|
inline object& operator>> (object o, object& v)
|
|
{
|
|
v = o;
|
|
return v;
|
|
}
|
|
|
|
template <typename T>
|
|
inline T& operator>> (object o, T& v)
|
|
{
|
|
v.msgpack_unpack(o.convert());
|
|
return v;
|
|
}
|
|
|
|
template <typename Stream, typename T>
|
|
inline packer<Stream>& operator<< (packer<Stream>& o, const T& v)
|
|
{
|
|
v.msgpack_pack(o);
|
|
return o;
|
|
}
|
|
|
|
template <typename T>
|
|
void operator<< (object::with_zone& o, const T& v)
|
|
{
|
|
v.msgpack_object(static_cast<object*>(&o), o.zone);
|
|
}
|
|
|
|
|
|
inline bool operator==(const object x, const object y)
|
|
{
|
|
return msgpack_object_equal(x, y);
|
|
}
|
|
|
|
template <typename T>
|
|
inline bool operator==(const object x, const T& y)
|
|
try {
|
|
return x == object(y);
|
|
} catch (msgpack::type_error&) {
|
|
return false;
|
|
}
|
|
|
|
inline bool operator!=(const object x, const object y)
|
|
{ return !(x == y); }
|
|
|
|
template <typename T>
|
|
inline bool operator==(const T& y, const object x)
|
|
{ return x == y; }
|
|
|
|
template <typename T>
|
|
inline bool operator!=(const object x, const T& y)
|
|
{ return !(x == y); }
|
|
|
|
template <typename T>
|
|
inline bool operator!=(const T& y, const object x)
|
|
{ return x != y; }
|
|
|
|
|
|
inline object::implicit_type object::convert() const
|
|
{
|
|
return implicit_type(*this);
|
|
}
|
|
|
|
template <typename T>
|
|
inline void object::convert(T* v) const
|
|
{
|
|
*this >> *v;
|
|
}
|
|
|
|
template <typename T>
|
|
inline T object::as() const
|
|
{
|
|
T v;
|
|
convert(&v);
|
|
return v;
|
|
}
|
|
|
|
|
|
inline object::object()
|
|
{
|
|
type = type::NIL;
|
|
}
|
|
|
|
template <typename T>
|
|
inline object::object(const T& v)
|
|
{
|
|
*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, zone* z)
|
|
{
|
|
with_zone oz(z);
|
|
oz << v;
|
|
type = oz.type;
|
|
via = oz.via;
|
|
}
|
|
|
|
|
|
inline object::object(msgpack_object o)
|
|
{
|
|
// FIXME beter way?
|
|
::memcpy(this, &o, sizeof(o));
|
|
}
|
|
|
|
inline void operator<< (object& o, msgpack_object v)
|
|
{
|
|
// FIXME beter way?
|
|
::memcpy(&o, &v, sizeof(v));
|
|
}
|
|
|
|
inline object::operator msgpack_object() const
|
|
{
|
|
// FIXME beter way?
|
|
msgpack_object obj;
|
|
::memcpy(&obj, this, sizeof(obj));
|
|
return obj;
|
|
}
|
|
|
|
|
|
// obsolete
|
|
template <typename T>
|
|
inline void convert(T& v, object o)
|
|
{
|
|
o.convert(&v);
|
|
}
|
|
|
|
// obsolete
|
|
template <typename Stream, typename T>
|
|
inline void pack(packer<Stream>& o, const T& v)
|
|
{
|
|
o.pack(v);
|
|
}
|
|
|
|
// obsolete
|
|
template <typename Stream, typename T>
|
|
inline void pack_copy(packer<Stream>& o, T v)
|
|
{
|
|
pack(o, v);
|
|
}
|
|
|
|
|
|
template <typename Stream>
|
|
packer<Stream>& operator<< (packer<Stream>& o, const object& v)
|
|
{
|
|
switch(v.type) {
|
|
case type::NIL:
|
|
o.pack_nil();
|
|
return o;
|
|
|
|
case type::BOOLEAN:
|
|
if(v.via.boolean) {
|
|
o.pack_true();
|
|
} else {
|
|
o.pack_false();
|
|
}
|
|
return o;
|
|
|
|
case type::POSITIVE_INTEGER:
|
|
o.pack_uint64(v.via.u64);
|
|
return o;
|
|
|
|
case type::NEGATIVE_INTEGER:
|
|
o.pack_int64(v.via.i64);
|
|
return o;
|
|
|
|
case type::DOUBLE:
|
|
o.pack_double(v.via.dec);
|
|
return o;
|
|
|
|
case type::RAW:
|
|
o.pack_raw(v.via.raw.size);
|
|
o.pack_raw_body(v.via.raw.ptr, v.via.raw.size);
|
|
return o;
|
|
|
|
case type::ARRAY:
|
|
o.pack_array(v.via.array.size);
|
|
for(object* p(v.via.array.ptr),
|
|
* const pend(v.via.array.ptr + v.via.array.size);
|
|
p < pend; ++p) {
|
|
o << *p;
|
|
}
|
|
return o;
|
|
|
|
case type::MAP:
|
|
o.pack_map(v.via.map.size);
|
|
for(object_kv* p(v.via.map.ptr),
|
|
* const pend(v.via.map.ptr + v.via.map.size);
|
|
p < pend; ++p) {
|
|
o << p->key;
|
|
o << p->val;
|
|
}
|
|
return o;
|
|
|
|
default:
|
|
throw type_error();
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace msgpack
|
|
|
|
#include "msgpack/type.hpp"
|
|
|
|
#endif /* msgpack/object.hpp */
|
|
|