diff options
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/Makefile.am | 21 | ||||
-rw-r--r-- | cpp/bench.cpp | 15 | ||||
-rw-r--r-- | cpp/bench.mk | 2 | ||||
-rw-r--r-- | cpp/object.cpp | 483 | ||||
-rw-r--r-- | cpp/object.hpp | 340 | ||||
-rw-r--r-- | cpp/pack.hpp | 10 | ||||
-rw-r--r-- | cpp/test.cpp | 148 | ||||
-rw-r--r-- | cpp/type.hpp | 9 | ||||
-rw-r--r-- | cpp/type/array.hpp | 59 | ||||
-rw-r--r-- | cpp/type/boolean.hpp | 49 | ||||
-rw-r--r-- | cpp/type/float.hpp | 67 | ||||
-rw-r--r-- | cpp/type/integer.hpp | 243 | ||||
-rw-r--r-- | cpp/type/map.hpp | 132 | ||||
-rw-r--r-- | cpp/type/nil.hpp | 47 | ||||
-rw-r--r-- | cpp/type/raw.hpp | 99 | ||||
-rw-r--r-- | cpp/type/tuple.hpp.erb | 172 | ||||
-rw-r--r-- | cpp/unpack.cpp | 149 | ||||
-rw-r--r-- | cpp/unpack.hpp | 16 | ||||
-rw-r--r-- | cpp/zone.cpp | 57 | ||||
-rw-r--r-- | cpp/zone.hpp | 70 | ||||
-rw-r--r-- | cpp/zone.hpp.erb | 202 |
21 files changed, 1307 insertions, 1083 deletions
diff --git a/cpp/Makefile.am b/cpp/Makefile.am index aa22cc7..8b13bea 100644 --- a/cpp/Makefile.am +++ b/cpp/Makefile.am @@ -10,20 +10,27 @@ nobase_include_HEADERS = \ msgpack/pack.hpp \ msgpack/unpack.hpp \ msgpack/object.hpp \ - msgpack/zone.hpp + msgpack/zone.hpp \ + msgpack/type.hpp \ + msgpack/type/array.hpp \ + msgpack/type/boolean.hpp \ + msgpack/type/integer.hpp \ + msgpack/type/map.hpp \ + msgpack/type/nil.hpp \ + msgpack/type/tuple.hpp noinst_HEADERS = \ - msgpack/zone.hpp.erb + msgpack/type/tuple.hpp.erb # FIXME -object.lo: msgpack/zone.hpp -unpack.lo: msgpack/zone.hpp -zone.lo: msgpack/zone.hpp +object.lo: msgpack/type/tuple.hpp +unpack.lo: msgpack/type/tuple.hpp +zone.lo: msgpack/type/tuple.hpp -msgpack/zone.hpp: msgpack/zone.hpp.erb +msgpack/type/tuple.hpp: msgpack/type/tuple.hpp.erb erb $< > $@ -MOSTLYCLEANFILES = zone.hpp +MOSTLYCLEANFILES = msgpack/type/tuple.hpp libmsgpack_la_LDFLAGS = -version-info 0:0:0 diff --git a/cpp/bench.cpp b/cpp/bench.cpp index 517a870..1aad807 100644 --- a/cpp/bench.cpp +++ b/cpp/bench.cpp @@ -6,10 +6,10 @@ #include <stdexcept> #include <string> -//static const unsigned int TASK_INT_NUM = 1<<24; -//static const unsigned int TASK_STR_LEN = 1<<15; -static const unsigned int TASK_INT_NUM = 1<<22; -static const unsigned int TASK_STR_LEN = 1<<13; +static const unsigned int TASK_INT_NUM = 1<<24; +static const unsigned int TASK_STR_LEN = 1<<15; +//static const unsigned int TASK_INT_NUM = 1<<22; +//static const unsigned int TASK_STR_LEN = 1<<13; static const char* TASK_STR_PTR; @@ -104,6 +104,7 @@ void bench_msgpack_int() } timer.show_stat(buf.size()); + std::cout << "----" << std::endl; std::cout << "unpack integer" << std::endl; @@ -116,6 +117,7 @@ void bench_msgpack_int() } timer.show_stat(buf.size()); + /* std::cout << "----" << std::endl; std::cout << "dynamic pack integer" << std::endl; @@ -124,6 +126,7 @@ void bench_msgpack_int() timer.reset(); msgpack::pack(buf, obj); timer.show_stat(buf.size()); + */ } void bench_msgpack_str() @@ -144,6 +147,7 @@ void bench_msgpack_str() } timer.show_stat(buf.size()); + std::cout << "----" << std::endl; std::cout << "unpack string" << std::endl; @@ -156,6 +160,8 @@ void bench_msgpack_str() } timer.show_stat(buf.size()); + + /* std::cout << "----" << std::endl; std::cout << "dynamic pack string" << std::endl; @@ -164,6 +170,7 @@ void bench_msgpack_str() timer.reset(); msgpack::pack(buf, obj); timer.show_stat(buf.size()); + */ } int main(void) diff --git a/cpp/bench.mk b/cpp/bench.mk index 52a4b80..8da2b7f 100644 --- a/cpp/bench.mk +++ b/cpp/bench.mk @@ -5,5 +5,5 @@ LDFLAGS += all: bench bench: bench.o unpack.o zone.o object.o pack.hpp unpack.hpp zone.hpp object.hpp - $(CXX) bench.o unpack.o zone.o object.o $(CFLAGS) $(LDFLAGS) -o $@ + $(CXX) bench.o unpack.o zone.o object.o $(CXXFLAGS) $(LDFLAGS) -o $@ diff --git a/cpp/object.cpp b/cpp/object.cpp index ef2a68c..276732c 100644 --- a/cpp/object.cpp +++ b/cpp/object.cpp @@ -16,417 +16,128 @@ // limitations under the License. // #include "msgpack/object.hpp" -#include "msgpack/pack.hpp" -namespace msgpack { - -namespace { - -template <typename T, typename X, bool TSigned, bool XSigned> -struct numeric_overflow_signed_impl; +#include <string.h> -template <typename T, typename X> -struct numeric_overflow_signed_impl<T, X, true, true> { - static int test(X x) { - if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) || - (!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) { - if( sizeof(T) < sizeof(X) ) { - if( static_cast<X>( std::numeric_limits<T>::max()) < x ) { return 1; } - if( static_cast<X>(-std::numeric_limits<T>::max()) > x ) { return -1; } - } - } else if(std::numeric_limits<T>::is_integer) { - if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; } - if( static_cast<X>(-std::numeric_limits<T>::max()) > x) { return -1; } - } - return 0; - } -}; +namespace msgpack { -template <typename T, typename X> -struct numeric_overflow_signed_impl<T, X, true, false> { - static int test(X x) { - if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) || - (!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) { - if( sizeof(T) <= sizeof(X) ) { - if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; } - } - } else if(std::numeric_limits<T>::is_integer) { - if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; } - } - return 0; - } -}; -template <typename T, typename X> -struct numeric_overflow_signed_impl<T, X, false, true> { - static int test(X x) { - if( static_cast<X>(0) > x ) { return -1; } - if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) || - (!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) { - if( sizeof(T) < sizeof(X) ) { - if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; } +std::ostream& operator<< (std::ostream& s, const object o) +{ + switch(o.type) { + case type::NIL: + s << "nil"; + break; + + case type::BOOLEAN: + s << (o.via.boolean ? "true" : "false"); + break; + + case type::POSITIVE_INTEGER: + s << o.via.u64; + break; + + case type::NEGATIVE_INTEGER: + s << o.via.i64; + break; + + case type::RAW: + (s << '"').write(o.via.ref.ptr, o.via.ref.size) << '"'; + break; + + case type::ARRAY: + s << "["; + if(o.via.container.size != 0) { + object* p(o.via.container.ptr); + s << *p; + ++p; + for(object* const pend(o.via.container.ptr + o.via.container.size); + p < pend; ++p) { + s << ", " << *p; } - } else if(std::numeric_limits<T>::is_integer) { - if( static_cast<X>( std::numeric_limits<T>::max()) < x) { return 1; } } - return 0; - } -}; - -template <typename T, typename X> -struct numeric_overflow_signed_impl<T, X, false, false> { - static int test(X x) { - if( ( std::numeric_limits<T>::is_integer && std::numeric_limits<X>::is_integer) || - (!std::numeric_limits<T>::is_integer && !std::numeric_limits<X>::is_integer) ) { - if( sizeof(T) < sizeof(X) ) { - if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; } + s << "]"; + break; + // FIXME loop optimiziation + + case type::MAP: + s << "{"; + if(o.via.container.size != 0) { + object* p(o.via.container.ptr); + object* const pend(o.via.container.ptr + o.via.container.size*2); + s << *p; ++p; + s << "=>"; + s << *p; ++p; + while(p < pend) { + s << ", "; + s << *p; ++p; + s << "=>"; + s << *p; ++p; } - } else if(std::numeric_limits<T>::is_integer) { - if( static_cast<X>(std::numeric_limits<T>::max()) < x ) { return 1; } } - return 0; - } -}; + s << "}"; + break; + // FIXME loop optimiziation -template <typename T, typename X> -struct numeric_overflow { - static int test(X x) { - return numeric_overflow_signed_impl<T, X, std::numeric_limits<T>::is_signed, std::numeric_limits<X>::is_signed>::test(x); - } - static void check(X x) { - int r = test(x); - if(r == 1) { throw positive_overflow_error(); } - if(r == -1) { throw negative_overflow_error(); } - } -}; - -template <typename T, typename X> -struct numeric_underflow { - static bool test(X x) { - return static_cast<X>(static_cast<T>(x)) != x; - } - static void check(X x) { - if(test(x)) { throw underflow_error(); } + default: + // FIXME + s << "#<UNKNOWN " << (uint16_t)o.type << ">" << std::endl; } -}; - -template <typename T, typename X> -inline T integer_cast(X x) { - numeric_overflow<T,X>::check(x); - return static_cast<T>(x); } - -template <typename T, typename X> -inline T float_cast(X x) { - numeric_overflow<T,X>::check(x); - numeric_underflow<T,X>::check(x); - return static_cast<T>(x); } - -template <typename V> -inline bool numequal(V v, const object_class* x) - try { return v == static_cast<V>(*x); } - catch (type_error&) { return false; } - -template <typename V> -inline bool numless(V v, const object_class* x) - try { return v < static_cast<V>(*x); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } - -template <typename V> -inline bool numgreater(V v, const object_class* x) - try { return v > static_cast<V>(*x); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } - -template <typename V> -inline void numeric_inspect(V v, std::ostream& s) - { s << v; } - -template <> -inline void numeric_inspect<uint8_t>(uint8_t v, std::ostream& s) - { s << (uint16_t)v; } - -template <> -inline void numeric_inspect<int8_t>(int8_t v, std::ostream& s) - { s << (int16_t)v; } - -template <typename V> -inline void numeric_pack(dynamic_packer& p, V v); - -template <> -inline void numeric_pack<uint8_t>(dynamic_packer& p, uint8_t v) - { p.pack_uint8(v); } - -template <> -inline void numeric_pack<uint16_t>(dynamic_packer& p, uint16_t v) - { p.pack_uint16(v); } - -template <> -inline void numeric_pack<uint32_t>(dynamic_packer& p, uint32_t v) - { p.pack_uint32(v); } - -template <> -inline void numeric_pack<uint64_t>(dynamic_packer& p, uint64_t v) - { p.pack_uint64(v); } - -template <> -inline void numeric_pack<int8_t>(dynamic_packer& p, int8_t v) - { p.pack_int8(v); } - -template <> -inline void numeric_pack<int16_t>(dynamic_packer& p, int16_t v) - { p.pack_int16(v); } - -template <> -inline void numeric_pack<int32_t>(dynamic_packer& p, int32_t v) - { p.pack_int32(v); } - -template <> -inline void numeric_pack<int64_t>(dynamic_packer& p, int64_t v) - { p.pack_int64(v); } - -template <> -inline void numeric_pack<float>(dynamic_packer& p, float v) - { p.pack_float(v); } - -template <> -inline void numeric_pack<double>(dynamic_packer& p, double v) - { p.pack_double(v); } - -} // noname namespace - - -bool object_nil::isnil() const { return true; } -bool object_nil::operator== (const object_class* x) const - { return typeid(*this) == typeid(*x); } -void object_nil::pack(dynamic_packer& p) const - { p.pack_nil(); } -const object_class* object_nil::inspect(std::ostream& s) const - { s << "nil"; return this; } - -bool object_true::xbool() const { return true; } -bool object_true::operator== (const object_class* x) const - { return typeid(*this) == typeid(*x); } -void object_true::pack(dynamic_packer& p) const - { p.pack_true(); } -const object_class* object_true::inspect(std::ostream& s) const - { s << "true"; return this; } - -bool object_false::xbool() const { return false; } -bool object_false::operator== (const object_class* x) const - { return typeid(*this) == typeid(*x); } -void object_false::pack(dynamic_packer& p) const - { p.pack_false(); } -const object_class* object_false::inspect(std::ostream& s) const - { s << "false"; return this; } - - -#define INTEGER_OBJECT(NAME) \ -uint8_t object_##NAME::xu8 () const { return val; } \ -uint16_t object_##NAME::xu16 () const { return integer_cast<uint16_t>(val); } \ -uint32_t object_##NAME::xu32 () const { return integer_cast<uint32_t>(val); } \ -uint64_t object_##NAME::xu64 () const { return integer_cast<uint64_t>(val); } \ -int8_t object_##NAME::xi8 () const { return integer_cast<int8_t>(val); } \ -int16_t object_##NAME::xi16 () const { return integer_cast<int16_t>(val); } \ -int32_t object_##NAME::xi32 () const { return integer_cast<int32_t>(val); } \ -int64_t object_##NAME::xi64 () const { return integer_cast<int64_t>(val); } \ -float object_##NAME::xfloat () const { return integer_cast<float>(val); } \ -double object_##NAME::xdouble() const { return integer_cast<double>(val); } \ -bool object_##NAME::operator== (const object_class* x) const \ - try { return val == x->x##NAME(); } \ - catch (type_error&) { return false; } \ -bool object_##NAME::operator< (const object_class* x) const \ - try { return val < x->x##NAME(); } \ - catch (positive_overflow_error&) { return true; } \ - catch (overflow_error&) { return false; } \ -bool object_##NAME::operator> (const object_class* x) const \ - try { return val > x->x##NAME(); } \ - catch (negative_overflow_error&) { return true; } \ - catch (overflow_error&) { return false; } \ -void object_##NAME::pack(dynamic_packer& p) const \ - { numeric_pack(p, val); } \ -const object_class* object_##NAME::inspect(std::ostream& s) const \ - { numeric_inspect(val, s); return this; } \ - - -INTEGER_OBJECT(u8) -INTEGER_OBJECT(u16) -INTEGER_OBJECT(u32) -INTEGER_OBJECT(u64) -INTEGER_OBJECT(i8) -INTEGER_OBJECT(i16) -INTEGER_OBJECT(i32) -INTEGER_OBJECT(i64) - -#undef INTEGER_OBJECT - - -#define FLOAT_OBJECT(NAME) \ -uint8_t object_##NAME::xu8 () const { return val; } \ -uint16_t object_##NAME::xu16 () const { return integer_cast<uint16_t>(val); } \ -uint32_t object_##NAME::xu32 () const { return integer_cast<uint32_t>(val); } \ -uint64_t object_##NAME::xu64 () const { return integer_cast<uint64_t>(val); } \ -int8_t object_##NAME::xi8 () const { return integer_cast<int8_t>(val); } \ -int16_t object_##NAME::xi16 () const { return integer_cast<int16_t>(val); } \ -int32_t object_##NAME::xi32 () const { return integer_cast<int32_t>(val); } \ -int64_t object_##NAME::xi64 () const { return integer_cast<int64_t>(val); } \ -float object_##NAME::xfloat () const { return float_cast<float>(val); } \ -double object_##NAME::xdouble() const { return float_cast<double>(val); } \ -bool object_##NAME::operator== (const object_class* x) const \ - try { return val == x->x##NAME(); } \ - catch (type_error&) { return false; } \ -bool object_##NAME::operator< (const object_class* x) const { \ - try { return val < x->xdouble(); } \ - catch (positive_overflow_error&) { return true; } \ - catch (overflow_error&) { return false; } \ - catch (underflow_error&) { \ - if(val < 0.0) { \ - if(numeric_overflow<int64_t, double>::test(val) == -1) { return true; } \ - try { return static_cast<int64_t>(val) < x->xi64(); } \ - catch (type_error&) { return true; } \ - } else { \ - if(numeric_overflow<uint64_t, double>::test(val) == 1) { return false; } \ - try { return static_cast<uint64_t>(val) < x->xu64(); } \ - catch (type_error&) { return false; } \ - } \ - } } \ -bool object_##NAME::operator> (const object_class* x) const { \ - try { return val > x->xdouble(); } \ - catch (negative_overflow_error&) { return true; } \ - catch (overflow_error&) { return false; } \ - catch (underflow_error&) { \ - if(val < 0.0) { \ - if(numeric_overflow<int64_t, double>::test(val) == -1) { return false; } \ - try { return static_cast<int64_t>(val) > x->xi64(); } \ - catch (type_error&) { return false; } \ - } else { \ - if(numeric_overflow<uint64_t, double>::test(val) == 1) { return true; } \ - try { return static_cast<uint64_t>(val) > x->xu64(); } \ - catch (type_error&) { return true; } \ - } \ - } } \ -void object_##NAME::pack(dynamic_packer& p) const \ - { numeric_pack(p, val); } \ -const object_class* object_##NAME::inspect(std::ostream& s) const \ - { s << val; return this; } \ - -FLOAT_OBJECT(float) -FLOAT_OBJECT(double) + return s; +} -#undef FLOAT_OBJECT +bool operator==(const object x, const object y) +{ + if(x.type != y.type) { return false; } -#define RAW_OBJECT(NAME, EXTRA) \ -EXTRA \ -bool object_##NAME::operator== (const object_class* x) const \ - try { \ - raw xr(x->xraw()); \ - return len == xr.len && (ptr == xr.ptr || memcmp(ptr, xr.ptr, len) == 0); \ - } catch (type_error&) { return false; } \ -bool object_##NAME::operator< (const object_class* x) const { \ - raw xr(x->xraw()); \ - if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) < 0; } \ - else { return len < xr.len; } } \ -bool object_##NAME::operator> (const object_class* x) const { \ - raw xr(x->xraw()); \ - if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) > 0; } \ - else { return len > xr.len; } } \ -void object_##NAME::pack(dynamic_packer& p) const \ - { p.pack_raw(ptr, len); } \ -const object_class* object_##NAME::inspect(std::ostream& s) const \ - { (s << '"').write(ptr, len) << '"'; return this; } // FIXME escape + switch(x.type) { + case type::NIL: + return true; + case type::BOOLEAN: + return x.via.boolean == y.via.boolean; -// FIXME -RAW_OBJECT(mutable_raw_ref, - /*mutable_raw object_mutable_raw_ref::xraw() { return mutable_raw(ptr, len); }*/ - raw object_mutable_raw_ref::xraw() const { return raw(ptr, len); } ) + case type::POSITIVE_INTEGER: + return x.via.u64 == y.via.u64; -RAW_OBJECT(raw_ref, - raw object_raw_ref::xraw() const { return raw(ptr, len); } ) + case type::NEGATIVE_INTEGER: + return x.via.i64 == y.via.i64; -#undef RAW_OBJECT + case type::RAW: + return x.via.ref.size == y.via.ref.size && + memcmp(x.via.ref.ptr, y.via.ref.ptr, x.via.ref.size) == 0; - - array& object_array::xarray() { return val; } -const array& object_array::xarray() const { return val; } -bool object_array::operator== (const object_class* x) const - try { - const std::vector<object>& xa(x->xarray()); - if(val.size() != xa.size()) { return false; } - for(std::vector<object>::const_iterator iv(val.begin()), iv_end(val.end()), ix(xa.begin()); - iv != iv_end; - ++iv, ++ix) { - if(*iv != *ix) { return false; } + case type::ARRAY: + if(x.via.container.size != y.via.container.size) { return false; } + for(object* px(x.via.container.ptr), + * const pxend(x.via.container.ptr + x.via.container.size), + * py(y.via.container.ptr); + px != pxend; ++px, ++py) { + if(*px != *py) { return false; } } return true; - } catch (type_error&) { return false; } -const object_class* object_array::inspect(std::ostream& s) const -{ - s << '['; - if(!val.empty()) { - std::vector<object>::const_iterator it(val.begin()); - s << *it; - ++it; - for(std::vector<object>::const_iterator it_end(val.end()); - it != it_end; - ++it) { - s << ", " << *it; + // FIXME loop optimiziation + + case type::MAP: + if(x.via.container.size != y.via.container.size) { return false; } + for(object* px(x.via.container.ptr), + * const pxend(x.via.container.ptr + x.via.container.size*2), + * py(y.via.container.ptr); + px != pxend; ++px, ++py) { + if(*px != *py) { return false; } } - } - s << ']'; - return this; -} -void object_array::pack(dynamic_packer& p) const -{ - p.pack_array(val.size()); - for(std::vector<object>::const_iterator it(val.begin()), it_end(val.end()); - it != it_end; - ++it) { - it->pack(p); + return true; + + default: + return false; } } - map& object_map::xmap() { return val; } -const map& object_map::xmap() const { return val; } -bool object_map::operator== (const object_class* x) const - try { - const std::map<object, object>& xm(x->xmap()); - if(val.size() != xm.size()) { return false; } - for(std::map<object, object>::const_iterator iv(val.begin()), iv_end(val.end()), ix(xm.begin()); - iv != iv_end; - ++iv, ++ix) { - if(iv->first != ix->first || iv->second != ix->first) { return false; } - } - return true; - } catch (type_error&) { return false; } -const object_class* object_map::inspect(std::ostream& s) const -{ - s << '{'; - if(!val.empty()) { - std::map<object, object>::const_iterator it(val.begin()); - s << it->first << "=>" << it->second; - ++it; - for(std::map<object, object>::const_iterator it_end(val.end()); - it != it_end; - ++it) { - s << ", " << it->first << "=>" << it->second; - } - } - s << '}'; - return this; -} -void object_map::pack(dynamic_packer& p) const -{ - p.pack_map(val.size()); - for(std::map<object, object>::const_iterator it(val.begin()), it_end(val.end()); - it != it_end; - ++it) { - it->first.pack(p); - it->second.pack(p); - } -} +// FIXME +//template <typename Stream> +//const object& operator>> (const object& v, packer<Stream>& o); } // namespace msgpack diff --git a/cpp/object.hpp b/cpp/object.hpp index 456210c..7007b90 100644 --- a/cpp/object.hpp +++ b/cpp/object.hpp @@ -1,5 +1,5 @@ // -// MessagePack for C++ dynamic typed objects +// MessagePack for C++ static resolution routine // // Copyright (C) 2008 FURUHASHI Sadayuki // @@ -18,305 +18,109 @@ #ifndef MSGPACK_OBJECT_HPP__ #define MSGPACK_OBJECT_HPP__ -#include <cstddef> +#include "msgpack/pack.hpp" +#include <stdint.h> #include <stdexcept> #include <typeinfo> #include <ostream> -#include <vector> -#include <map> -#include <string> namespace msgpack { -class type_error : public std::bad_cast { }; -class cast_error : public type_error { }; -class overflow_error : public type_error { }; -class underflow_error : public type_error { }; -class positive_overflow_error : public overflow_error { }; -class negative_overflow_error : public overflow_error { }; - - -struct mutable_raw { - explicit mutable_raw() : ptr(NULL), len(0) {} - explicit mutable_raw(char* p, size_t l) : ptr(p), len(l) {} -public: - char* ptr; - size_t len; -public: - std::string str() { return std::string(ptr, len); } -}; - -struct raw { - explicit raw() : ptr(NULL), len(0) {} - explicit raw(const char* p, size_t l) : ptr(p), len(l) {} - raw(const mutable_raw& m) : ptr(m.ptr), len(m.len) {} -public: - const char* ptr; - size_t len; -public: - std::string str() { return std::string(ptr, len); } -}; - - -struct object; - -typedef std::map<object, object> map; -typedef std::vector<object> array; - -class dynamic_packer; - - -struct object_class { - virtual ~object_class() {} - virtual bool isnil () const { return false; } - virtual bool xbool () const { throw cast_error(); } - virtual uint8_t xu8 () const { throw cast_error(); } - virtual uint16_t xu16 () const { throw cast_error(); } - virtual uint32_t xu32 () const { throw cast_error(); } - virtual uint64_t xu64 () const { throw cast_error(); } - virtual int8_t xi8 () const { throw cast_error(); } - virtual int16_t xi16 () const { throw cast_error(); } - virtual int32_t xi32 () const { throw cast_error(); } - virtual int64_t xi64 () const { throw cast_error(); } - virtual float xfloat () const { throw cast_error(); } - virtual double xdouble() const { throw cast_error(); } - //virtual mutable_raw xraw () { throw cast_error(); } // FIXME - virtual array& xarray() { throw cast_error(); } - virtual map& xmap () { throw cast_error(); } - virtual raw xraw () const { throw cast_error(); } - virtual const array& xarray() const { throw cast_error(); } - virtual const map& xmap () const { throw cast_error(); } - virtual bool operator== (const object_class* x) const { return false; } - virtual bool operator< (const object_class* x) const { throw cast_error(); } - virtual bool operator> (const object_class* x) const { throw cast_error(); } - bool operator!= (const object_class* x) const { return !(this->operator==(x)); } - virtual void pack(dynamic_packer& p) const = 0; - operator bool() const { return xbool(); } // FIXME !isnil(); - operator uint8_t() const { return xu8(); } - operator uint16_t() const { return xu16(); } - operator uint32_t() const { return xu32(); } - operator uint64_t() const { return xu64(); } - operator int8_t() const { return xi8(); } - operator int16_t() const { return xi16(); } - operator int32_t() const { return xi32(); } - operator int64_t() const { return xi64(); } - operator float() const { return xfloat(); } - operator double() const { return xdouble(); } - //operator mutable_raw() { return xraw(); } // FIXME - operator array&() { return xarray(); } - operator map&() { return xmap(); } - operator raw() const { return xraw(); } - operator const array&() const { return xarray(); } - operator const map&() const { return xmap(); } - virtual const object_class* inspect(std::ostream& s) const - { s << '<' << typeid(*this).name() << '>'; return this; } -}; - -inline std::ostream& operator<< (std::ostream& s, const object_class* o) - { o->inspect(s); return s; } - - -struct object_container_mixin {}; -struct object_constructor_mixin {}; +class type_error : public std::bad_cast { }; struct object { - explicit object() : val(NULL) {} - object(object_class* v) : val(v) {} - //object(object_class& v) : val(&v) {} - ~object() {} - bool isnil () const { return val->isnil(); } - bool xbool () const { return val->xbool(); } - uint8_t xu8 () const { return val->xu8(); } - uint16_t xu16 () const { return val->xu16(); } - uint32_t xu32 () const { return val->xu32(); } - uint64_t xu64 () const { return val->xu64(); } - int8_t xi8 () const { return val->xi8(); } - int16_t xi16 () const { return val->xi16(); } - int32_t xi32 () const { return val->xi32(); } - int64_t xi64 () const { return val->xi64(); } - float xfloat () const { return val->xfloat(); } - double xdouble() const { return val->xdouble(); } - //mutable_raw xraw () { return val->xraw(); } // FIXME - array& xarray() { return val->xarray(); } - map& xmap () { return val->xmap(); } - raw xraw () const { return const_cast<const object_class*>(val)->xraw(); } - const array& xarray() const { return const_cast<const object_class*>(val)->xarray(); } - const map& xmap () const { return const_cast<const object_class*>(val)->xmap(); } - bool operator== (object x) const { return val->operator== (x.val); } - bool operator!= (object x) const { return val->operator!= (x.val); } - bool operator< (object x) const { return val->operator< (x.val); } - bool operator> (object x) const { return val->operator> (x.val); } - void pack(dynamic_packer& p) const { val->pack(p); } - template <typename Stream> - void pack(Stream& s) const { dynamic_packer p(s); pack(p); } - operator bool() const { return val->operator bool(); } - operator uint8_t() const { return val->operator uint8_t(); } - operator uint16_t() const { return val->operator uint16_t(); } - operator uint32_t() const { return val->operator uint32_t(); } - operator uint64_t() const { return val->operator uint64_t(); } - operator int8_t() const { return val->operator int8_t(); } - operator int16_t() const { return val->operator int16_t(); } - operator int32_t() const { return val->operator int32_t(); } - operator int64_t() const { return val->operator int64_t(); } - operator float() const { return val->operator float(); } - operator double() const { return val->operator double(); } - //operator mutable_raw() { return val->operator mutable_raw(); } // FIXME - operator array&() { return val->operator array&(); } - operator map&() { return val->operator map&(); } - operator raw() const { return val->operator raw(); } - operator const array&() const { return val->operator const array&(); } - operator const map&() const { return val->operator const map&(); } - const object& inspect(std::ostream& s) const - { val->inspect(s); return *this; } -private: - friend class object_container_mixin; - friend class object_constructor_mixin; - object_class* val; + unsigned char type; + union { + bool boolean; + uint64_t u64; + int64_t i64; + double dec; + struct { + object* ptr; + uint32_t size; + } container; + struct { + const char* ptr; + uint32_t size; + } ref; + } via; + // FIXME template <typename T> operator T() { T v; convert(*this, v); return v; }; }; -inline std::ostream& operator<< (std::ostream& s, const object& o) - { o.inspect(s); return s; } +std::ostream& operator<< (std::ostream& s, const object o); +bool operator==(const object x, const object y); +inline bool operator!=(const object x, const object y) { return !(x == y); } -struct object_nil : object_class { - bool isnil() const; - bool operator== (const object_class* x) const; - void pack(dynamic_packer& p) const; - const object_class* inspect(std::ostream& s) const; -}; -struct object_true : object_class { - bool xbool() const; - bool operator== (const object_class* x) const; - void pack(dynamic_packer& p) const; - const object_class* inspect(std::ostream& s) const; -}; +template <typename Stream> +const object& operator>> (const object& v, packer<Stream>& o); -struct object_false : object_class { - bool xbool() const; - bool operator== (const object_class* x) const; - void pack(dynamic_packer& p) const; - const object_class* inspect(std::ostream& s) const; -}; -#define INTEGER_CLASS(TYPE, NAME) \ -struct object_##NAME : object_class { \ - explicit object_##NAME(TYPE v) : val(v) {} \ - uint8_t xu8 () const; \ - uint16_t xu16 () const; \ - uint32_t xu32 () const; \ - uint64_t xu64 () const; \ - int8_t xi8 () const; \ - int16_t xi16 () const; \ - int32_t xi32 () const; \ - int64_t xi64 () const; \ - float xfloat () const; \ - double xdouble() const; \ - bool operator== (const object_class* x) const; \ - bool operator< (const object_class* x) const; \ - bool operator> (const object_class* x) const; \ - void pack(dynamic_packer& p) const; \ - const object_class* inspect(std::ostream& s) const; \ -private: \ - TYPE val; \ -}; +namespace type { + static const unsigned char NIL = 0x01; + static const unsigned char BOOLEAN = 0x02; + static const unsigned char POSITIVE_INTEGER = 0x03; + static const unsigned char NEGATIVE_INTEGER = 0x04; + static const unsigned char DOUBLE = 0x05; + static const unsigned char RAW = 0x06; + static const unsigned char ARRAY = 0x07; + static const unsigned char MAP = 0x08; -INTEGER_CLASS(uint8_t, u8) -INTEGER_CLASS(uint16_t, u16) -INTEGER_CLASS(uint32_t, u32) -INTEGER_CLASS(uint64_t, u64) -INTEGER_CLASS(int8_t, i8) -INTEGER_CLASS(int16_t, i16) -INTEGER_CLASS(int32_t, i32) -INTEGER_CLASS(int64_t, i64) -#undef INTEGER_CLASS + template <typename T> + inline T& operator<< (T& v, object o) + { + v = o; + return v; + } -#define FLOAT_CLASS(TYPE, NAME) \ -struct object_##NAME : object_class { \ - object_##NAME(TYPE v) : val(v) {} \ - uint8_t xu8 () const; \ - uint16_t xu16 () const; \ - uint32_t xu32 () const; \ - uint64_t xu64 () const; \ - int8_t xi8 () const; \ - int16_t xi16 () const; \ - int32_t xi32 () const; \ - int64_t xi64 () const; \ - float xfloat () const; \ - double xdouble() const; \ - bool operator== (const object_class* x) const; \ - bool operator< (const object_class* x) const; \ - bool operator> (const object_class* x) const; \ - void pack(dynamic_packer& p) const; \ - const object_class* inspect(std::ostream& s) const; \ -private: \ - TYPE val; \ -}; + namespace detail { + template <typename Stream, typename T> + inline void pack_copy(T v, packer<Stream>& o) + { pack(v, o); } + } -FLOAT_CLASS(float, float) -FLOAT_CLASS(double, double) + template <typename Stream, typename T> + inline const T& operator>> (const T& v, packer<Stream>& o) + { + detail::pack_copy(v.pack(), o); + return v; + } -#undef FLOAT_CLASS +} // namespace type -#define RAW_CLASS(NAME, TYPE, EXTRA) \ -struct object_##NAME : object_class { \ - explicit object_##NAME(TYPE p, uint32_t l) : ptr(p), len(l) {} \ - EXTRA \ - bool operator== (const object_class* x) const; \ - bool operator< (const object_class* x) const; \ - bool operator> (const object_class* x) const; \ - void pack(dynamic_packer& p) const; \ - const object_class* inspect(std::ostream& s) const; \ -private: \ - TYPE ptr; \ - uint32_t len; \ -}; - -// FIXME -RAW_CLASS(mutable_raw_ref, char*, /*mutable_raw xraw();*/ raw xraw() const; ) -RAW_CLASS(raw_ref, const char*, raw xraw() const; ) - -#undef RAW_CLASS +template <typename T> +inline void convert(T& v, object o) +{ + using namespace type; + v << o; +} -struct object_array : object_class, object_container_mixin { - explicit object_array() {} - explicit object_array(uint32_t n) { val.reserve(n); } - array& xarray(); - const array& xarray() const; - bool operator== (const object_class* x) const; - // FIXME operator<, operator> - void pack(dynamic_packer& p) const; - const object_class* inspect(std::ostream& s) const; -public: - void push_back(object o) { val.push_back(o); } -private: - std::vector<object> val; -}; +template <typename Stream, typename T> +inline void pack(T& v, packer<Stream>& o) +{ + using namespace type; + v >> o; +} -// FIXME hash, operator==: nil, true, false, array, mapを入れられない -struct object_map : object_class, object_container_mixin { - explicit object_map() {} - map& xmap(); - const map& xmap() const; - bool operator== (const object_class* x) const; - // FIXME operator<, operator> - void pack(dynamic_packer& p) const; - const object_class* inspect(std::ostream& s) const; -public: - void store(object k, object v) { val[k] = v; } -private: - std::map<object, object> val; -}; +template <typename Stream, typename T> +inline void pack(T& v, Stream& s) +{ + packer<Stream> pk(s); + pack(v, pk); +} } // namespace msgpack +#include "msgpack/type.hpp" + #endif /* msgpack/object.hpp */ diff --git a/cpp/pack.hpp b/cpp/pack.hpp index f3eeb34..fe470b6 100644 --- a/cpp/pack.hpp +++ b/cpp/pack.hpp @@ -18,8 +18,6 @@ #ifndef MSGPACK_PACK_HPP__ #define MSGPACK_PACK_HPP__ -#include "msgpack/object.hpp" -#include "msgpack/zone.hpp" #include <arpa/inet.h> // __BYTE_ORDER #include <stdexcept> @@ -44,9 +42,9 @@ public: void pack_int64(uint64_t d) { pack_int64_impl(m_stream, d); } void pack_float(float d) { pack_float_impl(m_stream, d); } void pack_double(double d) { pack_double_impl(m_stream, d); } - void pack_nil() { pack_nil(m_stream); } - void pack_true() { pack_true(m_stream); } - void pack_false() { pack_false(m_stream); } + void pack_nil() { pack_nil_impl(m_stream); } + void pack_true() { pack_true_impl(m_stream); } + void pack_false() { pack_false_impl(m_stream); } void pack_array(unsigned int n) { pack_array_impl(m_stream, n); } void pack_map(unsigned int n) { pack_map_impl(m_stream, n); } void pack_raw(const char* b, size_t l) { pack_raw_impl(m_stream, (const void*)b, l); } @@ -92,6 +90,7 @@ template <typename Stream> packer<Stream>::packer(Stream& s) : m_stream(s) { } +/* class dynamic_stream { public: template <typename Stream> @@ -212,6 +211,7 @@ inline void pack(Stream& s, object o) dynamic_packer pk(s); o.pack(pk); } +*/ } // namespace msgpack diff --git a/cpp/test.cpp b/cpp/test.cpp index 68050a3..dff9101 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -1,37 +1,35 @@ #include <iostream> #include <string> -//#include <msgpack/unpack.hpp> -//#include <msgpack/pack.hpp> #include <msgpack.hpp> #include <sstream> #include <memory> +using namespace msgpack; + class checker { public: - void check(const char* d, size_t len, msgpack::object should) { - using msgpack::object; + template <typename T> + void check(const char* d, size_t len, T should) { try { std::cout << "----" << std::endl; object o; try { - o = msgpack::unpack(d, len, m_zone); + o = unpack(d, len, m_zone); } catch (std::runtime_error& e) { - std::cout << should << std::endl; + std::cout << o << std::endl; std::cout << "**" << e.what() << "**" << std::endl; return; } std::cout << o << std::endl; - if(o != should) { - std::cout << "** TEST FAILED **" << std::endl; - } try { std::stringstream s; - msgpack::pack(s, o); + pack(should, s); std::string str(s.str()); - object ro = msgpack::unpack(str.data(), str.size(), m_zone); + object ro = unpack(str.data(), str.size(), m_zone); + std::cout << ro << std::endl; if(ro != o) { throw std::runtime_error("NOT MATCH"); } } catch (std::runtime_error& e) { std::cout << "** REUNPACK FAILED **" << std::endl; @@ -45,7 +43,7 @@ public: m_zone.clear(); } private: - msgpack::zone m_zone; + zone m_zone; }; int main(void) @@ -53,54 +51,48 @@ int main(void) checker c; { // SimpleValue - msgpack::zone z; const char d[] = { 0x93, 0xc0, 0xc2, 0xc3, }; c.check(d, sizeof(d), - z.narray( - z.nnil(), z.nfalse(), z.ntrue() + type::make_tuple( + type::nil(), false, true ) ); } { // Fixnum - msgpack::zone z; const char d[] = { 0x92, 0x93, 0x00, 0x40, 0x7f, 0x93, 0xe0, 0xf0, 0xff, }; c.check(d, sizeof(d), - z.narray( - z.narray( - z.nu8(0), - z.nu8(64), - z.nu8(127) + type::make_tuple( + type::make_tuple( + 0, 64, 127 ), - z.narray( - z.ni8(-32), - z.ni8(-16), - z.ni8(-1) + type::make_tuple( + -32, -16, -1 ) ) ); } { // FixArray - msgpack::zone z; const char d[] = { 0x92, 0x90, 0x91, 0x91, 0xc0, }; + std::vector<int> empty; c.check(d, sizeof(d), - z.narray( - z.narray(), - z.narray( - z.narray( - z.nnil() + type::make_tuple( + empty, + type::make_tuple( + type::make_tuple( + type::nil() ) ) ) @@ -108,7 +100,6 @@ int main(void) } { // FixRaw - msgpack::zone z; const char d[] = { 0x94, 0xa0, @@ -117,91 +108,84 @@ int main(void) 0xa3, 'd', 'e', 'f', }; c.check(d, sizeof(d), - z.narray( - z.nraw_ref("", 0), - z.nraw_ref("a", 1), - z.nraw_ref("bc", 2), - z.nraw_ref("def", 3) + type::make_tuple( + std::string(""), + std::string("a"), + std::string("bc"), + type::raw_ref("def", 3) ) ); } - static const uint16_t TASK_ARRAY = 100; - static char tarray[3]; - static char traw[64]; + static const unsigned TASK_ARRAY = 100; + static const unsigned TASK_REPEAT = 10; + std::vector<std::string> task; + + // create task { + static char traw[64]; memset(traw, 'a', sizeof(traw)); - traw[0] = 0xda; - uint16_t n = htons(sizeof(traw)-3); - traw[1] = ((char*)&n)[0]; - traw[2] = ((char*)&n)[1]; - - msgpack::zone z; - std::cout << msgpack::unpack(traw, sizeof(traw), z) << std::endl;; + + task.resize(TASK_ARRAY); + for(unsigned i=0; i < TASK_ARRAY; ++i) { + task[i] = std::string(traw, sizeof(traw)); + } } - { - tarray[0] = 0xdc; - uint16_t n = htons(TASK_ARRAY); - tarray[1] = ((char*)&n)[0]; - tarray[2] = ((char*)&n)[1]; - } + std::stringstream stream; + + // send message { - // write message - ssize_t total_bytes = 0; - std::stringstream stream; - for(unsigned q=0; q < 10; ++q) { - stream.write(tarray, sizeof(tarray)); - total_bytes += sizeof(tarray); - for(uint16_t i=0; i < TASK_ARRAY; ++i) { - stream.write(traw, sizeof(traw)); - total_bytes += sizeof(traw); - } + for(unsigned i=0; i < TASK_REPEAT; ++i) { + pack(task, stream); } + std::cout << "send " << stream.str().size() << " bytes" << std::endl; + } - stream.seekg(0); + ssize_t total_bytes = stream.str().size(); + stream.seekg(0); - // reserive message + // reserive message + { unsigned num_msg = 0; - static const size_t RESERVE_SIZE = 32;//*1024; - msgpack::unpacker upk; + std::auto_ptr<zone> pz(new zone()); + + unpacker pac(*pz); + while(stream.good() && total_bytes > 0) { // 1. reserve buffer - upk.reserve_buffer(RESERVE_SIZE); + pac.reserve_buffer(RESERVE_SIZE); // 2. read data to buffer() up to buffer_capacity() bytes size_t sz = stream.readsome( - upk.buffer(), - upk.buffer_capacity()); + pac.buffer(), + pac.buffer_capacity()); total_bytes -= sz; std::cout << "read " << sz << " bytes to capacity " - << upk.buffer_capacity() << " bytes" + << pac.buffer_capacity() << " bytes" << std::endl; // 3. specify the number of bytes actually copied - upk.buffer_consumed(sz); + pac.buffer_consumed(sz); // 4. repeat execute() until it returns false - while( upk.execute() ) { - std::cout << "message parsed" << std::endl; - + while( pac.execute() ) { // 5.1. take out the parsed object - msgpack::object o = upk.data(); + object o = pac.data(); - // 5.2. the parsed object is valid until the zone is deleted - std::auto_ptr<msgpack::zone> pz(upk.release_zone()); - - std::cout << o << std::endl; + // do something using pz and o + std::cout << "message parsed: " << o << std::endl; ++num_msg; - // 5.3 re-initialize unpacker - upk.reset(); + // 5.3 re-initialize unpacker with next zone */ + pz.reset(new zone()); + pac.reset(*pz); } } diff --git a/cpp/type.hpp b/cpp/type.hpp new file mode 100644 index 0000000..1dfd414 --- /dev/null +++ b/cpp/type.hpp @@ -0,0 +1,9 @@ +#include "msgpack/type/array.hpp" +#include "msgpack/type/boolean.hpp" +#include "msgpack/type/float.hpp" +#include "msgpack/type/integer.hpp" +#include "msgpack/type/map.hpp" +#include "msgpack/type/nil.hpp" +#include "msgpack/type/raw.hpp" +#include "msgpack/type/tuple.hpp" + diff --git a/cpp/type/array.hpp b/cpp/type/array.hpp new file mode 100644 index 0000000..7066703 --- /dev/null +++ b/cpp/type/array.hpp @@ -0,0 +1,59 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_ARRAY_HPP__ +#define MSGPACK_TYPE_ARRAY_HPP__ + +#include "msgpack/object.hpp" +#include <vector> + +namespace msgpack { +namespace type { + + +template <typename T> +inline std::vector<T> operator<< (std::vector<T>& v, object o) +{ + if(o.type != ARRAY) { throw type_error(); } + v.resize(o.via.container.size); + object* p(o.via.container.ptr); + object* const pend(o.via.container.ptr + o.via.container.size); + T* it(&v.front()); + for(; p < pend; ++p, ++it) { + convert(*it, *p); + } + return v; +} + + +template <typename Stream, typename T> +inline const std::vector<T>& operator>> (const std::vector<T>& v, packer<Stream>& o) +{ + o.pack_array(v.size()); + for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + pack(*it, o); + } + return v; +} + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/array.hpp */ + diff --git a/cpp/type/boolean.hpp b/cpp/type/boolean.hpp new file mode 100644 index 0000000..0538495 --- /dev/null +++ b/cpp/type/boolean.hpp @@ -0,0 +1,49 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_BOOLEAN_HPP__ +#define MSGPACK_TYPE_BOOLEAN_HPP__ + +#include "msgpack/object.hpp" +#include <vector> + +namespace msgpack { +namespace type { + + +inline bool& operator<< (bool& v, object o) +{ + if(o.type != BOOLEAN) { throw type_error(); } + v = o.via.boolean; + return v; +} + + +template <typename Stream> +inline const bool& operator>> (const bool& v, packer<Stream> o) +{ + if(v) { o.pack_true(); } + else { o.pack_false(); } + return v; +} + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/bool.hpp */ + diff --git a/cpp/type/float.hpp b/cpp/type/float.hpp new file mode 100644 index 0000000..11fa280 --- /dev/null +++ b/cpp/type/float.hpp @@ -0,0 +1,67 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_FLOAT_HPP__ +#define MSGPACK_TYPE_FLOAT_HPP__ + +#include "msgpack/object.hpp" +#include <vector> + +namespace msgpack { +namespace type { + + +// FIXME check overflow, underflow + + +inline float& operator<< (float& v, object o) +{ + if(o.type != DOUBLE) { throw type_error(); } + v = o.via.dec; + return v; +} + + +template <typename Stream> +inline const float& operator>> (const float& v, packer<Stream> o) +{ + o.pack_float(v); + return v; +} + + +inline double& operator<< (double& v, object o) +{ + if(o.type != DOUBLE) { throw type_error(); } + v = o.via.dec; + return v; +} + + +template <typename Stream> +inline const double& operator>> (const double& v, packer<Stream> o) +{ + o.pack_double(v); + return v; +} + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/float.hpp */ + diff --git a/cpp/type/integer.hpp b/cpp/type/integer.hpp new file mode 100644 index 0000000..488c9d4 --- /dev/null +++ b/cpp/type/integer.hpp @@ -0,0 +1,243 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_INTEGER_HPP__ +#define MSGPACK_TYPE_INTEGER_HPP__ + +#include "msgpack/object.hpp" +#include <limits> + +namespace msgpack { +namespace type { + + +namespace detail { + template <typename T, bool Signed> + struct convert_integer_sign; + + template <typename T> + struct convert_integer_sign<T, true> { + static inline T convert(object o) { + if(o.type == POSITIVE_INTEGER) { + if(o.via.u64 > (uint64_t)std::numeric_limits<T>::max()) + { throw type_error(); } + return o.via.u64; + } else if(o.type == NEGATIVE_INTEGER) { + if(o.via.i64 < (int64_t)-std::numeric_limits<T>::max()) + { throw type_error(); } + return o.via.i64; + } + throw type_error(); + } + }; + + template <typename T> + struct convert_integer_sign<T, false> { + static inline T convert(object o) { + if(o.type == POSITIVE_INTEGER) { + if(o.via.u64 > (uint64_t)std::numeric_limits<T>::max()) + { throw type_error(); } + return o.via.u64; + } + throw type_error(); + } + }; + + template <typename T> + static inline T convert_integer(object o) + { + return detail::convert_integer_sign<T, std::numeric_limits<T>::is_signed>::convert(o); + } + + + + template <typename T, typename Stream, int Size, bool Signed> + struct pack_integer_size_sign; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 1, true> { + static inline void pack(T v, packer<Stream>& o) + { o.pack_int8(v); } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 1, false> { + static inline void pack(T v, packer<Stream>& o) + { o.pack_uint8(v); } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 2, true> { + static inline void pack(T v, packer<Stream>& o) { + if( (int16_t)v <= (int16_t)std::numeric_limits<int8_t>::max() && + (int16_t)v >= (int16_t)std::numeric_limits<int8_t>::min()) + { o.pack_int8(v); } + else { o.pack_int16(v); } + } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 2, false> { + static inline void pack(T v, packer<Stream>& o) { + if( (uint16_t)v <= (uint16_t)std::numeric_limits<uint8_t>::max()) + { o.pack_uint8(v); } + else { o.pack_uint16(v); } + } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 4, true> { + static inline void pack(T v, packer<Stream>& o) { + if( (int32_t)v <= (int32_t)std::numeric_limits<int8_t>::max() && + (int32_t)v >= (int32_t)std::numeric_limits<int8_t>::min()) + { o.pack_int8(v); } + else if( (int32_t)v <= (int32_t)std::numeric_limits<int16_t>::max() && + (int32_t)v >= (int32_t)std::numeric_limits<int16_t>::min()) + { o.pack_int16(v); } + else { o.pack_int32(v); } + } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 4, false> { + static inline void pack(T v, packer<Stream>& o) { + if( (uint32_t)v <= (uint32_t)std::numeric_limits<uint8_t>::max()) + { o.pack_uint8(v); } + else if( (uint32_t)v <= (uint32_t)std::numeric_limits<uint16_t>::max()) + { o.pack_uint16(v); } + else { o.pack_uint32(v); } + } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 8, true> { + static inline void pack(T v, packer<Stream>& o) { + if( (int64_t)v <= (int64_t)std::numeric_limits<int8_t>::max() && + (int64_t)v >= (int64_t)std::numeric_limits<int8_t>::min()) + { o.pack_int8(v); } + else if( (int64_t)v <= (int64_t)std::numeric_limits<int16_t>::max() && + (int64_t)v >= (int64_t)std::numeric_limits<int16_t>::min()) + { o.pack_int16(v); } + else if( (int64_t)v <= (int64_t)std::numeric_limits<int32_t>::max() && + (int64_t)v >= (int64_t)std::numeric_limits<int32_t>::min()) + { o.pack_int32(v); } + else { o.pack_int64(v); } + } + }; + + template <typename T, typename Stream> + struct pack_integer_size_sign<T, Stream, 8, false> { + static inline void pack(T v, packer<Stream>& o) { + if( (uint64_t)v <= (uint64_t)std::numeric_limits<uint8_t>::max()) + { o.pack_uint8(v); } + else if( (uint64_t)v <= (uint64_t)std::numeric_limits<uint16_t>::max()) + { o.pack_uint16(v); } + else if( (uint64_t)v <= (uint64_t)std::numeric_limits<uint32_t>::max()) + { o.pack_uint32(v); } + else { o.pack_uint64(v); } + } + }; + + + template <typename T, typename Stream> + static inline void pack_integer(T v, packer<Stream>& o) + { + pack_integer_size_sign<T, Stream, sizeof(T), std::numeric_limits<T>::is_signed>::pack(v, o); + } + +} // namespace detail + + +inline signed char& operator<< (signed char& v, object o) + { v = detail::convert_integer<signed char>(o); return v; } + +inline signed short& operator<< (signed short& v, object o) + { v = detail::convert_integer<signed short>(o); return v; } + +inline signed int& operator<< (signed int& v, object o) + { v = detail::convert_integer<signed int>(o); return v; } + +inline signed long& operator<< (signed long& v, object o) + { v = detail::convert_integer<signed long>(o); return v; } + +inline signed long long& operator<< (signed long long& v, object o) + { v = detail::convert_integer<signed long long>(o); return v; } + + +inline unsigned char& operator<< (unsigned char& v, object o) + { v = detail::convert_integer<unsigned char>(o); return v; } + +inline unsigned short& operator<< (unsigned short& v, object o) + { v = detail::convert_integer<unsigned short>(o); return v; } + +inline unsigned int& operator<< (unsigned int& v, object o) + { v = detail::convert_integer<unsigned int>(o); return v; } + +inline unsigned long& operator<< (unsigned long& v, object o) + { v = detail::convert_integer<unsigned long>(o); return v; } + +inline unsigned long long& operator<< (unsigned long long& v, object o) + { v = detail::convert_integer<unsigned long long>(o); return v; } + + +template <typename Stream> +inline const signed char& operator>> (const signed char& v, packer<Stream> o) + { detail::pack_integer<signed char>(v, o); return v; } + +template <typename Stream> +inline const signed short& operator>> (const signed short& v, packer<Stream> o) + { detail::pack_integer<signed short>(v, o); return v; } + +template <typename Stream> +inline const signed int& operator>> (const signed int& v, packer<Stream> o) + { detail::pack_integer<signed int>(v, o); return v; } + +template <typename Stream> +inline const signed long& operator>> (const signed long& v, packer<Stream> o) + { detail::pack_integer<signed long>(v, o); return v; } + +template <typename Stream> +inline const signed long long& operator>> (const signed long long& v, packer<Stream> o) + { detail::pack_integer<signed long long>(v, o); return v; } + + +template <typename Stream> +inline const unsigned char& operator>> (const unsigned char& v, packer<Stream> o) + { detail::pack_integer<unsigned char>(v, o); return v; } + +template <typename Stream> +inline const unsigned short& operator>> (const unsigned short& v, packer<Stream> o) + { detail::pack_integer<unsigned short>(v, o); return v; } + +template <typename Stream> +inline const unsigned int& operator>> (const unsigned int& v, packer<Stream> o) + { detail::pack_integer<unsigned int>(v, o); return v; } + +template <typename Stream> +inline const unsigned long& operator>> (const unsigned long& v, packer<Stream> o) + { detail::pack_integer<unsigned long>(v, o); return v; } + +template <typename Stream> +inline const unsigned long long& operator>> (const unsigned long long& v, packer<Stream> o) + { detail::pack_integer<unsigned long long>(v, o); return v; } + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/integer.hpp */ + diff --git a/cpp/type/map.hpp b/cpp/type/map.hpp new file mode 100644 index 0000000..1efecec --- /dev/null +++ b/cpp/type/map.hpp @@ -0,0 +1,132 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_MAP_HPP__ +#define MSGPACK_TYPE_MAP_HPP__ + +#include "msgpack/object.hpp" +#include <map> +#include <vector> + +namespace msgpack { +namespace type { + + +template <typename K, typename V> +class assoc_vector : public std::vector< std::pair<K, V> > {}; + +namespace detail { + template <typename K, typename V> + struct pair_first_less { + bool operator() (const std::pair<K, V>& x, const std::pair<K, V>& y) const + { return x.first < y.first; } + }; +} + +template <typename K, typename V> +inline assoc_vector<K,V>& operator<< (assoc_vector<K,V>& v, object o) +{ + if(o.type != MAP) { throw type_error(); } + v.resize(o.via.container.size); + object* p(o.via.container.ptr); + object* const pend(o.via.container.ptr + o.via.container.size); + std::pair<K, V>* it(&v.front()); + for(; p < pend; ++it) { + convert(it->first, *p); ++p; + convert(it->second, *p); ++p; + } + std::sort(v.begin(), v.end(), detail::pair_first_less<K,V>()); + return v; +} + +template <typename Stream, typename K, typename V> +inline const assoc_vector<K,V>& operator>> (const assoc_vector<K,V>& v, packer<Stream>& o) +{ + o.pack_map(v.size()); + for(typename assoc_vector<K,V>::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + pack(it->first, o); + pack(it->second, o); + } +} + + +template <typename K, typename V> +inline std::map<K, V> operator<< (std::map<K, V>& v, object o) +{ + if(o.type != MAP) { throw type_error(); } + object* p(o.via.container.ptr); + object* const pend(o.via.container.ptr + o.via.container.size*2); + while(p < pend) { + K key; + convert(key, *p); ++p; + typename std::map<K,V>::iterator it(v.find(key)); + if(it != v.end()) { + V val; + convert(val, *p); ++p; + it->insert( std::pair<K,V>(key, val) ); + } else { + convert(it->second, *p); ++p; + } + } + return v; +} + +template <typename Stream, typename K, typename V> +inline const std::map<K,V>& operator>> (const std::map<K,V>& v, packer<Stream>& o) +{ + o.pack_map(v.size()); + for(typename std::map<K,V>::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + pack(it->first, o); + pack(it->second, o); + } +} + + +template <typename K, typename V> +inline std::multimap<K, V> operator<< (std::multimap<K, V>& v, object o) +{ + if(o.type != MAP) { throw type_error(); } + object* p(o.via.container.ptr); + object* const pend(o.via.container.ptr + o.via.container.size*2); + while(p < pend) { + std::pair<K, V> value; + convert(value.first, *p); ++p; + convert(value.second, *p); ++p; + v.insert(value); + } + return v; +} + +template <typename Stream, typename K, typename V> +inline const std::multimap<K,V>& operator>> (const std::multimap<K,V>& v, packer<Stream>& o) +{ + o.pack_multimap(v.size()); + for(typename std::multimap<K,V>::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + pack(it->first, o); + pack(it->second, o); + } +} + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/map.hpp */ + diff --git a/cpp/type/nil.hpp b/cpp/type/nil.hpp new file mode 100644 index 0000000..73cedb4 --- /dev/null +++ b/cpp/type/nil.hpp @@ -0,0 +1,47 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_NIL_HPP__ +#define MSGPACK_TYPE_NIL_HPP__ + +#include "msgpack/object.hpp" + +namespace msgpack { +namespace type { + + +struct nil { }; + +inline nil& operator<< (nil& v, object o) +{ + if(o.type != NIL) { throw type_error(); } + return v; +} + +template <typename Stream> +inline const nil& operator>> (const nil& v, packer<Stream>& o) +{ + o.pack_nil(); + return v; +} + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/nil.hpp */ + diff --git a/cpp/type/raw.hpp b/cpp/type/raw.hpp new file mode 100644 index 0000000..8767238 --- /dev/null +++ b/cpp/type/raw.hpp @@ -0,0 +1,99 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_RAW_HPP__ +#define MSGPACK_TYPE_RAW_HPP__ + +#include "msgpack/object.hpp" +#include <string.h> +#include <string> + +namespace msgpack { +namespace type { + + +struct raw_ref { + raw_ref() : ptr(NULL), size(0) {} + raw_ref(const char* p, uint32_t s) : ptr(p), size(s) {} + + const char* ptr; + uint32_t size; + + std::string str() { return std::string(ptr, size); } + + bool operator== (const raw_ref& x) + { + return size == x.size && memcmp(ptr, x.ptr, size) == 0; + } + + bool operator!= (const raw_ref& x) + { + return !(*this != x); + } + + bool operator< (const raw_ref& x) + { + if(size == x.size) { return memcmp(ptr, x.ptr, size) < 0; } + else { return size < x.size; } + } + + bool operator> (const raw_ref& x) + { + if(size == x.size) { return memcmp(ptr, x.ptr, size) > 0; } + else { return size > x.size; } + } +}; + +inline raw_ref& operator<< (raw_ref& v, object o) +{ + if(o.type != RAW) { throw type_error(); } + v.ptr = o.via.ref.ptr; + v.size = o.via.ref.size; + return v; +} + + +inline std::string& operator<< (std::string& v, object o) +{ + raw_ref r; + r << o; + v.assign(r.ptr, r.size); + return v; +} + + +template <typename Stream> +inline const raw_ref& operator>> (const raw_ref& v, packer<Stream>& o) +{ + o.pack_raw(v.ptr, v.size); + return v; +} + + +template <typename Stream> +inline const std::string& operator>> (const std::string& v, packer<Stream>& o) +{ + o.pack_raw(v.data(), v.size()); + return v; +} + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/raw.hpp */ + diff --git a/cpp/type/tuple.hpp.erb b/cpp/type/tuple.hpp.erb new file mode 100644 index 0000000..2a8a2dd --- /dev/null +++ b/cpp/type/tuple.hpp.erb @@ -0,0 +1,172 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_TUPLE_HPP__ +#define MSGPACK_TYPE_TUPLE_HPP__ + +#include "msgpack/object.hpp" + +namespace msgpack { +namespace type { + + +// FIXME operator== +// FIXME operator!= + +<% GENERATION_LIMIT = 15 %> + +template < typename A0 <%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%> > +struct tuple; + +template <typename Tuple, int N> +struct tuple_type; + +template <typename Tuple, int N> +struct const_tuple_type; + +template <typename T> +struct tuple_element { + typedef T type; + tuple_element(T& x) : _x(x) {} + type& get() { return _x; } + const type& get() const { return _x; } +private: + type& _x; +}; + +template <typename T> +struct const_tuple_element { + typedef T type; + const_tuple_element(const T& x) : _x(x) {} + const type& get() const { return _x; } +private: + const type& _x; +}; + + +<%0.upto(GENERATION_LIMIT) {|i|%> +<%0.upto(i) {|j|%> +template < typename A0 <%1.upto(i) {|k|%>, typename A<%=k%> <%}%>> +struct tuple_type<tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>, <%=j%>> : tuple_element<A<%=j%>> { + tuple_type(tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>& x) : tuple_element<A<%=j%>>(x.a<%=j%>) {} +}; +<%}%> +<%}%> + + +<%0.upto(GENERATION_LIMIT) {|i|%> +<%0.upto(i) {|j|%> +template < typename A0 <%1.upto(i) {|k|%>, typename A<%=k%> <%}%>> +struct const_tuple_type<tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>, <%=j%>> : const_tuple_element<A<%=j%>> { + const_tuple_type(const tuple<A0 <%1.upto(i) {|k|%>, A<%=k%> <%}%>>& x) : const_tuple_element<A<%=j%>>(x.a<%=j%>) {} +}; +<%}%> +<%}%> + + +<%0.upto(GENERATION_LIMIT) {|i|%> +template < typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>> +tuple< A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>> make_tuple(const A0& a0 <%1.upto(i) {|j|%>, const A<%=j%>& a<%=j%><%}%>) +{ + return tuple< A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>(a0 <%1.upto(i) {|j|%>, a<%=j%><%}%>); +} +<%}%> + + +<%0.upto(GENERATION_LIMIT) {|i|%> +template < typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>> +struct tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>> { + tuple() {} + tuple(const A0& _a0 <%1.upto(i) {|j|%>, const A<%=j%>& _a<%=j%><%}%>) : + a0(_a0) <%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {} + tuple(object o) { convert(*this, o); } + template <int N> typename tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>::type& get() + { return tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>(*this).get(); } + template <int N> const typename const_tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>::type& get() const + { return const_tuple_type<tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>, N>(*this).get(); } + <%0.upto(i) {|j|%> + A<%=j%> a<%=j%>;<%}%> +}; +<%}%> + + +<%0.upto(GENERATION_LIMIT) {|i|%> +template < typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>> +tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& operator<< ( + tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& v, + object o) { + if(o.type != ARRAY) { throw type_error(); } + if(o.via.container.size < <%=i+1%>) { throw type_error(); } + <%0.upto(i) {|j|%> + convert<A<%=j%>>(v.template get<<%=j%>>(), o.via.container.ptr[<%=j%>]);<%}%> + return v; +} +<%}%> + + +// FIXME +/* +template <typename A0, typename A1 = void, typename A2 = void> +struct tuple_just; + +template <typename A0> +struct tuple_just<A0> { + A0 a0; + static inline void convert(object o, tuple_just<A0>& v) + { + if(o.type != ARRAY) { throw type_error(); } + if(o.v.container.size != 1) { throw type_error(); } + msgpack::convert<A0>(o.v.container.ptr[0], v.a0); + } +}; + +template <typename A0, typename A1> +struct tuple_just<A0, A1> { + A0 a0; + A1 a1; + static inline void convert(object o, tuple_just<A0, A1>& v) + { + if(o.type != ARRAY) { throw type_error(); } + if(o.v.container.size != 2) { throw type_error(); } + msgpack::convert<A0>(o.v.container.ptr[0], v.a0); + msgpack::convert<A1>(o.v.container.ptr[1], v.a1); + } +}; +*/ + + + +<%0.upto(GENERATION_LIMIT) {|i|%> +template < typename Stream , typename A0 <%1.upto(i) {|j|%>, typename A<%=j%> <%}%>> +const tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& operator>> ( + const tuple<A0 <%1.upto(i) {|j|%>, A<%=j%> <%}%>>& v, + packer<Stream> o) { + o.pack_array(<%=i+1%>); + <%0.upto(i) {|j|%> + pack(v.template get<<%=j%>>(), o);<%}%> + return v; +} +<%}%> + + + +} // namespace type +} // namespace msgpack + +#endif /* msgpack/type/tuple.hpp */ + + diff --git a/cpp/unpack.cpp b/cpp/unpack.cpp index 873d3da..71593a0 100644 --- a/cpp/unpack.cpp +++ b/cpp/unpack.cpp @@ -31,7 +31,7 @@ namespace msgpack { #define msgpack_unpack_callback(name) \ msgpack_unpack_##name -#define msgpack_unpack_object object_class* +#define msgpack_unpack_object object #define msgpack_unpack_user zone* @@ -40,68 +40,88 @@ struct msgpack_unpacker_context; static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx); -static object_class* msgpack_unpacker_data(struct msgpack_unpacker_context* ctx); +static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx); static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx, const char* data, size_t len, size_t* off); -static inline object_class* msgpack_unpack_init(zone** z) -{ return NULL; } +static inline object msgpack_unpack_init(zone** z) +{ return object(); } -static inline object_class* msgpack_unpack_uint8(zone** z, uint8_t d) -{ return (*z)->nu8(d); } +static inline object msgpack_unpack_uint8(zone** z, uint8_t d) +{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } -static inline object_class* msgpack_unpack_uint16(zone** z, uint16_t d) -{ return (*z)->nu16(d); } +static inline object msgpack_unpack_uint16(zone** z, uint16_t d) +{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } -static inline object_class* msgpack_unpack_uint32(zone** z, uint32_t d) -{ return (*z)->nu32(d); } +static inline object msgpack_unpack_uint32(zone** z, uint32_t d) +{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } -static inline object_class* msgpack_unpack_uint64(zone** z, uint64_t d) -{ return (*z)->nu64(d); } +static inline object msgpack_unpack_uint64(zone** z, uint64_t d) +{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } -static inline object_class* msgpack_unpack_int8(zone** z, int8_t d) -{ return (*z)->ni8(d); } +static inline object msgpack_unpack_int8(zone** z, int8_t d) +{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } + else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } } -static inline object_class* msgpack_unpack_int16(zone** z, int16_t d) -{ return (*z)->ni16(d); } +static inline object msgpack_unpack_int16(zone** z, int16_t d) +{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } + else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } } -static inline object_class* msgpack_unpack_int32(zone** z, int32_t d) -{ return (*z)->ni32(d); } +static inline object msgpack_unpack_int32(zone** z, int32_t d) +{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } + else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } } -static inline object_class* msgpack_unpack_int64(zone** z, int64_t d) -{ return (*z)->ni64(d); } +static inline object msgpack_unpack_int64(zone** z, int64_t d) +{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; } + else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } } -static inline object_class* msgpack_unpack_float(zone** z, float d) -{ return (*z)->nfloat(d); } +static inline object msgpack_unpack_float(zone** z, float d) +{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; } -static inline object_class* msgpack_unpack_double(zone** z, double d) -{ return (*z)->ndouble(d); } +static inline object msgpack_unpack_double(zone** z, double d) +{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; } -static inline object_class* msgpack_unpack_nil(zone** z) -{ return (*z)->nnil(); } +static inline object msgpack_unpack_nil(zone** z) +{ object o; o.type = type::NIL; return o; } -static inline object_class* msgpack_unpack_true(zone** z) -{ return (*z)->ntrue(); } +static inline object msgpack_unpack_true(zone** z) +{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; } -static inline object_class* msgpack_unpack_false(zone** z) -{ return (*z)->nfalse(); } +static inline object msgpack_unpack_false(zone** z) +{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; } -static inline object_class* msgpack_unpack_array(zone** z, unsigned int n) -{ return (*z)->narray(n); } +static inline object msgpack_unpack_array(zone** z, unsigned int n) +{ + object o; + o.type = type::ARRAY; + o.via.container.size = 0; + o.via.container.ptr = (*z)->malloc_container(n); + return o; +} -static inline void msgpack_unpack_array_item(zone** z, object_class* c, object_class* o) -{ reinterpret_cast<object_array*>(c)->push_back(o); } +static inline void msgpack_unpack_array_item(zone** z, object* c, object o) +{ c->via.container.ptr[ c->via.container.size++ ] = o; } -static inline object_class* msgpack_unpack_map(zone** z, unsigned int n) -{ return (*z)->nmap(); } +static inline object msgpack_unpack_map(zone** z, unsigned int n) +{ + object o; + o.type = type::MAP; + o.via.container.size = 0; + o.via.container.ptr = (*z)->malloc_container(n*2); + return o; +} -static inline void msgpack_unpack_map_item(zone** z, object_class* c, object_class* k, object_class* v) -{ reinterpret_cast<object_map*>(c)->store(k, v); } +static inline void msgpack_unpack_map_item(zone** z, object* c, object k, object v) +{ + c->via.container.ptr[ c->via.container.size ] = k; + c->via.container.ptr[ c->via.container.size+1 ] = v; + ++c->via.container.size; +} -static inline object_class* msgpack_unpack_raw(zone** z, const char* b, const char* p, unsigned int l) -{ return (*z)->nraw_ref(p, l); } +static inline object msgpack_unpack_raw(zone** z, const char* b, const char* p, unsigned int l) +{ object o; o.type = type::RAW; o.via.ref.ptr = p; o.via.ref.size = l; return o; } #include "msgpack/unpack_template.h" @@ -121,7 +141,7 @@ struct unpacker::context { return msgpack_unpacker_execute(&m_ctx, data, len, off); } - object_class* data() + object data() { return msgpack_unpacker_data(&m_ctx); } @@ -158,9 +178,8 @@ private: }; -unpacker::unpacker() : - m_zone(new zone()), - m_ctx(new context(m_zone)), +unpacker::unpacker(zone& z) : + m_ctx(new context(&z)), m_buffer(NULL), m_used(0), m_free(0), @@ -170,9 +189,7 @@ unpacker::unpacker() : unpacker::~unpacker() { - free(m_buffer); delete m_ctx; - delete m_zone; } @@ -184,32 +201,16 @@ void unpacker::expand_buffer(size_t len) else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; } while(next_size < len + m_used) { next_size *= 2; } - char* tmp = (char*)realloc(m_buffer, next_size); - if(!tmp) { throw std::bad_alloc(); } - m_buffer = tmp; - //char* tmp = (char*)malloc(next_size); - //if(!tmp) { throw std::bad_alloc(); } - //memcpy(tmp, m_buffer, m_used); - //free(m_buffer); - - m_buffer = tmp; + m_buffer = m_ctx->user()->realloc(m_buffer, next_size); m_free = next_size - m_used; } else { size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE; while(next_size < len + m_used - m_off) { next_size *= 2; } - char* tmp = (char*)malloc(next_size); - if(!tmp) { throw std::bad_alloc(); } + char* tmp = m_ctx->user()->malloc(next_size); memcpy(tmp, m_buffer+m_off, m_used-m_off); - try { - m_zone->push_finalizer<void>(&zone::finalize_free, NULL, m_buffer); - } catch (...) { - free(tmp); - throw; - } - m_buffer = tmp; m_used = m_used - m_off; m_free = next_size - m_used; @@ -230,29 +231,15 @@ bool unpacker::execute() } } -zone* unpacker::release_zone() -{ - zone* nz = new zone(); - zone* z = m_zone; - m_zone = nz; - m_ctx->user(m_zone); - return z; -} - object unpacker::data() { - return object(m_ctx->data()); + return m_ctx->data(); } -void unpacker::reset() +void unpacker::reset(zone& z) { if(m_off != 0) { expand_buffer(0); } - if(!m_zone->empty()) { - delete m_zone; - m_zone = NULL; - m_zone = new zone(); - } - m_ctx->reset(); + m_ctx->reset(&z); } diff --git a/cpp/unpack.hpp b/cpp/unpack.hpp index 86cfb6e..2730a08 100644 --- a/cpp/unpack.hpp +++ b/cpp/unpack.hpp @@ -40,7 +40,7 @@ struct unpack_error : public std::runtime_error { class unpacker { public: - unpacker(); + unpacker(zone& z); ~unpacker(); public: @@ -60,13 +60,8 @@ public: /*! 5.1. if execute() returns true, take out the parsed object */ object data(); - /*! 5.2. the parsed object is valid until the zone is deleted */ - // Note that once release_zone() from unpacker, you must delete it - // otherwise the memrory will leak. - zone* release_zone(); - - /*! 5.3. after release_zone(), re-initialize unpacker */ - void reset(); + /*! 5.2. re-initialize unpacker with next zone */ + void reset(zone& z); public: // These functions are usable when non-MessagePack message follows after @@ -85,8 +80,6 @@ public: void remove_nonparsed_buffer(); private: - zone* m_zone; - struct context; context* m_ctx; @@ -94,9 +87,12 @@ private: size_t m_used; size_t m_free; size_t m_off; + +private: void expand_buffer(size_t len); private: + unpacker(); unpacker(const unpacker&); public: diff --git a/cpp/zone.cpp b/cpp/zone.cpp index 4cc50d7..490bc25 100644 --- a/cpp/zone.cpp +++ b/cpp/zone.cpp @@ -20,52 +20,35 @@ namespace msgpack { -// FIXME custom allocator? +zone::zone() { } -void zone::expand_chunk() +zone::~zone() { clear(); } + +void zone::clear() { - cell_t* chunk = (cell_t*)malloc(sizeof(cell_t)*ZONE_CHUNK_SIZE); - if(!chunk) { throw std::bad_alloc(); } - try { - m_pool.push_back(chunk); - } catch (...) { - free(chunk); - throw; + for(std::vector<char*>::iterator it(m_ptrs.begin()), it_end(m_ptrs.end()); + it != it_end; ++it) { + free(*it); } + m_ptrs.clear(); } -void zone::clear() +char* zone::realloc(char* ptr, size_t count) { - if(!m_pool.empty()) { - size_t base_size = m_used / ZONE_CHUNK_SIZE; - size_t extend_size = m_used % ZONE_CHUNK_SIZE; - for(size_t b=0; b < base_size; ++b) { - cell_t* c(m_pool[b]); - for(size_t e=0; e < ZONE_CHUNK_SIZE; ++e) { - reinterpret_cast<object_class*>(c[e].data)->~object_class(); + if(ptr == NULL) { + return zone::malloc(count); + } else { + for(std::vector<char*>::reverse_iterator it(m_ptrs.rbegin()), it_end(m_ptrs.rend()); + it != it_end; ++it) { + if(*it == ptr) { + char* tmp = (char*)::realloc(ptr, count); + if(!tmp) { throw std::bad_alloc(); } + *it = tmp; + return tmp; } } - cell_t* c(m_pool.back()); - for(size_t e=0; e < extend_size; ++e) { - reinterpret_cast<object_class*>(c[e].data)->~object_class(); - } - - for(pool_t::iterator it(m_pool.begin()), it_end(m_pool.end()); - it != it_end; - ++it) { - free(*it); - } - m_pool.clear(); - } - m_used = 0; - - for(user_finalizer_t::reverse_iterator it(m_user_finalizer.rbegin()), - it_end(m_user_finalizer.rend()); - it != it_end; - ++it) { - it->call(); + throw std::bad_alloc(); } - m_user_finalizer.clear(); } diff --git a/cpp/zone.hpp b/cpp/zone.hpp new file mode 100644 index 0000000..f8c9cba --- /dev/null +++ b/cpp/zone.hpp @@ -0,0 +1,70 @@ +// +// MessagePack for C++ memory pool +// +// Copyright (C) 2008 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_ZONE_HPP__ +#define MSGPACK_ZONE_HPP__ + +#include "msgpack/object.hpp" +#include <cstdlib> +#include <vector> + +namespace msgpack { + + +class zone { +public: + zone(); + ~zone(); + +public: + char* malloc(size_t count); + char* realloc(char* ptr, size_t count); + object* malloc_container(size_t count); + + void clear(); + +private: + std::vector<char*> m_ptrs; + +private: + zone(const zone&); +}; + + +inline char* zone::malloc(size_t count) +{ + char* ptr = (char*)::malloc(count); + if(!ptr) { throw std::bad_alloc(); } + try { + m_ptrs.push_back(ptr); + } catch (...) { + free(ptr); + throw; + } + return ptr; +} + +inline object* zone::malloc_container(size_t count) +{ + return (object*)zone::malloc(sizeof(object)*count); +} + + +} // namespace msgpack + +#endif /* msgpack/zone.hpp */ + diff --git a/cpp/zone.hpp.erb b/cpp/zone.hpp.erb deleted file mode 100644 index 8af8da2..0000000 --- a/cpp/zone.hpp.erb +++ /dev/null @@ -1,202 +0,0 @@ -// -// MessagePack for C++ memory pool -// -// Copyright (C) 2008 FURUHASHI Sadayuki -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef MSGPACK_ZONE_HPP__ -#define MSGPACK_ZONE_HPP__ -#include <iostream> - -#include "msgpack/object.hpp" -#include <string.h> -#include <stdlib.h> -#include <stdexcept> - -#ifndef MSGPACK_ZONE_CHUNK_SIZE -#define MSGPACK_ZONE_CHUNK_SIZE 1024 -#endif - -namespace msgpack { - - -static const size_t ZONE_CHUNK_SIZE = MSGPACK_ZONE_CHUNK_SIZE; - - -class zone { -public: - zone() : m_used(0) { } - ~zone() { clear(); } - -public: - template <typename T> - void push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user); - -public: - object_nil* nnil () { return new (alloc()) object_nil(); } - object_true* ntrue () { return new (alloc()) object_true(); } - object_false* nfalse () { return new (alloc()) object_false(); } - object_u8* nu8 (uint8_t v) { return new (alloc()) object_u8(v); } - object_u16* nu16 (uint16_t v) { return new (alloc()) object_u16(v); } - object_u32* nu32 (uint32_t v) { return new (alloc()) object_u32(v); } - object_u64* nu64 (uint64_t v) { return new (alloc()) object_u64(v); } - object_i8* ni8 (int8_t v) { return new (alloc()) object_i8(v); } - object_i16* ni16 (int16_t v) { return new (alloc()) object_i16(v); } - object_i32* ni32 (int32_t v) { return new (alloc()) object_i32(v); } - object_i64* ni64 (int64_t v) { return new (alloc()) object_i64(v); } - object_float* nfloat (float v) { return new (alloc()) object_float(v); } - object_double* ndouble(double v) { return new (alloc()) object_double(v); } - - - object_mutable_raw_ref* nraw_ref(char* ptr, uint32_t len) - { return new (alloc()) object_mutable_raw_ref(ptr, len); } - - object_raw_ref* nraw_ref(const char* ptr, uint32_t len) - { return new (alloc()) object_raw_ref(ptr, len); } - - object_mutable_raw_ref* nraw_copy(const char* ptr, uint32_t len) - { - char* copy = (char*)malloc(len); - if(!copy) { throw std::bad_alloc(); } - object_mutable_raw_ref* o; - try { - o = new (alloc()) object_mutable_raw_ref(copy, len); - push_finalizer<void>(&zone::finalize_free, NULL, copy); - } catch (...) { - free(copy); - throw; - } - memcpy(copy, ptr, len); - return o; - } - - - object_mutable_raw_ref* nraw_cstr_ref(char* str) - { return nraw_ref(str, strlen(str)); } - - object_raw_ref* nraw_cstr_ref(const char* str) - { return nraw_ref(str, strlen(str)); } - - object_mutable_raw_ref* nraw_cstr_copy(const char* str) - { return nraw_copy(str, strlen(str)); } - - - object_array* narray() - { return new (alloc()) object_array(); } - - object_array* narray(size_t reserve_size) - { return new (alloc()) object_array(reserve_size); } - - object_map* nmap() - { return new (alloc()) object_map(); } - -<% GENERATION_SIZE = 16 %> -<% 1.upto(GENERATION_SIZE) {|i| %> - object_array* narray(<% 1.upto(i-1) {|n| %>object o<%=n%>, <% } %>object o<%=i%>) - { object_array* a = new (alloc()) object_array(<%=i%>); - <% 1.upto(i) {|n| %>a->push_back(o<%=n%>); - <% } %>return a; } -<% } %> - -<% 1.upto(GENERATION_SIZE) {|i| %> - object_map* nmap(<% 1.upto(i-1) {|n| %>object k<%=n%>, object v<%=n%>, <% } %>object k<%=i%>, object v<%=i%>) - { object_map* m = new (alloc()) object_map(); - <% 1.upto(i) {|n| %>m->store(k<%=n%>, v<%=n%>); - <% } %>return m; } -<% } %> - -public: - void clear(); - bool empty() const; - -private: - void* alloc(); - -private: - size_t m_used; - - static const size_t MAX_OBJECT_SIZE = - sizeof(object_raw_ref) > sizeof(object_array) - ? ( sizeof(object_raw_ref) > sizeof(object_map) - ? sizeof(object_raw_ref) - : sizeof(object_map) - ) - : ( sizeof(object_array) > sizeof(object_map) - ? sizeof(object_array) - : sizeof(object_map) - ) - ; - - struct cell_t { - char data[MAX_OBJECT_SIZE]; - }; - - typedef std::vector<cell_t*> pool_t; - pool_t m_pool; - - - class finalizer { - public: - finalizer(void (*func)(void*, void*), void* obj, void* user) : - m_obj(obj), m_user(user), m_func(func) {} - void call() { (*m_func)(m_obj, m_user); } - private: - void* m_obj; - void* m_user; - void (*m_func)(void*, void*); - }; - - typedef std::vector<finalizer> user_finalizer_t; - user_finalizer_t m_user_finalizer; - -private: - void expand_chunk(); - -public: - static void finalize_free(void* obj, void* user) - { free(user); } - -private: - zone(const zone&); -}; - - -template <typename T> -inline void zone::push_finalizer(void (*func)(void* obj, void* user), T* obj, void* user) -{ - m_user_finalizer.push_back( finalizer( - func, reinterpret_cast<void*>(obj), - user) ); -} - -inline bool zone::empty() const -{ - return m_used == 0 && m_user_finalizer.empty(); -} - -inline void* zone::alloc() -{ - if(m_pool.size() <= m_used/ZONE_CHUNK_SIZE) { - expand_chunk(); - } - void* data = m_pool[m_used/ZONE_CHUNK_SIZE][m_used%ZONE_CHUNK_SIZE].data; - ++m_used; - return data; -} - - -} // namespace msgpack - -#endif /* msgpack/zone.hpp */ - |