mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 13:02:13 +01:00
316 lines
5.6 KiB
C++
316 lines
5.6 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/pack.hpp"
|
|
#include <stdint.h>
|
|
#include <stdexcept>
|
|
#include <typeinfo>
|
|
#include <limits>
|
|
#include <ostream>
|
|
|
|
namespace msgpack {
|
|
|
|
|
|
class type_error : public std::bad_cast { };
|
|
|
|
|
|
namespace type {
|
|
enum object_type {
|
|
NIL = 0x01,
|
|
BOOLEAN = 0x02,
|
|
POSITIVE_INTEGER = 0x03,
|
|
NEGATIVE_INTEGER = 0x04,
|
|
DOUBLE = 0x05,
|
|
RAW = 0x06,
|
|
ARRAY = 0x07,
|
|
MAP = 0x08,
|
|
};
|
|
}
|
|
|
|
|
|
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;
|
|
};
|
|
|
|
type::object_type type;
|
|
union_type via;
|
|
|
|
bool is_nil() { return type == type::NIL; }
|
|
|
|
template <typename T>
|
|
T as();
|
|
|
|
template <typename T>
|
|
void convert(T* v);
|
|
|
|
private:
|
|
struct implicit_type;
|
|
|
|
public:
|
|
implicit_type convert();
|
|
};
|
|
|
|
struct object_kv {
|
|
object key;
|
|
object val;
|
|
};
|
|
|
|
bool operator==(const object x, const object y);
|
|
bool operator!=(const object x, const object y);
|
|
|
|
std::ostream& operator<< (std::ostream& s, const object o);
|
|
|
|
|
|
template <typename Stream, typename T>
|
|
inline void pack(Stream& s, const T& v);
|
|
|
|
template <typename Stream, typename T>
|
|
packer<Stream>& operator<< (packer<Stream>& o, const T& v);
|
|
|
|
template <typename T>
|
|
T& operator>> (object o, 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;
|
|
};
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
template <typename Stream, typename T>
|
|
inline void pack(Stream& s, const T& v)
|
|
{
|
|
packer<Stream>(s).pack(v);
|
|
}
|
|
|
|
template <typename Stream, typename T>
|
|
inline void pack_copy(packer<Stream>& o, T v)
|
|
{
|
|
pack(o, v);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
inline bool operator!=(const object x, const object y)
|
|
{ return !(x == y); }
|
|
|
|
|
|
inline object::implicit_type object::convert()
|
|
{
|
|
return implicit_type(*this);
|
|
}
|
|
|
|
template <typename T>
|
|
inline T object::as()
|
|
{
|
|
T v;
|
|
convert(&v);
|
|
return v;
|
|
}
|
|
|
|
template <typename T>
|
|
inline void object::convert(T* v)
|
|
{
|
|
*this >> *v;
|
|
}
|
|
|
|
|
|
// 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);
|
|
}
|
|
|
|
|
|
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:
|
|
if(v.via.u64 <= (uint64_t)std::numeric_limits<uint16_t>::max()) {
|
|
if(v.via.u64 <= (uint16_t)std::numeric_limits<uint8_t>::max()) {
|
|
o.pack_uint8(v.via.u64);
|
|
} else {
|
|
o.pack_uint16(v.via.u64);
|
|
}
|
|
} else {
|
|
if(v.via.u64 <= (uint64_t)std::numeric_limits<uint32_t>::max()) {
|
|
o.pack_uint32(v.via.u64);
|
|
} else {
|
|
o.pack_uint64(v.via.u64);
|
|
}
|
|
}
|
|
return o;
|
|
|
|
case type::NEGATIVE_INTEGER:
|
|
if(v.via.i64 >= (int64_t)std::numeric_limits<int16_t>::min()) {
|
|
if(v.via.i64 >= (int64_t)std::numeric_limits<int8_t>::min()) {
|
|
o.pack_int8(v.via.i64);
|
|
} else {
|
|
o.pack_int16(v.via.i64);
|
|
}
|
|
} else {
|
|
if(v.via.i64 >= (int64_t)std::numeric_limits<int32_t>::min()) {
|
|
o.pack_int64(v.via.i64);
|
|
} else {
|
|
o.pack_int64(v.via.i64);
|
|
}
|
|
}
|
|
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) {
|
|
*p >> o;
|
|
}
|
|
return o;
|
|
// FIXME loop optimiziation
|
|
|
|
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) {
|
|
p->key >> o;
|
|
p->val >> o;
|
|
}
|
|
return o;
|
|
// FIXME loop optimiziation
|
|
|
|
default:
|
|
throw type_error();
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace msgpack
|
|
|
|
#include "msgpack/type.hpp"
|
|
|
|
#endif /* msgpack/object.hpp */
|
|
|