diff options
author | frsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731> | 2009-02-15 09:09:56 +0000 |
---|---|---|
committer | frsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731> | 2009-02-15 09:09:56 +0000 |
commit | 7c427400a7071f0cb251edd102430945e142033f (patch) | |
tree | d079eada26acb6f2be6977f97d3a032ccf5556aa /cpp/object.cpp | |
parent | 529a50633dffc91dd5ce58ae5a905a0ac4a5fdf9 (diff) | |
download | msgpack-python-7c427400a7071f0cb251edd102430945e142033f.tar.gz |
lang/c/msgpack: update C++ code
git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@51 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
Diffstat (limited to 'cpp/object.cpp')
-rw-r--r-- | cpp/object.cpp | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/cpp/object.cpp b/cpp/object.cpp new file mode 100644 index 0000000..099b541 --- /dev/null +++ b/cpp/object.cpp @@ -0,0 +1,340 @@ +#include "msgpack/object.hpp" + +namespace msgpack { + +namespace { + +template <typename T, typename X, bool TSigned, bool XSigned> +struct numeric_overflow_signed_impl; + +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; + } +}; + +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; } + } + } 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; } + } + } 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 { + 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(); } + } +}; + +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; } + +} // 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<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; } \ +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<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; } \ + } \ + } } \ +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<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; } + } + 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; + } + } + 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<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; +} + + +} // namespace msgpack + |