diff options
| author | frsyuki <frsyuki@users.sourceforge.jp> | 2010-05-30 03:02:40 +0900 |
|---|---|---|
| committer | frsyuki <frsyuki@users.sourceforge.jp> | 2010-05-30 03:02:40 +0900 |
| commit | 602971408ba8c2c1490bd87d2987ab65900a5297 (patch) | |
| tree | 46370064d07f57fe027a8537a730c502d0e71687 /cpp/src | |
| parent | 2f5d83f07d7a50bfb7287e1fa28bc7a7fd7e7d49 (diff) | |
| download | msgpack-python-602971408ba8c2c1490bd87d2987ab65900a5297.tar.gz | |
cpp: move source files into src/ directory
Diffstat (limited to 'cpp/src')
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); +} + |
