mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-14 23:07:58 +02:00
lang/c/msgpack: update C++ code
git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@51 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
This commit is contained in:
@@ -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_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_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;
|
static const char* TASK_STR_PTR;
|
||||||
|
|
||||||
|
|
||||||
@@ -284,6 +284,7 @@ void bench_msgpack(void)
|
|||||||
msgpack_unpack_reset(mupk);
|
msgpack_unpack_reset(mupk);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
puts("----");
|
puts("----");
|
||||||
puts("pack string");
|
puts("pack string");
|
||||||
reset_timer();
|
reset_timer();
|
||||||
@@ -316,6 +317,7 @@ void bench_msgpack(void)
|
|||||||
sec = show_timer();
|
sec = show_timer();
|
||||||
|
|
||||||
printf("%f MB/s\n", len / sec / 1024 / 1024);
|
printf("%f MB/s\n", len / sec / 1024 / 1024);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
msgpack_unpack_free(mupk);
|
msgpack_unpack_free(mupk);
|
||||||
@@ -330,7 +332,7 @@ int main(int argc, char* argv[])
|
|||||||
TASK_STR_PTR = str;
|
TASK_STR_PTR = str;
|
||||||
|
|
||||||
bench_msgpack();
|
bench_msgpack();
|
||||||
bench_json();
|
// bench_json();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -9,12 +9,12 @@ all: test
|
|||||||
%.hpp: %.hpp.erb
|
%.hpp: %.hpp.erb
|
||||||
erb $< > $@
|
erb $< > $@
|
||||||
|
|
||||||
test: $(NEED_PREPROCESS) unpack.o unpack_inline.o zone.o test.o object.hpp unpack.hpp
|
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 test.o -o $@
|
$(CXX) $(LDFLAGS) unpack.o unpack_inline.o zone.o object.o test.o -o $@
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
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.o
|
||||||
$(RM) test
|
$(RM) test
|
||||||
$(RM) $(NEED_PREPROCESS)
|
$(RM) $(NEED_PREPROCESS)
|
||||||
|
340
cpp/object.cpp
Normal file
340
cpp/object.cpp
Normal file
@@ -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
|
||||||
|
|
652
cpp/object.hpp
652
cpp/object.hpp
@@ -48,96 +48,6 @@ typedef std::map<object, object> map;
|
|||||||
typedef std::vector<object> array;
|
typedef std::vector<object> array;
|
||||||
|
|
||||||
|
|
||||||
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(); }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct object_class {
|
struct object_class {
|
||||||
virtual ~object_class() {}
|
virtual ~object_class() {}
|
||||||
virtual bool isnil() const { return false; }
|
virtual bool isnil() const { return false; }
|
||||||
@@ -181,11 +91,6 @@ struct object_class {
|
|||||||
operator const map&() const { return xmap(); }
|
operator const map&() const { return xmap(); }
|
||||||
virtual const object_class* inspect(std::ostream& s) const
|
virtual const object_class* inspect(std::ostream& s) const
|
||||||
{ s << '<' << typeid(*this).name() << '>'; return this; }
|
{ s << '<' << typeid(*this).name() << '>'; return this; }
|
||||||
protected:
|
|
||||||
template <typename T, typename X>
|
|
||||||
static void check_overflow(X x) { numeric_overflow<T, X>::check(x); }
|
|
||||||
template <typename T, typename X>
|
|
||||||
static void check_underflow(X x) { numeric_underflow<T, X>::check(x); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<< (std::ostream& s, const object_class* o)
|
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 {
|
struct object_nil : object_class {
|
||||||
bool isnil() const { return true; }
|
bool isnil() const;
|
||||||
bool operator== (const object_class* x) const { return typeid(*this) == typeid(*x); }
|
bool operator== (const object_class* x) const;
|
||||||
const object_class* inspect(std::ostream& s) const
|
const object_class* inspect(std::ostream& s) const;
|
||||||
{ s << "nil"; return this; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object_true : object_class {
|
struct object_true : object_class {
|
||||||
bool xbool() const { return true; }
|
bool xbool() const;
|
||||||
bool operator== (const object_class* x) const { return typeid(*this) == typeid(*x); }
|
bool operator== (const object_class* x) const;
|
||||||
const object_class* inspect(std::ostream& s) const
|
const object_class* inspect(std::ostream& s) const;
|
||||||
{ s << "true"; return this; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object_false : object_class {
|
struct object_false : object_class {
|
||||||
bool xbool() const { return false; }
|
bool xbool() const;
|
||||||
bool operator== (const object_class* x) const { return typeid(*this) == typeid(*x); }
|
bool operator== (const object_class* x) const;
|
||||||
const object_class* inspect(std::ostream& s) const
|
const object_class* inspect(std::ostream& s) const;
|
||||||
{ s << "false"; return this; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object_u8 : object_class {
|
#define INTEGER_CLASS(TYPE, NAME) \
|
||||||
explicit object_u8(uint8_t v) : val(v) {}
|
struct object_##NAME : object_class { \
|
||||||
uint8_t xu8() const { return val; }
|
explicit object_##NAME(TYPE v) : val(v) {} \
|
||||||
uint16_t xu16() const { return static_cast<uint16_t>(val); }
|
uint8_t xu8 () const; \
|
||||||
uint32_t xu32() const { return static_cast<uint32_t>(val); }
|
uint16_t xu16 () const; \
|
||||||
uint64_t xu64() const { return static_cast<uint64_t>(val); }
|
uint32_t xu32 () const; \
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
uint64_t xu64 () const; \
|
||||||
return static_cast<int8_t>(val); }
|
int8_t xi8 () const; \
|
||||||
int16_t xi16() const { return static_cast<int16_t>(val); }
|
int16_t xi16 () const; \
|
||||||
int32_t xi32() const { return static_cast<int32_t>(val); }
|
int32_t xi32 () const; \
|
||||||
int64_t xi64() const { return static_cast<int64_t>(val); }
|
int64_t xi64 () const; \
|
||||||
float xfloat() const { return static_cast<float>(val); }
|
float xfloat () const; \
|
||||||
double xdouble() const { return static_cast<double>(val); }
|
double xdouble() const; \
|
||||||
bool operator== (const object_class* x) const { try { return val == x->xu8(); }
|
bool operator== (const object_class* x) const; \
|
||||||
catch (type_error&) { return false; } }
|
bool operator< (const object_class* x) const; \
|
||||||
bool operator< (const object_class* x) const { try { return val < x->xu8(); }
|
bool operator> (const object_class* x) const; \
|
||||||
catch (positive_overflow_error&) { return true; }
|
const object_class* inspect(std::ostream& s) const; \
|
||||||
catch (overflow_error&) { return false; } }
|
private: \
|
||||||
bool operator> (const object_class* x) const { try { return val > x->xu8(); }
|
TYPE val; \
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object_u16 : object_class {
|
INTEGER_CLASS(uint8_t, u8)
|
||||||
explicit object_u16(uint16_t v) : val(v) {}
|
INTEGER_CLASS(uint16_t, u16)
|
||||||
uint8_t xu8() const { check_overflow<uint8_t>(val);
|
INTEGER_CLASS(uint32_t, u32)
|
||||||
return static_cast<uint8_t>(val); }
|
INTEGER_CLASS(uint64_t, u64)
|
||||||
uint16_t xu16() const { return val; }
|
INTEGER_CLASS(int8_t, i8)
|
||||||
uint32_t xu32() const { return static_cast<uint32_t>(val); }
|
INTEGER_CLASS(int16_t, i16)
|
||||||
uint64_t xu64() const { return static_cast<uint64_t>(val); }
|
INTEGER_CLASS(int32_t, i32)
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
INTEGER_CLASS(int64_t, i64)
|
||||||
return static_cast<int8_t>(val); }
|
|
||||||
int16_t xi16() const { check_overflow<int16_t>(val);
|
#undef INTEGER_CLASS(TYPE, NAME)
|
||||||
return static_cast<int16_t>(val); }
|
|
||||||
int32_t xi32() const { return static_cast<int32_t>(val); }
|
|
||||||
int64_t xi64() const { return static_cast<int64_t>(val); }
|
#define FLOAT_CLASS(TYPE, NAME) \
|
||||||
float xfloat() const { return static_cast<float>(val); }
|
struct object_##NAME : object_class { \
|
||||||
double xdouble() const { return static_cast<double>(val); }
|
object_##NAME(TYPE v) : val(v) {} \
|
||||||
bool operator== (const object_class* x) const { try { return val == x->xu16(); }
|
uint8_t xu8 () const; \
|
||||||
catch (type_error&) { return false; } }
|
uint16_t xu16 () const; \
|
||||||
bool operator< (const object_class* x) const { try { return val < x->xu16(); }
|
uint32_t xu32 () const; \
|
||||||
catch (positive_overflow_error&) { return true; }
|
uint64_t xu64 () const; \
|
||||||
catch (type_error&) { return false; } }
|
int8_t xi8 () const; \
|
||||||
bool operator> (const object_class* x) const { try { return val > x->xu16(); }
|
int16_t xi16 () const; \
|
||||||
catch (negative_overflow_error&) { return true; }
|
int32_t xi32 () const; \
|
||||||
catch (type_error&) { return false; } }
|
int64_t xi64 () const; \
|
||||||
const object_class* inspect(std::ostream& s) const
|
float xfloat () const; \
|
||||||
{ s << val; return this; }
|
double xdouble() const; \
|
||||||
private:
|
bool operator== (const object_class* x) const; \
|
||||||
uint16_t val;
|
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 {
|
FLOAT_CLASS(float, float)
|
||||||
explicit object_u32(uint32_t v) : val(v) {}
|
FLOAT_CLASS(double, double)
|
||||||
uint8_t xu8() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
#undef FLOAT_CLASS(TYPE, NAME)
|
||||||
uint16_t xu16() const { check_overflow<uint16_t>(val);
|
|
||||||
return static_cast<uint16_t>(val); }
|
|
||||||
uint32_t xu32() const { return val; }
|
#define RAW_CLASS(NAME, TYPE, EXTRA) \
|
||||||
uint64_t xu64() const { return static_cast<uint64_t>(val); }
|
struct object_##NAME : object_class { \
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
explicit object_##NAME(TYPE p, uint32_t l) : ptr(p), len(l) {} \
|
||||||
return static_cast<int8_t>(val); }
|
EXTRA \
|
||||||
int16_t xi16() const { check_overflow<int16_t>(val);
|
bool operator== (const object_class* x) const; \
|
||||||
return static_cast<int16_t>(val); }
|
bool operator< (const object_class* x) const; \
|
||||||
int32_t xi32() const { check_overflow<int32_t>(val);
|
bool operator> (const object_class* x) const; \
|
||||||
return static_cast<int32_t>(val); }
|
const object_class* inspect(std::ostream& s) const; \
|
||||||
int64_t xi64() const { return static_cast<int64_t>(val); }
|
private: \
|
||||||
float xfloat() const { check_underflow<float>(val);
|
TYPE ptr; \
|
||||||
return static_cast<float>(val); }
|
uint32_t len; \
|
||||||
double xdouble() const { return static_cast<double>(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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object_u64 : object_class {
|
RAW_CLASS(raw, void*, raw xraw(); const_raw xraw() const; )
|
||||||
explicit object_u64(uint64_t v) : val(v) {}
|
RAW_CLASS(const_raw, const void*, const_raw xraw() const; )
|
||||||
uint8_t xu8() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint16_t>(val);
|
|
||||||
return static_cast<uint16_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint32_t>(val);
|
|
||||||
return static_cast<uint32_t>(val); }
|
|
||||||
uint64_t xu64() const { return val; }
|
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
|
||||||
return static_cast<int8_t>(val); }
|
|
||||||
int16_t xi16() const { check_overflow<int16_t>(val);
|
|
||||||
return static_cast<int16_t>(val); }
|
|
||||||
int32_t xi32() const { check_overflow<int32_t>(val);
|
|
||||||
return static_cast<int32_t>(val); }
|
|
||||||
int64_t xi64() const { check_overflow<int64_t>(val);
|
|
||||||
return static_cast<int64_t>(val); }
|
|
||||||
float xfloat() const { check_underflow<float>(val);
|
|
||||||
return static_cast<float>(val); }
|
|
||||||
double xdouble() const { check_underflow<double>(val);
|
|
||||||
return static_cast<double>(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;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct object_i8 : object_class {
|
#undef RAW_CLASS(NAME, TYPE, EXTRA)
|
||||||
explicit object_i8(int8_t v) : val(v) {}
|
|
||||||
uint8_t xu8() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint16_t>(val);
|
|
||||||
return static_cast<uint16_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint32_t>(val);
|
|
||||||
return static_cast<uint32_t>(val); }
|
|
||||||
uint64_t xu64() const { check_overflow<uint64_t>(val);
|
|
||||||
return static_cast<uint64_t>(val); }
|
|
||||||
int8_t xi8() const { return val; }
|
|
||||||
int16_t xi16() const { return static_cast<int16_t>(val); }
|
|
||||||
int32_t xi32() const { return static_cast<int32_t>(val); }
|
|
||||||
int64_t xi64() const { return static_cast<int64_t>(val); }
|
|
||||||
float xfloat() const { return static_cast<float>(val); }
|
|
||||||
double xdouble() const { return static_cast<double>(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;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct object_i16 : object_class {
|
|
||||||
explicit object_i16(int16_t v) : val(v) {}
|
|
||||||
uint8_t xu8() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint16_t>(val);
|
|
||||||
return static_cast<uint16_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint32_t>(val);
|
|
||||||
return static_cast<uint32_t>(val); }
|
|
||||||
uint64_t xu64() const { check_overflow<uint64_t>(val);
|
|
||||||
return static_cast<uint64_t>(val); }
|
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
|
||||||
return static_cast<int8_t>(val); }
|
|
||||||
int16_t xi16() const { return val; }
|
|
||||||
int32_t xi32() const { return static_cast<int32_t>(val); }
|
|
||||||
int64_t xi64() const { return static_cast<int64_t>(val); }
|
|
||||||
float xfloat() const { return static_cast<float>(val); }
|
|
||||||
double xdouble() const { return static_cast<double>(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<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint16_t>(val);
|
|
||||||
return static_cast<uint16_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint32_t>(val);
|
|
||||||
return static_cast<uint32_t>(val); }
|
|
||||||
uint64_t xu64() const { check_overflow<uint64_t>(val);
|
|
||||||
return static_cast<uint64_t>(val); }
|
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
|
||||||
return static_cast<int8_t>(val); }
|
|
||||||
int16_t xi16() const { check_overflow<int16_t>(val);
|
|
||||||
return static_cast<int16_t>(val); }
|
|
||||||
int32_t xi32() const { return val; }
|
|
||||||
int64_t xi64() const { return static_cast<int64_t>(val); }
|
|
||||||
float xfloat() const { check_underflow<float>(val);
|
|
||||||
return static_cast<float>(val); }
|
|
||||||
double xdouble() const { return static_cast<double>(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<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint16_t>(val);
|
|
||||||
return static_cast<uint16_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint32_t>(val);
|
|
||||||
return static_cast<uint32_t>(val); }
|
|
||||||
uint64_t xu64() const { check_overflow<uint64_t>(val);
|
|
||||||
return static_cast<uint64_t>(val); }
|
|
||||||
int8_t xi8() const { check_overflow<int8_t>(val);
|
|
||||||
return static_cast<int8_t>(val); }
|
|
||||||
int16_t xi16() const { check_overflow<int16_t>(val);
|
|
||||||
return static_cast<int16_t>(val); }
|
|
||||||
int32_t xi32() const { check_overflow<int32_t>(val);
|
|
||||||
return static_cast<int32_t>(val); }
|
|
||||||
int64_t xi64() const { return val; }
|
|
||||||
float xfloat() const { check_underflow<float>(val);
|
|
||||||
return static_cast<float>(val); }
|
|
||||||
double xdouble() const { check_underflow<double>(val);
|
|
||||||
return static_cast<double>(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<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint64_t xu64() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int8_t xi8() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int16_t xi16() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int32_t xi32() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int64_t xi64() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
float xfloat() const { return val; }
|
|
||||||
double xdouble() const { return static_cast<double>(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<double>(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, float>::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, float>::test(val) == 1) { return false; }
|
|
||||||
try { return static_cast<uint64_t>(val) < x->xu64(); }
|
|
||||||
catch (type_error&) { return false; }
|
|
||||||
}
|
|
||||||
} }
|
|
||||||
bool operator> (const object_class* x) const { try { return static_cast<double>(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, float>::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, float>::test(val) == 1) { return true; }
|
|
||||||
try { return static_cast<uint64_t>(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<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint16_t xu16() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint32_t xu32() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
uint64_t xu64() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int8_t xi8() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int16_t xi16() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int32_t xi32() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
int64_t xi64() const { check_overflow<uint8_t>(val);
|
|
||||||
return static_cast<uint8_t>(val); }
|
|
||||||
float xfloat() const { check_overflow<float>(val);
|
|
||||||
check_underflow<float>(val);
|
|
||||||
return static_cast<float>(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<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 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* 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 {
|
struct object_array : object_class, object_container_mixin {
|
||||||
explicit object_array() {}
|
explicit object_array() {}
|
||||||
explicit object_array(uint32_t n) { val.reserve(n); }
|
explicit object_array(uint32_t n) { val.reserve(n); }
|
||||||
array& xarray() { return val; }
|
array& xarray();
|
||||||
const array& xarray() const { return val; }
|
const array& xarray() const;
|
||||||
bool operator== (const object_class* x) const { try {
|
bool operator== (const object_class* x) const;
|
||||||
const std::vector<object>& xa(x->xarray());
|
// FIXME operator<, operator>
|
||||||
if(val.size() != xa.size()) { return false; }
|
const object_class* inspect(std::ostream& s) const;
|
||||||
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; } }
|
|
||||||
// FIXME operator< operator>
|
|
||||||
const object_class* 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; }
|
|
||||||
public:
|
public:
|
||||||
void push_back(object o) { val.push_back(o); }
|
void push_back(object o) { val.push_back(o); }
|
||||||
private:
|
private:
|
||||||
std::vector<object> val;
|
std::vector<object> val;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME hash, operator==: nil, true, false, containerを入れられない
|
|
||||||
|
// FIXME hash, operator==: nil, true, false, array, mapを入れられない
|
||||||
struct object_map : object_class, object_container_mixin {
|
struct object_map : object_class, object_container_mixin {
|
||||||
explicit object_map() {}
|
explicit object_map() {}
|
||||||
map& xmap() { return val; }
|
map& xmap();
|
||||||
const map& xmap() const { return val; }
|
const map& xmap() const;
|
||||||
bool operator== (const object_class* x) const { try {
|
bool operator== (const object_class* x) const;
|
||||||
const std::map<object, object>& xm(x->xmap());
|
// FIXME operator<, operator>
|
||||||
if(val.size() != xm.size()) { return false; }
|
const object_class* inspect(std::ostream& s) const;
|
||||||
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; } }
|
|
||||||
// FIXME operator< operator>
|
|
||||||
const object_class* 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; }
|
|
||||||
public:
|
public:
|
||||||
void store(object k, object v) { val[k] = v; }
|
void store(object k, object v) { val[k] = v; }
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user