diff options
| author | frsyuki <frsyuki@users.sourceforge.jp> | 2010-02-06 20:09:41 +0900 |
|---|---|---|
| committer | frsyuki <frsyuki@users.sourceforge.jp> | 2010-02-06 20:09:41 +0900 |
| commit | cd10fbc1fe39308045f0b7bf9cce5f8153f25f1d (patch) | |
| tree | 44e4a1e075deebc3339cdd44e1f550a3ea914e88 /cpp/msgpack | |
| parent | ca0b085d156260b6d916139495a6d306a1e7f886 (diff) | |
| download | msgpack-python-cd10fbc1fe39308045f0b7bf9cce5f8153f25f1d.tar.gz | |
removed symbolic links
Diffstat (limited to 'cpp/msgpack')
| l--------- | cpp/msgpack | 1 | ||||
| -rw-r--r-- | cpp/msgpack/object.hpp | 329 | ||||
| -rw-r--r-- | cpp/msgpack/pack.hpp | 252 | ||||
| -rw-r--r-- | cpp/msgpack/sbuffer.hpp | 103 | ||||
| -rw-r--r-- | cpp/msgpack/type.hpp | 15 | ||||
| -rw-r--r-- | cpp/msgpack/type/bool.hpp | 46 | ||||
| -rw-r--r-- | cpp/msgpack/type/define.hpp.erb | 98 | ||||
| -rw-r--r-- | cpp/msgpack/type/deque.hpp | 56 | ||||
| -rw-r--r-- | cpp/msgpack/type/float.hpp | 63 | ||||
| -rw-r--r-- | cpp/msgpack/type/int.hpp | 147 | ||||
| -rw-r--r-- | cpp/msgpack/type/list.hpp | 56 | ||||
| -rw-r--r-- | cpp/msgpack/type/map.hpp | 139 | ||||
| -rw-r--r-- | cpp/msgpack/type/nil.hpp | 49 | ||||
| -rw-r--r-- | cpp/msgpack/type/pair.hpp | 50 | ||||
| -rw-r--r-- | cpp/msgpack/type/raw.hpp | 84 | ||||
| -rw-r--r-- | cpp/msgpack/type/set.hpp | 80 | ||||
| -rw-r--r-- | cpp/msgpack/type/string.hpp | 46 | ||||
| -rw-r--r-- | cpp/msgpack/type/tr1/unordered_map.hpp | 85 | ||||
| -rw-r--r-- | cpp/msgpack/type/tr1/unordered_set.hpp | 80 | ||||
| -rw-r--r-- | cpp/msgpack/type/tuple.hpp.erb | 171 | ||||
| -rw-r--r-- | cpp/msgpack/type/vector.hpp | 60 | ||||
| -rw-r--r-- | cpp/msgpack/unpack.hpp | 301 | ||||
| -rw-r--r-- | cpp/msgpack/vrefbuffer.hpp | 92 | ||||
| -rw-r--r-- | cpp/msgpack/zone.hpp.erb | 149 |
24 files changed, 2551 insertions, 1 deletions
diff --git a/cpp/msgpack b/cpp/msgpack deleted file mode 120000 index 945c9b4..0000000 --- a/cpp/msgpack +++ /dev/null @@ -1 +0,0 @@ -.
\ No newline at end of file diff --git a/cpp/msgpack/object.hpp b/cpp/msgpack/object.hpp new file mode 100644 index 0000000..ed2e290 --- /dev/null +++ b/cpp/msgpack/object.hpp @@ -0,0 +1,329 @@ +// +// 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 <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 = 0x01, + BOOLEAN = 0x02, + POSITIVE_INTEGER = 0x03, + NEGATIVE_INTEGER = 0x04, + DOUBLE = 0x05, + RAW = 0x06, + ARRAY = 0x07, + MAP = 0x08, + }; +} + + +struct object; +struct object_kv; + +struct object_array { + uint32_t size; + object* ptr; +}; + +struct object_map { + uint32_t size; + object_kv* ptr; +}; + +struct object_raw { + uint32_t size; + const char* ptr; +}; + +struct object { + union union_type { + bool boolean; + uint64_t u64; + int64_t i64; + double dec; + object_array array; + object_map map; + object_raw raw; + 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 obj); + operator msgpack_object(); + +private: + struct implicit_type; + +public: + implicit_type convert() const; +}; + +struct object_kv { + object key; + object val; +}; + +bool operator==(const object x, const object y); +bool operator!=(const object x, const object y); + +std::ostream& operator<< (std::ostream& s, const object o); + + +template <typename Stream, typename T> +packer<Stream>& operator<< (packer<Stream>& o, const T& v); + +template <typename T> +T& operator>> (object o, T& v); + + +struct object::implicit_type { + implicit_type(object o) : obj(o) { } + ~implicit_type() { } + + template <typename T> + operator T() { return obj.as<T>(); } + +private: + object obj; +}; + + +// 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; +} + + +inline bool operator!=(const object x, const object y) +{ return !(x == y); } + + +inline object::object() { } + +inline object::object(msgpack_object obj) +{ + // FIXME beter way? + ::memcpy(this, &obj, sizeof(obj)); +} + +inline object::operator msgpack_object() +{ + // FIXME beter way? + msgpack_object obj; + ::memcpy(&obj, this, sizeof(obj)); + return obj; +} + + +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; +} + + +// 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: + if(v.via.u64 <= (uint64_t)std::numeric_limits<uint16_t>::max()) { + if(v.via.u64 <= (uint16_t)std::numeric_limits<uint8_t>::max()) { + o.pack_uint8(v.via.u64); + } else { + o.pack_uint16(v.via.u64); + } + } else { + if(v.via.u64 <= (uint64_t)std::numeric_limits<uint32_t>::max()) { + o.pack_uint32(v.via.u64); + } else { + o.pack_uint64(v.via.u64); + } + } + return o; + + case type::NEGATIVE_INTEGER: + if(v.via.i64 >= (int64_t)std::numeric_limits<int16_t>::min()) { + if(v.via.i64 >= (int64_t)std::numeric_limits<int8_t>::min()) { + o.pack_int8(v.via.i64); + } else { + o.pack_int16(v.via.i64); + } + } else { + if(v.via.i64 >= (int64_t)std::numeric_limits<int32_t>::min()) { + o.pack_int64(v.via.i64); + } else { + o.pack_int64(v.via.i64); + } + } + return o; + + case type::RAW: + o.pack_raw(v.via.raw.size); + o.pack_raw_body(v.via.raw.ptr, v.via.raw.size); + return o; + + case type::ARRAY: + o.pack_array(v.via.array.size); + for(object* p(v.via.array.ptr), + * const pend(v.via.array.ptr + v.via.array.size); + p < pend; ++p) { + 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/msgpack/pack.hpp b/cpp/msgpack/pack.hpp new file mode 100644 index 0000000..9c291c1 --- /dev/null +++ b/cpp/msgpack/pack.hpp @@ -0,0 +1,252 @@ +// +// MessagePack for C++ serializing 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_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(); + +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(uint8_t d); + packer<Stream>& pack_int16(uint16_t d); + packer<Stream>& pack_int32(uint32_t d); + packer<Stream>& pack_int64(uint64_t d); + + packer<Stream>& pack_short(int 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); +} + + +#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() { } + +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(uint8_t d) +{ _pack_int8(m_stream, d); return *this; } + +template <typename Stream> +inline packer<Stream>& packer<Stream>::pack_int16(uint16_t d) +{ _pack_int16(m_stream, d); return *this; } + +template <typename Stream> +inline packer<Stream>& packer<Stream>::pack_int32(uint32_t d) +{ _pack_int32(m_stream, d); return *this; } + +template <typename Stream> +inline packer<Stream>& packer<Stream>::pack_int64(uint64_t d) +{ _pack_int64(m_stream, d); return *this;} + + +template <typename Stream> +inline packer<Stream>& packer<Stream>::pack_short(int 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/msgpack/sbuffer.hpp b/cpp/msgpack/sbuffer.hpp new file mode 100644 index 0000000..ca06884e --- /dev/null +++ b/cpp/msgpack/sbuffer.hpp @@ -0,0 +1,103 @@ +// +// 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); + } + +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/msgpack/type.hpp b/cpp/msgpack/type.hpp new file mode 100644 index 0000000..fafa674 --- /dev/null +++ b/cpp/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/msgpack/type/bool.hpp b/cpp/msgpack/type/bool.hpp new file mode 100644 index 0000000..b945d85 --- /dev/null +++ b/cpp/msgpack/type/bool.hpp @@ -0,0 +1,46 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/bool.hpp */ + diff --git a/cpp/msgpack/type/define.hpp.erb b/cpp/msgpack/type/define.hpp.erb new file mode 100644 index 0000000..2eac4f4 --- /dev/null +++ b/cpp/msgpack/type/define.hpp.erb @@ -0,0 +1,98 @@ +// +// 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); \ + } + +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(); } + } +}; +<%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%>);<%}%> + } + <%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/msgpack/type/deque.hpp b/cpp/msgpack/type/deque.hpp new file mode 100644 index 0000000..d34d243 --- /dev/null +++ b/cpp/msgpack/type/deque.hpp @@ -0,0 +1,56 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/deque.hpp */ + diff --git a/cpp/msgpack/type/float.hpp b/cpp/msgpack/type/float.hpp new file mode 100644 index 0000000..390e340 --- /dev/null +++ b/cpp/msgpack/type/float.hpp @@ -0,0 +1,63 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/float.hpp */ + diff --git a/cpp/msgpack/type/int.hpp b/cpp/msgpack/type/int.hpp new file mode 100644 index 0000000..03500f7 --- /dev/null +++ b/cpp/msgpack/type/int.hpp @@ -0,0 +1,147 @@ +// +// 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; } + + +} // namespace msgpack + +#endif /* msgpack/type/int.hpp */ + diff --git a/cpp/msgpack/type/list.hpp b/cpp/msgpack/type/list.hpp new file mode 100644 index 0000000..6ecc02f --- /dev/null +++ b/cpp/msgpack/type/list.hpp @@ -0,0 +1,56 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/list.hpp */ + diff --git a/cpp/msgpack/type/map.hpp b/cpp/msgpack/type/map.hpp new file mode 100644 index 0000000..552de57 --- /dev/null +++ b/cpp/msgpack/type/map.hpp @@ -0,0 +1,139 @@ +// +// 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 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 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/map.hpp */ + diff --git a/cpp/msgpack/type/nil.hpp b/cpp/msgpack/type/nil.hpp new file mode 100644 index 0000000..93e66ff --- /dev/null +++ b/cpp/msgpack/type/nil.hpp @@ -0,0 +1,49 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/nil.hpp */ + diff --git a/cpp/msgpack/type/pair.hpp b/cpp/msgpack/type/pair.hpp new file mode 100644 index 0000000..ba72c1f --- /dev/null +++ b/cpp/msgpack/type/pair.hpp @@ -0,0 +1,50 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/pair.hpp */ + diff --git a/cpp/msgpack/type/raw.hpp b/cpp/msgpack/type/raw.hpp new file mode 100644 index 0000000..8c68aba --- /dev/null +++ b/cpp/msgpack/type/raw.hpp @@ -0,0 +1,84 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/raw.hpp */ + diff --git a/cpp/msgpack/type/set.hpp b/cpp/msgpack/type/set.hpp new file mode 100644 index 0000000..f2c5bfb --- /dev/null +++ b/cpp/msgpack/type/set.hpp @@ -0,0 +1,80 @@ +// +// 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 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/set.hpp */ + diff --git a/cpp/msgpack/type/string.hpp b/cpp/msgpack/type/string.hpp new file mode 100644 index 0000000..a085d53 --- /dev/null +++ b/cpp/msgpack/type/string.hpp @@ -0,0 +1,46 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/string.hpp */ + diff --git a/cpp/msgpack/type/tr1/unordered_map.hpp b/cpp/msgpack/type/tr1/unordered_map.hpp new file mode 100644 index 0000000..1996cfd --- /dev/null +++ b/cpp/msgpack/type/tr1/unordered_map.hpp @@ -0,0 +1,85 @@ +// +// 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 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/map.hpp */ + diff --git a/cpp/msgpack/type/tr1/unordered_set.hpp b/cpp/msgpack/type/tr1/unordered_set.hpp new file mode 100644 index 0000000..eb127b5 --- /dev/null +++ b/cpp/msgpack/type/tr1/unordered_set.hpp @@ -0,0 +1,80 @@ +// +// 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 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/set.hpp */ + diff --git a/cpp/msgpack/type/tuple.hpp.erb b/cpp/msgpack/type/tuple.hpp.erb new file mode 100644 index 0000000..2930ae0 --- /dev/null +++ b/cpp/msgpack/type/tuple.hpp.erb @@ -0,0 +1,171 @@ +// +// 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<A<%=j%>>(&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; +} +<%}%> + +} // namespace msgpack + +#endif /* msgpack/type/tuple.hpp */ + diff --git a/cpp/msgpack/type/vector.hpp b/cpp/msgpack/type/vector.hpp new file mode 100644 index 0000000..385d070 --- /dev/null +++ b/cpp/msgpack/type/vector.hpp @@ -0,0 +1,60 @@ +// +// 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; +} + + +} // namespace msgpack + +#endif /* msgpack/type/vector.hpp */ + diff --git a/cpp/msgpack/unpack.hpp b/cpp/msgpack/unpack.hpp new file mode 100644 index 0000000..324111a --- /dev/null +++ b/cpp/msgpack/unpack.hpp @@ -0,0 +1,301 @@ +// +// 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 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 execute() until it retunrs false */ + bool execute(); + + /*! 5.1. if execute() returns true, take out the parsed object */ + object data(); + + /*! 5.2. the object is valid until the zone is deleted */ + // Note that once release_zone() from unpacker, you must delete it + // otherwise the memrory will leak. + zone* release_zone(); + + /*! 5.2. this method is equivalence to `delete release_zone()` */ + void reset_zone(); + + /*! 5.3. after release_zone(), re-initialize unpacker */ + void reset(); + + /*! 6. 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( /* readable */ ) { + // + // // 1. + // pac.reserve(1024); + // + // // 2. + // ssize_t bytes = + // read(the_source, pac.buffer(), pac.buffer_capacity()); + // + // // error handling ... + // + // // 3. + // pac.buffer_consumed(bytes); + // + // // 4. + // while(pac.execute()) { + // // 5.1 + // object o = pac.data(); + // + // // 5.2 + // std::auto_ptr<msgpack::zone> olife( pac.release_zone() ); + // + // // boost::shared_ptr is also usable: + // // boost::shared_ptr<msgpack::zone> olife( pac.release_zone() ); + // + // // 5.3 + // pac.reset(); + // + // // do some with the object with the old zone. + // do_something(o, olife); + // } + // } + // + +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&); +}; + + +typedef enum { + UNPACK_SUCCESS = 2, + UNPACK_EXTRA_BYTES = 1, + UNPACK_CONTINUE = 0, + UNPACK_PARSE_ERROR = -1, +} unpack_return; + +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::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 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/msgpack/vrefbuffer.hpp b/cpp/msgpack/vrefbuffer.hpp new file mode 100644 index 0000000..c8eca7b --- /dev/null +++ b/cpp/msgpack/vrefbuffer.hpp @@ -0,0 +1,92 @@ +// +// 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(); + } + } + +private: + typedef msgpack_vrefbuffer base; + +private: + vrefbuffer(const vrefbuffer&); +}; + + +} // namespace msgpack + +#endif /* msgpack/vrefbuffer.hpp */ + diff --git a/cpp/msgpack/zone.hpp.erb b/cpp/msgpack/zone.hpp.erb new file mode 100644 index 0000000..48988ab --- /dev/null +++ b/cpp/msgpack/zone.hpp.erb @@ -0,0 +1,149 @@ +// +// 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/object.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 */ + |
