summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorfrsyuki <frsyuki@users.sourceforge.jp>2010-05-30 03:02:40 +0900
committerfrsyuki <frsyuki@users.sourceforge.jp>2010-05-30 03:02:40 +0900
commit602971408ba8c2c1490bd87d2987ab65900a5297 (patch)
tree46370064d07f57fe027a8537a730c502d0e71687 /cpp/src
parent2f5d83f07d7a50bfb7287e1fa28bc7a7fd7e7d49 (diff)
downloadmsgpack-python-602971408ba8c2c1490bd87d2987ab65900a5297.tar.gz
cpp: move source files into src/ directory
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Makefile.am75
-rw-r--r--cpp/src/msgpack.h23
-rw-r--r--cpp/src/msgpack.hpp24
-rw-r--r--cpp/src/msgpack/object.h90
-rw-r--r--cpp/src/msgpack/object.hpp412
-rw-r--r--cpp/src/msgpack/pack.h116
-rw-r--r--cpp/src/msgpack/pack.hpp262
-rw-r--r--cpp/src/msgpack/sbuffer.h90
-rw-r--r--cpp/src/msgpack/sbuffer.hpp108
-rw-r--r--cpp/src/msgpack/type.hpp15
-rw-r--r--cpp/src/msgpack/type/bool.hpp55
-rw-r--r--cpp/src/msgpack/type/define.hpp.erb117
-rw-r--r--cpp/src/msgpack/type/deque.hpp77
-rw-r--r--cpp/src/msgpack/type/float.hpp82
-rw-r--r--cpp/src/msgpack/type/int.hpp211
-rw-r--r--cpp/src/msgpack/type/list.hpp77
-rw-r--r--cpp/src/msgpack/type/map.hpp205
-rw-r--r--cpp/src/msgpack/type/nil.hpp65
-rw-r--r--cpp/src/msgpack/type/pair.hpp61
-rw-r--r--cpp/src/msgpack/type/raw.hpp94
-rw-r--r--cpp/src/msgpack/type/set.hpp122
-rw-r--r--cpp/src/msgpack/type/string.hpp62
-rw-r--r--cpp/src/msgpack/type/tr1/unordered_map.hpp129
-rw-r--r--cpp/src/msgpack/type/tr1/unordered_set.hpp122
-rw-r--r--cpp/src/msgpack/type/tuple.hpp.erb191
-rw-r--r--cpp/src/msgpack/type/vector.hpp81
-rw-r--r--cpp/src/msgpack/unpack.h123
-rw-r--r--cpp/src/msgpack/unpack.hpp383
-rw-r--r--cpp/src/msgpack/vrefbuffer.h113
-rw-r--r--cpp/src/msgpack/vrefbuffer.hpp97
-rw-r--r--cpp/src/msgpack/zbuffer.h180
-rw-r--r--cpp/src/msgpack/zbuffer.hpp100
-rw-r--r--cpp/src/msgpack/zone.h131
-rw-r--r--cpp/src/msgpack/zone.hpp.erb148
-rw-r--r--cpp/src/object.cpp87
-rw-r--r--cpp/src/objectc.c237
-rw-r--r--cpp/src/unpack.c399
-rw-r--r--cpp/src/vrefbuffer.c220
-rw-r--r--cpp/src/zone.c220
39 files changed, 5404 insertions, 0 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
new file mode 100644
index 0000000..4cfa87e
--- /dev/null
+++ b/cpp/src/Makefile.am
@@ -0,0 +1,75 @@
+
+lib_LTLIBRARIES = libmsgpack.la
+
+libmsgpack_la_SOURCES = \
+ unpack.c \
+ objectc.c \
+ vrefbuffer.c \
+ zone.c \
+ object.cpp
+
+# -version-info CURRENT:REVISION:AGE
+libmsgpack_la_LDFLAGS = -version-info 3:0:0
+
+
+# backward compatibility
+lib_LTLIBRARIES += libmsgpackc.la
+
+libmsgpackc_la_SOURCES = \
+ unpack.c \
+ objectc.c \
+ vrefbuffer.c \
+ zone.c
+
+libmsgpackc_la_LDFLAGS = -version-info 2:0:0
+
+# work around for duplicated file name
+kumo_manager_CFLAGS = $(AM_CFLAGS)
+kumo_manager_CXXFLAGS = $(AM_CXXFLAGS)
+
+
+nobase_include_HEADERS = \
+ msgpack/pack_define.h \
+ msgpack/pack_template.h \
+ msgpack/unpack_define.h \
+ msgpack/unpack_template.h \
+ msgpack/sysdep.h \
+ msgpack.h \
+ msgpack/sbuffer.h \
+ msgpack/vrefbuffer.h \
+ msgpack/zbuffer.h \
+ msgpack/pack.h \
+ msgpack/unpack.h \
+ msgpack/object.h \
+ msgpack/zone.h \
+ msgpack.hpp \
+ msgpack/sbuffer.hpp \
+ msgpack/vrefbuffer.hpp \
+ msgpack/zbuffer.hpp \
+ msgpack/pack.hpp \
+ msgpack/unpack.hpp \
+ msgpack/object.hpp \
+ msgpack/zone.hpp \
+ msgpack/type.hpp \
+ msgpack/type/bool.hpp \
+ msgpack/type/float.hpp \
+ msgpack/type/int.hpp \
+ msgpack/type/list.hpp \
+ msgpack/type/deque.hpp \
+ msgpack/type/map.hpp \
+ msgpack/type/nil.hpp \
+ msgpack/type/pair.hpp \
+ msgpack/type/raw.hpp \
+ msgpack/type/set.hpp \
+ msgpack/type/string.hpp \
+ msgpack/type/vector.hpp \
+ msgpack/type/tuple.hpp \
+ msgpack/type/define.hpp \
+ msgpack/type/tr1/unordered_map.hpp \
+ msgpack/type/tr1/unordered_set.hpp
+
+EXTRA_DIST = \
+ msgpack/zone.hpp.erb \
+ msgpack/type/define.hpp.erb \
+ msgpack/type/tuple.hpp.erb
+
diff --git a/cpp/src/msgpack.h b/cpp/src/msgpack.h
new file mode 100644
index 0000000..21729f4
--- /dev/null
+++ b/cpp/src/msgpack.h
@@ -0,0 +1,23 @@
+/*
+ * MessagePack for C
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "msgpack/object.h"
+#include "msgpack/zone.h"
+#include "msgpack/pack.h"
+#include "msgpack/unpack.h"
+#include "msgpack/sbuffer.h"
+#include "msgpack/vrefbuffer.h"
diff --git a/cpp/src/msgpack.hpp b/cpp/src/msgpack.hpp
new file mode 100644
index 0000000..e14680d
--- /dev/null
+++ b/cpp/src/msgpack.hpp
@@ -0,0 +1,24 @@
+//
+// MessagePack for C++
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "msgpack/object.hpp"
+#include "msgpack/zone.hpp"
+#include "msgpack/pack.hpp"
+#include "msgpack/unpack.hpp"
+#include "msgpack/sbuffer.hpp"
+#include "msgpack/vrefbuffer.hpp"
+#include "msgpack.h"
diff --git a/cpp/src/msgpack/object.h b/cpp/src/msgpack/object.h
new file mode 100644
index 0000000..71a27bb
--- /dev/null
+++ b/cpp/src/msgpack/object.h
@@ -0,0 +1,90 @@
+/*
+ * MessagePack for C dynamic typing routine
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MSGPACK_OBJECT_H__
+#define MSGPACK_OBJECT_H__
+
+#include "msgpack/zone.h"
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef enum {
+ MSGPACK_OBJECT_NIL = 0x00,
+ MSGPACK_OBJECT_BOOLEAN = 0x01,
+ MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02,
+ MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03,
+ MSGPACK_OBJECT_DOUBLE = 0x04,
+ MSGPACK_OBJECT_RAW = 0x05,
+ MSGPACK_OBJECT_ARRAY = 0x06,
+ MSGPACK_OBJECT_MAP = 0x07,
+} msgpack_object_type;
+
+
+struct msgpack_object;
+struct msgpack_object_kv;
+
+typedef struct {
+ uint32_t size;
+ struct msgpack_object* ptr;
+} msgpack_object_array;
+
+typedef struct {
+ uint32_t size;
+ struct msgpack_object_kv* ptr;
+} msgpack_object_map;
+
+typedef struct {
+ uint32_t size;
+ const char* ptr;
+} msgpack_object_raw;
+
+typedef union {
+ bool boolean;
+ uint64_t u64;
+ int64_t i64;
+ double dec;
+ msgpack_object_array array;
+ msgpack_object_map map;
+ msgpack_object_raw raw;
+} msgpack_object_union;
+
+typedef struct msgpack_object {
+ msgpack_object_type type;
+ msgpack_object_union via;
+} msgpack_object;
+
+typedef struct msgpack_object_kv {
+ msgpack_object key;
+ msgpack_object val;
+} msgpack_object_kv;
+
+
+void msgpack_object_print(FILE* out, msgpack_object o);
+
+bool msgpack_object_equal(const msgpack_object x, const msgpack_object y);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/object.h */
+
diff --git a/cpp/src/msgpack/object.hpp b/cpp/src/msgpack/object.hpp
new file mode 100644
index 0000000..f80a390
--- /dev/null
+++ b/cpp/src/msgpack/object.hpp
@@ -0,0 +1,412 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_OBJECT_HPP__
+#define MSGPACK_OBJECT_HPP__
+
+#include "msgpack/object.h"
+#include "msgpack/pack.hpp"
+#include "msgpack/zone.hpp"
+#include <string.h>
+#include <stdexcept>
+#include <typeinfo>
+#include <limits>
+#include <ostream>
+
+namespace msgpack {
+
+
+class type_error : public std::bad_cast { };
+
+
+namespace type {
+ enum object_type {
+ NIL = MSGPACK_OBJECT_NIL,
+ BOOLEAN = MSGPACK_OBJECT_BOOLEAN,
+ POSITIVE_INTEGER = MSGPACK_OBJECT_POSITIVE_INTEGER,
+ NEGATIVE_INTEGER = MSGPACK_OBJECT_NEGATIVE_INTEGER,
+ DOUBLE = MSGPACK_OBJECT_DOUBLE,
+ RAW = MSGPACK_OBJECT_RAW,
+ ARRAY = MSGPACK_OBJECT_ARRAY,
+ MAP = MSGPACK_OBJECT_MAP,
+ };
+}
+
+
+struct object;
+struct object_kv;
+
+struct object_array {
+ uint32_t size;
+ object* ptr;
+};
+
+struct object_map {
+ uint32_t size;
+ object_kv* ptr;
+};
+
+struct object_raw {
+ uint32_t size;
+ const char* ptr;
+};
+
+struct object {
+ union union_type {
+ bool boolean;
+ uint64_t u64;
+ int64_t i64;
+ double dec;
+ object_array array;
+ object_map map;
+ object_raw raw;
+ object_raw ref; // obsolete
+ };
+
+ type::object_type type;
+ union_type via;
+
+ bool is_nil() const { return type == type::NIL; }
+
+ template <typename T>
+ T as() const;
+
+ template <typename T>
+ void convert(T* v) const;
+
+ object();
+
+ object(msgpack_object o);
+
+ template <typename T>
+ explicit object(const T& v);
+
+ template <typename T>
+ object(const T& v, zone* z);
+
+ template <typename T>
+ object& operator=(const T& v);
+
+ operator msgpack_object() const;
+
+ struct with_zone;
+
+private:
+ struct implicit_type;
+
+public:
+ implicit_type convert() const;
+};
+
+struct object_kv {
+ object key;
+ object val;
+};
+
+struct object::with_zone : object {
+ with_zone(msgpack::zone* zone) : zone(zone) { }
+ msgpack::zone* zone;
+private:
+ with_zone();
+};
+
+
+bool operator==(const object x, const object y);
+bool operator!=(const object x, const object y);
+
+template <typename T>
+bool operator==(const object x, const T& y);
+
+template <typename T>
+bool operator==(const T& y, const object x);
+
+template <typename T>
+bool operator!=(const object x, const T& y);
+
+template <typename T>
+bool operator!=(const T& y, const object x);
+
+std::ostream& operator<< (std::ostream& s, const object o);
+
+
+// serialize operator
+template <typename Stream, typename T>
+packer<Stream>& operator<< (packer<Stream>& o, const T& v);
+
+// convert operator
+template <typename T>
+T& operator>> (object o, T& v);
+
+// deconvert operator
+template <typename T>
+void operator<< (object::with_zone& o, const T& v);
+
+
+struct object::implicit_type {
+ implicit_type(object o) : obj(o) { }
+ ~implicit_type() { }
+
+ template <typename T>
+ operator T() { return obj.as<T>(); }
+
+private:
+ object obj;
+};
+
+
+// obsolete
+template <typename Type>
+class define : public Type {
+public:
+ typedef Type msgpack_type;
+ typedef define<Type> define_type;
+
+ define() {}
+ define(const msgpack_type& v) : msgpack_type(v) {}
+
+ template <typename Packer>
+ void msgpack_pack(Packer& o) const
+ {
+ o << static_cast<const msgpack_type&>(*this);
+ }
+
+ void msgpack_unpack(object o)
+ {
+ o >> static_cast<msgpack_type&>(*this);
+ }
+};
+
+
+template <typename Stream>
+template <typename T>
+inline packer<Stream>& packer<Stream>::pack(const T& v)
+{
+ *this << v;
+ return *this;
+}
+
+inline object& operator>> (object o, object& v)
+{
+ v = o;
+ return v;
+}
+
+template <typename T>
+inline T& operator>> (object o, T& v)
+{
+ v.msgpack_unpack(o.convert());
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const T& v)
+{
+ v.msgpack_pack(o);
+ return o;
+}
+
+template <typename T>
+void operator<< (object::with_zone& o, const T& v)
+{
+ v.msgpack_object(static_cast<object*>(&o), o.zone);
+}
+
+
+inline bool operator==(const object x, const object y)
+{
+ return msgpack_object_equal(x, y);
+}
+
+template <typename T>
+inline bool operator==(const object x, const T& y)
+try {
+ return x == object(y);
+} catch (msgpack::type_error&) {
+ return false;
+}
+
+inline bool operator!=(const object x, const object y)
+{ return !(x == y); }
+
+template <typename T>
+inline bool operator==(const T& y, const object x)
+{ return x == y; }
+
+template <typename T>
+inline bool operator!=(const object x, const T& y)
+{ return !(x == y); }
+
+template <typename T>
+inline bool operator!=(const T& y, const object x)
+{ return x != y; }
+
+
+inline object::implicit_type object::convert() const
+{
+ return implicit_type(*this);
+}
+
+template <typename T>
+inline void object::convert(T* v) const
+{
+ *this >> *v;
+}
+
+template <typename T>
+inline T object::as() const
+{
+ T v;
+ convert(&v);
+ return v;
+}
+
+
+inline object::object()
+{
+ type = type::NIL;
+}
+
+template <typename T>
+inline object::object(const T& v)
+{
+ *this << v;
+}
+
+template <typename T>
+inline object& object::operator=(const T& v)
+{
+ *this = object(v);
+ return *this;
+}
+
+template <typename T>
+object::object(const T& v, zone* z)
+{
+ with_zone oz(z);
+ oz << v;
+ type = oz.type;
+ via = oz.via;
+}
+
+
+inline object::object(msgpack_object o)
+{
+ // FIXME beter way?
+ ::memcpy(this, &o, sizeof(o));
+}
+
+inline void operator<< (object& o, msgpack_object v)
+{
+ // FIXME beter way?
+ ::memcpy(&o, &v, sizeof(v));
+}
+
+inline object::operator msgpack_object() const
+{
+ // FIXME beter way?
+ msgpack_object obj;
+ ::memcpy(&obj, this, sizeof(obj));
+ return obj;
+}
+
+
+// obsolete
+template <typename T>
+inline void convert(T& v, object o)
+{
+ o.convert(&v);
+}
+
+// obsolete
+template <typename Stream, typename T>
+inline void pack(packer<Stream>& o, const T& v)
+{
+ o.pack(v);
+}
+
+// obsolete
+template <typename Stream, typename T>
+inline void pack_copy(packer<Stream>& o, T v)
+{
+ pack(o, v);
+}
+
+
+template <typename Stream>
+packer<Stream>& operator<< (packer<Stream>& o, const object& v)
+{
+ switch(v.type) {
+ case type::NIL:
+ o.pack_nil();
+ return o;
+
+ case type::BOOLEAN:
+ if(v.via.boolean) {
+ o.pack_true();
+ } else {
+ o.pack_false();
+ }
+ return o;
+
+ case type::POSITIVE_INTEGER:
+ o.pack_uint64(v.via.u64);
+ return o;
+
+ case type::NEGATIVE_INTEGER:
+ o.pack_int64(v.via.i64);
+ return o;
+
+ case type::DOUBLE:
+ o.pack_double(v.via.dec);
+ return o;
+
+ case type::RAW:
+ o.pack_raw(v.via.raw.size);
+ o.pack_raw_body(v.via.raw.ptr, v.via.raw.size);
+ return o;
+
+ case type::ARRAY:
+ o.pack_array(v.via.array.size);
+ for(object* p(v.via.array.ptr),
+ * const pend(v.via.array.ptr + v.via.array.size);
+ p < pend; ++p) {
+ o << *p;
+ }
+ return o;
+
+ case type::MAP:
+ o.pack_map(v.via.map.size);
+ for(object_kv* p(v.via.map.ptr),
+ * const pend(v.via.map.ptr + v.via.map.size);
+ p < pend; ++p) {
+ o << p->key;
+ o << p->val;
+ }
+ return o;
+
+ default:
+ throw type_error();
+ }
+}
+
+
+} // namespace msgpack
+
+#include "msgpack/type.hpp"
+
+#endif /* msgpack/object.hpp */
+
diff --git a/cpp/src/msgpack/pack.h b/cpp/src/msgpack/pack.h
new file mode 100644
index 0000000..1525e0f
--- /dev/null
+++ b/cpp/src/msgpack/pack.h
@@ -0,0 +1,116 @@
+/*
+ * MessagePack for C packing routine
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MSGPACK_PACK_H__
+#define MSGPACK_PACK_H__
+
+#include "msgpack/pack_define.h"
+#include "msgpack/object.h"
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef int (*msgpack_packer_write)(void* data, const char* buf, unsigned int len);
+
+typedef struct msgpack_packer {
+ void* data;
+ msgpack_packer_write callback;
+} msgpack_packer;
+
+static void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback);
+
+static msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback);
+static void msgpack_packer_free(msgpack_packer* pk);
+
+static int msgpack_pack_short(msgpack_packer* pk, short d);
+static int msgpack_pack_int(msgpack_packer* pk, int d);
+static int msgpack_pack_long(msgpack_packer* pk, long d);
+static int msgpack_pack_long_long(msgpack_packer* pk, long long d);
+static int msgpack_pack_unsigned_short(msgpack_packer* pk, unsigned short d);
+static int msgpack_pack_unsigned_int(msgpack_packer* pk, unsigned int d);
+static int msgpack_pack_unsigned_long(msgpack_packer* pk, unsigned long d);
+static int msgpack_pack_unsigned_long_long(msgpack_packer* pk, unsigned long long d);
+
+static int msgpack_pack_uint8(msgpack_packer* pk, uint8_t d);
+static int msgpack_pack_uint16(msgpack_packer* pk, uint16_t d);
+static int msgpack_pack_uint32(msgpack_packer* pk, uint32_t d);
+static int msgpack_pack_uint64(msgpack_packer* pk, uint64_t d);
+static int msgpack_pack_int8(msgpack_packer* pk, int8_t d);
+static int msgpack_pack_int16(msgpack_packer* pk, int16_t d);
+static int msgpack_pack_int32(msgpack_packer* pk, int32_t d);
+static int msgpack_pack_int64(msgpack_packer* pk, int64_t d);
+
+static int msgpack_pack_float(msgpack_packer* pk, float d);
+static int msgpack_pack_double(msgpack_packer* pk, double d);
+
+static int msgpack_pack_nil(msgpack_packer* pk);
+static int msgpack_pack_true(msgpack_packer* pk);
+static int msgpack_pack_false(msgpack_packer* pk);
+
+static int msgpack_pack_array(msgpack_packer* pk, unsigned int n);
+
+static int msgpack_pack_map(msgpack_packer* pk, unsigned int n);
+
+static int msgpack_pack_raw(msgpack_packer* pk, size_t l);
+static int msgpack_pack_raw_body(msgpack_packer* pk, const void* b, size_t l);
+
+int msgpack_pack_object(msgpack_packer* pk, msgpack_object d);
+
+
+
+#define msgpack_pack_inline_func(name) \
+ inline int msgpack_pack ## name
+
+#define msgpack_pack_inline_func_cint(name) \
+ inline int msgpack_pack ## name
+
+#define msgpack_pack_user msgpack_packer*
+
+#define msgpack_pack_append_buffer(user, buf, len) \
+ return (*(user)->callback)((user)->data, (const char*)buf, len)
+
+#include "msgpack/pack_template.h"
+
+inline void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback)
+{
+ pk->data = data;
+ pk->callback = callback;
+}
+
+inline msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback)
+{
+ msgpack_packer* pk = (msgpack_packer*)calloc(1, sizeof(msgpack_packer));
+ if(!pk) { return NULL; }
+ msgpack_packer_init(pk, data, callback);
+ return pk;
+}
+
+inline void msgpack_packer_free(msgpack_packer* pk)
+{
+ free(pk);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/pack.h */
+
diff --git a/cpp/src/msgpack/pack.hpp b/cpp/src/msgpack/pack.hpp
new file mode 100644
index 0000000..ee90690
--- /dev/null
+++ b/cpp/src/msgpack/pack.hpp
@@ -0,0 +1,262 @@
+//
+// MessagePack for C++ serializing routine
+//
+// Copyright (C) 2008-2010 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_PACK_HPP__
+#define MSGPACK_PACK_HPP__
+
+#include "msgpack/pack_define.h"
+#include <stdexcept>
+#include <limits.h>
+
+namespace msgpack {
+
+
+template <typename Stream>
+class packer {
+public:
+ packer(Stream* s);
+ packer(Stream& s);
+ ~packer();
+
+public:
+ template <typename T>
+ packer<Stream>& pack(const T& v);
+
+ packer<Stream>& pack_uint8(uint8_t d);
+ packer<Stream>& pack_uint16(uint16_t d);
+ packer<Stream>& pack_uint32(uint32_t d);
+ packer<Stream>& pack_uint64(uint64_t d);
+ packer<Stream>& pack_int8(int8_t d);
+ packer<Stream>& pack_int16(int16_t d);
+ packer<Stream>& pack_int32(int32_t d);
+ packer<Stream>& pack_int64(int64_t d);
+
+ packer<Stream>& pack_short(short d);
+ packer<Stream>& pack_int(int d);
+ packer<Stream>& pack_long(long d);
+ packer<Stream>& pack_long_long(long long d);
+ packer<Stream>& pack_unsigned_short(unsigned short d);
+ packer<Stream>& pack_unsigned_int(unsigned int d);
+ packer<Stream>& pack_unsigned_long(unsigned long d);
+ packer<Stream>& pack_unsigned_long_long(unsigned long long d);
+
+ packer<Stream>& pack_float(float d);
+ packer<Stream>& pack_double(double d);
+
+ packer<Stream>& pack_nil();
+ packer<Stream>& pack_true();
+ packer<Stream>& pack_false();
+
+ packer<Stream>& pack_array(unsigned int n);
+
+ packer<Stream>& pack_map(unsigned int n);
+
+ packer<Stream>& pack_raw(size_t l);
+ packer<Stream>& pack_raw_body(const char* b, size_t l);
+
+private:
+ static void _pack_uint8(Stream& x, uint8_t d);
+ static void _pack_uint16(Stream& x, uint16_t d);
+ static void _pack_uint32(Stream& x, uint32_t d);
+ static void _pack_uint64(Stream& x, uint64_t d);
+ static void _pack_int8(Stream& x, int8_t d);
+ static void _pack_int16(Stream& x, int16_t d);
+ static void _pack_int32(Stream& x, int32_t d);
+ static void _pack_int64(Stream& x, int64_t d);
+
+ static void _pack_short(Stream& x, short d);
+ static void _pack_int(Stream& x, int d);
+ static void _pack_long(Stream& x, long d);
+ static void _pack_long_long(Stream& x, long long d);
+ static void _pack_unsigned_short(Stream& x, unsigned short d);
+ static void _pack_unsigned_int(Stream& x, unsigned int d);
+ static void _pack_unsigned_long(Stream& x, unsigned long d);
+ static void _pack_unsigned_long_long(Stream& x, unsigned long long d);
+
+ static void _pack_float(Stream& x, float d);
+ static void _pack_double(Stream& x, double d);
+
+ static void _pack_nil(Stream& x);
+ static void _pack_true(Stream& x);
+ static void _pack_false(Stream& x);
+
+ static void _pack_array(Stream& x, unsigned int n);
+
+ static void _pack_map(Stream& x, unsigned int n);
+
+ static void _pack_raw(Stream& x, size_t l);
+ static void _pack_raw_body(Stream& x, const void* b, size_t l);
+
+ static void append_buffer(Stream& x, const unsigned char* buf, unsigned int len)
+ { x.write((const char*)buf, len); }
+
+private:
+ Stream& m_stream;
+
+private:
+ packer();
+};
+
+
+template <typename Stream, typename T>
+inline void pack(Stream* s, const T& v)
+{
+ packer<Stream>(s).pack(v);
+}
+
+template <typename Stream, typename T>
+inline void pack(Stream& s, const T& v)
+{
+ packer<Stream>(s).pack(v);
+}
+
+
+#define msgpack_pack_inline_func(name) \
+ template <typename Stream> \
+ inline void packer<Stream>::_pack ## name
+
+#define msgpack_pack_inline_func_cint(name) \
+ template <typename Stream> \
+ inline void packer<Stream>::_pack ## name
+
+#define msgpack_pack_user Stream&
+
+#define msgpack_pack_append_buffer append_buffer
+
+#include "msgpack/pack_template.h"
+
+
+template <typename Stream>
+packer<Stream>::packer(Stream* s) : m_stream(*s) { }
+
+template <typename Stream>
+packer<Stream>::packer(Stream& s) : m_stream(s) { }
+
+template <typename Stream>
+packer<Stream>::~packer() { }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_uint8(uint8_t d)
+{ _pack_uint8(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_uint16(uint16_t d)
+{ _pack_uint16(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_uint32(uint32_t d)
+{ _pack_uint32(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_uint64(uint64_t d)
+{ _pack_uint64(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_int8(int8_t d)
+{ _pack_int8(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_int16(int16_t d)
+{ _pack_int16(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_int32(int32_t d)
+{ _pack_int32(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_int64(int64_t d)
+{ _pack_int64(m_stream, d); return *this;}
+
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_short(short d)
+{ _pack_short(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_int(int d)
+{ _pack_int(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_long(long d)
+{ _pack_long(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_long_long(long long d)
+{ _pack_long_long(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_unsigned_short(unsigned short d)
+{ _pack_unsigned_short(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_unsigned_int(unsigned int d)
+{ _pack_unsigned_int(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_unsigned_long(unsigned long d)
+{ _pack_unsigned_long(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_unsigned_long_long(unsigned long long d)
+{ _pack_unsigned_long_long(m_stream, d); return *this; }
+
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_float(float d)
+{ _pack_float(m_stream, d); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_double(double d)
+{ _pack_double(m_stream, d); return *this; }
+
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_nil()
+{ _pack_nil(m_stream); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_true()
+{ _pack_true(m_stream); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_false()
+{ _pack_false(m_stream); return *this; }
+
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_array(unsigned int n)
+{ _pack_array(m_stream, n); return *this; }
+
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_map(unsigned int n)
+{ _pack_map(m_stream, n); return *this; }
+
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_raw(size_t l)
+{ _pack_raw(m_stream, l); return *this; }
+
+template <typename Stream>
+inline packer<Stream>& packer<Stream>::pack_raw_body(const char* b, size_t l)
+{ _pack_raw_body(m_stream, b, l); return *this; }
+
+
+} // namespace msgpack
+
+#endif /* msgpack/pack.hpp */
+
diff --git a/cpp/src/msgpack/sbuffer.h b/cpp/src/msgpack/sbuffer.h
new file mode 100644
index 0000000..57f424a
--- /dev/null
+++ b/cpp/src/msgpack/sbuffer.h
@@ -0,0 +1,90 @@
+/*
+ * MessagePack for C simple buffer implementation
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MSGPACK_SBUFFER_H__
+#define MSGPACK_SBUFFER_H__
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef MSGPACK_SBUFFER_INIT_SIZE
+#define MSGPACK_SBUFFER_INIT_SIZE 8192
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct msgpack_sbuffer {
+ size_t size;
+ char* data;
+ size_t alloc;
+} msgpack_sbuffer;
+
+static inline void msgpack_sbuffer_init(msgpack_sbuffer* sbuf)
+{
+ memset(sbuf, 0, sizeof(msgpack_sbuffer));
+}
+
+static inline void msgpack_sbuffer_destroy(msgpack_sbuffer* sbuf)
+{
+ free(sbuf->data);
+}
+
+static inline int msgpack_sbuffer_write(void* data, const char* buf, unsigned int len)
+{
+ msgpack_sbuffer* sbuf = (msgpack_sbuffer*)data;
+
+ if(sbuf->alloc - sbuf->size < len) {
+ size_t nsize = (sbuf->alloc) ?
+ sbuf->alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
+
+ while(nsize < sbuf->size + len) { nsize *= 2; }
+
+ void* tmp = realloc(sbuf->data, nsize);
+ if(!tmp) { return -1; }
+
+ sbuf->data = (char*)tmp;
+ sbuf->alloc = nsize;
+ }
+
+ memcpy(sbuf->data + sbuf->size, buf, len);
+ sbuf->size += len;
+ return 0;
+}
+
+static inline char* msgpack_sbuffer_release(msgpack_sbuffer* sbuf)
+{
+ char* tmp = sbuf->data;
+ sbuf->size = 0;
+ sbuf->data = NULL;
+ sbuf->alloc = 0;
+ return tmp;
+}
+
+static inline void msgpack_sbuffer_clear(msgpack_sbuffer* sbuf)
+{
+ sbuf->size = 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/sbuffer.h */
+
diff --git a/cpp/src/msgpack/sbuffer.hpp b/cpp/src/msgpack/sbuffer.hpp
new file mode 100644
index 0000000..e4a3f96
--- /dev/null
+++ b/cpp/src/msgpack/sbuffer.hpp
@@ -0,0 +1,108 @@
+//
+// MessagePack for C++ simple buffer implementation
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_SBUFFER_HPP__
+#define MSGPACK_SBUFFER_HPP__
+
+#include "msgpack/sbuffer.h"
+#include <stdexcept>
+
+namespace msgpack {
+
+
+class sbuffer : public msgpack_sbuffer {
+public:
+ sbuffer(size_t initsz = MSGPACK_SBUFFER_INIT_SIZE)
+ {
+ base::data = (char*)::malloc(initsz);
+ if(!base::data) {
+ throw std::bad_alloc();
+ }
+
+ base::size = 0;
+ base::alloc = initsz;
+ }
+
+ ~sbuffer()
+ {
+ ::free(base::data);
+ }
+
+public:
+ void write(const char* buf, unsigned int len)
+ {
+ if(base::alloc - base::size < len) {
+ expand_buffer(len);
+ }
+ memcpy(base::data + base::size, buf, len);
+ base::size += len;
+ }
+
+ char* data()
+ {
+ return base::data;
+ }
+
+ const char* data() const
+ {
+ return base::data;
+ }
+
+ size_t size() const
+ {
+ return base::size;
+ }
+
+ char* release()
+ {
+ return msgpack_sbuffer_release(this);
+ }
+
+ void clear()
+ {
+ msgpack_sbuffer_clear(this);
+ }
+
+private:
+ void expand_buffer(size_t len)
+ {
+ size_t nsize = (base::alloc) ?
+ base::alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
+
+ while(nsize < base::size + len) { nsize *= 2; }
+
+ void* tmp = realloc(base::data, nsize);
+ if(!tmp) {
+ throw std::bad_alloc();
+ }
+
+ base::data = (char*)tmp;
+ base::alloc = nsize;
+ }
+
+private:
+ typedef msgpack_sbuffer base;
+
+private:
+ sbuffer(const sbuffer&);
+};
+
+
+} // namespace msgpack
+
+#endif /* msgpack/sbuffer.hpp */
+
diff --git a/cpp/src/msgpack/type.hpp b/cpp/src/msgpack/type.hpp
new file mode 100644
index 0000000..fafa674
--- /dev/null
+++ b/cpp/src/msgpack/type.hpp
@@ -0,0 +1,15 @@
+#include "msgpack/type/bool.hpp"
+#include "msgpack/type/float.hpp"
+#include "msgpack/type/int.hpp"
+#include "msgpack/type/list.hpp"
+#include "msgpack/type/deque.hpp"
+#include "msgpack/type/map.hpp"
+#include "msgpack/type/nil.hpp"
+#include "msgpack/type/pair.hpp"
+#include "msgpack/type/raw.hpp"
+#include "msgpack/type/set.hpp"
+#include "msgpack/type/string.hpp"
+#include "msgpack/type/vector.hpp"
+#include "msgpack/type/tuple.hpp"
+#include "msgpack/type/define.hpp"
+
diff --git a/cpp/src/msgpack/type/bool.hpp b/cpp/src/msgpack/type/bool.hpp
new file mode 100644
index 0000000..9433a98
--- /dev/null
+++ b/cpp/src/msgpack/type/bool.hpp
@@ -0,0 +1,55 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_BOOL_HPP__
+#define MSGPACK_TYPE_BOOL_HPP__
+
+#include "msgpack/object.hpp"
+#include <vector>
+
+namespace msgpack {
+
+
+inline bool& operator>> (object o, bool& v)
+{
+ if(o.type != type::BOOLEAN) { throw type_error(); }
+ v = o.via.boolean;
+ return v;
+}
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const bool& v)
+{
+ if(v) { o.pack_true(); }
+ else { o.pack_false(); }
+ return o;
+}
+
+inline void operator<< (object& o, bool v)
+{
+ o.type = type::BOOLEAN;
+ o.via.boolean = v;
+}
+
+inline void operator<< (object::with_zone& o, bool v)
+ { static_cast<object&>(o) << v; }
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/bool.hpp */
+
diff --git a/cpp/src/msgpack/type/define.hpp.erb b/cpp/src/msgpack/type/define.hpp.erb
new file mode 100644
index 0000000..9db6f08
--- /dev/null
+++ b/cpp/src/msgpack/type/define.hpp.erb
@@ -0,0 +1,117 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_DEFINE_HPP__
+#define MSGPACK_TYPE_DEFINE_HPP__
+
+#define MSGPACK_DEFINE(...) \
+ template <typename Packer> \
+ void msgpack_pack(Packer& pk) const \
+ { \
+ msgpack::type::make_define(__VA_ARGS__).msgpack_pack(pk); \
+ } \
+ void msgpack_unpack(msgpack::object o) \
+ { \
+ msgpack::type::make_define(__VA_ARGS__).msgpack_unpack(o); \
+ }\
+ template <typename MSGPACK_OBJECT> \
+ void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone* z) const \
+ { \
+ msgpack::type::make_define(__VA_ARGS__).msgpack_object(o, z); \
+ }
+
+namespace msgpack {
+namespace type {
+
+
+<% GENERATION_LIMIT = 31 %>
+template <typename A0 = void<%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%>>
+struct define;
+
+
+template <>
+struct define<> {
+ typedef define<> value_type;
+ typedef tuple<> tuple_type;
+ template <typename Packer>
+ void msgpack_pack(Packer& pk) const
+ {
+ pk.pack_array(1);
+ }
+ void msgpack_unpack(msgpack::object o)
+ {
+ if(o.type != type::ARRAY) { throw type_error(); }
+ }
+ void msgpack_object(msgpack::object* o, msgpack::zone* z) const
+ {
+ o->type = type::ARRAY;
+ o->via.array.ptr = NULL;
+ o->via.array.size = 0;
+ }
+};
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+struct define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
+ typedef define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> value_type;
+ typedef tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> tuple_type;
+ define(A0& _a0<%1.upto(i) {|j|%>, A<%=j%>& _a<%=j%><%}%>) :
+ a0(_a0)<%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {}
+ template <typename Packer>
+ void msgpack_pack(Packer& pk) const
+ {
+ pk.pack_array(<%=i+1%>);
+ <%0.upto(i) {|j|%>
+ pk.pack(a<%=j%>);<%}%>
+ }
+ void msgpack_unpack(msgpack::object o)
+ {
+ if(o.type != type::ARRAY) { throw type_error(); }
+ const size_t size = o.via.array.size;
+ <%0.upto(i) {|j|%>
+ if(size <= <%=j%>) { return; } o.via.array.ptr[<%=j%>].convert(&a<%=j%>);<%}%>
+ }
+ void msgpack_object(msgpack::object* o, msgpack::zone* z) const
+ {
+ o->type = type::ARRAY;
+ o->via.array.ptr = (object*)z->malloc(sizeof(object)*<%=i+1%>);
+ o->via.array.size = <%=i+1%>;
+ <%0.upto(i) {|j|%>
+ o->via.array.ptr[<%=j%>] = object(a<%=j%>, z);<%}%>
+ }
+ <%0.upto(i) {|j|%>
+ A<%=j%>& a<%=j%>;<%}%>
+};
+<%}%>
+
+inline define<> make_define()
+{
+ return define<>();
+}
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_define(A0& a0<%1.upto(i) {|j|%>, A<%=j%>& a<%=j%><%}%>)
+{
+ return define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
+}
+<%}%>
+
+} // namespace type
+} // namespace msgpack
+
+
+#endif /* msgpack/type/define.hpp */
+
diff --git a/cpp/src/msgpack/type/deque.hpp b/cpp/src/msgpack/type/deque.hpp
new file mode 100644
index 0000000..d21ceea
--- /dev/null
+++ b/cpp/src/msgpack/type/deque.hpp
@@ -0,0 +1,77 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_DEQUE_HPP__
+#define MSGPACK_TYPE_DEQUE_HPP__
+
+#include "msgpack/object.hpp"
+#include <deque>
+
+namespace msgpack {
+
+
+template <typename T>
+inline std::deque<T>& operator>> (object o, std::deque<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ v.resize(o.via.array.size);
+ object* p = o.via.array.ptr;
+ object* const pend = o.via.array.ptr + o.via.array.size;
+ typename std::deque<T>::iterator it = v.begin();
+ for(; p < pend; ++p, ++it) {
+ p->convert(&*it);
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::deque<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::deque<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::deque<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::deque<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/deque.hpp */
+
diff --git a/cpp/src/msgpack/type/float.hpp b/cpp/src/msgpack/type/float.hpp
new file mode 100644
index 0000000..a60ef0b
--- /dev/null
+++ b/cpp/src/msgpack/type/float.hpp
@@ -0,0 +1,82 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_FLOAT_HPP__
+#define MSGPACK_TYPE_FLOAT_HPP__
+
+#include "msgpack/object.hpp"
+#include <vector>
+
+namespace msgpack {
+
+
+// FIXME check overflow, underflow
+
+
+inline float& operator>> (object o, float& v)
+{
+ if(o.type != type::DOUBLE) { throw type_error(); }
+ v = o.via.dec;
+ return v;
+}
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const float& v)
+{
+ o.pack_float(v);
+ return o;
+}
+
+
+inline double& operator>> (object o, double& v)
+{
+ if(o.type != type::DOUBLE) { throw type_error(); }
+ v = o.via.dec;
+ return v;
+}
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const double& v)
+{
+ o.pack_double(v);
+ return o;
+}
+
+
+inline void operator<< (object& o, float v)
+{
+ o.type = type::DOUBLE;
+ o.via.dec = v;
+}
+
+inline void operator<< (object& o, double v)
+{
+ o.type = type::DOUBLE;
+ o.via.dec = v;
+}
+
+inline void operator<< (object::with_zone& o, float v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, double v)
+ { static_cast<object&>(o) << v; }
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/float.hpp */
+
diff --git a/cpp/src/msgpack/type/int.hpp b/cpp/src/msgpack/type/int.hpp
new file mode 100644
index 0000000..e2d1820
--- /dev/null
+++ b/cpp/src/msgpack/type/int.hpp
@@ -0,0 +1,211 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_INT_HPP__
+#define MSGPACK_TYPE_INT_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 == 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 == type::NEGATIVE_INTEGER) {
+ if(o.via.i64 < (int64_t)std::numeric_limits<T>::min())
+ { 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 == 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);
+ }
+
+} // namespace detail
+} // namespace type
+
+
+inline signed char& operator>> (object o, signed char& v)
+ { v = type::detail::convert_integer<signed char>(o); return v; }
+
+inline signed short& operator>> (object o, signed short& v)
+ { v = type::detail::convert_integer<signed short>(o); return v; }
+
+inline signed int& operator>> (object o, signed int& v)
+ { v = type::detail::convert_integer<signed int>(o); return v; }
+
+inline signed long& operator>> (object o, signed long& v)
+ { v = type::detail::convert_integer<signed long>(o); return v; }
+
+inline signed long long& operator>> (object o, signed long long& v)
+ { v = type::detail::convert_integer<signed long long>(o); return v; }
+
+
+inline unsigned char& operator>> (object o, unsigned char& v)
+ { v = type::detail::convert_integer<unsigned char>(o); return v; }
+
+inline unsigned short& operator>> (object o, unsigned short& v)
+ { v = type::detail::convert_integer<unsigned short>(o); return v; }
+
+inline unsigned int& operator>> (object o, unsigned int& v)
+ { v = type::detail::convert_integer<unsigned int>(o); return v; }
+
+inline unsigned long& operator>> (object o, unsigned long& v)
+ { v = type::detail::convert_integer<unsigned long>(o); return v; }
+
+inline unsigned long long& operator>> (object o, unsigned long long& v)
+ { v = type::detail::convert_integer<unsigned long long>(o); return v; }
+
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const signed char& v)
+ { o.pack_int8(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const signed short& v)
+ { o.pack_short(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const signed int& v)
+ { o.pack_int(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const signed long& v)
+ { o.pack_long(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const signed long long& v)
+ { o.pack_long_long(v); return o; }
+
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned char& v)
+ { o.pack_uint8(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned short& v)
+ { o.pack_unsigned_short(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned int& v)
+ { o.pack_unsigned_int(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned long& v)
+ { o.pack_unsigned_long(v); return o; }
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned long long& v)
+ { o.pack_unsigned_long_long(v); return o; }
+
+
+inline void operator<< (object& o, signed char v)
+ { v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, signed short v)
+ { v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, signed int v)
+ { v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, signed long v)
+ { v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, signed long long v)
+ { v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+
+inline void operator<< (object& o, unsigned char v)
+ { o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, unsigned short v)
+ { o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, unsigned int v)
+ { o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, unsigned long v)
+ { o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+inline void operator<< (object& o, unsigned long long v)
+ { o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
+
+
+inline void operator<< (object::with_zone& o, signed char v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, signed short v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, signed int v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, signed long v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, signed long long v)
+ { static_cast<object&>(o) << v; }
+
+
+inline void operator<< (object::with_zone& o, unsigned char v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, unsigned short v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, unsigned int v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, unsigned long v)
+ { static_cast<object&>(o) << v; }
+
+inline void operator<< (object::with_zone& o, unsigned long long v)
+ { static_cast<object&>(o) << v; }
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/int.hpp */
+
diff --git a/cpp/src/msgpack/type/list.hpp b/cpp/src/msgpack/type/list.hpp
new file mode 100644
index 0000000..c0f8ce6
--- /dev/null
+++ b/cpp/src/msgpack/type/list.hpp
@@ -0,0 +1,77 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_LIST_HPP__
+#define MSGPACK_TYPE_LIST_HPP__
+
+#include "msgpack/object.hpp"
+#include <list>
+
+namespace msgpack {
+
+
+template <typename T>
+inline std::list<T>& operator>> (object o, std::list<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ v.resize(o.via.array.size);
+ object* p = o.via.array.ptr;
+ object* const pend = o.via.array.ptr + o.via.array.size;
+ typename std::list<T>::iterator it = v.begin();
+ for(; p < pend; ++p, ++it) {
+ p->convert(&*it);
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::list<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::list<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::list<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::list<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/list.hpp */
+
diff --git a/cpp/src/msgpack/type/map.hpp b/cpp/src/msgpack/type/map.hpp
new file mode 100644
index 0000000..958447d
--- /dev/null
+++ b/cpp/src/msgpack/type/map.hpp
@@ -0,0 +1,205 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_MAP_HPP__
+#define MSGPACK_TYPE_MAP_HPP__
+
+#include "msgpack/object.hpp"
+#include <map>
+#include <vector>
+#include <algorithm>
+
+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; }
+ };
+}
+
+} //namespace type
+
+
+template <typename K, typename V>
+inline type::assoc_vector<K,V>& operator>> (object o, type::assoc_vector<K,V>& v)
+{
+ if(o.type != type::MAP) { throw type_error(); }
+ v.resize(o.via.map.size);
+ object_kv* p = o.via.map.ptr;
+ object_kv* const pend = o.via.map.ptr + o.via.map.size;
+ std::pair<K, V>* it(&v.front());
+ for(; p < pend; ++p, ++it) {
+ p->key.convert(&it->first);
+ p->val.convert(&it->second);
+ }
+ std::sort(v.begin(), v.end(), type::detail::pair_first_less<K,V>());
+ return v;
+}
+
+template <typename Stream, typename K, typename V>
+inline packer<Stream>& operator<< (packer<Stream>& o, const type::assoc_vector<K,V>& v)
+{
+ o.pack_map(v.size());
+ for(typename type::assoc_vector<K,V>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(it->first);
+ o.pack(it->second);
+ }
+ return o;
+}
+
+template <typename K, typename V>
+inline void operator<< (object::with_zone& o, const type::assoc_vector<K,V>& v)
+{
+ o.type = type::MAP;
+ if(v.empty()) {
+ o.via.map.ptr = NULL;
+ o.via.map.size = 0;
+ } else {
+ object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
+ object_kv* const pend = p + v.size();
+ o.via.map.ptr = p;
+ o.via.map.size = v.size();
+ typename type::assoc_vector<K,V>::const_iterator it(v.begin());
+ do {
+ p->key = object(it->first, o.zone);
+ p->val = object(it->second, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+template <typename K, typename V>
+inline std::map<K, V> operator>> (object o, std::map<K, V>& v)
+{
+ if(o.type != type::MAP) { throw type_error(); }
+ object_kv* p(o.via.map.ptr);
+ object_kv* const pend(o.via.map.ptr + o.via.map.size);
+ for(; p != pend; ++p) {
+ K key;
+ p->key.convert(&key);
+ typename std::map<K,V>::iterator it(v.lower_bound(key));
+ if(it != v.end() && !(key < it->first)) {
+ p->val.convert(&it->second);
+ } else {
+ V val;
+ p->val.convert(&val);
+ v.insert(it, std::pair<K,V>(key, val));
+ }
+ }
+ return v;
+}
+
+template <typename Stream, typename K, typename V>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::map<K,V>& v)
+{
+ o.pack_map(v.size());
+ for(typename std::map<K,V>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(it->first);
+ o.pack(it->second);
+ }
+ return o;
+}
+
+template <typename K, typename V>
+inline void operator<< (object::with_zone& o, const std::map<K,V>& v)
+{
+ o.type = type::MAP;
+ if(v.empty()) {
+ o.via.map.ptr = NULL;
+ o.via.map.size = 0;
+ } else {
+ object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
+ object_kv* const pend = p + v.size();
+ o.via.map.ptr = p;
+ o.via.map.size = v.size();
+ typename std::map<K,V>::const_iterator it(v.begin());
+ do {
+ p->key = object(it->first, o.zone);
+ p->val = object(it->second, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+template <typename K, typename V>
+inline std::multimap<K, V> operator>> (object o, std::multimap<K, V>& v)
+{
+ if(o.type != type::MAP) { throw type_error(); }
+ object_kv* p(o.via.map.ptr);
+ object_kv* const pend(o.via.map.ptr + o.via.map.size);
+ for(; p != pend; ++p) {
+ std::pair<K, V> value;
+ p->key.convert(&value.first);
+ p->val.convert(&value.second);
+ v.insert(value);
+ }
+ return v;
+}
+
+template <typename Stream, typename K, typename V>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::multimap<K,V>& v)
+{
+ o.pack_map(v.size());
+ for(typename std::multimap<K,V>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(it->first);
+ o.pack(it->second);
+ }
+ return o;
+}
+
+template <typename K, typename V>
+inline void operator<< (object::with_zone& o, const std::multimap<K,V>& v)
+{
+ o.type = type::MAP;
+ if(v.empty()) {
+ o.via.map.ptr = NULL;
+ o.via.map.size = 0;
+ } else {
+ object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
+ object_kv* const pend = p + v.size();
+ o.via.map.ptr = p;
+ o.via.map.size = v.size();
+ typename std::multimap<K,V>::const_iterator it(v.begin());
+ do {
+ p->key = object(it->first, o.zone);
+ p->val = object(it->second, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/map.hpp */
+
diff --git a/cpp/src/msgpack/type/nil.hpp b/cpp/src/msgpack/type/nil.hpp
new file mode 100644
index 0000000..f44e45e
--- /dev/null
+++ b/cpp/src/msgpack/type/nil.hpp
@@ -0,0 +1,65 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_NIL_HPP__
+#define MSGPACK_TYPE_NIL_HPP__
+
+#include "msgpack/object.hpp"
+
+namespace msgpack {
+
+namespace type {
+
+struct nil { };
+
+} // namespace type
+
+
+inline type::nil& operator>> (object o, type::nil& v)
+{
+ if(o.type != type::NIL) { throw type_error(); }
+ return v;
+}
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const type::nil& v)
+{
+ o.pack_nil();
+ return o;
+}
+
+inline void operator<< (object& o, type::nil v)
+{
+ o.type = type::NIL;
+}
+
+inline void operator<< (object::with_zone& o, type::nil v)
+ { static_cast<object&>(o) << v; }
+
+
+template <>
+inline void object::as<void>() const
+{
+ msgpack::type::nil v;
+ convert(&v);
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/nil.hpp */
+
diff --git a/cpp/src/msgpack/type/pair.hpp b/cpp/src/msgpack/type/pair.hpp
new file mode 100644
index 0000000..296a8b6
--- /dev/null
+++ b/cpp/src/msgpack/type/pair.hpp
@@ -0,0 +1,61 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_PAIR_HPP__
+#define MSGPACK_TYPE_PAIR_HPP__
+
+#include "msgpack/object.hpp"
+#include <utility>
+
+namespace msgpack {
+
+
+template <typename T1, typename T2>
+inline std::pair<T1, T2>& operator>> (object o, std::pair<T1, T2>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ if(o.via.array.size != 2) { throw type_error(); }
+ o.via.array.ptr[0].convert(&v.first);
+ o.via.array.ptr[1].convert(&v.second);
+ return v;
+}
+
+template <typename Stream, typename T1, typename T2>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::pair<T1, T2>& v)
+{
+ o.pack_array(2);
+ o.pack(v.first);
+ o.pack(v.second);
+ return o;
+}
+
+template <typename T1, typename T2>
+inline void operator<< (object::with_zone& o, const std::pair<T1, T2>& v)
+{
+ o.type = type::ARRAY;
+ object* p = (object*)o.zone->malloc(sizeof(object)*2);
+ o.via.array.ptr = p;
+ o.via.array.size = 2;
+ p[0] = object(v.first, o.zone);
+ p[1] = object(v.second, o.zone);
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/pair.hpp */
+
diff --git a/cpp/src/msgpack/type/raw.hpp b/cpp/src/msgpack/type/raw.hpp
new file mode 100644
index 0000000..21d9a0d
--- /dev/null
+++ b/cpp/src/msgpack/type/raw.hpp
@@ -0,0 +1,94 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_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() : size(0), ptr(NULL) {}
+ raw_ref(const char* p, uint32_t s) : size(s), ptr(p) {}
+
+ uint32_t size;
+ const char* ptr;
+
+ 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; }
+ }
+};
+
+} // namespace type
+
+
+inline type::raw_ref& operator>> (object o, type::raw_ref& v)
+{
+ if(o.type != type::RAW) { throw type_error(); }
+ v.ptr = o.via.raw.ptr;
+ v.size = o.via.raw.size;
+ return v;
+}
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const type::raw_ref& v)
+{
+ o.pack_raw(v.size);
+ o.pack_raw_body(v.ptr, v.size);
+ return o;
+}
+
+inline void operator<< (object& o, const type::raw_ref& v)
+{
+ o.type = type::RAW;
+ o.via.raw.ptr = v.ptr;
+ o.via.raw.size = v.size;
+}
+
+inline void operator<< (object::with_zone& o, const type::raw_ref& v)
+ { static_cast<object&>(o) << v; }
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/raw.hpp */
+
diff --git a/cpp/src/msgpack/type/set.hpp b/cpp/src/msgpack/type/set.hpp
new file mode 100644
index 0000000..bcf1030
--- /dev/null
+++ b/cpp/src/msgpack/type/set.hpp
@@ -0,0 +1,122 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_SET_HPP__
+#define MSGPACK_TYPE_SET_HPP__
+
+#include "msgpack/object.hpp"
+#include <set>
+
+namespace msgpack {
+
+
+template <typename T>
+inline std::set<T>& operator>> (object o, std::set<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ object* p = o.via.array.ptr + o.via.array.size;
+ object* const pbegin = o.via.array.ptr;
+ while(p > pbegin) {
+ --p;
+ v.insert(p->as<T>());
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::set<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::set<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::set<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::set<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+template <typename T>
+inline std::multiset<T>& operator>> (object o, std::multiset<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ object* p = o.via.array.ptr + o.via.array.size;
+ object* const pbegin = o.via.array.ptr;
+ while(p > pbegin) {
+ --p;
+ v.insert(p->as<T>());
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::multiset<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::multiset<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::multiset<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::multiset<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/set.hpp */
+
diff --git a/cpp/src/msgpack/type/string.hpp b/cpp/src/msgpack/type/string.hpp
new file mode 100644
index 0000000..f11a5e6
--- /dev/null
+++ b/cpp/src/msgpack/type/string.hpp
@@ -0,0 +1,62 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_STRING_HPP__
+#define MSGPACK_TYPE_STRING_HPP__
+
+#include "msgpack/object.hpp"
+#include <string>
+
+namespace msgpack {
+
+
+inline std::string& operator>> (object o, std::string& v)
+{
+ if(o.type != type::RAW) { throw type_error(); }
+ v.assign(o.via.raw.ptr, o.via.raw.size);
+ return v;
+}
+
+template <typename Stream>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::string& v)
+{
+ o.pack_raw(v.size());
+ o.pack_raw_body(v.data(), v.size());
+ return o;
+}
+
+inline void operator<< (object::with_zone& o, const std::string& v)
+{
+ o.type = type::RAW;
+ char* ptr = (char*)o.zone->malloc(v.size());
+ o.via.raw.ptr = ptr;
+ o.via.raw.size = v.size();
+ memcpy(ptr, v.data(), v.size());
+}
+
+inline void operator<< (object& o, const std::string& v)
+{
+ o.type = type::RAW;
+ o.via.raw.ptr = v.data();
+ o.via.raw.size = v.size();
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/string.hpp */
+
diff --git a/cpp/src/msgpack/type/tr1/unordered_map.hpp b/cpp/src/msgpack/type/tr1/unordered_map.hpp
new file mode 100644
index 0000000..4b29f0c
--- /dev/null
+++ b/cpp/src/msgpack/type/tr1/unordered_map.hpp
@@ -0,0 +1,129 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_TR1_UNORDERED_MAP_HPP__
+#define MSGPACK_TYPE_TR1_UNORDERED_MAP_HPP__
+
+#include "msgpack/object.hpp"
+#include <tr1/unordered_map>
+
+namespace msgpack {
+
+
+template <typename K, typename V>
+inline std::tr1::unordered_map<K, V> operator>> (object o, std::tr1::unordered_map<K, V>& v)
+{
+ if(o.type != type::MAP) { throw type_error(); }
+ object_kv* p(o.via.map.ptr);
+ object_kv* const pend(o.via.map.ptr + o.via.map.size);
+ for(; p != pend; ++p) {
+ K key;
+ p->key.convert(&key);
+ p->val.convert(&v[key]);
+ }
+ return v;
+}
+
+template <typename Stream, typename K, typename V>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_map<K,V>& v)
+{
+ o.pack_map(v.size());
+ for(typename std::tr1::unordered_map<K,V>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(it->first);
+ o.pack(it->second);
+ }
+ return o;
+}
+
+template <typename K, typename V>
+inline void operator<< (object::with_zone& o, const std::tr1::unordered_map<K,V>& v)
+{
+ o.type = type::MAP;
+ if(v.empty()) {
+ o.via.map.ptr = NULL;
+ o.via.map.size = 0;
+ } else {
+ object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
+ object_kv* const pend = p + v.size();
+ o.via.map.ptr = p;
+ o.via.map.size = v.size();
+ typename std::tr1::unordered_map<K,V>::const_iterator it(v.begin());
+ do {
+ p->key = object(it->first, o.zone);
+ p->val = object(it->second, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+template <typename K, typename V>
+inline std::tr1::unordered_multimap<K, V> operator>> (object o, std::tr1::unordered_multimap<K, V>& v)
+{
+ if(o.type != type::MAP) { throw type_error(); }
+ object_kv* p(o.via.map.ptr);
+ object_kv* const pend(o.via.map.ptr + o.via.map.size);
+ for(; p != pend; ++p) {
+ std::pair<K, V> value;
+ p->key.convert(&value.first);
+ p->val.convert(&value.second);
+ v.insert(value);
+ }
+ return v;
+}
+
+template <typename Stream, typename K, typename V>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_multimap<K,V>& v)
+{
+ o.pack_map(v.size());
+ for(typename std::tr1::unordered_multimap<K,V>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(it->first);
+ o.pack(it->second);
+ }
+ return o;
+}
+
+template <typename K, typename V>
+inline void operator<< (object::with_zone& o, const std::tr1::unordered_multimap<K,V>& v)
+{
+ o.type = type::MAP;
+ if(v.empty()) {
+ o.via.map.ptr = NULL;
+ o.via.map.size = 0;
+ } else {
+ object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
+ object_kv* const pend = p + v.size();
+ o.via.map.ptr = p;
+ o.via.map.size = v.size();
+ typename std::tr1::unordered_multimap<K,V>::const_iterator it(v.begin());
+ do {
+ p->key = object(it->first, o.zone);
+ p->val = object(it->second, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/map.hpp */
+
diff --git a/cpp/src/msgpack/type/tr1/unordered_set.hpp b/cpp/src/msgpack/type/tr1/unordered_set.hpp
new file mode 100644
index 0000000..4af6801
--- /dev/null
+++ b/cpp/src/msgpack/type/tr1/unordered_set.hpp
@@ -0,0 +1,122 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_TR1_UNORDERED_SET_HPP__
+#define MSGPACK_TYPE_TR1_UNORDERED_SET_HPP__
+
+#include "msgpack/object.hpp"
+#include <tr1/unordered_set>
+
+namespace msgpack {
+
+
+template <typename T>
+inline std::tr1::unordered_set<T>& operator>> (object o, std::tr1::unordered_set<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ object* p = o.via.array.ptr + o.via.array.size;
+ object* const pbegin = o.via.array.ptr;
+ while(p > pbegin) {
+ --p;
+ v.insert(p->as<T>());
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_set<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::tr1::unordered_set<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::tr1::unordered_set<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::tr1::unordered_set<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+template <typename T>
+inline std::tr1::unordered_multiset<T>& operator>> (object o, std::tr1::unordered_multiset<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ object* p = o.via.array.ptr + o.via.array.size;
+ object* const pbegin = o.via.array.ptr;
+ while(p > pbegin) {
+ --p;
+ v.insert(p->as<T>());
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_multiset<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::tr1::unordered_multiset<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::tr1::unordered_multiset<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::tr1::unordered_multiset<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/set.hpp */
+
diff --git a/cpp/src/msgpack/type/tuple.hpp.erb b/cpp/src/msgpack/type/tuple.hpp.erb
new file mode 100644
index 0000000..0d9ae91
--- /dev/null
+++ b/cpp/src/msgpack/type/tuple.hpp.erb
@@ -0,0 +1,191 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_TUPLE_HPP__
+#define MSGPACK_TYPE_TUPLE_HPP__
+
+#include "msgpack/object.hpp"
+
+namespace msgpack {
+
+namespace type {
+
+// FIXME operator==
+// FIXME operator!=
+<% GENERATION_LIMIT = 31 %>
+
+template <typename A0 = void<%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%>>
+struct tuple;
+
+template <typename Tuple, int N>
+struct tuple_element;
+
+template <typename Tuple, int N>
+struct const_tuple_element;
+
+template <typename T>
+struct tuple_type {
+ typedef T type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef const T& transparent_reference;
+};
+
+template <typename T>
+struct tuple_type<T&> {
+ typedef T type;
+ typedef T& value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T& transparent_reference;
+};
+
+template <typename T>
+struct tuple_type<const T&> {
+ typedef T type;
+ typedef T& value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef const T& transparent_reference;
+};
+
+<%0.upto(GENERATION_LIMIT) {|i|%>
+<%0.upto(i) {|j|%>
+template <typename A0<%1.upto(i) {|k|%>, typename A<%=k%><%}%>>
+struct tuple_element<tuple<A0<%1.upto(i) {|k|%>, A<%=k%><%}%>>, <%=j%>> : tuple_type<A<%=j%>> {
+ tuple_element(tuple<A0<%1.upto(i) {|k|%>, A<%=k%> <%}%>>& x) : _x(x.a<%=j%>) {}
+ typename tuple_type<A<%=j%>>::reference get() { return _x; }
+ typename tuple_type<A<%=j%>>::const_reference get() const { return _x; }
+private:
+ typename tuple_type<A<%=j%>>::reference _x;
+};
+<%}%>
+<%}%>
+
+<%0.upto(GENERATION_LIMIT) {|i|%>
+<%0.upto(i) {|j|%>
+template <typename A0<%1.upto(i) {|k|%>, typename A<%=k%><%}%>>
+struct const_tuple_element<tuple<A0<%1.upto(i) {|k|%>, A<%=k%><%}%>>, <%=j%>> : tuple_type<A<%=j%>> {
+ const_tuple_element(const tuple<A0<%1.upto(i) {|k|%>, A<%=k%><%}%>>& x) : _x(x.a<%=j%>) {}
+ typename tuple_type<A<%=j%>>::const_reference get() const { return _x; }
+private:
+ typename tuple_type<A<%=j%>>::const_reference _x;
+};
+<%}%>
+<%}%>
+
+template <>
+struct tuple<> {
+ tuple() {}
+ tuple(object o) { o.convert(this); }
+ typedef tuple<> value_type;
+};
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+struct tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
+ typedef tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> value_type;
+ tuple() {}
+ tuple(typename tuple_type<A0>::transparent_reference _a0<%1.upto(i) {|j|%>, typename tuple_type<A<%=j%>>::transparent_reference _a<%=j%><%}%>) :
+ a0(_a0)<%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {}
+ tuple(object o) { o.convert(this); }
+ template <int N> typename tuple_element<value_type, N>::reference get()
+ { return tuple_element<value_type, N>(*this).get(); }
+ template <int N> typename const_tuple_element<value_type, N>::const_reference get() const
+ { return const_tuple_element<value_type, N>(*this).get(); }
+ <%0.upto(i) {|j|%>
+ A<%=j%> a<%=j%>;<%}%>
+};
+<%}%>
+
+inline tuple<> make_tuple()
+{
+ return tuple<>();
+}
+<%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(typename tuple_type<A0>::transparent_reference a0<%1.upto(i) {|j|%>, typename tuple_type<A<%=j%>>::transparent_reference a<%=j%><%}%>)
+{
+ return tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
+}
+<%}%>
+
+} // namespace type
+
+
+inline type::tuple<>& operator>> (
+ object o,
+ type::tuple<>& v) {
+ if(o.type != type::ARRAY) { throw type_error(); }
+ return v;
+}
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& operator>> (
+ object o,
+ type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
+ if(o.type != type::ARRAY) { throw type_error(); }
+ if(o.via.array.size < <%=i+1%>) { throw type_error(); }
+ <%0.upto(i) {|j|%>
+ o.via.array.ptr[<%=j%>].convert<typename type::tuple_type<A<%=j%>>::type>(&v.template get<<%=j%>>());<%}%>
+ return v;
+}
+<%}%>
+
+template <typename Stream>
+const packer<Stream>& operator<< (
+ packer<Stream>& o,
+ const type::tuple<>& v) {
+ o.pack_array(0);
+ return o;
+}
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename Stream, typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+const packer<Stream>& operator<< (
+ packer<Stream>& o,
+ const type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
+ o.pack_array(<%=i+1%>);
+ <%0.upto(i) {|j|%>
+ o.pack(v.template get<<%=j%>>());<%}%>
+ return o;
+}
+<%}%>
+
+inline void operator<< (
+ object::with_zone& o,
+ const type::tuple<>& v) {
+ o.type = type::ARRAY;
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+}
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+inline void operator<< (
+ object::with_zone& o,
+ const type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
+ o.type = type::ARRAY;
+ o.via.array.ptr = (object*)o.zone->malloc(sizeof(object)*<%=i+1%>);
+ o.via.array.size = <%=i+1%>;
+ <%0.upto(i) {|j|%>
+ o.via.array.ptr[<%=j%>] = object(v.template get<<%=j%>>(), o.zone);<%}%>
+}
+<%}%>
+
+} // namespace msgpack
+
+#endif /* msgpack/type/tuple.hpp */
+
diff --git a/cpp/src/msgpack/type/vector.hpp b/cpp/src/msgpack/type/vector.hpp
new file mode 100644
index 0000000..bd073ef
--- /dev/null
+++ b/cpp/src/msgpack/type/vector.hpp
@@ -0,0 +1,81 @@
+//
+// MessagePack for C++ static resolution routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_TYPE_VECTOR_HPP__
+#define MSGPACK_TYPE_VECTOR_HPP__
+
+#include "msgpack/object.hpp"
+#include <vector>
+
+namespace msgpack {
+
+
+template <typename T>
+inline std::vector<T>& operator>> (object o, std::vector<T>& v)
+{
+ if(o.type != type::ARRAY) { throw type_error(); }
+ v.resize(o.via.array.size);
+ if(o.via.array.size > 0) {
+ object* p = o.via.array.ptr;
+ object* const pend = o.via.array.ptr + o.via.array.size;
+ T* it = &v[0];
+ do {
+ p->convert(it);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+ return v;
+}
+
+template <typename Stream, typename T>
+inline packer<Stream>& operator<< (packer<Stream>& o, const std::vector<T>& v)
+{
+ o.pack_array(v.size());
+ for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end());
+ it != it_end; ++it) {
+ o.pack(*it);
+ }
+ return o;
+}
+
+template <typename T>
+inline void operator<< (object::with_zone& o, const std::vector<T>& v)
+{
+ o.type = type::ARRAY;
+ if(v.empty()) {
+ o.via.array.ptr = NULL;
+ o.via.array.size = 0;
+ } else {
+ object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
+ object* const pend = p + v.size();
+ o.via.array.ptr = p;
+ o.via.array.size = v.size();
+ typename std::vector<T>::const_iterator it(v.begin());
+ do {
+ *p = object(*it, o.zone);
+ ++p;
+ ++it;
+ } while(p < pend);
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/type/vector.hpp */
+
diff --git a/cpp/src/msgpack/unpack.h b/cpp/src/msgpack/unpack.h
new file mode 100644
index 0000000..e17d0d8
--- /dev/null
+++ b/cpp/src/msgpack/unpack.h
@@ -0,0 +1,123 @@
+/*
+ * MessagePack for C unpacking routine
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MSGPACK_UNPACKER_H__
+#define MSGPACK_UNPACKER_H__
+
+#include "msgpack/zone.h"
+#include "msgpack/object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct msgpack_unpacker {
+ char* buffer;
+ size_t used;
+ size_t free;
+ size_t off;
+ size_t parsed;
+ msgpack_zone* z;
+ size_t initial_buffer_size;
+ void* ctx;
+} msgpack_unpacker;
+
+
+bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
+void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
+
+msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
+void msgpack_unpacker_free(msgpack_unpacker* mpac);
+
+static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
+static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac);
+static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac);
+static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size);
+
+
+int msgpack_unpacker_execute(msgpack_unpacker* mpac);
+
+msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
+
+msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
+
+void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac);
+
+void msgpack_unpacker_reset(msgpack_unpacker* mpac);
+
+static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac);
+
+
+
+typedef enum {
+ MSGPACK_UNPACK_SUCCESS = 2,
+ MSGPACK_UNPACK_EXTRA_BYTES = 1,
+ MSGPACK_UNPACK_CONTINUE = 0,
+ MSGPACK_UNPACK_PARSE_ERROR = -1,
+} msgpack_unpack_return;
+
+msgpack_unpack_return
+msgpack_unpack(const char* data, size_t len, size_t* off,
+ msgpack_zone* z, msgpack_object* result);
+
+
+static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
+
+bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
+
+bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
+
+bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
+{
+ if(mpac->free >= size) { return true; }
+ return msgpack_unpacker_expand_buffer(mpac, size);
+}
+
+char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
+{
+ return mpac->buffer + mpac->used;
+}
+
+size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
+{
+ return mpac->free;
+}
+
+void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
+{
+ mpac->used += size;
+ mpac->free -= size;
+}
+
+size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
+{
+ return mpac->parsed - mpac->off + mpac->used;
+}
+
+size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac)
+{
+ return mpac->parsed;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/unpack.h */
+
diff --git a/cpp/src/msgpack/unpack.hpp b/cpp/src/msgpack/unpack.hpp
new file mode 100644
index 0000000..56ce0f6
--- /dev/null
+++ b/cpp/src/msgpack/unpack.hpp
@@ -0,0 +1,383 @@
+//
+// MessagePack for C++ deserializing routine
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_UNPACK_HPP__
+#define MSGPACK_UNPACK_HPP__
+
+#include "msgpack/unpack.h"
+#include "msgpack/object.hpp"
+#include "msgpack/zone.hpp"
+#include <memory>
+#include <stdexcept>
+
+#ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
+#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE (32*1024)
+#endif
+
+namespace msgpack {
+
+
+struct unpack_error : public std::runtime_error {
+ unpack_error(const std::string& msg) :
+ std::runtime_error(msg) { }
+};
+
+
+class unpacked {
+public:
+ unpacked() { }
+
+ unpacked(object obj, std::auto_ptr<msgpack::zone> z) :
+ m_obj(obj), m_zone(z) { }
+
+ object& get()
+ { return m_obj; }
+
+ const object& get() const
+ { return m_obj; }
+
+ std::auto_ptr<msgpack::zone>& zone()
+ { return m_zone; }
+
+ const std::auto_ptr<msgpack::zone>& zone() const
+ { return m_zone; }
+
+private:
+ object m_obj;
+ std::auto_ptr<msgpack::zone> m_zone;
+};
+
+
+class unpacker : public msgpack_unpacker {
+public:
+ unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
+ ~unpacker();
+
+public:
+ /*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
+ void reserve_buffer(size_t size);
+
+ /*! 2. read data to the buffer() up to buffer_capacity() bytes */
+ char* buffer();
+ size_t buffer_capacity() const;
+
+ /*! 3. specify the number of bytes actually copied */
+ void buffer_consumed(size_t size);
+
+ /*! 4. repeat next() until it retunrs false */
+ bool next(unpacked* result);
+
+ /*! 5. check if the size of message doesn't exceed assumption. */
+ size_t message_size() const;
+
+ // Basic usage of the unpacker is as following:
+ //
+ // msgpack::unpacker pac;
+ // while( /* input is readable */ ) {
+ //
+ // // 1.
+ // pac.reserve_buffer(32*1024);
+ //
+ // // 2.
+ // size_t bytes = input.readsome(pac.buffer(), pac.buffer_capacity());
+ //
+ // // error handling ...
+ //
+ // // 3.
+ // pac.buffer_consumed(bytes);
+ //
+ // // 4.
+ // msgpack::unpacked result;
+ // while(pac.next(&result)) {
+ // // do some with the object with the zone.
+ // msgpack::object obj = result.get();
+ // std::auto_ptr<msgpack:zone> z = result.zone();
+ // on_message(obj, z);
+ //
+ // //// boost::shared_ptr is also usable:
+ // // boost::shared_ptr<msgpack::zone> life(z.release());
+ // // on_message(result.get(), life);
+ // }
+ //
+ // // 5.
+ // if(pac.message_size() > 10*1024*1024) {
+ // throw std::runtime_error("message is too large");
+ // }
+ // }
+ //
+
+ /*! for backward compatibility */
+ bool execute();
+
+ /*! for backward compatibility */
+ object data();
+
+ /*! for backward compatibility */
+ zone* release_zone();
+
+ /*! for backward compatibility */
+ void reset_zone();
+
+ /*! for backward compatibility */
+ void reset();
+
+public:
+ // These functions are usable when non-MessagePack message follows after
+ // MessagePack message.
+ size_t parsed_size() const;
+
+ /*! get address of the buffer that is not parsed */
+ char* nonparsed_buffer();
+ size_t nonparsed_size() const;
+
+ /*! skip specified size of non-parsed buffer, leaving the buffer */
+ // Note that the `size' argument must be smaller than nonparsed_size()
+ void skip_nonparsed_buffer(size_t size);
+
+ /*! remove unparsed buffer from unpacker */
+ // Note that reset() leaves non-parsed buffer.
+ void remove_nonparsed_buffer();
+
+private:
+ typedef msgpack_unpacker base;
+
+private:
+ unpacker(const unpacker&);
+};
+
+
+static bool unpack(unpacked* result,
+ const char* data, size_t len, size_t* offset = NULL);
+
+
+// obsolete
+typedef enum {
+ UNPACK_SUCCESS = 2,
+ UNPACK_EXTRA_BYTES = 1,
+ UNPACK_CONTINUE = 0,
+ UNPACK_PARSE_ERROR = -1,
+} unpack_return;
+
+// obsolete
+static unpack_return unpack(const char* data, size_t len, size_t* off,
+ zone* z, object* result);
+
+
+// obsolete
+static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
+
+
+inline unpacker::unpacker(size_t initial_buffer_size)
+{
+ if(!msgpack_unpacker_init(this, initial_buffer_size)) {
+ throw std::bad_alloc();
+ }
+}
+
+inline unpacker::~unpacker()
+{
+ msgpack_unpacker_destroy(this);
+}
+
+
+inline void unpacker::reserve_buffer(size_t size)
+{
+ if(!msgpack_unpacker_reserve_buffer(this, size)) {
+ throw std::bad_alloc();
+ }
+}
+
+inline char* unpacker::buffer()
+{
+ return msgpack_unpacker_buffer(this);
+}
+
+inline size_t unpacker::buffer_capacity() const
+{
+ return msgpack_unpacker_buffer_capacity(this);
+}
+
+inline void unpacker::buffer_consumed(size_t size)
+{
+ return msgpack_unpacker_buffer_consumed(this, size);
+}
+
+inline bool unpacker::next(unpacked* result)
+{
+ int ret = msgpack_unpacker_execute(this);
+
+ if(ret < 0) {
+ throw unpack_error("parse error");
+ }
+
+ if(ret == 0) {
+ result->zone().reset();
+ result->get() = object();
+ return false;
+
+ } else {
+ result->zone().reset( release_zone() );
+ result->get() = data();
+ reset();
+ return true;
+ }
+}
+
+
+inline bool unpacker::execute()
+{
+ int ret = msgpack_unpacker_execute(this);
+ if(ret < 0) {
+ throw unpack_error("parse error");
+ } else if(ret == 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+inline object unpacker::data()
+{
+ return msgpack_unpacker_data(this);
+}
+
+inline zone* unpacker::release_zone()
+{
+ if(!msgpack_unpacker_flush_zone(this)) {
+ throw std::bad_alloc();
+ }
+
+ zone* r = new zone();
+
+ msgpack_zone old = *base::z;
+ *base::z = *r;
+ *static_cast<msgpack_zone*>(r) = old;
+
+ return r;
+}
+
+inline void unpacker::reset_zone()
+{
+ msgpack_unpacker_reset_zone(this);
+}
+
+inline void unpacker::reset()
+{
+ msgpack_unpacker_reset(this);
+}
+
+
+inline size_t unpacker::message_size() const
+{
+ return msgpack_unpacker_message_size(this);
+}
+
+inline size_t unpacker::parsed_size() const
+{
+ return msgpack_unpacker_parsed_size(this);
+}
+
+inline char* unpacker::nonparsed_buffer()
+{
+ return base::buffer + base::off;
+}
+
+inline size_t unpacker::nonparsed_size() const
+{
+ return base::used - base::off;
+}
+
+inline void unpacker::skip_nonparsed_buffer(size_t size)
+{
+ base::off += size;
+}
+
+inline void unpacker::remove_nonparsed_buffer()
+{
+ base::used = base::off;
+}
+
+
+inline bool unpack(unpacked* result,
+ const char* data, size_t len, size_t* offset)
+{
+ msgpack::object obj;
+ std::auto_ptr<msgpack::zone> z(new zone());
+
+ unpack_return ret = (unpack_return)msgpack_unpack(
+ data, len, offset, z.get(),
+ reinterpret_cast<msgpack_object*>(&obj));
+
+ switch(ret) {
+ case UNPACK_SUCCESS:
+ result->get() = obj;
+ result->zone() = z;
+ return false;
+
+ case UNPACK_EXTRA_BYTES:
+ result->get() = obj;
+ result->zone() = z;
+ return true;
+
+ case UNPACK_CONTINUE:
+ throw unpack_error("insufficient bytes");
+
+ case UNPACK_PARSE_ERROR:
+ default:
+ throw unpack_error("parse error");
+ }
+}
+
+
+// obsolete
+inline unpack_return unpack(const char* data, size_t len, size_t* off,
+ zone* z, object* result)
+{
+ return (unpack_return)msgpack_unpack(data, len, off,
+ z, reinterpret_cast<msgpack_object*>(result));
+}
+
+// obsolete
+inline object unpack(const char* data, size_t len, zone& z, size_t* off)
+{
+ object result;
+
+ switch( msgpack::unpack(data, len, off, &z, &result) ) {
+ case UNPACK_SUCCESS:
+ return result;
+
+ case UNPACK_EXTRA_BYTES:
+ if(off) {
+ return result;
+ } else {
+ throw unpack_error("extra bytes");
+ }
+
+ case UNPACK_CONTINUE:
+ throw unpack_error("insufficient bytes");
+
+ case UNPACK_PARSE_ERROR:
+ default:
+ throw unpack_error("parse error");
+ }
+}
+
+
+} // namespace msgpack
+
+#endif /* msgpack/unpack.hpp */
+
diff --git a/cpp/src/msgpack/vrefbuffer.h b/cpp/src/msgpack/vrefbuffer.h
new file mode 100644
index 0000000..a08e0d0
--- /dev/null
+++ b/cpp/src/msgpack/vrefbuffer.h
@@ -0,0 +1,113 @@
+/*
+ * MessagePack for C zero-copy buffer implementation
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MSGPACK_VREFBUFFER_H__
+#define MSGPACK_VREFBUFFER_H__
+
+#include "msgpack/zone.h"
+
+#ifndef _WIN32
+#include <sys/uio.h>
+#else
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+#endif
+
+#ifndef MSGPACK_VREFBUFFER_REF_SIZE
+#define MSGPACK_VREFBUFFER_REF_SIZE 32
+#endif
+
+#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
+#define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct msgpack_vrefbuffer_chunk;
+typedef struct msgpack_vrefbuffer_chunk msgpack_vrefbuffer_chunk;
+
+typedef struct msgpack_vrefbuffer_inner_buffer {
+ size_t free;
+ char* ptr;
+ msgpack_vrefbuffer_chunk* head;
+} msgpack_vrefbuffer_inner_buffer;
+
+typedef struct msgpack_vrefbuffer {
+ struct iovec* tail;
+ struct iovec* end;
+ struct iovec* array;
+
+ size_t chunk_size;
+ size_t ref_size;
+
+ msgpack_vrefbuffer_inner_buffer inner_buffer;
+} msgpack_vrefbuffer;
+
+
+bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
+ size_t ref_size, size_t chunk_size);
+void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf);
+
+static inline int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len);
+
+static inline const struct iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref);
+static inline size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref);
+
+int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
+ const char* buf, unsigned int len);
+
+int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
+ const char* buf, unsigned int len);
+
+int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to);
+
+void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vref);
+
+
+int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len)
+{
+ msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)data;
+
+ if(len < vbuf->ref_size) {
+ return msgpack_vrefbuffer_append_copy(vbuf, buf, len);
+ } else {
+ return msgpack_vrefbuffer_append_ref(vbuf, buf, len);
+ }
+}
+
+const struct iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref)
+{
+ return vref->array;
+}
+
+size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref)
+{
+ return vref->tail - vref->array;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/vrefbuffer.h */
+
diff --git a/cpp/src/msgpack/vrefbuffer.hpp b/cpp/src/msgpack/vrefbuffer.hpp
new file mode 100644
index 0000000..7e0ffb2
--- /dev/null
+++ b/cpp/src/msgpack/vrefbuffer.hpp
@@ -0,0 +1,97 @@
+//
+// MessagePack for C++ zero-copy buffer implementation
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_VREFBUFFER_HPP__
+#define MSGPACK_VREFBUFFER_HPP__
+
+#include "msgpack/vrefbuffer.h"
+#include <stdexcept>
+
+namespace msgpack {
+
+
+class vrefbuffer : public msgpack_vrefbuffer {
+public:
+ vrefbuffer(size_t ref_size = MSGPACK_VREFBUFFER_REF_SIZE,
+ size_t chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE)
+ {
+ msgpack_vrefbuffer_init(this, ref_size, chunk_size);
+ }
+
+ ~vrefbuffer()
+ {
+ msgpack_vrefbuffer_destroy(this);
+ }
+
+public:
+ void write(const char* buf, unsigned int len)
+ {
+ if(len < base::ref_size) {
+ append_copy(buf, len);
+ } else {
+ append_ref(buf, len);
+ }
+ }
+
+ void append_ref(const char* buf, size_t len)
+ {
+ if(msgpack_vrefbuffer_append_ref(this, buf, len) < 0) {
+ throw std::bad_alloc();
+ }
+ }
+
+ void append_copy(const char* buf, size_t len)
+ {
+ if(msgpack_vrefbuffer_append_copy(this, buf, len) < 0) {
+ throw std::bad_alloc();
+ }
+ }
+
+ const struct iovec* vector() const
+ {
+ return msgpack_vrefbuffer_vec(this);
+ }
+
+ size_t vector_size() const
+ {
+ return msgpack_vrefbuffer_veclen(this);
+ }
+
+ void migrate(vrefbuffer* to)
+ {
+ if(msgpack_vrefbuffer_migrate(this, to) < 0) {
+ throw std::bad_alloc();
+ }
+ }
+
+ void clear()
+ {
+ msgpack_vrefbuffer_clear(this);
+ }
+
+private:
+ typedef msgpack_vrefbuffer base;
+
+private:
+ vrefbuffer(const vrefbuffer&);
+};
+
+
+} // namespace msgpack
+
+#endif /* msgpack/vrefbuffer.hpp */
+
diff --git a/cpp/src/msgpack/zbuffer.h b/cpp/src/msgpack/zbuffer.h
new file mode 100644
index 0000000..2a32206
--- /dev/null
+++ b/cpp/src/msgpack/zbuffer.h
@@ -0,0 +1,180 @@
+/*
+ * MessagePack for C deflate buffer implementation
+ *
+ * Copyright (C) 2010 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_ZBUFFER_H__
+#define MSGPACK_ZBUFFER_H__
+
+#include "msgpack/sysdep.h"
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+
+#ifndef MSGPACK_ZBUFFER_INIT_SIZE
+#define MSGPACK_ZBUFFER_INIT_SIZE 8192
+#endif
+
+#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
+#define MSGPACK_ZBUFFER_RESERVE_SIZE 512
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct msgpack_zbuffer {
+ z_stream stream;
+ char* data;
+ size_t init_size;
+} msgpack_zbuffer;
+
+
+static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
+ int level, size_t init_size);
+static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
+
+static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
+
+static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
+static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
+
+static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
+static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
+static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
+
+
+static inline int msgpack_zbuffer_write(void* data, const char* buf, unsigned int len);
+
+static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
+
+
+bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
+ int level, size_t init_size)
+{
+ memset(zbuf, 0, sizeof(msgpack_zbuffer));
+ zbuf->init_size = init_size;
+ if(deflateInit(&zbuf->stream, level) != Z_OK) {
+ free(zbuf->data);
+ return false;
+ }
+ return true;
+}
+
+void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
+{
+ deflateEnd(&zbuf->stream);
+ free(zbuf->data);
+}
+
+bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
+{
+ size_t used = (char*)zbuf->stream.next_out - zbuf->data;
+ size_t csize = used + zbuf->stream.avail_out;
+ size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
+
+ char* tmp = (char*)realloc(zbuf->data, nsize);
+ if(tmp == NULL) {
+ return false;
+ }
+
+ zbuf->data = tmp;
+ zbuf->stream.next_out = (Bytef*)(tmp + used);
+ zbuf->stream.avail_out = nsize - used;
+
+ return true;
+}
+
+int msgpack_zbuffer_write(void* data, const char* buf, unsigned int len)
+{
+ msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
+
+ zbuf->stream.next_in = (Bytef*)buf;
+ zbuf->stream.avail_in = len;
+
+ do {
+ if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
+ if(!msgpack_zbuffer_expand(zbuf)) {
+ return -1;
+ }
+ }
+
+ if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
+ return -1;
+ }
+ } while(zbuf->stream.avail_in > 0);
+
+ return 0;
+}
+
+char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
+{
+ while(true) {
+ switch(deflate(&zbuf->stream, Z_FINISH)) {
+ case Z_STREAM_END:
+ return zbuf->data;
+ case Z_OK:
+ if(!msgpack_zbuffer_expand(zbuf)) {
+ return NULL;
+ }
+ break;
+ default:
+ return NULL;
+ }
+ }
+}
+
+const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
+{
+ return zbuf->data;
+}
+
+size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
+{
+ return (char*)zbuf->stream.next_out - zbuf->data;
+}
+
+void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
+{
+ zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data;
+ zbuf->stream.next_out = (Bytef*)zbuf->data;
+}
+
+bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
+{
+ if(deflateReset(&zbuf->stream) != Z_OK) {
+ return false;
+ }
+ msgpack_zbuffer_reset_buffer(zbuf);
+ return true;
+}
+
+char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
+{
+ char* tmp = zbuf->data;
+ zbuf->data = NULL;
+ zbuf->stream.next_out = NULL;
+ zbuf->stream.avail_out = 0;
+ return tmp;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/zbuffer.h */
+
diff --git a/cpp/src/msgpack/zbuffer.hpp b/cpp/src/msgpack/zbuffer.hpp
new file mode 100644
index 0000000..278f076
--- /dev/null
+++ b/cpp/src/msgpack/zbuffer.hpp
@@ -0,0 +1,100 @@
+//
+// MessagePack for C++ deflate buffer implementation
+//
+// Copyright (C) 2010 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_ZBUFFER_HPP__
+#define MSGPACK_ZBUFFER_HPP__
+
+#include "msgpack/zbuffer.h"
+#include <stdexcept>
+
+namespace msgpack {
+
+
+class zbuffer : public msgpack_zbuffer {
+public:
+ zbuffer(int level = Z_DEFAULT_COMPRESSION,
+ size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE)
+ {
+ msgpack_zbuffer_init(this, level, init_size);
+ }
+
+ ~zbuffer()
+ {
+ msgpack_zbuffer_destroy(this);
+ }
+
+public:
+ void write(const char* buf, unsigned int len)
+ {
+ if(msgpack_zbuffer_write(this, buf, len) < 0) {
+ throw std::bad_alloc();
+ }
+ }
+
+ char* flush()
+ {
+ char* buf = msgpack_zbuffer_flush(this);
+ if(!buf) {
+ throw std::bad_alloc();
+ }
+ return buf;
+ }
+
+ char* data()
+ {
+ return base::data;
+ }
+
+ const char* data() const
+ {
+ return base::data;
+ }
+
+ size_t size() const
+ {
+ return msgpack_zbuffer_size(this);
+ }
+
+ void reset()
+ {
+ if(!msgpack_zbuffer_reset(this)) {
+ throw std::bad_alloc();
+ }
+ }
+
+ void reset_buffer()
+ {
+ msgpack_zbuffer_reset_buffer(this);
+ }
+
+ char* release_buffer()
+ {
+ return msgpack_zbuffer_release_buffer(this);
+ }
+
+private:
+ typedef msgpack_zbuffer base;
+
+private:
+ zbuffer(const zbuffer&);
+};
+
+
+} // namespace msgpack
+
+#endif /* msgpack/zbuffer.hpp */
+
diff --git a/cpp/src/msgpack/zone.h b/cpp/src/msgpack/zone.h
new file mode 100644
index 0000000..ce5be6d
--- /dev/null
+++ b/cpp/src/msgpack/zone.h
@@ -0,0 +1,131 @@
+/*
+ * MessagePack for C memory pool implementation
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MSGPACK_ZONE_H__
+#define MSGPACK_ZONE_H__
+
+#include "msgpack/sysdep.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct msgpack_zone_finalizer {
+ void (*func)(void* data);
+ void* data;
+} msgpack_zone_finalizer;
+
+typedef struct msgpack_zone_finalizer_array {
+ msgpack_zone_finalizer* tail;
+ msgpack_zone_finalizer* end;
+ msgpack_zone_finalizer* array;
+} msgpack_zone_finalizer_array;
+
+struct msgpack_zone_chunk;
+typedef struct msgpack_zone_chunk msgpack_zone_chunk;
+
+typedef struct msgpack_zone_chunk_list {
+ size_t free;
+ char* ptr;
+ msgpack_zone_chunk* head;
+} msgpack_zone_chunk_list;
+
+typedef struct msgpack_zone {
+ msgpack_zone_chunk_list chunk_list;
+ msgpack_zone_finalizer_array finalizer_array;
+ size_t chunk_size;
+} msgpack_zone;
+
+#ifndef MSGPACK_ZONE_CHUNK_SIZE
+#define MSGPACK_ZONE_CHUNK_SIZE 8192
+#endif
+
+bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size);
+void msgpack_zone_destroy(msgpack_zone* zone);
+
+msgpack_zone* msgpack_zone_new(size_t chunk_size);
+void msgpack_zone_free(msgpack_zone* zone);
+
+static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size);
+static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size);
+
+static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone,
+ void (*func)(void* data), void* data);
+
+bool msgpack_zone_is_empty(msgpack_zone* zone);
+
+void msgpack_zone_clear(msgpack_zone* zone);
+
+
+
+#ifndef MSGPACK_ZONE_ALIGN
+#define MSGPACK_ZONE_ALIGN sizeof(int)
+#endif
+
+void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size);
+
+void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size)
+{
+ msgpack_zone_chunk_list* cl = &zone->chunk_list;
+
+ if(zone->chunk_list.free < size) {
+ return msgpack_zone_malloc_expand(zone, size);
+ }
+
+ char* ptr = cl->ptr;
+ cl->free -= size;
+ cl->ptr += size;
+
+ return ptr;
+}
+
+void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
+{
+ return msgpack_zone_malloc_no_align(zone,
+ ((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1));
+}
+
+
+bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
+ void (*func)(void* data), void* data);
+
+bool msgpack_zone_push_finalizer(msgpack_zone* zone,
+ void (*func)(void* data), void* data)
+{
+ msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
+ msgpack_zone_finalizer* fin = fa->tail;
+
+ if(fin == fa->end) {
+ return msgpack_zone_push_finalizer_expand(zone, func, data);
+ }
+
+ fin->func = func;
+ fin->data = data;
+
+ ++fa->tail;
+
+ return true;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* msgpack/zone.h */
+
diff --git a/cpp/src/msgpack/zone.hpp.erb b/cpp/src/msgpack/zone.hpp.erb
new file mode 100644
index 0000000..8e69aa4
--- /dev/null
+++ b/cpp/src/msgpack/zone.hpp.erb
@@ -0,0 +1,148 @@
+//
+// MessagePack for C++ memory pool
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_ZONE_HPP__
+#define MSGPACK_ZONE_HPP__
+
+#include "msgpack/zone.h"
+#include <cstdlib>
+#include <memory>
+#include <vector>
+
+<% GENERATION_LIMIT = 15 %>
+namespace msgpack {
+
+
+class zone : public msgpack_zone {
+public:
+ zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
+ ~zone();
+
+public:
+ void* malloc(size_t size);
+ void* malloc_no_align(size_t size);
+
+ void push_finalizer(void (*func)(void*), void* data);
+
+ template <typename T>
+ void push_finalizer(std::auto_ptr<T> obj);
+
+ void clear();
+
+ <%0.upto(GENERATION_LIMIT) {|i|%>
+ template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+ T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
+ <%}%>
+
+private:
+ void undo_malloc(size_t size);
+
+ template <typename T>
+ static void object_destructor(void* obj);
+
+ typedef msgpack_zone base;
+
+private:
+ zone(const zone&);
+};
+
+
+
+inline zone::zone(size_t chunk_size)
+{
+ msgpack_zone_init(this, chunk_size);
+}
+
+inline zone::~zone()
+{
+ msgpack_zone_destroy(this);
+}
+
+inline void* zone::malloc(size_t size)
+{
+ void* ptr = msgpack_zone_malloc(this, size);
+ if(!ptr) {
+ throw std::bad_alloc();
+ }
+ return ptr;
+}
+
+inline void* zone::malloc_no_align(size_t size)
+{
+ void* ptr = msgpack_zone_malloc_no_align(this, size);
+ if(!ptr) {
+ throw std::bad_alloc();
+ }
+ return ptr;
+}
+
+inline void zone::push_finalizer(void (*func)(void*), void* data)
+{
+ if(!msgpack_zone_push_finalizer(this, func, data)) {
+ throw std::bad_alloc();
+ }
+}
+
+template <typename T>
+inline void zone::push_finalizer(std::auto_ptr<T> obj)
+{
+ if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, obj.get())) {
+ throw std::bad_alloc();
+ }
+ obj.release();
+}
+
+inline void zone::clear()
+{
+ msgpack_zone_clear(this);
+}
+
+template <typename T>
+void zone::object_destructor(void* obj)
+{
+ reinterpret_cast<T*>(obj)->~T();
+}
+
+inline void zone::undo_malloc(size_t size)
+{
+ base::chunk_list.ptr -= size;
+ base::chunk_list.free += size;
+}
+
+<%0.upto(GENERATION_LIMIT) {|i|%>
+template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
+T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
+{
+ void* x = malloc(sizeof(T));
+ if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, x)) {
+ undo_malloc(sizeof(T));
+ throw std::bad_alloc();
+ }
+ try {
+ return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
+ } catch (...) {
+ --base::finalizer_array.tail;
+ undo_malloc(sizeof(T));
+ throw;
+ }
+}
+<%}%>
+
+} // namespace msgpack
+
+#endif /* msgpack/zone.hpp */
+
diff --git a/cpp/src/object.cpp b/cpp/src/object.cpp
new file mode 100644
index 0000000..dfe32bb
--- /dev/null
+++ b/cpp/src/object.cpp
@@ -0,0 +1,87 @@
+//
+// MessagePack for C++ dynamic typed objects
+//
+// Copyright (C) 2008-2009 FURUHASHI Sadayuki
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "msgpack/object.hpp"
+
+namespace msgpack {
+
+
+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::DOUBLE:
+ s << o.via.dec;
+ break;
+
+ case type::RAW:
+ (s << '"').write(o.via.raw.ptr, o.via.raw.size) << '"';
+ break;
+
+ case type::ARRAY:
+ s << "[";
+ if(o.via.array.size != 0) {
+ object* p(o.via.array.ptr);
+ s << *p;
+ ++p;
+ for(object* const pend(o.via.array.ptr + o.via.array.size);
+ p < pend; ++p) {
+ s << ", " << *p;
+ }
+ }
+ s << "]";
+ break;
+
+ case type::MAP:
+ s << "{";
+ if(o.via.map.size != 0) {
+ object_kv* p(o.via.map.ptr);
+ s << p->key << "=>" << p->val;
+ ++p;
+ for(object_kv* const pend(o.via.map.ptr + o.via.map.size);
+ p < pend; ++p) {
+ s << ", " << p->key << "=>" << p->val;
+ }
+ }
+ s << "}";
+ break;
+
+ default:
+ // FIXME
+ s << "#<UNKNOWN " << (uint16_t)o.type << ">";
+ }
+ return s;
+}
+
+
+} // namespace msgpack
+
diff --git a/cpp/src/objectc.c b/cpp/src/objectc.c
new file mode 100644
index 0000000..d4f1c8a
--- /dev/null
+++ b/cpp/src/objectc.c
@@ -0,0 +1,237 @@
+/*
+ * MessagePack for C dynamic typing routine
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "msgpack/object.h"
+#include "msgpack/pack.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifndef _MSC_VER
+#include <inttypes.h>
+#else
+#ifndef PRIu64
+#define PRIu64 "I64u"
+#endif
+#ifndef PRIi64
+#define PRIi64 "I64d"
+#endif
+#endif
+
+
+int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
+{
+ switch(d.type) {
+ case MSGPACK_OBJECT_NIL:
+ return msgpack_pack_nil(pk);
+
+ case MSGPACK_OBJECT_BOOLEAN:
+ if(d.via.boolean) {
+ return msgpack_pack_true(pk);
+ } else {
+ return msgpack_pack_false(pk);
+ }
+
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
+ return msgpack_pack_uint64(pk, d.via.u64);
+
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
+ return msgpack_pack_int64(pk, d.via.i64);
+
+ case MSGPACK_OBJECT_DOUBLE:
+ return msgpack_pack_double(pk, d.via.dec);
+
+ case MSGPACK_OBJECT_RAW:
+ {
+ int ret = msgpack_pack_raw(pk, d.via.raw.size);
+ if(ret < 0) { return ret; }
+ return msgpack_pack_raw_body(pk, d.via.raw.ptr, d.via.raw.size);
+ }
+
+ case MSGPACK_OBJECT_ARRAY:
+ {
+ int ret = msgpack_pack_array(pk, d.via.array.size);
+ if(ret < 0) { return ret; }
+
+ msgpack_object* o = d.via.array.ptr;
+ msgpack_object* const oend = d.via.array.ptr + d.via.array.size;
+ for(; o != oend; ++o) {
+ ret = msgpack_pack_object(pk, *o);
+ if(ret < 0) { return ret; }
+ }
+
+ return 0;
+ }
+
+ case MSGPACK_OBJECT_MAP:
+ {
+ int ret = msgpack_pack_map(pk, d.via.map.size);
+ if(ret < 0) { return ret; }
+
+ msgpack_object_kv* kv = d.via.map.ptr;
+ msgpack_object_kv* const kvend = d.via.map.ptr + d.via.map.size;
+ for(; kv != kvend; ++kv) {
+ ret = msgpack_pack_object(pk, kv->key);
+ if(ret < 0) { return ret; }
+ ret = msgpack_pack_object(pk, kv->val);
+ if(ret < 0) { return ret; }
+ }
+
+ return 0;
+ }
+
+ default:
+ return -1;
+ }
+}
+
+
+void msgpack_object_print(FILE* out, msgpack_object o)
+{
+ switch(o.type) {
+ case MSGPACK_OBJECT_NIL:
+ fprintf(out, "nil");
+ break;
+
+ case MSGPACK_OBJECT_BOOLEAN:
+ fprintf(out, (o.via.boolean ? "true" : "false"));
+ break;
+
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
+ fprintf(out, "%"PRIu64, o.via.u64);
+ break;
+
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
+ fprintf(out, "%"PRIi64, o.via.i64);
+ break;
+
+ case MSGPACK_OBJECT_DOUBLE:
+ fprintf(out, "%f", o.via.dec);
+ break;
+
+ case MSGPACK_OBJECT_RAW:
+ fprintf(out, "\"");
+ fwrite(o.via.raw.ptr, o.via.raw.size, 1, out);
+ fprintf(out, "\"");
+ break;
+
+ case MSGPACK_OBJECT_ARRAY:
+ fprintf(out, "[");
+ if(o.via.array.size != 0) {
+ msgpack_object* p = o.via.array.ptr;
+ msgpack_object_print(out, *p);
+ ++p;
+ msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
+ for(; p < pend; ++p) {
+ fprintf(out, ", ");
+ msgpack_object_print(out, *p);
+ }
+ }
+ fprintf(out, "]");
+ break;
+
+ case MSGPACK_OBJECT_MAP:
+ fprintf(out, "{");
+ if(o.via.map.size != 0) {
+ msgpack_object_kv* p = o.via.map.ptr;
+ msgpack_object_print(out, p->key);
+ fprintf(out, "=>");
+ msgpack_object_print(out, p->val);
+ ++p;
+ msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
+ for(; p < pend; ++p) {
+ fprintf(out, ", ");
+ msgpack_object_print(out, p->key);
+ fprintf(out, "=>");
+ msgpack_object_print(out, p->val);
+ }
+ }
+ fprintf(out, "}");
+ break;
+
+ default:
+ // FIXME
+ fprintf(out, "#<UNKNOWN %hu %"PRIu64">", o.type, o.via.u64);
+ }
+}
+
+bool msgpack_object_equal(const msgpack_object x, const msgpack_object y)
+{
+ if(x.type != y.type) { return false; }
+
+ switch(x.type) {
+ case MSGPACK_OBJECT_NIL:
+ return true;
+
+ case MSGPACK_OBJECT_BOOLEAN:
+ return x.via.boolean == y.via.boolean;
+
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
+ return x.via.u64 == y.via.u64;
+
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
+ return x.via.i64 == y.via.i64;
+
+ case MSGPACK_OBJECT_DOUBLE:
+ return x.via.dec == y.via.dec;
+
+ case MSGPACK_OBJECT_RAW:
+ return x.via.raw.size == y.via.raw.size &&
+ memcmp(x.via.raw.ptr, y.via.raw.ptr, x.via.raw.size) == 0;
+
+ case MSGPACK_OBJECT_ARRAY:
+ if(x.via.array.size != y.via.array.size) {
+ return false;
+ } else if(x.via.array.size == 0) {
+ return true;
+ } else {
+ msgpack_object* px = x.via.array.ptr;
+ msgpack_object* const pxend = x.via.array.ptr + x.via.array.size;
+ msgpack_object* py = y.via.array.ptr;
+ do {
+ if(!msgpack_object_equal(*px, *py)) {
+ return false;
+ }
+ ++px;
+ ++py;
+ } while(px < pxend);
+ return true;
+ }
+
+ case MSGPACK_OBJECT_MAP:
+ if(x.via.map.size != y.via.map.size) {
+ return false;
+ } else if(x.via.map.size == 0) {
+ return true;
+ } else {
+ msgpack_object_kv* px = x.via.map.ptr;
+ msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size;
+ msgpack_object_kv* py = y.via.map.ptr;
+ do {
+ if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) {
+ return false;
+ }
+ ++px;
+ ++py;
+ } while(px < pxend);
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
diff --git a/cpp/src/unpack.c b/cpp/src/unpack.c
new file mode 100644
index 0000000..4a42526
--- /dev/null
+++ b/cpp/src/unpack.c
@@ -0,0 +1,399 @@
+/*
+ * MessagePack for C unpacking routine
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "msgpack/unpack.h"
+#include "msgpack/unpack_define.h"
+#include <stdlib.h>
+
+
+typedef struct {
+ msgpack_zone* z;
+ bool referenced;
+} unpack_user;
+
+
+#define msgpack_unpack_struct(name) \
+ struct template ## name
+
+#define msgpack_unpack_func(ret, name) \
+ ret template ## name
+
+#define msgpack_unpack_callback(name) \
+ template_callback ## name
+
+#define msgpack_unpack_object msgpack_object
+
+#define msgpack_unpack_user unpack_user
+
+
+struct template_context;
+typedef struct template_context template_context;
+
+static void template_init(template_context* ctx);
+
+static msgpack_object template_data(template_context* ctx);
+
+static int template_execute(template_context* ctx,
+ const char* data, size_t len, size_t* off);
+
+
+static inline msgpack_object template_callback_root(unpack_user* u)
+{ msgpack_object o = {}; return o; }
+
+static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+
+static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+
+static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+
+static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+
+static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_object* o)
+{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+ else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
+
+static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_object* o)
+{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+ else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
+
+static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_object* o)
+{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+ else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
+
+static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_object* o)
+{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
+ else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
+
+static inline int template_callback_float(unpack_user* u, float d, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
+
+static inline int template_callback_double(unpack_user* u, double d, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
+
+static inline int template_callback_nil(unpack_user* u, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_NIL; return 0; }
+
+static inline int template_callback_true(unpack_user* u, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = true; return 0; }
+
+static inline int template_callback_false(unpack_user* u, msgpack_object* o)
+{ o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = false; return 0; }
+
+static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_object* o)
+{
+ o->type = MSGPACK_OBJECT_ARRAY;
+ o->via.array.size = 0;
+ o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
+ if(o->via.array.ptr == NULL) { return -1; }
+ return 0;
+}
+
+static inline int template_callback_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
+{ c->via.array.ptr[c->via.array.size++] = o; return 0; }
+
+static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_object* o)
+{
+ o->type = MSGPACK_OBJECT_MAP;
+ o->via.map.size = 0;
+ o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object_kv));
+ if(o->via.map.ptr == NULL) { return -1; }
+ return 0;
+}
+
+static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
+{
+ c->via.map.ptr[c->via.map.size].key = k;
+ c->via.map.ptr[c->via.map.size].val = v;
+ ++c->via.map.size;
+ return 0;
+}
+
+static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
+{
+ o->type = MSGPACK_OBJECT_RAW;
+ o->via.raw.ptr = p;
+ o->via.raw.size = l;
+ u->referenced = true;
+ return 0;
+}
+
+#include "msgpack/unpack_template.h"
+
+
+#define CTX_CAST(m) ((template_context*)(m))
+#define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced
+
+#define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
+
+
+static inline void init_count(void* buffer)
+{
+ *(volatile _msgpack_atomic_counter_t*)buffer = 1;
+}
+
+static inline void decl_count(void* buffer)
+{
+ // atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
+ if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
+ free(buffer);
+ }
+}
+
+static inline void incr_count(void* buffer)
+{
+ // atomic ++*(_msgpack_atomic_counter_t*)buffer;
+ _msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
+}
+
+static inline _msgpack_atomic_counter_t get_count(void* buffer)
+{
+ return *(volatile _msgpack_atomic_counter_t*)buffer;
+}
+
+
+
+bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
+{
+ if(initial_buffer_size < COUNTER_SIZE) {
+ initial_buffer_size = COUNTER_SIZE;
+ }
+
+ char* buffer = (char*)malloc(initial_buffer_size);
+ if(buffer == NULL) {
+ return false;
+ }
+
+ void* ctx = malloc(sizeof(template_context));
+ if(ctx == NULL) {
+ free(buffer);
+ return false;
+ }
+
+ msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
+ if(z == NULL) {
+ free(ctx);
+ free(buffer);
+ return false;
+ }
+
+ mpac->buffer = buffer;
+ mpac->used = COUNTER_SIZE;
+ mpac->free = initial_buffer_size - mpac->used;
+ mpac->off = COUNTER_SIZE;
+ mpac->parsed = 0;
+ mpac->initial_buffer_size = initial_buffer_size;
+ mpac->z = z;
+ mpac->ctx = ctx;
+
+ init_count(mpac->buffer);
+
+ template_init(CTX_CAST(mpac->ctx));
+ CTX_CAST(mpac->ctx)->user.z = mpac->z;
+ CTX_CAST(mpac->ctx)->user.referenced = false;
+
+ return true;
+}
+
+void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
+{
+ msgpack_zone_free(mpac->z);
+ free(mpac->ctx);
+ decl_count(mpac->buffer);
+}
+
+
+msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size)
+{
+ msgpack_unpacker* mpac = (msgpack_unpacker*)malloc(sizeof(msgpack_unpacker));
+ if(mpac == NULL) {
+ return NULL;
+ }
+
+ if(!msgpack_unpacker_init(mpac, initial_buffer_size)) {
+ free(mpac);
+ return NULL;
+ }
+
+ return mpac;
+}
+
+void msgpack_unpacker_free(msgpack_unpacker* mpac)
+{
+ msgpack_unpacker_destroy(mpac);
+ free(mpac);
+}
+
+bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size)
+{
+ if(mpac->used == mpac->off && get_count(mpac->buffer) == 1
+ && !CTX_REFERENCED(mpac)) {
+ // rewind buffer
+ mpac->free += mpac->used - COUNTER_SIZE;
+ mpac->used = COUNTER_SIZE;
+ mpac->off = COUNTER_SIZE;
+
+ if(mpac->free >= size) {
+ return true;
+ }
+ }
+
+ if(mpac->off == COUNTER_SIZE) {
+ size_t next_size = (mpac->used + mpac->free) * 2; // include COUNTER_SIZE
+ while(next_size < size + mpac->used) {
+ next_size *= 2;
+ }
+
+ char* tmp = (char*)realloc(mpac->buffer, next_size);
+ if(tmp == NULL) {
+ return false;
+ }
+
+ mpac->buffer = tmp;
+ mpac->free = next_size - mpac->used;
+
+ } else {
+ size_t next_size = mpac->initial_buffer_size; // include COUNTER_SIZE
+ size_t not_parsed = mpac->used - mpac->off;
+ while(next_size < size + not_parsed + COUNTER_SIZE) {
+ next_size *= 2;
+ }
+
+ char* tmp = (char*)malloc(next_size);
+ if(tmp == NULL) {
+ return false;
+ }
+
+ init_count(tmp);
+
+ memcpy(tmp+COUNTER_SIZE, mpac->buffer+mpac->off, not_parsed);
+
+ if(CTX_REFERENCED(mpac)) {
+ if(!msgpack_zone_push_finalizer(mpac->z, decl_count, mpac->buffer)) {
+ free(tmp);
+ return false;
+ }
+ CTX_REFERENCED(mpac) = false;
+ } else {
+ decl_count(mpac->buffer);
+ }
+
+ mpac->buffer = tmp;
+ mpac->used = not_parsed + COUNTER_SIZE;
+ mpac->free = next_size - mpac->used;
+ mpac->off = COUNTER_SIZE;
+ }
+
+ return true;
+}
+
+int msgpack_unpacker_execute(msgpack_unpacker* mpac)
+{
+ size_t off = mpac->off;
+ int ret = template_execute(CTX_CAST(mpac->ctx),
+ mpac->buffer, mpac->used, &mpac->off);
+ if(mpac->off > off) {
+ mpac->parsed += mpac->off - off;
+ }
+ return ret;
+}
+
+msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac)
+{
+ return template_data(CTX_CAST(mpac->ctx));
+}
+
+msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
+{
+ if(!msgpack_unpacker_flush_zone(mpac)) {
+ return NULL;
+ }
+
+ msgpack_zone* r = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
+ if(r == NULL) {
+ return NULL;
+ }
+
+ msgpack_zone* old = mpac->z;
+ mpac->z = r;
+
+ return old;
+}
+
+void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac)
+{
+ msgpack_zone_clear(mpac->z);
+}
+
+bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac)
+{
+ if(CTX_REFERENCED(mpac)) {
+ if(!msgpack_zone_push_finalizer(mpac->z, decl_count, mpac->buffer)) {
+ return false;
+ }
+ CTX_REFERENCED(mpac) = false;
+
+ incr_count(mpac->buffer);
+ }
+
+ return true;
+}
+
+void msgpack_unpacker_reset(msgpack_unpacker* mpac)
+{
+ template_init(CTX_CAST(mpac->ctx));
+ // don't reset referenced flag
+ mpac->parsed = 0;
+}
+
+
+msgpack_unpack_return
+msgpack_unpack(const char* data, size_t len, size_t* off,
+ msgpack_zone* z, msgpack_object* result)
+{
+ template_context ctx;
+ template_init(&ctx);
+
+ ctx.user.z = z;
+ ctx.user.referenced = false;
+
+ size_t noff = 0;
+ if(off != NULL) { noff = *off; }
+
+ int e = template_execute(&ctx, data, len, &noff);
+ if(e < 0) {
+ return MSGPACK_UNPACK_PARSE_ERROR;
+ }
+
+ if(off != NULL) { *off = noff; }
+
+ if(e == 0) {
+ return MSGPACK_UNPACK_CONTINUE;
+ }
+
+ *result = template_data(&ctx);
+
+ if(noff < len) {
+ return MSGPACK_UNPACK_EXTRA_BYTES;
+ }
+
+ return MSGPACK_UNPACK_SUCCESS;
+}
+
diff --git a/cpp/src/vrefbuffer.c b/cpp/src/vrefbuffer.c
new file mode 100644
index 0000000..a27b138
--- /dev/null
+++ b/cpp/src/vrefbuffer.c
@@ -0,0 +1,220 @@
+/*
+ * MessagePack for C zero-copy buffer implementation
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "msgpack/vrefbuffer.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct msgpack_vrefbuffer_chunk {
+ struct msgpack_vrefbuffer_chunk* next;
+ /* data ... */
+};
+
+bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
+ size_t ref_size, size_t chunk_size)
+{
+ vbuf->chunk_size = chunk_size;
+ vbuf->ref_size = ref_size;
+
+ size_t nfirst = (sizeof(struct iovec) < 72/2) ?
+ 72 / sizeof(struct iovec) : 8;
+
+ struct iovec* array = (struct iovec*)malloc(
+ sizeof(struct iovec) * nfirst);
+ if(array == NULL) {
+ return false;
+ }
+
+ vbuf->tail = array;
+ vbuf->end = array + nfirst;
+ vbuf->array = array;
+
+ msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
+ sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
+ if(chunk == NULL) {
+ free(array);
+ return false;
+ }
+
+ msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+
+ ib->free = chunk_size;
+ ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
+ ib->head = chunk;
+ chunk->next = NULL;
+
+ return true;
+}
+
+void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
+{
+ msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
+ while(true) {
+ msgpack_vrefbuffer_chunk* n = c->next;
+ free(c);
+ if(n != NULL) {
+ c = n;
+ } else {
+ break;
+ }
+ }
+ free(vbuf->array);
+}
+
+void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
+{
+ msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
+ msgpack_vrefbuffer_chunk* n;
+ while(c != NULL) {
+ n = c->next;
+ free(c);
+ c = n;
+ }
+
+ msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+ msgpack_vrefbuffer_chunk* chunk = ib->head;
+ chunk->next = NULL;
+ ib->free = vbuf->chunk_size;
+ ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
+
+ vbuf->tail = vbuf->array;
+}
+
+int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
+ const char* buf, unsigned int len)
+{
+ if(vbuf->tail == vbuf->end) {
+ const size_t nused = vbuf->tail - vbuf->array;
+ const size_t nnext = nused * 2;
+
+ struct iovec* nvec = (struct iovec*)realloc(
+ vbuf->array, sizeof(struct iovec)*nnext);
+ if(nvec == NULL) {
+ return -1;
+ }
+
+ vbuf->array = nvec;
+ vbuf->end = nvec + nnext;
+ vbuf->tail = nvec + nused;
+ }
+
+ vbuf->tail->iov_base = (char*)buf;
+ vbuf->tail->iov_len = len;
+ ++vbuf->tail;
+
+ return 0;
+}
+
+int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
+ const char* buf, unsigned int len)
+{
+ msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+
+ if(ib->free < len) {
+ size_t sz = vbuf->chunk_size;
+ if(sz < len) {
+ sz = len;
+ }
+
+ msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
+ sizeof(msgpack_vrefbuffer_chunk) + sz);
+ if(chunk == NULL) {
+ return -1;
+ }
+
+ chunk->next = ib->head;
+ ib->head = chunk;
+ ib->free = sz;
+ ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
+ }
+
+ char* m = ib->ptr;
+ memcpy(m, buf, len);
+ ib->free -= len;
+ ib->ptr += len;
+
+ if(vbuf->tail != vbuf->array && m ==
+ (const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
+ (vbuf->tail-1)->iov_len += len;
+ return 0;
+ } else {
+ return msgpack_vrefbuffer_append_ref(vbuf, m, len);
+ }
+}
+
+int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
+{
+ size_t sz = vbuf->chunk_size;
+
+ msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc(
+ sizeof(msgpack_vrefbuffer_chunk) + sz);
+ if(empty == NULL) {
+ return -1;
+ }
+
+ empty->next = NULL;
+
+
+ const size_t nused = vbuf->tail - vbuf->array;
+ if(to->tail + nused < vbuf->end) {
+ const size_t tosize = to->tail - to->array;
+ const size_t reqsize = nused + tosize;
+ size_t nnext = (to->end - to->array) * 2;
+ while(nnext < reqsize) {
+ nnext *= 2;
+ }
+
+ struct iovec* nvec = (struct iovec*)realloc(
+ to->array, sizeof(struct iovec)*nnext);
+ if(nvec == NULL) {
+ free(empty);
+ return -1;
+ }
+
+ to->array = nvec;
+ to->end = nvec + nnext;
+ to->tail = nvec + tosize;
+ }
+
+ memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused);
+
+ to->tail += nused;
+ vbuf->tail = vbuf->array;
+
+
+ msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+ msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
+
+ msgpack_vrefbuffer_chunk* last = ib->head;
+ while(last->next != NULL) {
+ last = last->next;
+ }
+ last->next = toib->head;
+ toib->head = ib->head;
+
+ if(toib->free < ib->free) {
+ toib->free = ib->free;
+ toib->ptr = ib->ptr;
+ }
+
+ ib->head = empty;
+ ib->free = sz;
+ ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
+
+ return 0;
+}
+
diff --git a/cpp/src/zone.c b/cpp/src/zone.c
new file mode 100644
index 0000000..85de765
--- /dev/null
+++ b/cpp/src/zone.c
@@ -0,0 +1,220 @@
+/*
+ * MessagePack for C memory pool implementation
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "msgpack/zone.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct msgpack_zone_chunk {
+ struct msgpack_zone_chunk* next;
+ /* data ... */
+};
+
+static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
+{
+ msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
+ sizeof(msgpack_zone_chunk) + chunk_size);
+ if(chunk == NULL) {
+ return false;
+ }
+
+ cl->head = chunk;
+ cl->free = chunk_size;
+ cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
+ chunk->next = NULL;
+
+ return true;
+}
+
+static inline void destroy_chunk_list(msgpack_zone_chunk_list* cl)
+{
+ msgpack_zone_chunk* c = cl->head;
+ while(true) {
+ msgpack_zone_chunk* n = c->next;
+ free(c);
+ if(n != NULL) {
+ c = n;
+ } else {
+ break;
+ }
+ }
+}
+
+static inline void clear_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
+{
+ msgpack_zone_chunk* c = cl->head;
+ while(true) {
+ msgpack_zone_chunk* n = c->next;
+ if(n != NULL) {
+ free(c);
+ c = n;
+ } else {
+ break;
+ }
+ }
+ cl->head->next = NULL;
+ cl->free = chunk_size;
+ cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk);
+}
+
+void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
+{
+ msgpack_zone_chunk_list* const cl = &zone->chunk_list;
+
+ size_t sz = zone->chunk_size;
+
+ while(sz < size) {
+ sz *= 2;
+ }
+
+ msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
+ sizeof(msgpack_zone_chunk) + sz);
+
+ char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
+
+ chunk->next = cl->head;
+ cl->head = chunk;
+ cl->free = sz - size;
+ cl->ptr = ptr + size;
+
+ return ptr;
+}
+
+
+static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa)
+{
+ fa->tail = NULL;
+ fa->end = NULL;
+ fa->array = NULL;
+}
+
+static inline void call_finalizer_array(msgpack_zone_finalizer_array* fa)
+{
+ msgpack_zone_finalizer* fin = fa->tail;
+ for(; fin != fa->array; --fin) {
+ (*(fin-1)->func)((fin-1)->data);
+ }
+}
+
+static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa)
+{
+ call_finalizer_array(fa);
+ free(fa->array);
+}
+
+static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa)
+{
+ call_finalizer_array(fa);
+ fa->tail = fa->array;
+}
+
+bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
+ void (*func)(void* data), void* data)
+{
+ msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
+
+ const size_t nused = fa->end - fa->array;
+
+ size_t nnext;
+ if(nused == 0) {
+ nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
+ 72 / sizeof(msgpack_zone_finalizer) : 8;
+
+ } else {
+ nnext = nused * 2;
+ }
+
+ msgpack_zone_finalizer* tmp =
+ (msgpack_zone_finalizer*)realloc(fa->array,
+ sizeof(msgpack_zone_finalizer) * nnext);
+ if(tmp == NULL) {
+ return false;
+ }
+
+ fa->array = tmp;
+ fa->end = tmp + nnext;
+ fa->tail = tmp + nused;
+
+ fa->tail->func = func;
+ fa->tail->data = data;
+
+ ++fa->tail;
+
+ return true;
+}
+
+
+bool msgpack_zone_is_empty(msgpack_zone* zone)
+{
+ msgpack_zone_chunk_list* const cl = &zone->chunk_list;
+ msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
+ return cl->free == zone->chunk_size && cl->head->next == NULL &&
+ fa->tail == fa->array;
+}
+
+
+void msgpack_zone_destroy(msgpack_zone* zone)
+{
+ destroy_finalizer_array(&zone->finalizer_array);
+ destroy_chunk_list(&zone->chunk_list);
+}
+
+void msgpack_zone_clear(msgpack_zone* zone)
+{
+ clear_finalizer_array(&zone->finalizer_array);
+ clear_chunk_list(&zone->chunk_list, zone->chunk_size);
+}
+
+bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
+{
+ zone->chunk_size = chunk_size;
+
+ if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
+ return false;
+ }
+
+ init_finalizer_array(&zone->finalizer_array);
+
+ return true;
+}
+
+msgpack_zone* msgpack_zone_new(size_t chunk_size)
+{
+ msgpack_zone* zone = (msgpack_zone*)malloc(
+ sizeof(msgpack_zone) + chunk_size);
+ if(zone == NULL) {
+ return NULL;
+ }
+
+ zone->chunk_size = chunk_size;
+
+ if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
+ free(zone);
+ return NULL;
+ }
+
+ init_finalizer_array(&zone->finalizer_array);
+
+ return zone;
+}
+
+void msgpack_zone_free(msgpack_zone* zone)
+{
+ msgpack_zone_destroy(zone);
+ free(zone);
+}
+