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:
frsyuki 2009-02-15 09:09:58 +00:00
parent 1222466a1c
commit 9923cf4daf
26 changed files with 1338 additions and 1116 deletions

View File

@ -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); }

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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 $@

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View File

@ -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);
}

View File

@ -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:

View File

@ -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
View 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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;

View File

@ -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); }