summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/Makefile.am21
-rw-r--r--cpp/bench.cpp15
-rw-r--r--cpp/bench.mk2
-rw-r--r--cpp/object.cpp483
-rw-r--r--cpp/object.hpp340
-rw-r--r--cpp/pack.hpp10
-rw-r--r--cpp/test.cpp148
-rw-r--r--cpp/type.hpp9
-rw-r--r--cpp/type/array.hpp59
-rw-r--r--cpp/type/boolean.hpp49
-rw-r--r--cpp/type/float.hpp67
-rw-r--r--cpp/type/integer.hpp243
-rw-r--r--cpp/type/map.hpp132
-rw-r--r--cpp/type/nil.hpp47
-rw-r--r--cpp/type/raw.hpp99
-rw-r--r--cpp/type/tuple.hpp.erb172
-rw-r--r--cpp/unpack.cpp149
-rw-r--r--cpp/unpack.hpp16
-rw-r--r--cpp/zone.cpp57
-rw-r--r--cpp/zone.hpp70
-rw-r--r--cpp/zone.hpp.erb202
21 files changed, 1307 insertions, 1083 deletions
diff --git a/cpp/Makefile.am b/cpp/Makefile.am
index aa22cc7..8b13bea 100644
--- a/cpp/Makefile.am
+++ b/cpp/Makefile.am
@@ -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
diff --git a/cpp/bench.cpp b/cpp/bench.cpp
index 517a870..1aad807 100644
--- a/cpp/bench.cpp
+++ b/cpp/bench.cpp
@@ -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)
diff --git a/cpp/bench.mk b/cpp/bench.mk
index 52a4b80..8da2b7f 100644
--- a/cpp/bench.mk
+++ b/cpp/bench.mk
@@ -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 $@
diff --git a/cpp/object.cpp b/cpp/object.cpp
index ef2a68c..276732c 100644
--- a/cpp/object.cpp
+++ b/cpp/object.cpp
@@ -16,417 +16,128 @@
// limitations under the License.
//
#include "msgpack/object.hpp"
-#include "msgpack/pack.hpp"
-namespace msgpack {
-
-namespace {
-
-template <typename T, typename X, bool TSigned, bool XSigned>
-struct numeric_overflow_signed_impl;
+#include <string.h>
-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; }
- }
- } 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;
- }
-};
+namespace msgpack {
-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; }
- }
- } else if(std::numeric_limits<T>::is_integer) {
- if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; }
- }
- return 0;
- }
-};
-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; }
+std::ostream& operator<< (std::ostream& s, const object o)
+{
+ switch(o.type) {
+ case type::NIL:
+ s << "nil";
+ break;
+
+ 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; }
}
- return 0;
- }
-};
-
-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; }
+ s << "]";
+ break;
+ // FIXME loop optimiziation
+
+ 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 {
- 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(); }
+ default:
+ // FIXME
+ s << "#<UNKNOWN " << (uint16_t)o.type << ">" << std::endl;
}
-};
-
-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)
+ return s;
+}
-#undef FLOAT_OBJECT
+bool operator==(const object x, const object y)
+{
+ if(x.type != y.type) { return false; }
-#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
+ switch(x.type) {
+ case type::NIL:
+ return true;
+ case type::BOOLEAN:
+ return x.via.boolean == y.via.boolean;
-// 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); } )
+ case type::POSITIVE_INTEGER:
+ return x.via.u64 == y.via.u64;
-RAW_OBJECT(raw_ref,
- raw object_raw_ref::xraw() const { return raw(ptr, len); } )
+ case type::NEGATIVE_INTEGER:
+ return x.via.i64 == y.via.i64;
-#undef RAW_OBJECT
+ 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;
-
- 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; }
+ 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 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;
+ // FIXME loop optimiziation
+
+ 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; }
}
- }
- 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);
+ return true;
+
+ default:
+ return false;
}
}
- 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);
- }
-}
+// FIXME
+//template <typename Stream>
+//const object& operator>> (const object& v, packer<Stream>& o);
} // namespace msgpack
diff --git a/cpp/object.hpp b/cpp/object.hpp
index 456210c..7007b90 100644
--- a/cpp/object.hpp
+++ b/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;
-};
+template <typename Stream>
+const object& operator>> (const object& v, packer<Stream>& o);
-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; \
-};
+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;
-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 T>
+ inline T& operator<< (T& v, object o)
+ {
+ v = o;
+ return v;
+ }
-#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; \
-};
+ namespace detail {
+ template <typename Stream, typename T>
+ inline void pack_copy(T v, packer<Stream>& o)
+ { pack(v, o); }
+ }
-FLOAT_CLASS(float, float)
-FLOAT_CLASS(double, double)
+ template <typename Stream, typename T>
+ inline const T& operator>> (const T& v, packer<Stream>& o)
+ {
+ detail::pack_copy(v.pack(), o);
+ return v;
+ }
-#undef FLOAT_CLASS
+} // namespace type
-#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 void convert(T& v, object o)
+{
+ using namespace type;
+ v << o;
+}
-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;
-};
+template <typename Stream, typename T>
+inline void pack(T& v, packer<Stream>& o)
+{
+ using namespace type;
+ v >> o;
+}
-// 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 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 */
diff --git a/cpp/pack.hpp b/cpp/pack.hpp
index f3eeb34..fe470b6 100644
--- a/cpp/pack.hpp
+++ b/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
diff --git a/cpp/test.cpp b/cpp/test.cpp
index 68050a3..dff9101 100644
--- a/cpp/test.cpp
+++ b/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;;
+
+ task.resize(TASK_ARRAY);
+ for(unsigned i=0; i < TASK_ARRAY; ++i) {
+ task[i] = std::string(traw, sizeof(traw));
+ }
}
- {
- tarray[0] = 0xdc;
- uint16_t n = htons(TASK_ARRAY);
- tarray[1] = ((char*)&n)[0];
- tarray[2] = ((char*)&n)[1];
- }
+ std::stringstream stream;
+
+ // send message
{
- // 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);
- }
+ for(unsigned i=0; i < TASK_REPEAT; ++i) {
+ pack(task, stream);
}
+ std::cout << "send " << stream.str().size() << " bytes" << std::endl;
+ }
- stream.seekg(0);
+ ssize_t total_bytes = stream.str().size();
+ stream.seekg(0);
- // reserive message
+ // 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);
}
}
diff --git a/cpp/type.hpp b/cpp/type.hpp
new file mode 100644
index 0000000..1dfd414
--- /dev/null
+++ b/cpp/type.hpp
@@ -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"
+
diff --git a/cpp/type/array.hpp b/cpp/type/array.hpp
new file mode 100644
index 0000000..7066703
--- /dev/null
+++ b/cpp/type/array.hpp
@@ -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 */
+
diff --git a/cpp/type/boolean.hpp b/cpp/type/boolean.hpp
new file mode 100644
index 0000000..0538495
--- /dev/null
+++ b/cpp/type/boolean.hpp
@@ -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 */
+
diff --git a/cpp/type/float.hpp b/cpp/type/float.hpp
new file mode 100644
index 0000000..11fa280
--- /dev/null
+++ b/cpp/type/float.hpp
@@ -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 */
+
diff --git a/cpp/type/integer.hpp b/cpp/type/integer.hpp
new file mode 100644
index 0000000..488c9d4
--- /dev/null
+++ b/cpp/type/integer.hpp
@@ -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 */
+
diff --git a/cpp/type/map.hpp b/cpp/type/map.hpp
new file mode 100644
index 0000000..1efecec
--- /dev/null
+++ b/cpp/type/map.hpp
@@ -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 */
+
diff --git a/cpp/type/nil.hpp b/cpp/type/nil.hpp
new file mode 100644
index 0000000..73cedb4
--- /dev/null
+++ b/cpp/type/nil.hpp
@@ -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 */
+
diff --git a/cpp/type/raw.hpp b/cpp/type/raw.hpp
new file mode 100644
index 0000000..8767238
--- /dev/null
+++ b/cpp/type/raw.hpp
@@ -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 */
+
diff --git a/cpp/type/tuple.hpp.erb b/cpp/type/tuple.hpp.erb
new file mode 100644
index 0000000..2a8a2dd
--- /dev/null
+++ b/cpp/type/tuple.hpp.erb
@@ -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 */
+
+
diff --git a/cpp/unpack.cpp b/cpp/unpack.cpp
index 873d3da..71593a0 100644
--- a/cpp/unpack.cpp
+++ b/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);
}
diff --git a/cpp/unpack.hpp b/cpp/unpack.hpp
index 86cfb6e..2730a08 100644
--- a/cpp/unpack.hpp
+++ b/cpp/unpack.hpp
@@ -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:
diff --git a/cpp/zone.cpp b/cpp/zone.cpp
index 4cc50d7..490bc25 100644
--- a/cpp/zone.cpp
+++ b/cpp/zone.cpp
@@ -20,52 +20,35 @@
namespace msgpack {
-// FIXME custom allocator?
+zone::zone() { }
-void zone::expand_chunk()
+zone::~zone() { clear(); }
+
+void zone::clear()
{
- 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;
+ for(std::vector<char*>::iterator it(m_ptrs.begin()), it_end(m_ptrs.end());
+ it != it_end; ++it) {
+ free(*it);
}
+ m_ptrs.clear();
}
-void zone::clear()
+char* zone::realloc(char* ptr, size_t count)
{
- 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();
+ 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();
- }
- 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();
+ throw std::bad_alloc();
}
- m_user_finalizer.clear();
}
diff --git a/cpp/zone.hpp b/cpp/zone.hpp
new file mode 100644
index 0000000..f8c9cba
--- /dev/null
+++ b/cpp/zone.hpp
@@ -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 */
+
diff --git a/cpp/zone.hpp.erb b/cpp/zone.hpp.erb
deleted file mode 100644
index 8af8da2..0000000
--- a/cpp/zone.hpp.erb
+++ /dev/null
@@ -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 */
-