diff --git a/c/bench.c b/c/bench.c index f27350a0..0f316dca 100644 --- a/c/bench.c +++ b/c/bench.c @@ -98,9 +98,9 @@ static void pack_append_buffer(void* user, const unsigned char* b, unsigned int static const unsigned int TASK_INT_NUM = 1<<24; -static const unsigned int TASK_STR_LEN = 1<<15; +//static const unsigned int TASK_STR_LEN = 1<<15; //static const unsigned int TASK_INT_NUM = 1<<20; -//static const unsigned int TASK_STR_LEN = 1<<12; +static const unsigned int TASK_STR_LEN = 1<<12; static const char* TASK_STR_PTR; @@ -284,6 +284,7 @@ void bench_msgpack(void) msgpack_unpack_reset(mupk); + /* puts("----"); puts("pack string"); reset_timer(); @@ -316,6 +317,7 @@ void bench_msgpack(void) sec = show_timer(); printf("%f MB/s\n", len / sec / 1024 / 1024); + */ msgpack_unpack_free(mupk); @@ -330,7 +332,7 @@ int main(int argc, char* argv[]) TASK_STR_PTR = str; bench_msgpack(); - bench_json(); +// bench_json(); return 0; } diff --git a/cpp/Makefile b/cpp/Makefile index eafa6832..04b421c9 100644 --- a/cpp/Makefile +++ b/cpp/Makefile @@ -9,12 +9,12 @@ all: test %.hpp: %.hpp.erb erb $< > $@ -test: $(NEED_PREPROCESS) unpack.o unpack_inline.o zone.o test.o object.hpp unpack.hpp - $(CXX) $(LDFLAGS) unpack.o unpack_inline.o zone.o test.o -o $@ +test: $(NEED_PREPROCESS) unpack.o unpack_inline.o object.o zone.o test.o object.hpp unpack.hpp + $(CXX) $(LDFLAGS) unpack.o unpack_inline.o zone.o object.o test.o -o $@ .PHONY: clean clean: - $(RM) unpack.o unpack_inline.o zone.o + $(RM) unpack.o unpack_inline.o object.o zone.o $(RM) test.o $(RM) test $(RM) $(NEED_PREPROCESS) diff --git a/cpp/object.cpp b/cpp/object.cpp new file mode 100644 index 00000000..099b5414 --- /dev/null +++ b/cpp/object.cpp @@ -0,0 +1,340 @@ +#include "msgpack/object.hpp" + +namespace msgpack { + +namespace { + +template +struct numeric_overflow_signed_impl; + +template +struct numeric_overflow_signed_impl { + static int test(X x) { + if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || + (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { + if( sizeof(T) < sizeof(X) ) { + if( static_cast( std::numeric_limits::max()) < x ) { return 1; } + if( static_cast(-std::numeric_limits::max()) > x ) { return -1; } + } + } else if(std::numeric_limits::is_integer) { + if( static_cast( std::numeric_limits::max()) < x) { return 1; } + if( static_cast(-std::numeric_limits::max()) > x) { return -1; } + } + return 0; + } +}; + +template +struct numeric_overflow_signed_impl { + static int test(X x) { + if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || + (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { + if( sizeof(T) <= sizeof(X) ) { + if( static_cast(std::numeric_limits::max()) < x ) { return 1; } + } + } else if(std::numeric_limits::is_integer) { + if( static_cast( std::numeric_limits::max()) < x) { return 1; } + } + return 0; + } +}; + +template +struct numeric_overflow_signed_impl { + static int test(X x) { + if( static_cast(0) > x ) { return -1; } + if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || + (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { + if( sizeof(T) < sizeof(X) ) { + if( static_cast(std::numeric_limits::max()) < x ) { return 1; } + } + } else if(std::numeric_limits::is_integer) { + if( static_cast( std::numeric_limits::max()) < x) { return 1; } + } + return 0; + } +}; + +template +struct numeric_overflow_signed_impl { + static int test(X x) { + if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || + (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { + if( sizeof(T) < sizeof(X) ) { + if( static_cast(std::numeric_limits::max()) < x ) { return 1; } + } + } else if(std::numeric_limits::is_integer) { + if( static_cast(std::numeric_limits::max()) < x ) { return 1; } + } + return 0; + } +}; + +template +struct numeric_overflow { + static int test(X x) { + return numeric_overflow_signed_impl::is_signed, std::numeric_limits::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 +struct numeric_underflow { + static bool test(X x) { + return static_cast(static_cast(x)) != x; + } + static void check(X x) { + if(test(x)) { throw underflow_error(); } + } +}; + +template +inline T integer_cast(X x) { + numeric_overflow::check(x); + return static_cast(x); } + +template +inline T float_cast(X x) { + numeric_overflow::check(x); + numeric_underflow::check(x); + return static_cast(x); } + +template +inline bool numequal(V v, const object_class* x) + try { return v == static_cast(*x); } + catch (type_error&) { return false; } + +template +inline bool numless(V v, const object_class* x) + try { return v < static_cast(*x); } + catch (positive_overflow_error&) { return true; } + catch (overflow_error&) { return false; } + +template +inline bool numgreater(V v, const object_class* x) + try { return v > static_cast(*x); } + catch (negative_overflow_error&) { return true; } + catch (overflow_error&) { return false; } + +template +inline void numeric_inspect(V v, std::ostream& s) + { s << v; } + +template <> +inline void numeric_inspect(uint8_t v, std::ostream& s) + { s << (uint16_t)v; } + +template <> +inline void numeric_inspect(int8_t v, std::ostream& s) + { s << (int16_t)v; } + +} // noname namespace + + +bool object_nil::isnil() const { return true; } +bool object_nil::operator== (const object_class* x) const + { return typeid(*this) == typeid(*x); } +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); } +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); } +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(val); } \ +uint32_t object_##NAME::xu32 () const { return integer_cast(val); } \ +uint64_t object_##NAME::xu64 () const { return integer_cast(val); } \ +int8_t object_##NAME::xi8 () const { return integer_cast(val); } \ +int16_t object_##NAME::xi16 () const { return integer_cast(val); } \ +int32_t object_##NAME::xi32 () const { return integer_cast(val); } \ +int64_t object_##NAME::xi64 () const { return integer_cast(val); } \ +float object_##NAME::xfloat () const { return integer_cast(val); } \ +double object_##NAME::xdouble() const { return integer_cast(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; } \ +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(NAME) + + +#define FLOAT_OBJECT(NAME) \ +uint8_t object_##NAME::xu8 () const { return val; } \ +uint16_t object_##NAME::xu16 () const { return integer_cast(val); } \ +uint32_t object_##NAME::xu32 () const { return integer_cast(val); } \ +uint64_t object_##NAME::xu64 () const { return integer_cast(val); } \ +int8_t object_##NAME::xi8 () const { return integer_cast(val); } \ +int16_t object_##NAME::xi16 () const { return integer_cast(val); } \ +int32_t object_##NAME::xi32 () const { return integer_cast(val); } \ +int64_t object_##NAME::xi64 () const { return integer_cast(val); } \ +float object_##NAME::xfloat () const { return float_cast(val); } \ +double object_##NAME::xdouble() const { return float_cast(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::test(val) == -1) { return true; } \ + try { return static_cast(val) < x->xi64(); } \ + catch (type_error&) { return true; } \ + } else { \ + if(numeric_overflow::test(val) == 1) { return false; } \ + try { return static_cast(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::test(val) == -1) { return false; } \ + try { return static_cast(val) > x->xi64(); } \ + catch (type_error&) { return false; } \ + } else { \ + if(numeric_overflow::test(val) == 1) { return true; } \ + try { return static_cast(val) > x->xu64(); } \ + catch (type_error&) { return true; } \ + } \ + } } \ +const object_class* object_##NAME::inspect(std::ostream& s) const \ + { s << val; return this; } \ + +FLOAT_OBJECT(float) +FLOAT_OBJECT(double) + +#undef FLOAT_OBJECT(NAME) + + +#define RAW_OBJECT(NAME, EXTRA) \ +EXTRA \ +bool object_##NAME::operator== (const object_class* x) const \ + try { \ + const_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 { \ + 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 { \ + const_raw xr(x->xraw()); \ + if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) > 0; } \ + else { return len > xr.len; } } \ +const object_class* object_##NAME::inspect(std::ostream& s) const \ + { (s << '"').write((const char*)ptr, len) << '"'; return this; } // FIXME escape + + +RAW_OBJECT(raw, + raw object_raw::xraw() { return raw(ptr, len); } + const_raw object_raw::xraw() const { return const_raw(ptr, len); } ) + +RAW_OBJECT(const_raw, + const_raw object_const_raw::xraw() const { return const_raw(ptr, len); } ) + +#undef RAW_OBJECT(NAME, EXTRA) + + + 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& xa(x->xarray()); + if(val.size() != xa.size()) { return false; } + for(std::vector::const_iterator iv(val.begin()), iv_end(val.end()), ix(xa.begin()); + iv != iv_end; + ++iv, ++ix) { + if(*iv != *ix) { 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::const_iterator it(val.begin()); + s << *it; + ++it; + for(std::vector::const_iterator it_end(val.end()); + it != it_end; + ++it) { + s << ", " << *it; + } + } + s << ']'; + return this; +} + + + 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& xm(x->xmap()); + if(val.size() != xm.size()) { return false; } + for(std::map::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::const_iterator it(val.begin()); + s << it->first << "=>" << it->second; + ++it; + for(std::map::const_iterator it_end(val.end()); + it != it_end; + ++it) { + s << ", " << it->first << "=>" << it->second; + } + } + s << '}'; + return this; +} + + +} // namespace msgpack + diff --git a/cpp/object.hpp b/cpp/object.hpp index c4e94d74..992ac1ed 100644 --- a/cpp/object.hpp +++ b/cpp/object.hpp @@ -48,96 +48,6 @@ typedef std::map map; typedef std::vector array; -template -struct numeric_overflow_signed_impl; - -template -struct numeric_overflow_signed_impl { - static int test(X x) { - if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || - (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { - if( sizeof(T) < sizeof(X) ) { - if( static_cast( std::numeric_limits::max()) < x ) { return 1; } - if( static_cast(-std::numeric_limits::max()) > x ) { return -1; } - } - } else if(std::numeric_limits::is_integer) { - if( static_cast( std::numeric_limits::max()) < x) { return 1; } - if( static_cast(-std::numeric_limits::max()) > x) { return -1; } - } - return 0; - } -}; - -template -struct numeric_overflow_signed_impl { - static int test(X x) { - if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || - (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { - if( sizeof(T) <= sizeof(X) ) { - if( static_cast(std::numeric_limits::max()) < x ) { return 1; } - } - } else if(std::numeric_limits::is_integer) { - if( static_cast( std::numeric_limits::max()) < x) { return 1; } - } - return 0; - } -}; - -template -struct numeric_overflow_signed_impl { - static int test(X x) { - if( static_cast(0) > x ) { return -1; } - if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || - (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { - if( sizeof(T) < sizeof(X) ) { - if( static_cast(std::numeric_limits::max()) < x ) { return 1; } - } - } else if(std::numeric_limits::is_integer) { - if( static_cast( std::numeric_limits::max()) < x) { return 1; } - } - return 0; - } -}; - -template -struct numeric_overflow_signed_impl { - static int test(X x) { - if( ( std::numeric_limits::is_integer && std::numeric_limits::is_integer) || - (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer) ) { - if( sizeof(T) < sizeof(X) ) { - if( static_cast(std::numeric_limits::max()) < x ) { return 1; } - } - } else if(std::numeric_limits::is_integer) { - if( static_cast(std::numeric_limits::max()) < x ) { return 1; } - } - return 0; - } -}; - -template -struct numeric_overflow { - static int test(X x) { - return numeric_overflow_signed_impl::is_signed, std::numeric_limits::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 -struct numeric_underflow { - static bool test(X x) { - return static_cast(static_cast(x)) != x; - } - static void check(X x) { - if(test(x)) { throw underflow_error(); } - } -}; - - struct object_class { virtual ~object_class() {} virtual bool isnil() const { return false; } @@ -181,11 +91,6 @@ struct object_class { operator const map&() const { return xmap(); } virtual const object_class* inspect(std::ostream& s) const { s << '<' << typeid(*this).name() << '>'; return this; } -protected: - template - static void check_overflow(X x) { numeric_overflow::check(x); } - template - static void check_underflow(X x) { numeric_underflow::check(x); } }; inline std::ostream& operator<< (std::ostream& s, const object_class* o) @@ -253,500 +158,125 @@ inline std::ostream& operator<< (std::ostream& s, const object& o) struct object_nil : object_class { - bool isnil() const { return true; } - bool operator== (const object_class* x) const { return typeid(*this) == typeid(*x); } - const object_class* inspect(std::ostream& s) const - { s << "nil"; return this; } + bool isnil() const; + bool operator== (const object_class* x) const; + const object_class* inspect(std::ostream& s) const; }; struct object_true : object_class { - bool xbool() const { return true; } - bool operator== (const object_class* x) const { return typeid(*this) == typeid(*x); } - const object_class* inspect(std::ostream& s) const - { s << "true"; return this; } + bool xbool() const; + bool operator== (const object_class* x) const; + const object_class* inspect(std::ostream& s) const; }; struct object_false : object_class { - bool xbool() const { return false; } - bool operator== (const object_class* x) const { return typeid(*this) == typeid(*x); } - const object_class* inspect(std::ostream& s) const - { s << "false"; return this; } + bool xbool() const; + bool operator== (const object_class* x) const; + const object_class* inspect(std::ostream& s) const; }; -struct object_u8 : object_class { - explicit object_u8(uint8_t v) : val(v) {} - uint8_t xu8() const { return val; } - uint16_t xu16() const { return static_cast(val); } - uint32_t xu32() const { return static_cast(val); } - uint64_t xu64() const { return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { return static_cast(val); } - int32_t xi32() const { return static_cast(val); } - int64_t xi64() const { return static_cast(val); } - float xfloat() const { return static_cast(val); } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xu8(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xu8(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xu8(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << (uint16_t)val; return this; } -private: - uint8_t val; +#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; \ + const object_class* inspect(std::ostream& s) const; \ +private: \ + TYPE val; \ }; -struct object_u16 : object_class { - explicit object_u16(uint16_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { return val; } - uint32_t xu32() const { return static_cast(val); } - uint64_t xu64() const { return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { return static_cast(val); } - int64_t xi64() const { return static_cast(val); } - float xfloat() const { return static_cast(val); } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xu16(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xu16(); } - catch (positive_overflow_error&) { return true; } - catch (type_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xu16(); } - catch (negative_overflow_error&) { return true; } - catch (type_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - uint16_t val; +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(TYPE, NAME) + + +#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; \ + const object_class* inspect(std::ostream& s) const; \ +private: \ + TYPE val; \ }; -struct object_u32 : object_class { - explicit object_u32(uint32_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { return val; } - uint64_t xu64() const { return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { check_overflow(val); - return static_cast(val); } - int64_t xi64() const { return static_cast(val); } - float xfloat() const { check_underflow(val); - return static_cast(val); } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xu32(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xu32(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xu32(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - uint32_t val; +FLOAT_CLASS(float, float) +FLOAT_CLASS(double, double) + +#undef FLOAT_CLASS(TYPE, NAME) + + +#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; \ + const object_class* inspect(std::ostream& s) const; \ +private: \ + TYPE ptr; \ + uint32_t len; \ }; -struct object_u64 : object_class { - explicit object_u64(uint64_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { return val; } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { check_overflow(val); - return static_cast(val); } - int64_t xi64() const { check_overflow(val); - return static_cast(val); } - float xfloat() const { check_underflow(val); - return static_cast(val); } - double xdouble() const { check_underflow(val); - return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xu64(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xu64(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xu64(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - uint64_t val; -}; +RAW_CLASS(raw, void*, raw xraw(); const_raw xraw() const; ) +RAW_CLASS(const_raw, const void*, const_raw xraw() const; ) -struct object_i8 : object_class { - explicit object_i8(int8_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { check_overflow(val); - return static_cast(val); } - int8_t xi8() const { return val; } - int16_t xi16() const { return static_cast(val); } - int32_t xi32() const { return static_cast(val); } - int64_t xi64() const { return static_cast(val); } - float xfloat() const { return static_cast(val); } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xi8(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xi8(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xi8(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << (int16_t)val; return this; } -private: - int8_t val; -}; +#undef RAW_CLASS(NAME, TYPE, EXTRA) -struct object_i16 : object_class { - explicit object_i16(int16_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { check_overflow(val); - return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { return val; } - int32_t xi32() const { return static_cast(val); } - int64_t xi64() const { return static_cast(val); } - float xfloat() const { return static_cast(val); } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xi16(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xi16(); } - catch (positive_overflow_error&) { return true; } - catch (type_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xi16(); } - catch (negative_overflow_error&) { return true; } - catch (type_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - int16_t val; -}; - -struct object_i32 : object_class { - explicit object_i32(int32_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { check_overflow(val); - return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { return val; } - int64_t xi64() const { return static_cast(val); } - float xfloat() const { check_underflow(val); - return static_cast(val); } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xi32(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xi32(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xi32(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - int32_t val; -}; - -struct object_i64 : object_class { - explicit object_i64(int64_t v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { check_overflow(val); - return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { check_overflow(val); - return static_cast(val); } - int64_t xi64() const { return val; } - float xfloat() const { check_underflow(val); - return static_cast(val); } - double xdouble() const { check_underflow(val); - return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xi64(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return val < x->xi64(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - bool operator> (const object_class* x) const { try { return val > x->xi64(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - int64_t val; -}; - - -struct object_float : object_class { - object_float(float v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { check_overflow(val); - return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { check_overflow(val); - return static_cast(val); } - int64_t xi64() const { check_overflow(val); - return static_cast(val); } - float xfloat() const { return val; } - double xdouble() const { return static_cast(val); } - bool operator== (const object_class* x) const { try { return val == x->xfloat(); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { try { return static_cast(val) < x->xdouble(); } - catch (positive_overflow_error&) { return true; } - catch (overflow_error&) { return false; } - catch (underflow_error&) { - if(val < 0.0) { - if(numeric_overflow::test(val) == -1) { return true; } - try { return static_cast(val) < x->xi64(); } - catch (type_error&) { return true; } - } else { - if(numeric_overflow::test(val) == 1) { return false; } - try { return static_cast(val) < x->xu64(); } - catch (type_error&) { return false; } - } - } } - bool operator> (const object_class* x) const { try { return static_cast(val) > x->xdouble(); } - catch (negative_overflow_error&) { return true; } - catch (overflow_error&) { return false; } - catch (underflow_error&) { - if(val < 0.0) { - if(numeric_overflow::test(val) == -1) { return false; } - try { return static_cast(val) > x->xi64(); } - catch (type_error&) { return false; } - } else { - if(numeric_overflow::test(val) == 1) { return true; } - try { return static_cast(val) > x->xu64(); } - catch (type_error&) { return true; } - } - } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - float val; -}; - - -struct object_double : object_class { - object_double(double v) : val(v) {} - uint8_t xu8() const { check_overflow(val); - return static_cast(val); } - uint16_t xu16() const { check_overflow(val); - return static_cast(val); } - uint32_t xu32() const { check_overflow(val); - return static_cast(val); } - uint64_t xu64() const { check_overflow(val); - return static_cast(val); } - int8_t xi8() const { check_overflow(val); - return static_cast(val); } - int16_t xi16() const { check_overflow(val); - return static_cast(val); } - int32_t xi32() const { check_overflow(val); - return static_cast(val); } - int64_t xi64() const { check_overflow(val); - return static_cast(val); } - float xfloat() const { check_overflow(val); - check_underflow(val); - return static_cast(val); } - double xdouble() const { return val; } - bool operator== (const object_class* x) const { try { return val == x->xdouble(); } - catch (type_error&) { return false; } } - bool 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::test(val) == -1) { return true; } - try { return static_cast(val) < x->xi64(); } - catch (type_error&) { return true; } - } else { - if(numeric_overflow::test(val) == 1) { return false; } - try { return static_cast(val) < x->xu64(); } - catch (type_error&) { return false; } - } - } } - bool 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::test(val) == -1) { return false; } - try { return static_cast(val) > x->xi64(); } - catch (type_error&) { return false; } - } else { - if(numeric_overflow::test(val) == 1) { return true; } - try { return static_cast(val) > x->xu64(); } - catch (type_error&) { return true; } - } - } } - const object_class* inspect(std::ostream& s) const - { s << val; return this; } -private: - double val; -}; - - -struct object_raw : object_class { - explicit object_raw(void* p, uint32_t l) : ptr(p), len(l) {} - raw xraw() { return raw(ptr, len); } - const_raw xraw() const { return const_raw(ptr, len); } - bool operator== (const object_class* x) const { try { const_raw xr(x->xraw()); - return len == xr.len && (ptr == xr.ptr || memcmp(ptr, xr.ptr, len) == 0); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { 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 operator> (const object_class* x) const { const_raw xr(x->xraw()); - if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) > 0; } - else { return len > xr.len; } } - const object_class* inspect(std::ostream& s) const - { (s << '"').write((const char*)ptr, len) << '"'; return this; } // FIXME escape -private: - void* ptr; - uint32_t len; -}; - -struct object_const_raw : object_class { - explicit object_const_raw(const void* p, uint32_t l) : ptr(p), len(l) {} - const_raw xraw() const { return const_raw(ptr, len); } - bool operator== (const object_class* x) const { try { const_raw xr(x->xraw()); - return len == xr.len && (ptr == xr.ptr || memcmp(ptr, xr.ptr, len) == 0); } - catch (type_error&) { return false; } } - bool operator< (const object_class* x) const { 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 operator> (const object_class* x) const { const_raw xr(x->xraw()); - if(len == xr.len) { return ptr != xr.ptr && memcmp(ptr, xr.ptr, len) > 0; } - else { return len > xr.len; } } - const object_class* inspect(std::ostream& s) const - { (s << '"').write((const char*)ptr, len) << '"'; return this; } // FIXME escape -private: - const void* ptr; - uint32_t len; -}; struct object_array : object_class, object_container_mixin { explicit object_array() {} explicit object_array(uint32_t n) { val.reserve(n); } - array& xarray() { return val; } - const array& xarray() const { return val; } - bool operator== (const object_class* x) const { try { - const std::vector& xa(x->xarray()); - if(val.size() != xa.size()) { return false; } - for(std::vector::const_iterator iv(val.begin()), iv_end(val.end()), ix(xa.begin()); - iv != iv_end; - ++iv, ++ix) { - if(*iv != *ix) { return false; } - } - return true; - } catch (type_error&) { return false; } } - // FIXME operator< operator> - const object_class* inspect(std::ostream& s) const { - s << '['; - if(!val.empty()) { - std::vector::const_iterator it(val.begin()); - s << *it; - ++it; - for(std::vector::const_iterator it_end(val.end()); - it != it_end; - ++it) { - s << ", " << *it; - } - } - s << ']'; - return this; } + array& xarray(); + const array& xarray() const; + bool operator== (const object_class* x) const; + // FIXME operator<, operator> + const object_class* inspect(std::ostream& s) const; public: void push_back(object o) { val.push_back(o); } private: std::vector val; }; -// FIXME hash, operator==: nil, true, false, containerを入れられない + +// FIXME hash, operator==: nil, true, false, array, mapを入れられない struct object_map : object_class, object_container_mixin { explicit object_map() {} - map& xmap() { return val; } - const map& xmap() const { return val; } - bool operator== (const object_class* x) const { try { - const std::map& xm(x->xmap()); - if(val.size() != xm.size()) { return false; } - for(std::map::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; } } - // FIXME operator< operator> - const object_class* inspect(std::ostream& s) const { - s << '{'; - if(!val.empty()) { - std::map::const_iterator it(val.begin()); - s << it->first << "=>" << it->second; - ++it; - for(std::map::const_iterator it_end(val.end()); - it != it_end; - ++it) { - s << ", " << it->first << "=>" << it->second; - } - } - s << '}'; - return this; } + map& xmap(); + const map& xmap() const; + bool operator== (const object_class* x) const; + // FIXME operator<, operator> + const object_class* inspect(std::ostream& s) const; public: void store(object k, object v) { val[k] = v; } private: