// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com) // and Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef __boxed_pod_value_hpp__ #define __boxed_pod_value_hpp__ #include "type_info.hpp" #include "boxed_value.hpp" #include "boxed_cast_helper.hpp" #include #include #include namespace chaiscript { /** * Object which attempts to convert a Boxed_Value into a generic * POD type and provide generic POD type operations */ struct Boxed_POD_Value { Boxed_POD_Value(const Boxed_Value &v) : d(0), i(0), m_isfloat(false) { if (v.get_type_info().is_undef()) { throw boost::bad_any_cast(); } const Type_Info &inp_ = v.get_type_info(); if (inp_ == typeid(double)) { d = boxed_cast(v); m_isfloat = true; } else if (inp_ == typeid(float)) { d = boxed_cast(v); m_isfloat = true; } else if (inp_ == typeid(bool)) { i = boxed_cast(v); } else if (inp_ == typeid(char)) { i = boxed_cast(v); } else if (inp_ == typeid(int)) { i = boxed_cast(v); } else if (inp_ == typeid(unsigned int)) { i = boxed_cast(v); } else if (inp_ == typeid(long)) { i = boxed_cast(v); } else if (inp_ == typeid(unsigned long)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::int8_t)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::int16_t)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::int32_t)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::int64_t)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::uint8_t)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::uint16_t)) { i = boxed_cast(v); } else if (inp_ == typeid(boost::uint32_t)) { i = boxed_cast(v); } else { throw boost::bad_any_cast(); } } bool operator==(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i); } bool operator<(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) < ((r.m_isfloat)?r.d:r.i); } bool operator>(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) > ((r.m_isfloat)?r.d:r.i); } bool operator>=(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) >= ((r.m_isfloat)?r.d:r.i); } bool operator<=(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) <= ((r.m_isfloat)?r.d:r.i); } bool operator!=(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) != ((r.m_isfloat)?r.d:r.i); } Boxed_Value operator+(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i + r.i); } return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i)); } Boxed_Value operator-(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i - r.i); } return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i)); } Boxed_Value operator&(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return Boxed_Value(i & r.i); } throw bad_boxed_cast("& only valid for integer types"); } Boxed_Value operator^(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return Boxed_Value(i ^ r.i); } throw bad_boxed_cast("^ only valid for integer types"); } Boxed_Value operator|(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return Boxed_Value(i | r.i); } throw bad_boxed_cast("| only valid for integer types"); } Boxed_Value operator/(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i / r.i); } return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i)); } Boxed_Value operator<<(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i << r.i); } throw bad_boxed_cast("<< only valid for integer types"); } Boxed_Value operator*(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i * r.i); } return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i)); } Boxed_Value operator%(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i % r.i); } throw bad_boxed_cast("% only valid for integer types"); } Boxed_Value operator>>(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { return smart_size(i >> r.i); } throw bad_boxed_cast(">> only valid for integer types"); } Boxed_Value smart_size(boost::int64_t i) const { if (i < boost::integer_traits::const_min || i > boost::integer_traits::const_max) { return Boxed_Value(i); } else { return Boxed_Value(static_cast(i)); } } double d; boost::int64_t i; bool m_isfloat; }; namespace detail { /** * Cast_Helper for converting from Boxed_Value to Boxed_POD_Value */ template<> struct Cast_Helper { typedef Boxed_POD_Value Result_Type; static Result_Type cast(const Boxed_Value &ob) { return Boxed_POD_Value(ob); } }; /** * Cast_Helper for converting from Boxed_Value to Boxed_POD_Value */ template<> struct Cast_Helper { typedef Boxed_POD_Value Result_Type; static Result_Type cast(const Boxed_Value &ob) { return Boxed_POD_Value(ob); } }; /** * Cast_Helper for converting from Boxed_Value to Boxed_POD_Value */ template<> struct Cast_Helper { typedef Boxed_POD_Value Result_Type; static Result_Type cast(const Boxed_Value &ob) { return Boxed_POD_Value(ob); } }; } } #endif