mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-14 18:10:30 +01:00
lang/c/msgpack: reimplemented C++ binding with template-based static resolution design
git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@67 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
This commit is contained in:
parent
1222466a1c
commit
9923cf4daf
@ -89,14 +89,14 @@ static inline void* template_callback_false(msgpack_unpack_t* x)
|
||||
static inline void* template_callback_array(msgpack_unpack_t* x, unsigned int n)
|
||||
{ return x->callback.unpack_array(x->data, n); }
|
||||
|
||||
static inline void template_callback_array_item(msgpack_unpack_t* x, void* c, void* o)
|
||||
{ x->callback.unpack_array_item(x->data, c, o); }
|
||||
static inline void template_callback_array_item(msgpack_unpack_t* x, void** c, void* o)
|
||||
{ x->callback.unpack_array_item(x->data, *c, o); }
|
||||
|
||||
static inline void* template_callback_map(msgpack_unpack_t* x, unsigned int n)
|
||||
{ return x->callback.unpack_map(x->data, n); }
|
||||
|
||||
static inline void template_callback_map_item(msgpack_unpack_t* x, void* c, void* k, void* v)
|
||||
{ x->callback.unpack_map_item(x->data, c, k, v); }
|
||||
static inline void template_callback_map_item(msgpack_unpack_t* x, void** c, void* k, void* v)
|
||||
{ x->callback.unpack_map_item(x->data, *c, k, v); }
|
||||
|
||||
static inline void* template_callback_raw(msgpack_unpack_t* x, const char* b, const char* p, unsigned int l)
|
||||
{ return x->callback.unpack_raw(x->data, b, p, l); }
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT(msgpack/unpack/inline_impl.h)
|
||||
AC_INIT(msgpack/unpack_template.h)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.1.0)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
|
@ -10,20 +10,27 @@ nobase_include_HEADERS = \
|
||||
msgpack/pack.hpp \
|
||||
msgpack/unpack.hpp \
|
||||
msgpack/object.hpp \
|
||||
msgpack/zone.hpp
|
||||
msgpack/zone.hpp \
|
||||
msgpack/type.hpp \
|
||||
msgpack/type/array.hpp \
|
||||
msgpack/type/boolean.hpp \
|
||||
msgpack/type/integer.hpp \
|
||||
msgpack/type/map.hpp \
|
||||
msgpack/type/nil.hpp \
|
||||
msgpack/type/tuple.hpp
|
||||
|
||||
noinst_HEADERS = \
|
||||
msgpack/zone.hpp.erb
|
||||
msgpack/type/tuple.hpp.erb
|
||||
|
||||
# FIXME
|
||||
object.lo: msgpack/zone.hpp
|
||||
unpack.lo: msgpack/zone.hpp
|
||||
zone.lo: msgpack/zone.hpp
|
||||
object.lo: msgpack/type/tuple.hpp
|
||||
unpack.lo: msgpack/type/tuple.hpp
|
||||
zone.lo: msgpack/type/tuple.hpp
|
||||
|
||||
msgpack/zone.hpp: msgpack/zone.hpp.erb
|
||||
msgpack/type/tuple.hpp: msgpack/type/tuple.hpp.erb
|
||||
erb $< > $@
|
||||
|
||||
MOSTLYCLEANFILES = zone.hpp
|
||||
MOSTLYCLEANFILES = msgpack/type/tuple.hpp
|
||||
|
||||
libmsgpack_la_LDFLAGS = -version-info 0:0:0
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
//static const unsigned int TASK_INT_NUM = 1<<24;
|
||||
//static const unsigned int TASK_STR_LEN = 1<<15;
|
||||
static const unsigned int TASK_INT_NUM = 1<<22;
|
||||
static const unsigned int TASK_STR_LEN = 1<<13;
|
||||
static const unsigned int TASK_INT_NUM = 1<<24;
|
||||
static const unsigned int TASK_STR_LEN = 1<<15;
|
||||
//static const unsigned int TASK_INT_NUM = 1<<22;
|
||||
//static const unsigned int TASK_STR_LEN = 1<<13;
|
||||
static const char* TASK_STR_PTR;
|
||||
|
||||
|
||||
@ -104,6 +104,7 @@ void bench_msgpack_int()
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "unpack integer" << std::endl;
|
||||
|
||||
@ -116,6 +117,7 @@ void bench_msgpack_int()
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
/*
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "dynamic pack integer" << std::endl;
|
||||
|
||||
@ -124,6 +126,7 @@ void bench_msgpack_int()
|
||||
timer.reset();
|
||||
msgpack::pack(buf, obj);
|
||||
timer.show_stat(buf.size());
|
||||
*/
|
||||
}
|
||||
|
||||
void bench_msgpack_str()
|
||||
@ -144,6 +147,7 @@ void bench_msgpack_str()
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "unpack string" << std::endl;
|
||||
|
||||
@ -156,6 +160,8 @@ void bench_msgpack_str()
|
||||
}
|
||||
timer.show_stat(buf.size());
|
||||
|
||||
|
||||
/*
|
||||
std::cout << "----" << std::endl;
|
||||
std::cout << "dynamic pack string" << std::endl;
|
||||
|
||||
@ -164,6 +170,7 @@ void bench_msgpack_str()
|
||||
timer.reset();
|
||||
msgpack::pack(buf, obj);
|
||||
timer.show_stat(buf.size());
|
||||
*/
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -5,5 +5,5 @@ LDFLAGS +=
|
||||
all: bench
|
||||
|
||||
bench: bench.o unpack.o zone.o object.o pack.hpp unpack.hpp zone.hpp object.hpp
|
||||
$(CXX) bench.o unpack.o zone.o object.o $(CFLAGS) $(LDFLAGS) -o $@
|
||||
$(CXX) bench.o unpack.o zone.o object.o $(CXXFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
|
497
cpp/object.cpp
497
cpp/object.cpp
@ -16,417 +16,128 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/pack.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T, typename X, bool TSigned, bool XSigned>
|
||||
struct numeric_overflow_signed_impl;
|
||||
std::ostream& operator<< (std::ostream& s, const object o)
|
||||
{
|
||||
switch(o.type) {
|
||||
case type::NIL:
|
||||
s << "nil";
|
||||
break;
|
||||
|
||||
template <typename T, typename X>
|
||||
struct numeric_overflow_signed_impl<T, X, true, true> {
|
||||
static int test(X x) {
|
||||
if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) ||
|
||||
(!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) {
|
||||
if( sizeof(T) < sizeof(X) ) {
|
||||
if( static_cast<X>( std::numeric_limits<T>::max()) < x ) { return 1; }
|
||||
if( static_cast<X>(-std::numeric_limits<T>::max()) > x ) { return -1; }
|
||||
case type::BOOLEAN:
|
||||
s << (o.via.boolean ? "true" : "false");
|
||||
break;
|
||||
|
||||
case type::POSITIVE_INTEGER:
|
||||
s << o.via.u64;
|
||||
break;
|
||||
|
||||
case type::NEGATIVE_INTEGER:
|
||||
s << o.via.i64;
|
||||
break;
|
||||
|
||||
case type::RAW:
|
||||
(s << '"').write(o.via.ref.ptr, o.via.ref.size) << '"';
|
||||
break;
|
||||
|
||||
case type::ARRAY:
|
||||
s << "[";
|
||||
if(o.via.container.size != 0) {
|
||||
object* p(o.via.container.ptr);
|
||||
s << *p;
|
||||
++p;
|
||||
for(object* const pend(o.via.container.ptr + o.via.container.size);
|
||||
p < pend; ++p) {
|
||||
s << ", " << *p;
|
||||
}
|
||||
} else if(std::numeric_limits<T>::is_integer) {
|
||||
if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; }
|
||||
if( static_cast<X>(-std::numeric_limits<T>::max()) > x) { return -1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
s << "]";
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
template <typename T, typename X>
|
||||
struct numeric_overflow_signed_impl<T, X, true, false> {
|
||||
static int test(X x) {
|
||||
if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) ||
|
||||
(!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) {
|
||||
if( sizeof(T) <= sizeof(X) ) {
|
||||
if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; }
|
||||
case type::MAP:
|
||||
s << "{";
|
||||
if(o.via.container.size != 0) {
|
||||
object* p(o.via.container.ptr);
|
||||
object* const pend(o.via.container.ptr + o.via.container.size*2);
|
||||
s << *p; ++p;
|
||||
s << "=>";
|
||||
s << *p; ++p;
|
||||
while(p < pend) {
|
||||
s << ", ";
|
||||
s << *p; ++p;
|
||||
s << "=>";
|
||||
s << *p; ++p;
|
||||
}
|
||||
} else if(std::numeric_limits<T>::is_integer) {
|
||||
if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
s << "}";
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
template <typename T, typename X>
|
||||
struct numeric_overflow_signed_impl<T, X, false, true> {
|
||||
static int test(X x) {
|
||||
if( static_cast<X>(0) > x ) { return -1; }
|
||||
if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) ||
|
||||
(!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) {
|
||||
if( sizeof(T) < sizeof(X) ) {
|
||||
if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; }
|
||||
}
|
||||
} else if(std::numeric_limits<T>::is_integer) {
|
||||
if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; }
|
||||
default:
|
||||
// FIXME
|
||||
s << "#<UNKNOWN " << (uint16_t)o.type << ">" << std::endl;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const object x, const object y)
|
||||
{
|
||||
if(x.type != y.type) { return false; }
|
||||
|
||||
switch(x.type) {
|
||||
case type::NIL:
|
||||
return true;
|
||||
|
||||
case type::BOOLEAN:
|
||||
return x.via.boolean == y.via.boolean;
|
||||
|
||||
case type::POSITIVE_INTEGER:
|
||||
return x.via.u64 == y.via.u64;
|
||||
|
||||
case type::NEGATIVE_INTEGER:
|
||||
return x.via.i64 == y.via.i64;
|
||||
|
||||
case type::RAW:
|
||||
return x.via.ref.size == y.via.ref.size &&
|
||||
memcmp(x.via.ref.ptr, y.via.ref.ptr, x.via.ref.size) == 0;
|
||||
|
||||
case type::ARRAY:
|
||||
if(x.via.container.size != y.via.container.size) { return false; }
|
||||
for(object* px(x.via.container.ptr),
|
||||
* const pxend(x.via.container.ptr + x.via.container.size),
|
||||
* py(y.via.container.ptr);
|
||||
px != pxend; ++px, ++py) {
|
||||
if(*px != *py) { return false; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
return true;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
template <typename T, typename X>
|
||||
struct numeric_overflow_signed_impl<T, X, false, false> {
|
||||
static int test(X x) {
|
||||
if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) ||
|
||||
(!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) {
|
||||
if( sizeof(T) < sizeof(X) ) {
|
||||
if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; }
|
||||
}
|
||||
} else if(std::numeric_limits<T>::is_integer) {
|
||||
if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; }
|
||||
case type::MAP:
|
||||
if(x.via.container.size != y.via.container.size) { return false; }
|
||||
for(object* px(x.via.container.ptr),
|
||||
* const pxend(x.via.container.ptr + x.via.container.size*2),
|
||||
* py(y.via.container.ptr);
|
||||
px != pxend; ++px, ++py) {
|
||||
if(*px != *py) { return false; }
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename X>
|
||||
struct numeric_overflow {
|
||||
static int test(X x) {
|
||||
return numeric_overflow_signed_impl<T, X, std::numeric_limits<T>::is_signed, std::numeric_limits<X>::is_signed>::test(x);
|
||||
}
|
||||
static void check(X x) {
|
||||
int r = test(x);
|
||||
if(r == 1) { throw positive_overflow_error(); }
|
||||
if(r == -1) { throw negative_overflow_error(); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename X>
|
||||
struct numeric_underflow {
|
||||
static bool test(X x) {
|
||||
return static_cast<X>(static_cast<T>(x)) != x;
|
||||
}
|
||||
static void check(X x) {
|
||||
if(test(x)) { throw underflow_error(); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename X>
|
||||
inline T integer_cast(X x) {
|
||||
numeric_overflow<T,X>::check(x);
|
||||
return static_cast<T>(x); }
|
||||
|
||||
template <typename T, typename X>
|
||||
inline T float_cast(X x) {
|
||||
numeric_overflow<T,X>::check(x);
|
||||
numeric_underflow<T,X>::check(x);
|
||||
return static_cast<T>(x); }
|
||||
|
||||
template <typename V>
|
||||
inline bool numequal(V v, const object_class* x)
|
||||
try { return v == static_cast<V>(*x); }
|
||||
catch (type_error&) { return false; }
|
||||
|
||||
template <typename V>
|
||||
inline bool numless(V v, const object_class* x)
|
||||
try { return v < static_cast<V>(*x); }
|
||||
catch (positive_overflow_error&) { return true; }
|
||||
catch (overflow_error&) { return false; }
|
||||
|
||||
template <typename V>
|
||||
inline bool numgreater(V v, const object_class* x)
|
||||
try { return v > static_cast<V>(*x); }
|
||||
catch (negative_overflow_error&) { return true; }
|
||||
catch (overflow_error&) { return false; }
|
||||
|
||||
template <typename V>
|
||||
inline void numeric_inspect(V v, std::ostream& s)
|
||||
{ s << v; }
|
||||
|
||||
template <>
|
||||
inline void numeric_inspect<uint8_t>(uint8_t v, std::ostream& s)
|
||||
{ s << (uint16_t)v; }
|
||||
|
||||
template <>
|
||||
inline void numeric_inspect<int8_t>(int8_t v, std::ostream& s)
|
||||
{ s << (int16_t)v; }
|
||||
|
||||
template <typename V>
|
||||
inline void numeric_pack(dynamic_packer& p, V v);
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<uint8_t>(dynamic_packer& p, uint8_t v)
|
||||
{ p.pack_uint8(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<uint16_t>(dynamic_packer& p, uint16_t v)
|
||||
{ p.pack_uint16(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<uint32_t>(dynamic_packer& p, uint32_t v)
|
||||
{ p.pack_uint32(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<uint64_t>(dynamic_packer& p, uint64_t v)
|
||||
{ p.pack_uint64(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<int8_t>(dynamic_packer& p, int8_t v)
|
||||
{ p.pack_int8(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<int16_t>(dynamic_packer& p, int16_t v)
|
||||
{ p.pack_int16(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<int32_t>(dynamic_packer& p, int32_t v)
|
||||
{ p.pack_int32(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<int64_t>(dynamic_packer& p, int64_t v)
|
||||
{ p.pack_int64(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<float>(dynamic_packer& p, float v)
|
||||
{ p.pack_float(v); }
|
||||
|
||||
template <>
|
||||
inline void numeric_pack<double>(dynamic_packer& p, double v)
|
||||
{ p.pack_double(v); }
|
||||
|
||||
} // noname namespace
|
||||
|
||||
|
||||
bool object_nil::isnil() const { return true; }
|
||||
bool object_nil::operator== (const object_class* x) const
|
||||
{ return typeid(*this) == typeid(*x); }
|
||||
void object_nil::pack(dynamic_packer& p) const
|
||||
{ p.pack_nil(); }
|
||||
const object_class* object_nil::inspect(std::ostream& s) const
|
||||
{ s << "nil"; return this; }
|
||||
|
||||
bool object_true::xbool() const { return true; }
|
||||
bool object_true::operator== (const object_class* x) const
|
||||
{ return typeid(*this) == typeid(*x); }
|
||||
void object_true::pack(dynamic_packer& p) const
|
||||
{ p.pack_true(); }
|
||||
const object_class* object_true::inspect(std::ostream& s) const
|
||||
{ s << "true"; return this; }
|
||||
|
||||
bool object_false::xbool() const { return false; }
|
||||
bool object_false::operator== (const object_class* x) const
|
||||
{ return typeid(*this) == typeid(*x); }
|
||||
void object_false::pack(dynamic_packer& p) const
|
||||
{ p.pack_false(); }
|
||||
const object_class* object_false::inspect(std::ostream& s) const
|
||||
{ s << "false"; return this; }
|
||||
|
||||
|
||||
#define INTEGER_OBJECT(NAME) \
|
||||
uint8_t object_##NAME::xu8 () const { return val; } \
|
||||
uint16_t object_##NAME::xu16 () const { return integer_cast<uint16_t>(val); } \
|
||||
uint32_t object_##NAME::xu32 () const { return integer_cast<uint32_t>(val); } \
|
||||
uint64_t object_##NAME::xu64 () const { return integer_cast<uint64_t>(val); } \
|
||||
int8_t object_##NAME::xi8 () const { return integer_cast<int8_t>(val); } \
|
||||
int16_t object_##NAME::xi16 () const { return integer_cast<int16_t>(val); } \
|
||||
int32_t object_##NAME::xi32 () const { return integer_cast<int32_t>(val); } \
|
||||
int64_t object_##NAME::xi64 () const { return integer_cast<int64_t>(val); } \
|
||||
float object_##NAME::xfloat () const { return integer_cast<float>(val); } \
|
||||
double object_##NAME::xdouble() const { return integer_cast<double>(val); } \
|
||||
bool object_##NAME::operator== (const object_class* x) const \
|
||||
try { return val == x->x##NAME(); } \
|
||||
catch (type_error&) { return false; } \
|
||||
bool object_##NAME::operator< (const object_class* x) const \
|
||||
try { return val < x->x##NAME(); } \
|
||||
catch (positive_overflow_error&) { return true; } \
|
||||
catch (overflow_error&) { return false; } \
|
||||
bool object_##NAME::operator> (const object_class* x) const \
|
||||
try { return val > x->x##NAME(); } \
|
||||
catch (negative_overflow_error&) { return true; } \
|
||||
catch (overflow_error&) { return false; } \
|
||||
void object_##NAME::pack(dynamic_packer& p) const \
|
||||
{ numeric_pack(p, val); } \
|
||||
const object_class* object_##NAME::inspect(std::ostream& s) const \
|
||||
{ numeric_inspect(val, s); return this; } \
|
||||
|
||||
|
||||
INTEGER_OBJECT(u8)
|
||||
INTEGER_OBJECT(u16)
|
||||
INTEGER_OBJECT(u32)
|
||||
INTEGER_OBJECT(u64)
|
||||
INTEGER_OBJECT(i8)
|
||||
INTEGER_OBJECT(i16)
|
||||
INTEGER_OBJECT(i32)
|
||||
INTEGER_OBJECT(i64)
|
||||
|
||||
#undef INTEGER_OBJECT
|
||||
|
||||
|
||||
#define FLOAT_OBJECT(NAME) \
|
||||
uint8_t object_##NAME::xu8 () const { return val; } \
|
||||
uint16_t object_##NAME::xu16 () const { return integer_cast<uint16_t>(val); } \
|
||||
uint32_t object_##NAME::xu32 () const { return integer_cast<uint32_t>(val); } \
|
||||
uint64_t object_##NAME::xu64 () const { return integer_cast<uint64_t>(val); } \
|
||||
int8_t object_##NAME::xi8 () const { return integer_cast<int8_t>(val); } \
|
||||
int16_t object_##NAME::xi16 () const { return integer_cast<int16_t>(val); } \
|
||||
int32_t object_##NAME::xi32 () const { return integer_cast<int32_t>(val); } \
|
||||
int64_t object_##NAME::xi64 () const { return integer_cast<int64_t>(val); } \
|
||||
float object_##NAME::xfloat () const { return float_cast<float>(val); } \
|
||||
double object_##NAME::xdouble() const { return float_cast<double>(val); } \
|
||||
bool object_##NAME::operator== (const object_class* x) const \
|
||||
try { return val == x->x##NAME(); } \
|
||||
catch (type_error&) { return false; } \
|
||||
bool object_##NAME::operator< (const object_class* x) const { \
|
||||
try { return val < x->xdouble(); } \
|
||||
catch (positive_overflow_error&) { return true; } \
|
||||
catch (overflow_error&) { return false; } \
|
||||
catch (underflow_error&) { \
|
||||
if(val < 0.0) { \
|
||||
if(numeric_overflow<int64_t, double>::test(val) == -1) { return true; } \
|
||||
try { return static_cast<int64_t>(val) < x->xi64(); } \
|
||||
catch (type_error&) { return true; } \
|
||||
} else { \
|
||||
if(numeric_overflow<uint64_t, double>::test(val) == 1) { return false; } \
|
||||
try { return static_cast<uint64_t>(val) < x->xu64(); } \
|
||||
catch (type_error&) { return false; } \
|
||||
} \
|
||||
} } \
|
||||
bool object_##NAME::operator> (const object_class* x) const { \
|
||||
try { return val > x->xdouble(); } \
|
||||
catch (negative_overflow_error&) { return true; } \
|
||||
catch (overflow_error&) { return false; } \
|
||||
catch (underflow_error&) { \
|
||||
if(val < 0.0) { \
|
||||
if(numeric_overflow<int64_t, double>::test(val) == -1) { return false; } \
|
||||
try { return static_cast<int64_t>(val) > x->xi64(); } \
|
||||
catch (type_error&) { return false; } \
|
||||
} else { \
|
||||
if(numeric_overflow<uint64_t, double>::test(val) == 1) { return true; } \
|
||||
try { return static_cast<uint64_t>(val) > x->xu64(); } \
|
||||
catch (type_error&) { return true; } \
|
||||
} \
|
||||
} } \
|
||||
void object_##NAME::pack(dynamic_packer& p) const \
|
||||
{ numeric_pack(p, val); } \
|
||||
const object_class* object_##NAME::inspect(std::ostream& s) const \
|
||||
{ s << val; return this; } \
|
||||
|
||||
FLOAT_OBJECT(float)
|
||||
FLOAT_OBJECT(double)
|
||||
|
||||
#undef FLOAT_OBJECT
|
||||
|
||||
|
||||
#define RAW_OBJECT(NAME, EXTRA) \
|
||||
EXTRA \
|
||||
bool object_##NAME::operator== (const object_class* x) const \
|
||||
try { \
|
||||
raw xr(x->xraw()); \
|
||||
return len == xr.len && (ptr == xr.ptr || memcmp(ptr, xr.ptr, len) == 0); \
|
||||
} catch (type_error&) { return false; } \
|
||||
bool object_##NAME::operator< (const object_class* x) const { \
|
||||
raw xr(x->xraw()); \
|
||||
if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) < 0; } \
|
||||
else { return len < xr.len; } } \
|
||||
bool object_##NAME::operator> (const object_class* x) const { \
|
||||
raw xr(x->xraw()); \
|
||||
if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) > 0; } \
|
||||
else { return len > xr.len; } } \
|
||||
void object_##NAME::pack(dynamic_packer& p) const \
|
||||
{ p.pack_raw(ptr, len); } \
|
||||
const object_class* object_##NAME::inspect(std::ostream& s) const \
|
||||
{ (s << '"').write(ptr, len) << '"'; return this; } // FIXME escape
|
||||
}
|
||||
|
||||
|
||||
// FIXME
|
||||
RAW_OBJECT(mutable_raw_ref,
|
||||
/*mutable_raw object_mutable_raw_ref::xraw() { return mutable_raw(ptr, len); }*/
|
||||
raw object_mutable_raw_ref::xraw() const { return raw(ptr, len); } )
|
||||
|
||||
RAW_OBJECT(raw_ref,
|
||||
raw object_raw_ref::xraw() const { return raw(ptr, len); } )
|
||||
|
||||
#undef RAW_OBJECT
|
||||
|
||||
|
||||
array& object_array::xarray() { return val; }
|
||||
const array& object_array::xarray() const { return val; }
|
||||
bool object_array::operator== (const object_class* x) const
|
||||
try {
|
||||
const std::vector<object>& xa(x->xarray());
|
||||
if(val.size() != xa.size()) { return false; }
|
||||
for(std::vector<object>::const_iterator iv(val.begin()), iv_end(val.end()), ix(xa.begin());
|
||||
iv != iv_end;
|
||||
++iv, ++ix) {
|
||||
if(*iv != *ix) { return false; }
|
||||
}
|
||||
return true;
|
||||
} catch (type_error&) { return false; }
|
||||
const object_class* object_array::inspect(std::ostream& s) const
|
||||
{
|
||||
s << '[';
|
||||
if(!val.empty()) {
|
||||
std::vector<object>::const_iterator it(val.begin());
|
||||
s << *it;
|
||||
++it;
|
||||
for(std::vector<object>::const_iterator it_end(val.end());
|
||||
it != it_end;
|
||||
++it) {
|
||||
s << ", " << *it;
|
||||
}
|
||||
}
|
||||
s << ']';
|
||||
return this;
|
||||
}
|
||||
void object_array::pack(dynamic_packer& p) const
|
||||
{
|
||||
p.pack_array(val.size());
|
||||
for(std::vector<object>::const_iterator it(val.begin()), it_end(val.end());
|
||||
it != it_end;
|
||||
++it) {
|
||||
it->pack(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
map& object_map::xmap() { return val; }
|
||||
const map& object_map::xmap() const { return val; }
|
||||
bool object_map::operator== (const object_class* x) const
|
||||
try {
|
||||
const std::map<object, object>& xm(x->xmap());
|
||||
if(val.size() != xm.size()) { return false; }
|
||||
for(std::map<object, object>::const_iterator iv(val.begin()), iv_end(val.end()), ix(xm.begin());
|
||||
iv != iv_end;
|
||||
++iv, ++ix) {
|
||||
if(iv->first != ix->first || iv->second != ix->first) { return false; }
|
||||
}
|
||||
return true;
|
||||
} catch (type_error&) { return false; }
|
||||
const object_class* object_map::inspect(std::ostream& s) const
|
||||
{
|
||||
s << '{';
|
||||
if(!val.empty()) {
|
||||
std::map<object, object>::const_iterator it(val.begin());
|
||||
s << it->first << "=>" << it->second;
|
||||
++it;
|
||||
for(std::map<object, object>::const_iterator it_end(val.end());
|
||||
it != it_end;
|
||||
++it) {
|
||||
s << ", " << it->first << "=>" << it->second;
|
||||
}
|
||||
}
|
||||
s << '}';
|
||||
return this;
|
||||
}
|
||||
void object_map::pack(dynamic_packer& p) const
|
||||
{
|
||||
p.pack_map(val.size());
|
||||
for(std::map<object, object>::const_iterator it(val.begin()), it_end(val.end());
|
||||
it != it_end;
|
||||
++it) {
|
||||
it->first.pack(p);
|
||||
it->second.pack(p);
|
||||
}
|
||||
}
|
||||
//template <typename Stream>
|
||||
//const object& operator>> (const object& v, packer<Stream>& o);
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
354
cpp/object.hpp
354
cpp/object.hpp
@ -1,5 +1,5 @@
|
||||
//
|
||||
// MessagePack for C++ dynamic typed objects
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
//
|
||||
@ -18,305 +18,109 @@
|
||||
#ifndef MSGPACK_OBJECT_HPP__
|
||||
#define MSGPACK_OBJECT_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include "msgpack/pack.hpp"
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class type_error : public std::bad_cast { };
|
||||
class cast_error : public type_error { };
|
||||
class overflow_error : public type_error { };
|
||||
class underflow_error : public type_error { };
|
||||
class positive_overflow_error : public overflow_error { };
|
||||
class negative_overflow_error : public overflow_error { };
|
||||
|
||||
|
||||
struct mutable_raw {
|
||||
explicit mutable_raw() : ptr(NULL), len(0) {}
|
||||
explicit mutable_raw(char* p, size_t l) : ptr(p), len(l) {}
|
||||
public:
|
||||
char* ptr;
|
||||
size_t len;
|
||||
public:
|
||||
std::string str() { return std::string(ptr, len); }
|
||||
};
|
||||
|
||||
struct raw {
|
||||
explicit raw() : ptr(NULL), len(0) {}
|
||||
explicit raw(const char* p, size_t l) : ptr(p), len(l) {}
|
||||
raw(const mutable_raw& m) : ptr(m.ptr), len(m.len) {}
|
||||
public:
|
||||
const char* ptr;
|
||||
size_t len;
|
||||
public:
|
||||
std::string str() { return std::string(ptr, len); }
|
||||
};
|
||||
|
||||
|
||||
struct object;
|
||||
|
||||
typedef std::map<object, object> map;
|
||||
typedef std::vector<object> array;
|
||||
|
||||
class dynamic_packer;
|
||||
|
||||
|
||||
struct object_class {
|
||||
virtual ~object_class() {}
|
||||
virtual bool isnil () const { return false; }
|
||||
virtual bool xbool () const { throw cast_error(); }
|
||||
virtual uint8_t xu8 () const { throw cast_error(); }
|
||||
virtual uint16_t xu16 () const { throw cast_error(); }
|
||||
virtual uint32_t xu32 () const { throw cast_error(); }
|
||||
virtual uint64_t xu64 () const { throw cast_error(); }
|
||||
virtual int8_t xi8 () const { throw cast_error(); }
|
||||
virtual int16_t xi16 () const { throw cast_error(); }
|
||||
virtual int32_t xi32 () const { throw cast_error(); }
|
||||
virtual int64_t xi64 () const { throw cast_error(); }
|
||||
virtual float xfloat () const { throw cast_error(); }
|
||||
virtual double xdouble() const { throw cast_error(); }
|
||||
//virtual mutable_raw xraw () { throw cast_error(); } // FIXME
|
||||
virtual array& xarray() { throw cast_error(); }
|
||||
virtual map& xmap () { throw cast_error(); }
|
||||
virtual raw xraw () const { throw cast_error(); }
|
||||
virtual const array& xarray() const { throw cast_error(); }
|
||||
virtual const map& xmap () const { throw cast_error(); }
|
||||
virtual bool operator== (const object_class* x) const { return false; }
|
||||
virtual bool operator< (const object_class* x) const { throw cast_error(); }
|
||||
virtual bool operator> (const object_class* x) const { throw cast_error(); }
|
||||
bool operator!= (const object_class* x) const { return !(this->operator==(x)); }
|
||||
virtual void pack(dynamic_packer& p) const = 0;
|
||||
operator bool() const { return xbool(); } // FIXME !isnil();
|
||||
operator uint8_t() const { return xu8(); }
|
||||
operator uint16_t() const { return xu16(); }
|
||||
operator uint32_t() const { return xu32(); }
|
||||
operator uint64_t() const { return xu64(); }
|
||||
operator int8_t() const { return xi8(); }
|
||||
operator int16_t() const { return xi16(); }
|
||||
operator int32_t() const { return xi32(); }
|
||||
operator int64_t() const { return xi64(); }
|
||||
operator float() const { return xfloat(); }
|
||||
operator double() const { return xdouble(); }
|
||||
//operator mutable_raw() { return xraw(); } // FIXME
|
||||
operator array&() { return xarray(); }
|
||||
operator map&() { return xmap(); }
|
||||
operator raw() const { return xraw(); }
|
||||
operator const array&() const { return xarray(); }
|
||||
operator const map&() const { return xmap(); }
|
||||
virtual const object_class* inspect(std::ostream& s) const
|
||||
{ s << '<' << typeid(*this).name() << '>'; return this; }
|
||||
};
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& s, const object_class* o)
|
||||
{ o->inspect(s); return s; }
|
||||
|
||||
|
||||
struct object_container_mixin {};
|
||||
struct object_constructor_mixin {};
|
||||
class type_error : public std::bad_cast { };
|
||||
|
||||
|
||||
struct object {
|
||||
explicit object() : val(NULL) {}
|
||||
object(object_class* v) : val(v) {}
|
||||
//object(object_class& v) : val(&v) {}
|
||||
~object() {}
|
||||
bool isnil () const { return val->isnil(); }
|
||||
bool xbool () const { return val->xbool(); }
|
||||
uint8_t xu8 () const { return val->xu8(); }
|
||||
uint16_t xu16 () const { return val->xu16(); }
|
||||
uint32_t xu32 () const { return val->xu32(); }
|
||||
uint64_t xu64 () const { return val->xu64(); }
|
||||
int8_t xi8 () const { return val->xi8(); }
|
||||
int16_t xi16 () const { return val->xi16(); }
|
||||
int32_t xi32 () const { return val->xi32(); }
|
||||
int64_t xi64 () const { return val->xi64(); }
|
||||
float xfloat () const { return val->xfloat(); }
|
||||
double xdouble() const { return val->xdouble(); }
|
||||
//mutable_raw xraw () { return val->xraw(); } // FIXME
|
||||
array& xarray() { return val->xarray(); }
|
||||
map& xmap () { return val->xmap(); }
|
||||
raw xraw () const { return const_cast<const object_class*>(val)->xraw(); }
|
||||
const array& xarray() const { return const_cast<const object_class*>(val)->xarray(); }
|
||||
const map& xmap () const { return const_cast<const object_class*>(val)->xmap(); }
|
||||
bool operator== (object x) const { return val->operator== (x.val); }
|
||||
bool operator!= (object x) const { return val->operator!= (x.val); }
|
||||
bool operator< (object x) const { return val->operator< (x.val); }
|
||||
bool operator> (object x) const { return val->operator> (x.val); }
|
||||
void pack(dynamic_packer& p) const { val->pack(p); }
|
||||
template <typename Stream>
|
||||
void pack(Stream& s) const { dynamic_packer p(s); pack(p); }
|
||||
operator bool() const { return val->operator bool(); }
|
||||
operator uint8_t() const { return val->operator uint8_t(); }
|
||||
operator uint16_t() const { return val->operator uint16_t(); }
|
||||
operator uint32_t() const { return val->operator uint32_t(); }
|
||||
operator uint64_t() const { return val->operator uint64_t(); }
|
||||
operator int8_t() const { return val->operator int8_t(); }
|
||||
operator int16_t() const { return val->operator int16_t(); }
|
||||
operator int32_t() const { return val->operator int32_t(); }
|
||||
operator int64_t() const { return val->operator int64_t(); }
|
||||
operator float() const { return val->operator float(); }
|
||||
operator double() const { return val->operator double(); }
|
||||
//operator mutable_raw() { return val->operator mutable_raw(); } // FIXME
|
||||
operator array&() { return val->operator array&(); }
|
||||
operator map&() { return val->operator map&(); }
|
||||
operator raw() const { return val->operator raw(); }
|
||||
operator const array&() const { return val->operator const array&(); }
|
||||
operator const map&() const { return val->operator const map&(); }
|
||||
const object& inspect(std::ostream& s) const
|
||||
{ val->inspect(s); return *this; }
|
||||
private:
|
||||
friend class object_container_mixin;
|
||||
friend class object_constructor_mixin;
|
||||
object_class* val;
|
||||
unsigned char type;
|
||||
union {
|
||||
bool boolean;
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
double dec;
|
||||
struct {
|
||||
object* ptr;
|
||||
uint32_t size;
|
||||
} container;
|
||||
struct {
|
||||
const char* ptr;
|
||||
uint32_t size;
|
||||
} ref;
|
||||
} via;
|
||||
// FIXME template <typename T> operator T() { T v; convert(*this, v); return v; };
|
||||
};
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& s, const object& o)
|
||||
{ o.inspect(s); return s; }
|
||||
std::ostream& operator<< (std::ostream& s, const object o);
|
||||
|
||||
bool operator==(const object x, const object y);
|
||||
inline bool operator!=(const object x, const object y) { return !(x == y); }
|
||||
|
||||
|
||||
struct object_nil : object_class {
|
||||
bool isnil() const;
|
||||
bool operator== (const object_class* x) const;
|
||||
void pack(dynamic_packer& p) const;
|
||||
const object_class* inspect(std::ostream& s) const;
|
||||
};
|
||||
|
||||
struct object_true : object_class {
|
||||
bool xbool() const;
|
||||
bool operator== (const object_class* x) const;
|
||||
void pack(dynamic_packer& p) const;
|
||||
const object_class* inspect(std::ostream& s) const;
|
||||
};
|
||||
|
||||
struct object_false : object_class {
|
||||
bool xbool() const;
|
||||
bool operator== (const object_class* x) const;
|
||||
void pack(dynamic_packer& p) const;
|
||||
const object_class* inspect(std::ostream& s) const;
|
||||
};
|
||||
|
||||
#define INTEGER_CLASS(TYPE, NAME) \
|
||||
struct object_##NAME : object_class { \
|
||||
explicit object_##NAME(TYPE v) : val(v) {} \
|
||||
uint8_t xu8 () const; \
|
||||
uint16_t xu16 () const; \
|
||||
uint32_t xu32 () const; \
|
||||
uint64_t xu64 () const; \
|
||||
int8_t xi8 () const; \
|
||||
int16_t xi16 () const; \
|
||||
int32_t xi32 () const; \
|
||||
int64_t xi64 () const; \
|
||||
float xfloat () const; \
|
||||
double xdouble() const; \
|
||||
bool operator== (const object_class* x) const; \
|
||||
bool operator< (const object_class* x) const; \
|
||||
bool operator> (const object_class* x) const; \
|
||||
void pack(dynamic_packer& p) const; \
|
||||
const object_class* inspect(std::ostream& s) const; \
|
||||
private: \
|
||||
TYPE val; \
|
||||
};
|
||||
|
||||
INTEGER_CLASS(uint8_t, u8)
|
||||
INTEGER_CLASS(uint16_t, u16)
|
||||
INTEGER_CLASS(uint32_t, u32)
|
||||
INTEGER_CLASS(uint64_t, u64)
|
||||
INTEGER_CLASS(int8_t, i8)
|
||||
INTEGER_CLASS(int16_t, i16)
|
||||
INTEGER_CLASS(int32_t, i32)
|
||||
INTEGER_CLASS(int64_t, i64)
|
||||
|
||||
#undef INTEGER_CLASS
|
||||
template <typename Stream>
|
||||
const object& operator>> (const object& v, packer<Stream>& o);
|
||||
|
||||
|
||||
#define FLOAT_CLASS(TYPE, NAME) \
|
||||
struct object_##NAME : object_class { \
|
||||
object_##NAME(TYPE v) : val(v) {} \
|
||||
uint8_t xu8 () const; \
|
||||
uint16_t xu16 () const; \
|
||||
uint32_t xu32 () const; \
|
||||
uint64_t xu64 () const; \
|
||||
int8_t xi8 () const; \
|
||||
int16_t xi16 () const; \
|
||||
int32_t xi32 () const; \
|
||||
int64_t xi64 () const; \
|
||||
float xfloat () const; \
|
||||
double xdouble() const; \
|
||||
bool operator== (const object_class* x) const; \
|
||||
bool operator< (const object_class* x) const; \
|
||||
bool operator> (const object_class* x) const; \
|
||||
void pack(dynamic_packer& p) const; \
|
||||
const object_class* inspect(std::ostream& s) const; \
|
||||
private: \
|
||||
TYPE val; \
|
||||
};
|
||||
|
||||
FLOAT_CLASS(float, float)
|
||||
FLOAT_CLASS(double, double)
|
||||
|
||||
#undef FLOAT_CLASS
|
||||
namespace type {
|
||||
static const unsigned char NIL = 0x01;
|
||||
static const unsigned char BOOLEAN = 0x02;
|
||||
static const unsigned char POSITIVE_INTEGER = 0x03;
|
||||
static const unsigned char NEGATIVE_INTEGER = 0x04;
|
||||
static const unsigned char DOUBLE = 0x05;
|
||||
static const unsigned char RAW = 0x06;
|
||||
static const unsigned char ARRAY = 0x07;
|
||||
static const unsigned char MAP = 0x08;
|
||||
|
||||
|
||||
#define RAW_CLASS(NAME, TYPE, EXTRA) \
|
||||
struct object_##NAME : object_class { \
|
||||
explicit object_##NAME(TYPE p, uint32_t l) : ptr(p), len(l) {} \
|
||||
EXTRA \
|
||||
bool operator== (const object_class* x) const; \
|
||||
bool operator< (const object_class* x) const; \
|
||||
bool operator> (const object_class* x) const; \
|
||||
void pack(dynamic_packer& p) const; \
|
||||
const object_class* inspect(std::ostream& s) const; \
|
||||
private: \
|
||||
TYPE ptr; \
|
||||
uint32_t len; \
|
||||
};
|
||||
|
||||
// FIXME
|
||||
RAW_CLASS(mutable_raw_ref, char*, /*mutable_raw xraw();*/ raw xraw() const; )
|
||||
RAW_CLASS(raw_ref, const char*, raw xraw() const; )
|
||||
|
||||
#undef RAW_CLASS
|
||||
template <typename T>
|
||||
inline T& operator<< (T& v, object o)
|
||||
{
|
||||
v = o;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
struct object_array : object_class, object_container_mixin {
|
||||
explicit object_array() {}
|
||||
explicit object_array(uint32_t n) { val.reserve(n); }
|
||||
array& xarray();
|
||||
const array& xarray() const;
|
||||
bool operator== (const object_class* x) const;
|
||||
// FIXME operator<, operator>
|
||||
void pack(dynamic_packer& p) const;
|
||||
const object_class* inspect(std::ostream& s) const;
|
||||
public:
|
||||
void push_back(object o) { val.push_back(o); }
|
||||
private:
|
||||
std::vector<object> val;
|
||||
};
|
||||
namespace detail {
|
||||
template <typename Stream, typename T>
|
||||
inline void pack_copy(T v, packer<Stream>& o)
|
||||
{ pack(v, o); }
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline const T& operator>> (const T& v, packer<Stream>& o)
|
||||
{
|
||||
detail::pack_copy(v.pack(), o);
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace type
|
||||
|
||||
|
||||
// FIXME hash, operator==: nil, true, false, array, mapを入れられない
|
||||
struct object_map : object_class, object_container_mixin {
|
||||
explicit object_map() {}
|
||||
map& xmap();
|
||||
const map& xmap() const;
|
||||
bool operator== (const object_class* x) const;
|
||||
// FIXME operator<, operator>
|
||||
void pack(dynamic_packer& p) const;
|
||||
const object_class* inspect(std::ostream& s) const;
|
||||
public:
|
||||
void store(object k, object v) { val[k] = v; }
|
||||
private:
|
||||
std::map<object, object> val;
|
||||
};
|
||||
template <typename T>
|
||||
inline void convert(T& v, object o)
|
||||
{
|
||||
using namespace type;
|
||||
v << o;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline void pack(T& v, packer<Stream>& o)
|
||||
{
|
||||
using namespace type;
|
||||
v >> o;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline void pack(T& v, Stream& s)
|
||||
{
|
||||
packer<Stream> pk(s);
|
||||
pack(v, pk);
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#include "msgpack/type.hpp"
|
||||
|
||||
#endif /* msgpack/object.hpp */
|
||||
|
||||
|
10
cpp/pack.hpp
10
cpp/pack.hpp
@ -18,8 +18,6 @@
|
||||
#ifndef MSGPACK_PACK_HPP__
|
||||
#define MSGPACK_PACK_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.hpp"
|
||||
#include <arpa/inet.h> // __BYTE_ORDER
|
||||
#include <stdexcept>
|
||||
|
||||
@ -44,9 +42,9 @@ public:
|
||||
void pack_int64(uint64_t d) { pack_int64_impl(m_stream, d); }
|
||||
void pack_float(float d) { pack_float_impl(m_stream, d); }
|
||||
void pack_double(double d) { pack_double_impl(m_stream, d); }
|
||||
void pack_nil() { pack_nil(m_stream); }
|
||||
void pack_true() { pack_true(m_stream); }
|
||||
void pack_false() { pack_false(m_stream); }
|
||||
void pack_nil() { pack_nil_impl(m_stream); }
|
||||
void pack_true() { pack_true_impl(m_stream); }
|
||||
void pack_false() { pack_false_impl(m_stream); }
|
||||
void pack_array(unsigned int n) { pack_array_impl(m_stream, n); }
|
||||
void pack_map(unsigned int n) { pack_map_impl(m_stream, n); }
|
||||
void pack_raw(const char* b, size_t l) { pack_raw_impl(m_stream, (const void*)b, l); }
|
||||
@ -92,6 +90,7 @@ template <typename Stream>
|
||||
packer<Stream>::packer(Stream& s) : m_stream(s) { }
|
||||
|
||||
|
||||
/*
|
||||
class dynamic_stream {
|
||||
public:
|
||||
template <typename Stream>
|
||||
@ -212,6 +211,7 @@ inline void pack(Stream& s, object o)
|
||||
dynamic_packer pk(s);
|
||||
o.pack(pk);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
156
cpp/test.cpp
156
cpp/test.cpp
@ -1,37 +1,35 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
//#include <msgpack/unpack.hpp>
|
||||
//#include <msgpack/pack.hpp>
|
||||
#include <msgpack.hpp>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
using namespace msgpack;
|
||||
|
||||
class checker {
|
||||
public:
|
||||
void check(const char* d, size_t len, msgpack::object should) {
|
||||
using msgpack::object;
|
||||
template <typename T>
|
||||
void check(const char* d, size_t len, T should) {
|
||||
try {
|
||||
std::cout << "----" << std::endl;
|
||||
|
||||
object o;
|
||||
try {
|
||||
o = msgpack::unpack(d, len, m_zone);
|
||||
o = unpack(d, len, m_zone);
|
||||
} catch (std::runtime_error& e) {
|
||||
std::cout << should << std::endl;
|
||||
std::cout << o << std::endl;
|
||||
std::cout << "**" << e.what() << "**" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << o << std::endl;
|
||||
if(o != should) {
|
||||
std::cout << "** TEST FAILED **" << std::endl;
|
||||
}
|
||||
|
||||
try {
|
||||
std::stringstream s;
|
||||
msgpack::pack(s, o);
|
||||
pack(should, s);
|
||||
std::string str(s.str());
|
||||
object ro = msgpack::unpack(str.data(), str.size(), m_zone);
|
||||
object ro = unpack(str.data(), str.size(), m_zone);
|
||||
std::cout << ro << std::endl;
|
||||
if(ro != o) { throw std::runtime_error("NOT MATCH"); }
|
||||
} catch (std::runtime_error& e) {
|
||||
std::cout << "** REUNPACK FAILED **" << std::endl;
|
||||
@ -45,7 +43,7 @@ public:
|
||||
m_zone.clear();
|
||||
}
|
||||
private:
|
||||
msgpack::zone m_zone;
|
||||
zone m_zone;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
@ -53,54 +51,48 @@ int main(void)
|
||||
checker c;
|
||||
|
||||
{ // SimpleValue
|
||||
msgpack::zone z;
|
||||
const char d[] = {
|
||||
0x93, 0xc0, 0xc2, 0xc3,
|
||||
};
|
||||
c.check(d, sizeof(d),
|
||||
z.narray(
|
||||
z.nnil(), z.nfalse(), z.ntrue()
|
||||
type::make_tuple(
|
||||
type::nil(), false, true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
{ // Fixnum
|
||||
msgpack::zone z;
|
||||
const char d[] = {
|
||||
0x92,
|
||||
0x93, 0x00, 0x40, 0x7f,
|
||||
0x93, 0xe0, 0xf0, 0xff,
|
||||
};
|
||||
c.check(d, sizeof(d),
|
||||
z.narray(
|
||||
z.narray(
|
||||
z.nu8(0),
|
||||
z.nu8(64),
|
||||
z.nu8(127)
|
||||
type::make_tuple(
|
||||
type::make_tuple(
|
||||
0, 64, 127
|
||||
),
|
||||
z.narray(
|
||||
z.ni8(-32),
|
||||
z.ni8(-16),
|
||||
z.ni8(-1)
|
||||
type::make_tuple(
|
||||
-32, -16, -1
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
{ // FixArray
|
||||
msgpack::zone z;
|
||||
const char d[] = {
|
||||
0x92,
|
||||
0x90,
|
||||
0x91,
|
||||
0x91, 0xc0,
|
||||
};
|
||||
std::vector<int> empty;
|
||||
c.check(d, sizeof(d),
|
||||
z.narray(
|
||||
z.narray(),
|
||||
z.narray(
|
||||
z.narray(
|
||||
z.nnil()
|
||||
type::make_tuple(
|
||||
empty,
|
||||
type::make_tuple(
|
||||
type::make_tuple(
|
||||
type::nil()
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -108,7 +100,6 @@ int main(void)
|
||||
}
|
||||
|
||||
{ // FixRaw
|
||||
msgpack::zone z;
|
||||
const char d[] = {
|
||||
0x94,
|
||||
0xa0,
|
||||
@ -117,91 +108,84 @@ int main(void)
|
||||
0xa3, 'd', 'e', 'f',
|
||||
};
|
||||
c.check(d, sizeof(d),
|
||||
z.narray(
|
||||
z.nraw_ref("", 0),
|
||||
z.nraw_ref("a", 1),
|
||||
z.nraw_ref("bc", 2),
|
||||
z.nraw_ref("def", 3)
|
||||
type::make_tuple(
|
||||
std::string(""),
|
||||
std::string("a"),
|
||||
std::string("bc"),
|
||||
type::raw_ref("def", 3)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static const uint16_t TASK_ARRAY = 100;
|
||||
static char tarray[3];
|
||||
static char traw[64];
|
||||
|
||||
static const unsigned TASK_ARRAY = 100;
|
||||
static const unsigned TASK_REPEAT = 10;
|
||||
std::vector<std::string> task;
|
||||
|
||||
// create task
|
||||
{
|
||||
static char traw[64];
|
||||
memset(traw, 'a', sizeof(traw));
|
||||
traw[0] = 0xda;
|
||||
uint16_t n = htons(sizeof(traw)-3);
|
||||
traw[1] = ((char*)&n)[0];
|
||||
traw[2] = ((char*)&n)[1];
|
||||
|
||||
msgpack::zone z;
|
||||
std::cout << msgpack::unpack(traw, sizeof(traw), z) << std::endl;;
|
||||
}
|
||||
|
||||
{
|
||||
tarray[0] = 0xdc;
|
||||
uint16_t n = htons(TASK_ARRAY);
|
||||
tarray[1] = ((char*)&n)[0];
|
||||
tarray[2] = ((char*)&n)[1];
|
||||
}
|
||||
|
||||
{
|
||||
// write message
|
||||
ssize_t total_bytes = 0;
|
||||
std::stringstream stream;
|
||||
for(unsigned q=0; q < 10; ++q) {
|
||||
stream.write(tarray, sizeof(tarray));
|
||||
total_bytes += sizeof(tarray);
|
||||
for(uint16_t i=0; i < TASK_ARRAY; ++i) {
|
||||
stream.write(traw, sizeof(traw));
|
||||
total_bytes += sizeof(traw);
|
||||
}
|
||||
|
||||
task.resize(TASK_ARRAY);
|
||||
for(unsigned i=0; i < TASK_ARRAY; ++i) {
|
||||
task[i] = std::string(traw, sizeof(traw));
|
||||
}
|
||||
}
|
||||
|
||||
stream.seekg(0);
|
||||
|
||||
// reserive message
|
||||
std::stringstream stream;
|
||||
|
||||
// send message
|
||||
{
|
||||
for(unsigned i=0; i < TASK_REPEAT; ++i) {
|
||||
pack(task, stream);
|
||||
}
|
||||
std::cout << "send " << stream.str().size() << " bytes" << std::endl;
|
||||
}
|
||||
|
||||
ssize_t total_bytes = stream.str().size();
|
||||
stream.seekg(0);
|
||||
|
||||
// reserive message
|
||||
{
|
||||
unsigned num_msg = 0;
|
||||
|
||||
static const size_t RESERVE_SIZE = 32;//*1024;
|
||||
|
||||
msgpack::unpacker upk;
|
||||
std::auto_ptr<zone> pz(new zone());
|
||||
|
||||
unpacker pac(*pz);
|
||||
|
||||
while(stream.good() && total_bytes > 0) {
|
||||
|
||||
// 1. reserve buffer
|
||||
upk.reserve_buffer(RESERVE_SIZE);
|
||||
pac.reserve_buffer(RESERVE_SIZE);
|
||||
|
||||
// 2. read data to buffer() up to buffer_capacity() bytes
|
||||
size_t sz = stream.readsome(
|
||||
upk.buffer(),
|
||||
upk.buffer_capacity());
|
||||
pac.buffer(),
|
||||
pac.buffer_capacity());
|
||||
|
||||
total_bytes -= sz;
|
||||
std::cout << "read " << sz << " bytes to capacity "
|
||||
<< upk.buffer_capacity() << " bytes"
|
||||
<< pac.buffer_capacity() << " bytes"
|
||||
<< std::endl;
|
||||
|
||||
// 3. specify the number of bytes actually copied
|
||||
upk.buffer_consumed(sz);
|
||||
pac.buffer_consumed(sz);
|
||||
|
||||
// 4. repeat execute() until it returns false
|
||||
while( upk.execute() ) {
|
||||
std::cout << "message parsed" << std::endl;
|
||||
|
||||
while( pac.execute() ) {
|
||||
// 5.1. take out the parsed object
|
||||
msgpack::object o = upk.data();
|
||||
object o = pac.data();
|
||||
|
||||
// 5.2. the parsed object is valid until the zone is deleted
|
||||
std::auto_ptr<msgpack::zone> pz(upk.release_zone());
|
||||
|
||||
std::cout << o << std::endl;
|
||||
// do something using pz and o
|
||||
std::cout << "message parsed: " << o << std::endl;
|
||||
++num_msg;
|
||||
|
||||
// 5.3 re-initialize unpacker
|
||||
upk.reset();
|
||||
// 5.3 re-initialize unpacker with next zone */
|
||||
pz.reset(new zone());
|
||||
pac.reset(*pz);
|
||||
}
|
||||
|
||||
}
|
||||
|
9
cpp/type.hpp
Normal file
9
cpp/type.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "msgpack/type/array.hpp"
|
||||
#include "msgpack/type/boolean.hpp"
|
||||
#include "msgpack/type/float.hpp"
|
||||
#include "msgpack/type/integer.hpp"
|
||||
#include "msgpack/type/map.hpp"
|
||||
#include "msgpack/type/nil.hpp"
|
||||
#include "msgpack/type/raw.hpp"
|
||||
#include "msgpack/type/tuple.hpp"
|
||||
|
59
cpp/type/array.hpp
Normal file
59
cpp/type/array.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_ARRAY_HPP__
|
||||
#define MSGPACK_TYPE_ARRAY_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T> operator<< (std::vector<T>& v, object o)
|
||||
{
|
||||
if(o.type != ARRAY) { throw type_error(); }
|
||||
v.resize(o.via.container.size);
|
||||
object* p(o.via.container.ptr);
|
||||
object* const pend(o.via.container.ptr + o.via.container.size);
|
||||
T* it(&v.front());
|
||||
for(; p < pend; ++p, ++it) {
|
||||
convert(*it, *p);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream, typename T>
|
||||
inline const std::vector<T>& operator>> (const std::vector<T>& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_array(v.size());
|
||||
for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
pack(*it, o);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/array.hpp */
|
||||
|
49
cpp/type/boolean.hpp
Normal file
49
cpp/type/boolean.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_BOOLEAN_HPP__
|
||||
#define MSGPACK_TYPE_BOOLEAN_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
inline bool& operator<< (bool& v, object o)
|
||||
{
|
||||
if(o.type != BOOLEAN) { throw type_error(); }
|
||||
v = o.via.boolean;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const bool& operator>> (const bool& v, packer<Stream> o)
|
||||
{
|
||||
if(v) { o.pack_true(); }
|
||||
else { o.pack_false(); }
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/bool.hpp */
|
||||
|
67
cpp/type/float.hpp
Normal file
67
cpp/type/float.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_FLOAT_HPP__
|
||||
#define MSGPACK_TYPE_FLOAT_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
// FIXME check overflow, underflow
|
||||
|
||||
|
||||
inline float& operator<< (float& v, object o)
|
||||
{
|
||||
if(o.type != DOUBLE) { throw type_error(); }
|
||||
v = o.via.dec;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const float& operator>> (const float& v, packer<Stream> o)
|
||||
{
|
||||
o.pack_float(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
inline double& operator<< (double& v, object o)
|
||||
{
|
||||
if(o.type != DOUBLE) { throw type_error(); }
|
||||
v = o.via.dec;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const double& operator>> (const double& v, packer<Stream> o)
|
||||
{
|
||||
o.pack_double(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/float.hpp */
|
||||
|
243
cpp/type/integer.hpp
Normal file
243
cpp/type/integer.hpp
Normal file
@ -0,0 +1,243 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_INTEGER_HPP__
|
||||
#define MSGPACK_TYPE_INTEGER_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <limits>
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
namespace detail {
|
||||
template <typename T, bool Signed>
|
||||
struct convert_integer_sign;
|
||||
|
||||
template <typename T>
|
||||
struct convert_integer_sign<T, true> {
|
||||
static inline T convert(object o) {
|
||||
if(o.type == POSITIVE_INTEGER) {
|
||||
if(o.via.u64 > (uint64_t)std::numeric_limits<T>::max())
|
||||
{ throw type_error(); }
|
||||
return o.via.u64;
|
||||
} else if(o.type == NEGATIVE_INTEGER) {
|
||||
if(o.via.i64 < (int64_t)-std::numeric_limits<T>::max())
|
||||
{ throw type_error(); }
|
||||
return o.via.i64;
|
||||
}
|
||||
throw type_error();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct convert_integer_sign<T, false> {
|
||||
static inline T convert(object o) {
|
||||
if(o.type == POSITIVE_INTEGER) {
|
||||
if(o.via.u64 > (uint64_t)std::numeric_limits<T>::max())
|
||||
{ throw type_error(); }
|
||||
return o.via.u64;
|
||||
}
|
||||
throw type_error();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static inline T convert_integer(object o)
|
||||
{
|
||||
return detail::convert_integer_sign<T, std::numeric_limits<T>::is_signed>::convert(o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T, typename Stream, int Size, bool Signed>
|
||||
struct pack_integer_size_sign;
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 1, true> {
|
||||
static inline void pack(T v, packer<Stream>& o)
|
||||
{ o.pack_int8(v); }
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 1, false> {
|
||||
static inline void pack(T v, packer<Stream>& o)
|
||||
{ o.pack_uint8(v); }
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 2, true> {
|
||||
static inline void pack(T v, packer<Stream>& o) {
|
||||
if( (int16_t)v <= (int16_t)std::numeric_limits<int8_t>::max() &&
|
||||
(int16_t)v >= (int16_t)std::numeric_limits<int8_t>::min())
|
||||
{ o.pack_int8(v); }
|
||||
else { o.pack_int16(v); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 2, false> {
|
||||
static inline void pack(T v, packer<Stream>& o) {
|
||||
if( (uint16_t)v <= (uint16_t)std::numeric_limits<uint8_t>::max())
|
||||
{ o.pack_uint8(v); }
|
||||
else { o.pack_uint16(v); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 4, true> {
|
||||
static inline void pack(T v, packer<Stream>& o) {
|
||||
if( (int32_t)v <= (int32_t)std::numeric_limits<int8_t>::max() &&
|
||||
(int32_t)v >= (int32_t)std::numeric_limits<int8_t>::min())
|
||||
{ o.pack_int8(v); }
|
||||
else if( (int32_t)v <= (int32_t)std::numeric_limits<int16_t>::max() &&
|
||||
(int32_t)v >= (int32_t)std::numeric_limits<int16_t>::min())
|
||||
{ o.pack_int16(v); }
|
||||
else { o.pack_int32(v); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 4, false> {
|
||||
static inline void pack(T v, packer<Stream>& o) {
|
||||
if( (uint32_t)v <= (uint32_t)std::numeric_limits<uint8_t>::max())
|
||||
{ o.pack_uint8(v); }
|
||||
else if( (uint32_t)v <= (uint32_t)std::numeric_limits<uint16_t>::max())
|
||||
{ o.pack_uint16(v); }
|
||||
else { o.pack_uint32(v); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 8, true> {
|
||||
static inline void pack(T v, packer<Stream>& o) {
|
||||
if( (int64_t)v <= (int64_t)std::numeric_limits<int8_t>::max() &&
|
||||
(int64_t)v >= (int64_t)std::numeric_limits<int8_t>::min())
|
||||
{ o.pack_int8(v); }
|
||||
else if( (int64_t)v <= (int64_t)std::numeric_limits<int16_t>::max() &&
|
||||
(int64_t)v >= (int64_t)std::numeric_limits<int16_t>::min())
|
||||
{ o.pack_int16(v); }
|
||||
else if( (int64_t)v <= (int64_t)std::numeric_limits<int32_t>::max() &&
|
||||
(int64_t)v >= (int64_t)std::numeric_limits<int32_t>::min())
|
||||
{ o.pack_int32(v); }
|
||||
else { o.pack_int64(v); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Stream>
|
||||
struct pack_integer_size_sign<T, Stream, 8, false> {
|
||||
static inline void pack(T v, packer<Stream>& o) {
|
||||
if( (uint64_t)v <= (uint64_t)std::numeric_limits<uint8_t>::max())
|
||||
{ o.pack_uint8(v); }
|
||||
else if( (uint64_t)v <= (uint64_t)std::numeric_limits<uint16_t>::max())
|
||||
{ o.pack_uint16(v); }
|
||||
else if( (uint64_t)v <= (uint64_t)std::numeric_limits<uint32_t>::max())
|
||||
{ o.pack_uint32(v); }
|
||||
else { o.pack_uint64(v); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename Stream>
|
||||
static inline void pack_integer(T v, packer<Stream>& o)
|
||||
{
|
||||
pack_integer_size_sign<T, Stream, sizeof(T), std::numeric_limits<T>::is_signed>::pack(v, o);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
inline signed char& operator<< (signed char& v, object o)
|
||||
{ v = detail::convert_integer<signed char>(o); return v; }
|
||||
|
||||
inline signed short& operator<< (signed short& v, object o)
|
||||
{ v = detail::convert_integer<signed short>(o); return v; }
|
||||
|
||||
inline signed int& operator<< (signed int& v, object o)
|
||||
{ v = detail::convert_integer<signed int>(o); return v; }
|
||||
|
||||
inline signed long& operator<< (signed long& v, object o)
|
||||
{ v = detail::convert_integer<signed long>(o); return v; }
|
||||
|
||||
inline signed long long& operator<< (signed long long& v, object o)
|
||||
{ v = detail::convert_integer<signed long long>(o); return v; }
|
||||
|
||||
|
||||
inline unsigned char& operator<< (unsigned char& v, object o)
|
||||
{ v = detail::convert_integer<unsigned char>(o); return v; }
|
||||
|
||||
inline unsigned short& operator<< (unsigned short& v, object o)
|
||||
{ v = detail::convert_integer<unsigned short>(o); return v; }
|
||||
|
||||
inline unsigned int& operator<< (unsigned int& v, object o)
|
||||
{ v = detail::convert_integer<unsigned int>(o); return v; }
|
||||
|
||||
inline unsigned long& operator<< (unsigned long& v, object o)
|
||||
{ v = detail::convert_integer<unsigned long>(o); return v; }
|
||||
|
||||
inline unsigned long long& operator<< (unsigned long long& v, object o)
|
||||
{ v = detail::convert_integer<unsigned long long>(o); return v; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const signed char& operator>> (const signed char& v, packer<Stream> o)
|
||||
{ detail::pack_integer<signed char>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const signed short& operator>> (const signed short& v, packer<Stream> o)
|
||||
{ detail::pack_integer<signed short>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const signed int& operator>> (const signed int& v, packer<Stream> o)
|
||||
{ detail::pack_integer<signed int>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const signed long& operator>> (const signed long& v, packer<Stream> o)
|
||||
{ detail::pack_integer<signed long>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const signed long long& operator>> (const signed long long& v, packer<Stream> o)
|
||||
{ detail::pack_integer<signed long long>(v, o); return v; }
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const unsigned char& operator>> (const unsigned char& v, packer<Stream> o)
|
||||
{ detail::pack_integer<unsigned char>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const unsigned short& operator>> (const unsigned short& v, packer<Stream> o)
|
||||
{ detail::pack_integer<unsigned short>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const unsigned int& operator>> (const unsigned int& v, packer<Stream> o)
|
||||
{ detail::pack_integer<unsigned int>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const unsigned long& operator>> (const unsigned long& v, packer<Stream> o)
|
||||
{ detail::pack_integer<unsigned long>(v, o); return v; }
|
||||
|
||||
template <typename Stream>
|
||||
inline const unsigned long long& operator>> (const unsigned long long& v, packer<Stream> o)
|
||||
{ detail::pack_integer<unsigned long long>(v, o); return v; }
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/integer.hpp */
|
||||
|
132
cpp/type/map.hpp
Normal file
132
cpp/type/map.hpp
Normal file
@ -0,0 +1,132 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_MAP_HPP__
|
||||
#define MSGPACK_TYPE_MAP_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
class assoc_vector : public std::vector< std::pair<K, V> > {};
|
||||
|
||||
namespace detail {
|
||||
template <typename K, typename V>
|
||||
struct pair_first_less {
|
||||
bool operator() (const std::pair<K, V>& x, const std::pair<K, V>& y) const
|
||||
{ return x.first < y.first; }
|
||||
};
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
inline assoc_vector<K,V>& operator<< (assoc_vector<K,V>& v, object o)
|
||||
{
|
||||
if(o.type != MAP) { throw type_error(); }
|
||||
v.resize(o.via.container.size);
|
||||
object* p(o.via.container.ptr);
|
||||
object* const pend(o.via.container.ptr + o.via.container.size);
|
||||
std::pair<K, V>* it(&v.front());
|
||||
for(; p < pend; ++it) {
|
||||
convert(it->first, *p); ++p;
|
||||
convert(it->second, *p); ++p;
|
||||
}
|
||||
std::sort(v.begin(), v.end(), detail::pair_first_less<K,V>());
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename K, typename V>
|
||||
inline const assoc_vector<K,V>& operator>> (const assoc_vector<K,V>& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_map(v.size());
|
||||
for(typename assoc_vector<K,V>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
pack(it->first, o);
|
||||
pack(it->second, o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
inline std::map<K, V> operator<< (std::map<K, V>& v, object o)
|
||||
{
|
||||
if(o.type != MAP) { throw type_error(); }
|
||||
object* p(o.via.container.ptr);
|
||||
object* const pend(o.via.container.ptr + o.via.container.size*2);
|
||||
while(p < pend) {
|
||||
K key;
|
||||
convert(key, *p); ++p;
|
||||
typename std::map<K,V>::iterator it(v.find(key));
|
||||
if(it != v.end()) {
|
||||
V val;
|
||||
convert(val, *p); ++p;
|
||||
it->insert( std::pair<K,V>(key, val) );
|
||||
} else {
|
||||
convert(it->second, *p); ++p;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename K, typename V>
|
||||
inline const std::map<K,V>& operator>> (const std::map<K,V>& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_map(v.size());
|
||||
for(typename std::map<K,V>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
pack(it->first, o);
|
||||
pack(it->second, o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
inline std::multimap<K, V> operator<< (std::multimap<K, V>& v, object o)
|
||||
{
|
||||
if(o.type != MAP) { throw type_error(); }
|
||||
object* p(o.via.container.ptr);
|
||||
object* const pend(o.via.container.ptr + o.via.container.size*2);
|
||||
while(p < pend) {
|
||||
std::pair<K, V> value;
|
||||
convert(value.first, *p); ++p;
|
||||
convert(value.second, *p); ++p;
|
||||
v.insert(value);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream, typename K, typename V>
|
||||
inline const std::multimap<K,V>& operator>> (const std::multimap<K,V>& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_multimap(v.size());
|
||||
for(typename std::multimap<K,V>::const_iterator it(v.begin()), it_end(v.end());
|
||||
it != it_end; ++it) {
|
||||
pack(it->first, o);
|
||||
pack(it->second, o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/map.hpp */
|
||||
|
47
cpp/type/nil.hpp
Normal file
47
cpp/type/nil.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_NIL_HPP__
|
||||
#define MSGPACK_TYPE_NIL_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
struct nil { };
|
||||
|
||||
inline nil& operator<< (nil& v, object o)
|
||||
{
|
||||
if(o.type != NIL) { throw type_error(); }
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline const nil& operator>> (const nil& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_nil();
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/nil.hpp */
|
||||
|
99
cpp/type/raw.hpp
Normal file
99
cpp/type/raw.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_RAW_HPP__
|
||||
#define MSGPACK_TYPE_RAW_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
struct raw_ref {
|
||||
raw_ref() : ptr(NULL), size(0) {}
|
||||
raw_ref(const char* p, uint32_t s) : ptr(p), size(s) {}
|
||||
|
||||
const char* ptr;
|
||||
uint32_t size;
|
||||
|
||||
std::string str() { return std::string(ptr, size); }
|
||||
|
||||
bool operator== (const raw_ref& x)
|
||||
{
|
||||
return size == x.size && memcmp(ptr, x.ptr, size) == 0;
|
||||
}
|
||||
|
||||
bool operator!= (const raw_ref& x)
|
||||
{
|
||||
return !(*this != x);
|
||||
}
|
||||
|
||||
bool operator< (const raw_ref& x)
|
||||
{
|
||||
if(size == x.size) { return memcmp(ptr, x.ptr, size) < 0; }
|
||||
else { return size < x.size; }
|
||||
}
|
||||
|
||||
bool operator> (const raw_ref& x)
|
||||
{
|
||||
if(size == x.size) { return memcmp(ptr, x.ptr, size) > 0; }
|
||||
else { return size > x.size; }
|
||||
}
|
||||
};
|
||||
|
||||
inline raw_ref& operator<< (raw_ref& v, object o)
|
||||
{
|
||||
if(o.type != RAW) { throw type_error(); }
|
||||
v.ptr = o.via.ref.ptr;
|
||||
v.size = o.via.ref.size;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
inline std::string& operator<< (std::string& v, object o)
|
||||
{
|
||||
raw_ref r;
|
||||
r << o;
|
||||
v.assign(r.ptr, r.size);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const raw_ref& operator>> (const raw_ref& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_raw(v.ptr, v.size);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <typename Stream>
|
||||
inline const std::string& operator>> (const std::string& v, packer<Stream>& o)
|
||||
{
|
||||
o.pack_raw(v.data(), v.size());
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/raw.hpp */
|
||||
|
172
cpp/type/tuple.hpp.erb
Normal file
172
cpp/type/tuple.hpp.erb
Normal file
@ -0,0 +1,172 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 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_TYPE_TUPLE_HPP__
|
||||
#define MSGPACK_TYPE_TUPLE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
|
||||
// FIXME operator==
|
||||
// FIXME operator!=
|
||||
|
||||
<% GENERATION_LIMIT = 15 %>
|
||||
|
||||
template < typename A0 <%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%> >
|
||||
struct tuple;
|
||||
|
||||
template <typename Tuple, int N>
|
||||
struct tuple_type;
|
||||
|
||||
template <typename Tuple, int N>
|
||||
struct const_tuple_type;
|
||||
|
||||
template <typename T>
|
||||
struct tuple_element {
|
||||
typedef T type;
|
||||
tuple_element(T& x) : _x(x) {}
|
||||
type& get() { return _x; }
|
||||
const type& get() const { return _x; }
|
||||
private:
|
||||
type& _x;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct const_tuple_element {
|
||||
typedef T type;
|
||||
const_tuple_element(const T& x) : _x(x) {}
|
||||
const type& get() const { return _x; }
|
||||
private:
|
||||
const type& _x;
|
||||
};
|
||||
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
<%0.upto(i) {|j|%>
|
||||
template < typename A0 <%1.upto(i) {|k|%>, typename A<%=k%> <%}%>>
|
||||
struct tuple_type<tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>, <%=j%>> : tuple_element<A<%=j%>> {
|
||||
tuple_type(tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>& x) : tuple_element<A<%=j%>>(x.a<%=j%>) {}
|
||||
};
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
<%0.upto(i) {|j|%>
|
||||
template < typename A0 <%1.upto(i) {|k|%>, typename A<%=k%> <%}%>>
|
||||
struct const_tuple_type<tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>, <%=j%>> : const_tuple_element<A<%=j%>> {
|
||||
const_tuple_type(const tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>& x) : const_tuple_element<A<%=j%>>(x.a<%=j%>) {}
|
||||
};
|
||||
<%}%>
|
||||
<%}%>
|
||||
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template < typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>>
|
||||
tuple< A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>> make_tuple(const A0& a0 <%1.upto(i) {|j|%>, const A<%=j%>& a<%=j%><%}%>)
|
||||
{
|
||||
return tuple< A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>(a0 <%1.upto(i) {|j|%>, a<%=j%><%}%>);
|
||||
}
|
||||
<%}%>
|
||||
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template < typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>>
|
||||
struct tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>> {
|
||||
tuple() {}
|
||||
tuple(const A0& _a0 <%1.upto(i) {|j|%>, const A<%=j%>& _a<%=j%><%}%>) :
|
||||
a0(_a0) <%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {}
|
||||
tuple(object o) { convert(*this, o); }
|
||||
template <int N> typename tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>::type& get()
|
||||
{ return tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>(*this).get(); }
|
||||
template <int N> const typename const_tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>::type& get() const
|
||||
{ return const_tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>(*this).get(); }
|
||||
<%0.upto(i) {|j|%>
|
||||
A<%=j%> a<%=j%>;<%}%>
|
||||
};
|
||||
<%}%>
|
||||
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template < typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>>
|
||||
tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& operator<< (
|
||||
tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& v,
|
||||
object o) {
|
||||
if(o.type != ARRAY) { throw type_error(); }
|
||||
if(o.via.container.size < <%=i+1%>) { throw type_error(); }
|
||||
<%0.upto(i) {|j|%>
|
||||
convert<A<%=j%>>(v.template get<<%=j%>>(), o.via.container.ptr[<%=j%>]);<%}%>
|
||||
return v;
|
||||
}
|
||||
<%}%>
|
||||
|
||||
|
||||
// FIXME
|
||||
/*
|
||||
template <typename A0, typename A1 = void, typename A2 = void>
|
||||
struct tuple_just;
|
||||
|
||||
template <typename A0>
|
||||
struct tuple_just<A0> {
|
||||
A0 a0;
|
||||
static inline void convert(object o, tuple_just<A0>& v)
|
||||
{
|
||||
if(o.type != ARRAY) { throw type_error(); }
|
||||
if(o.v.container.size != 1) { throw type_error(); }
|
||||
msgpack::convert<A0>(o.v.container.ptr[0], v.a0);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename A0, typename A1>
|
||||
struct tuple_just<A0, A1> {
|
||||
A0 a0;
|
||||
A1 a1;
|
||||
static inline void convert(object o, tuple_just<A0, A1>& v)
|
||||
{
|
||||
if(o.type != ARRAY) { throw type_error(); }
|
||||
if(o.v.container.size != 2) { throw type_error(); }
|
||||
msgpack::convert<A0>(o.v.container.ptr[0], v.a0);
|
||||
msgpack::convert<A1>(o.v.container.ptr[1], v.a1);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template < typename Stream , typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>>
|
||||
const tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& operator>> (
|
||||
const tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& v,
|
||||
packer<Stream> o) {
|
||||
o.pack_array(<%=i+1%>);
|
||||
<%0.upto(i) {|j|%>
|
||||
pack(v.template get<<%=j%>>(), o);<%}%>
|
||||
return v;
|
||||
}
|
||||
<%}%>
|
||||
|
||||
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/tuple.hpp */
|
||||
|
||||
|
149
cpp/unpack.cpp
149
cpp/unpack.cpp
@ -31,7 +31,7 @@ namespace msgpack {
|
||||
#define msgpack_unpack_callback(name) \
|
||||
msgpack_unpack_##name
|
||||
|
||||
#define msgpack_unpack_object object_class*
|
||||
#define msgpack_unpack_object object
|
||||
|
||||
#define msgpack_unpack_user zone*
|
||||
|
||||
@ -40,68 +40,88 @@ struct msgpack_unpacker_context;
|
||||
|
||||
static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static object_class* msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);
|
||||
static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
|
||||
static inline object_class* msgpack_unpack_init(zone** z)
|
||||
{ return NULL; }
|
||||
static inline object msgpack_unpack_init(zone** z)
|
||||
{ return object(); }
|
||||
|
||||
static inline object_class* msgpack_unpack_uint8(zone** z, uint8_t d)
|
||||
{ return (*z)->nu8(d); }
|
||||
static inline object msgpack_unpack_uint8(zone** z, uint8_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_uint16(zone** z, uint16_t d)
|
||||
{ return (*z)->nu16(d); }
|
||||
static inline object msgpack_unpack_uint16(zone** z, uint16_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_uint32(zone** z, uint32_t d)
|
||||
{ return (*z)->nu32(d); }
|
||||
static inline object msgpack_unpack_uint32(zone** z, uint32_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_uint64(zone** z, uint64_t d)
|
||||
{ return (*z)->nu64(d); }
|
||||
static inline object msgpack_unpack_uint64(zone** z, uint64_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_int8(zone** z, int8_t d)
|
||||
{ return (*z)->ni8(d); }
|
||||
static inline object msgpack_unpack_int8(zone** z, int8_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object_class* msgpack_unpack_int16(zone** z, int16_t d)
|
||||
{ return (*z)->ni16(d); }
|
||||
static inline object msgpack_unpack_int16(zone** z, int16_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object_class* msgpack_unpack_int32(zone** z, int32_t d)
|
||||
{ return (*z)->ni32(d); }
|
||||
static inline object msgpack_unpack_int32(zone** z, int32_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object_class* msgpack_unpack_int64(zone** z, int64_t d)
|
||||
{ return (*z)->ni64(d); }
|
||||
static inline object msgpack_unpack_int64(zone** z, int64_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object_class* msgpack_unpack_float(zone** z, float d)
|
||||
{ return (*z)->nfloat(d); }
|
||||
static inline object msgpack_unpack_float(zone** z, float d)
|
||||
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_double(zone** z, double d)
|
||||
{ return (*z)->ndouble(d); }
|
||||
static inline object msgpack_unpack_double(zone** z, double d)
|
||||
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_nil(zone** z)
|
||||
{ return (*z)->nnil(); }
|
||||
static inline object msgpack_unpack_nil(zone** z)
|
||||
{ object o; o.type = type::NIL; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_true(zone** z)
|
||||
{ return (*z)->ntrue(); }
|
||||
static inline object msgpack_unpack_true(zone** z)
|
||||
{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_false(zone** z)
|
||||
{ return (*z)->nfalse(); }
|
||||
static inline object msgpack_unpack_false(zone** z)
|
||||
{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_array(zone** z, unsigned int n)
|
||||
{ return (*z)->narray(n); }
|
||||
static inline object msgpack_unpack_array(zone** z, unsigned int n)
|
||||
{
|
||||
object o;
|
||||
o.type = type::ARRAY;
|
||||
o.via.container.size = 0;
|
||||
o.via.container.ptr = (*z)->malloc_container(n);
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpack_array_item(zone** z, object_class* c, object_class* o)
|
||||
{ reinterpret_cast<object_array*>(c)->push_back(o); }
|
||||
static inline void msgpack_unpack_array_item(zone** z, object* c, object o)
|
||||
{ c->via.container.ptr[ c->via.container.size++ ] = o; }
|
||||
|
||||
static inline object_class* msgpack_unpack_map(zone** z, unsigned int n)
|
||||
{ return (*z)->nmap(); }
|
||||
static inline object msgpack_unpack_map(zone** z, unsigned int n)
|
||||
{
|
||||
object o;
|
||||
o.type = type::MAP;
|
||||
o.via.container.size = 0;
|
||||
o.via.container.ptr = (*z)->malloc_container(n*2);
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpack_map_item(zone** z, object_class* c, object_class* k, object_class* v)
|
||||
{ reinterpret_cast<object_map*>(c)->store(k, v); }
|
||||
static inline void msgpack_unpack_map_item(zone** z, object* c, object k, object v)
|
||||
{
|
||||
c->via.container.ptr[ c->via.container.size ] = k;
|
||||
c->via.container.ptr[ c->via.container.size+1 ] = v;
|
||||
++c->via.container.size;
|
||||
}
|
||||
|
||||
static inline object_class* msgpack_unpack_raw(zone** z, const char* b, const char* p, unsigned int l)
|
||||
{ return (*z)->nraw_ref(p, l); }
|
||||
static inline object msgpack_unpack_raw(zone** z, const char* b, const char* p, unsigned int l)
|
||||
{ object o; o.type = type::RAW; o.via.ref.ptr = p; o.via.ref.size = l; return o; }
|
||||
|
||||
|
||||
#include "msgpack/unpack_template.h"
|
||||
@ -121,7 +141,7 @@ struct unpacker::context {
|
||||
return msgpack_unpacker_execute(&m_ctx, data, len, off);
|
||||
}
|
||||
|
||||
object_class* data()
|
||||
object data()
|
||||
{
|
||||
return msgpack_unpacker_data(&m_ctx);
|
||||
}
|
||||
@ -158,9 +178,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
unpacker::unpacker() :
|
||||
m_zone(new zone()),
|
||||
m_ctx(new context(m_zone)),
|
||||
unpacker::unpacker(zone& z) :
|
||||
m_ctx(new context(&z)),
|
||||
m_buffer(NULL),
|
||||
m_used(0),
|
||||
m_free(0),
|
||||
@ -170,9 +189,7 @@ unpacker::unpacker() :
|
||||
|
||||
unpacker::~unpacker()
|
||||
{
|
||||
free(m_buffer);
|
||||
delete m_ctx;
|
||||
delete m_zone;
|
||||
}
|
||||
|
||||
|
||||
@ -184,32 +201,16 @@ void unpacker::expand_buffer(size_t len)
|
||||
else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; }
|
||||
while(next_size < len + m_used) { next_size *= 2; }
|
||||
|
||||
char* tmp = (char*)realloc(m_buffer, next_size);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
m_buffer = tmp;
|
||||
//char* tmp = (char*)malloc(next_size);
|
||||
//if(!tmp) { throw std::bad_alloc(); }
|
||||
//memcpy(tmp, m_buffer, m_used);
|
||||
//free(m_buffer);
|
||||
|
||||
m_buffer = tmp;
|
||||
m_buffer = m_ctx->user()->realloc(m_buffer, next_size);
|
||||
m_free = next_size - m_used;
|
||||
|
||||
} else {
|
||||
size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
|
||||
while(next_size < len + m_used - m_off) { next_size *= 2; }
|
||||
|
||||
char* tmp = (char*)malloc(next_size);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
char* tmp = m_ctx->user()->malloc(next_size);
|
||||
memcpy(tmp, m_buffer+m_off, m_used-m_off);
|
||||
|
||||
try {
|
||||
m_zone->push_finalizer<void>(&zone::finalize_free, NULL, m_buffer);
|
||||
} catch (...) {
|
||||
free(tmp);
|
||||
throw;
|
||||
}
|
||||
|
||||
m_buffer = tmp;
|
||||
m_used = m_used - m_off;
|
||||
m_free = next_size - m_used;
|
||||
@ -230,29 +231,15 @@ bool unpacker::execute()
|
||||
}
|
||||
}
|
||||
|
||||
zone* unpacker::release_zone()
|
||||
{
|
||||
zone* nz = new zone();
|
||||
zone* z = m_zone;
|
||||
m_zone = nz;
|
||||
m_ctx->user(m_zone);
|
||||
return z;
|
||||
}
|
||||
|
||||
object unpacker::data()
|
||||
{
|
||||
return object(m_ctx->data());
|
||||
return m_ctx->data();
|
||||
}
|
||||
|
||||
void unpacker::reset()
|
||||
void unpacker::reset(zone& z)
|
||||
{
|
||||
if(m_off != 0) { expand_buffer(0); }
|
||||
if(!m_zone->empty()) {
|
||||
delete m_zone;
|
||||
m_zone = NULL;
|
||||
m_zone = new zone();
|
||||
}
|
||||
m_ctx->reset();
|
||||
m_ctx->reset(&z);
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ struct unpack_error : public std::runtime_error {
|
||||
|
||||
class unpacker {
|
||||
public:
|
||||
unpacker();
|
||||
unpacker(zone& z);
|
||||
~unpacker();
|
||||
|
||||
public:
|
||||
@ -60,13 +60,8 @@ public:
|
||||
/*! 5.1. if execute() returns true, take out the parsed object */
|
||||
object data();
|
||||
|
||||
/*! 5.2. the parsed object is valid until the zone is deleted */
|
||||
// Note that once release_zone() from unpacker, you must delete it
|
||||
// otherwise the memrory will leak.
|
||||
zone* release_zone();
|
||||
|
||||
/*! 5.3. after release_zone(), re-initialize unpacker */
|
||||
void reset();
|
||||
/*! 5.2. re-initialize unpacker with next zone */
|
||||
void reset(zone& z);
|
||||
|
||||
public:
|
||||
// These functions are usable when non-MessagePack message follows after
|
||||
@ -85,8 +80,6 @@ public:
|
||||
void remove_nonparsed_buffer();
|
||||
|
||||
private:
|
||||
zone* m_zone;
|
||||
|
||||
struct context;
|
||||
context* m_ctx;
|
||||
|
||||
@ -94,9 +87,12 @@ private:
|
||||
size_t m_used;
|
||||
size_t m_free;
|
||||
size_t m_off;
|
||||
|
||||
private:
|
||||
void expand_buffer(size_t len);
|
||||
|
||||
private:
|
||||
unpacker();
|
||||
unpacker(const unpacker&);
|
||||
|
||||
public:
|
||||
|
61
cpp/zone.cpp
61
cpp/zone.cpp
@ -20,52 +20,35 @@
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
// FIXME custom allocator?
|
||||
zone::zone() { }
|
||||
|
||||
void zone::expand_chunk()
|
||||
{
|
||||
cell_t* chunk = (cell_t*)malloc(sizeof(cell_t)*ZONE_CHUNK_SIZE);
|
||||
if(!chunk) { throw std::bad_alloc(); }
|
||||
try {
|
||||
m_pool.push_back(chunk);
|
||||
} catch (...) {
|
||||
free(chunk);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
zone::~zone() { clear(); }
|
||||
|
||||
void zone::clear()
|
||||
{
|
||||
if(!m_pool.empty()) {
|
||||
size_t base_size = m_used / ZONE_CHUNK_SIZE;
|
||||
size_t extend_size = m_used % ZONE_CHUNK_SIZE;
|
||||
for(size_t b=0; b < base_size; ++b) {
|
||||
cell_t* c(m_pool[b]);
|
||||
for(size_t e=0; e < ZONE_CHUNK_SIZE; ++e) {
|
||||
reinterpret_cast<object_class*>(c[e].data)->~object_class();
|
||||
for(std::vector<char*>::iterator it(m_ptrs.begin()), it_end(m_ptrs.end());
|
||||
it != it_end; ++it) {
|
||||
free(*it);
|
||||
}
|
||||
m_ptrs.clear();
|
||||
}
|
||||
|
||||
char* zone::realloc(char* ptr, size_t count)
|
||||
{
|
||||
if(ptr == NULL) {
|
||||
return zone::malloc(count);
|
||||
} else {
|
||||
for(std::vector<char*>::reverse_iterator it(m_ptrs.rbegin()), it_end(m_ptrs.rend());
|
||||
it != it_end; ++it) {
|
||||
if(*it == ptr) {
|
||||
char* tmp = (char*)::realloc(ptr, count);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
*it = tmp;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
cell_t* c(m_pool.back());
|
||||
for(size_t e=0; e < extend_size; ++e) {
|
||||
reinterpret_cast<object_class*>(c[e].data)->~object_class();
|
||||
}
|
||||
|
||||
for(pool_t::iterator it(m_pool.begin()), it_end(m_pool.end());
|
||||
it != it_end;
|
||||
++it) {
|
||||
free(*it);
|
||||
}
|
||||
m_pool.clear();
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
m_used = 0;
|
||||
|
||||
for(user_finalizer_t::reverse_iterator it(m_user_finalizer.rbegin()),
|
||||
it_end(m_user_finalizer.rend());
|
||||
it != it_end;
|
||||
++it) {
|
||||
it->call();
|
||||
}
|
||||
m_user_finalizer.clear();
|
||||
}
|
||||
|
||||
|
||||
|
70
cpp/zone.hpp
Normal file
70
cpp/zone.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// MessagePack for C++ memory pool
|
||||
//
|
||||
// Copyright (C) 2008 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_ZONE_HPP__
|
||||
#define MSGPACK_ZONE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class zone {
|
||||
public:
|
||||
zone();
|
||||
~zone();
|
||||
|
||||
public:
|
||||
char* malloc(size_t count);
|
||||
char* realloc(char* ptr, size_t count);
|
||||
object* malloc_container(size_t count);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::vector<char*> m_ptrs;
|
||||
|
||||
private:
|
||||
zone(const zone&);
|
||||
};
|
||||
|
||||
|
||||
inline char* zone::malloc(size_t count)
|
||||
{
|
||||
char* ptr = (char*)::malloc(count);
|
||||
if(!ptr) { throw std::bad_alloc(); }
|
||||
try {
|
||||
m_ptrs.push_back(ptr);
|
||||
} catch (...) {
|
||||
free(ptr);
|
||||
throw;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline object* zone::malloc_container(size_t count)
|
||||
{
|
||||
return (object*)zone::malloc(sizeof(object)*count);
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/zone.hpp */
|
||||
|
202
cpp/zone.hpp.erb
202
cpp/zone.hpp.erb
@ -1,202 +0,0 @@
|
||||
//
|
||||
// MessagePack for C++ memory pool
|
||||
//
|
||||
// Copyright (C) 2008 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_ZONE_HPP__
|
||||
#define MSGPACK_ZONE_HPP__
|
||||
#include <iostream>
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 1024
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
static const size_t ZONE_CHUNK_SIZE = MSGPACK_ZONE_CHUNK_SIZE;
|
||||
|
||||
|
||||
class zone {
|
||||
public:
|
||||
zone() : m_used(0) { }
|
||||
~zone() { clear(); }
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
void push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user);
|
||||
|
||||
public:
|
||||
object_nil* nnil () { return new (alloc()) object_nil(); }
|
||||
object_true* ntrue () { return new (alloc()) object_true(); }
|
||||
object_false* nfalse () { return new (alloc()) object_false(); }
|
||||
object_u8* nu8 (uint8_t v) { return new (alloc()) object_u8(v); }
|
||||
object_u16* nu16 (uint16_t v) { return new (alloc()) object_u16(v); }
|
||||
object_u32* nu32 (uint32_t v) { return new (alloc()) object_u32(v); }
|
||||
object_u64* nu64 (uint64_t v) { return new (alloc()) object_u64(v); }
|
||||
object_i8* ni8 (int8_t v) { return new (alloc()) object_i8(v); }
|
||||
object_i16* ni16 (int16_t v) { return new (alloc()) object_i16(v); }
|
||||
object_i32* ni32 (int32_t v) { return new (alloc()) object_i32(v); }
|
||||
object_i64* ni64 (int64_t v) { return new (alloc()) object_i64(v); }
|
||||
object_float* nfloat (float v) { return new (alloc()) object_float(v); }
|
||||
object_double* ndouble(double v) { return new (alloc()) object_double(v); }
|
||||
|
||||
|
||||
object_mutable_raw_ref* nraw_ref(char* ptr, uint32_t len)
|
||||
{ return new (alloc()) object_mutable_raw_ref(ptr, len); }
|
||||
|
||||
object_raw_ref* nraw_ref(const char* ptr, uint32_t len)
|
||||
{ return new (alloc()) object_raw_ref(ptr, len); }
|
||||
|
||||
object_mutable_raw_ref* nraw_copy(const char* ptr, uint32_t len)
|
||||
{
|
||||
char* copy = (char*)malloc(len);
|
||||
if(!copy) { throw std::bad_alloc(); }
|
||||
object_mutable_raw_ref* o;
|
||||
try {
|
||||
o = new (alloc()) object_mutable_raw_ref(copy, len);
|
||||
push_finalizer<void>(&zone::finalize_free, NULL, copy);
|
||||
} catch (...) {
|
||||
free(copy);
|
||||
throw;
|
||||
}
|
||||
memcpy(copy, ptr, len);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
object_mutable_raw_ref* nraw_cstr_ref(char* str)
|
||||
{ return nraw_ref(str, strlen(str)); }
|
||||
|
||||
object_raw_ref* nraw_cstr_ref(const char* str)
|
||||
{ return nraw_ref(str, strlen(str)); }
|
||||
|
||||
object_mutable_raw_ref* nraw_cstr_copy(const char* str)
|
||||
{ return nraw_copy(str, strlen(str)); }
|
||||
|
||||
|
||||
object_array* narray()
|
||||
{ return new (alloc()) object_array(); }
|
||||
|
||||
object_array* narray(size_t reserve_size)
|
||||
{ return new (alloc()) object_array(reserve_size); }
|
||||
|
||||
object_map* nmap()
|
||||
{ return new (alloc()) object_map(); }
|
||||
|
||||
<% GENERATION_SIZE = 16 %>
|
||||
<% 1.upto(GENERATION_SIZE) {|i| %>
|
||||
object_array* narray(<% 1.upto(i-1) {|n| %>object o<%=n%>, <% } %>object o<%=i%>)
|
||||
{ object_array* a = new (alloc()) object_array(<%=i%>);
|
||||
<% 1.upto(i) {|n| %>a->push_back(o<%=n%>);
|
||||
<% } %>return a; }
|
||||
<% } %>
|
||||
|
||||
<% 1.upto(GENERATION_SIZE) {|i| %>
|
||||
object_map* nmap(<% 1.upto(i-1) {|n| %>object k<%=n%>, object v<%=n%>, <% } %>object k<%=i%>, object v<%=i%>)
|
||||
{ object_map* m = new (alloc()) object_map();
|
||||
<% 1.upto(i) {|n| %>m->store(k<%=n%>, v<%=n%>);
|
||||
<% } %>return m; }
|
||||
<% } %>
|
||||
|
||||
public:
|
||||
void clear();
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
void* alloc();
|
||||
|
||||
private:
|
||||
size_t m_used;
|
||||
|
||||
static const size_t MAX_OBJECT_SIZE =
|
||||
sizeof(object_raw_ref) > sizeof(object_array)
|
||||
? ( sizeof(object_raw_ref) > sizeof(object_map)
|
||||
? sizeof(object_raw_ref)
|
||||
: sizeof(object_map)
|
||||
)
|
||||
: ( sizeof(object_array) > sizeof(object_map)
|
||||
? sizeof(object_array)
|
||||
: sizeof(object_map)
|
||||
)
|
||||
;
|
||||
|
||||
struct cell_t {
|
||||
char data[MAX_OBJECT_SIZE];
|
||||
};
|
||||
|
||||
typedef std::vector<cell_t*> pool_t;
|
||||
pool_t m_pool;
|
||||
|
||||
|
||||
class finalizer {
|
||||
public:
|
||||
finalizer(void (*func)(void*, void*), void* obj, void* user) :
|
||||
m_obj(obj), m_user(user), m_func(func) {}
|
||||
void call() { (*m_func)(m_obj, m_user); }
|
||||
private:
|
||||
void* m_obj;
|
||||
void* m_user;
|
||||
void (*m_func)(void*, void*);
|
||||
};
|
||||
|
||||
typedef std::vector<finalizer> user_finalizer_t;
|
||||
user_finalizer_t m_user_finalizer;
|
||||
|
||||
private:
|
||||
void expand_chunk();
|
||||
|
||||
public:
|
||||
static void finalize_free(void* obj, void* user)
|
||||
{ free(user); }
|
||||
|
||||
private:
|
||||
zone(const zone&);
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline void zone::push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user)
|
||||
{
|
||||
m_user_finalizer.push_back( finalizer(
|
||||
func, reinterpret_cast<void*>(obj),
|
||||
user) );
|
||||
}
|
||||
|
||||
inline bool zone::empty() const
|
||||
{
|
||||
return m_used == 0 && m_user_finalizer.empty();
|
||||
}
|
||||
|
||||
inline void* zone::alloc()
|
||||
{
|
||||
if(m_pool.size() <= m_used/ZONE_CHUNK_SIZE) {
|
||||
expand_chunk();
|
||||
}
|
||||
void* data = m_pool[m_used/ZONE_CHUNK_SIZE][m_used%ZONE_CHUNK_SIZE].data;
|
||||
++m_used;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/zone.hpp */
|
||||
|
@ -146,7 +146,6 @@ msgpack_pack_inline_func(uint32)(msgpack_pack_user x, uint32_t d)
|
||||
|
||||
msgpack_pack_inline_func(uint64)(msgpack_pack_user x, uint64_t d)
|
||||
{
|
||||
// FIXME optimization
|
||||
const unsigned char buf[9] = {0xcf, STORE_BE64(d)};
|
||||
msgpack_pack_append_buffer(x, buf, 9);
|
||||
}
|
||||
@ -177,7 +176,6 @@ msgpack_pack_inline_func(int32)(msgpack_pack_user x, int32_t d)
|
||||
|
||||
msgpack_pack_inline_func(int64)(msgpack_pack_user x, int64_t d)
|
||||
{
|
||||
// FIXME optimization
|
||||
const unsigned char buf[9] = {0xd3, STORE_BE64(d)};
|
||||
msgpack_pack_append_buffer(x, buf, 9);
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ _push:
|
||||
c = &stack[top-1];
|
||||
switch(c->ct) {
|
||||
case CT_ARRAY_ITEM:
|
||||
msgpack_unpack_callback(array_item)(user, c->obj, obj);
|
||||
msgpack_unpack_callback(array_item)(user, &c->obj, obj);
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
@ -292,7 +292,7 @@ _push:
|
||||
c->ct = CT_MAP_VALUE;
|
||||
goto _header_again;
|
||||
case CT_MAP_VALUE:
|
||||
msgpack_unpack_callback(map_item)(user, c->obj, c->map_key, obj);
|
||||
msgpack_unpack_callback(map_item)(user, &c->obj, c->map_key, obj);
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
|
@ -94,14 +94,14 @@ static inline VALUE template_callback_false(msgpack_unpack_context* x)
|
||||
static inline VALUE template_callback_array(msgpack_unpack_context* x, unsigned int n)
|
||||
{ return rb_ary_new2(n); }
|
||||
|
||||
static inline void template_callback_array_item(msgpack_unpack_context* x, VALUE c, VALUE o)
|
||||
{ rb_ary_push(c, o); } // FIXME set value directry RARRAY_PTR(obj)[RARRAY_LEN(obj)++]
|
||||
static inline void template_callback_array_item(msgpack_unpack_context* x, VALUE* c, VALUE o)
|
||||
{ rb_ary_push(*c, o); } // FIXME set value directry RARRAY_PTR(obj)[RARRAY_LEN(obj)++]
|
||||
|
||||
static inline VALUE template_callback_map(msgpack_unpack_context* x, unsigned int n)
|
||||
{ return rb_hash_new(); }
|
||||
|
||||
static inline void template_callback_map_item(msgpack_unpack_context* x, VALUE c, VALUE k, VALUE v)
|
||||
{ rb_hash_aset(c, k, v); }
|
||||
static inline void template_callback_map_item(msgpack_unpack_context* x, VALUE* c, VALUE k, VALUE v)
|
||||
{ rb_hash_aset(*c, k, v); }
|
||||
|
||||
static inline VALUE template_callback_raw(msgpack_unpack_context* x, const char* b, const char* p, unsigned int l)
|
||||
{ return rb_str_new(p, l); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user