decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr) { if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) { try { return (detail::Cast_Helper<Type>::cast(bv, t_conversions)); } catch (const chaiscript::detail::exception::bad_any_cast &) { } } if (t_conversions && (*t_conversions)->convertable_type<Type>()) { try { // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // either way, we are not responsible if it doesn't work return (detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions)); } catch (...) { try { // try going the other way return (detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions)); } catch (const chaiscript::detail::exception::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } } } else { // If it's not convertable, just throw the error, don't waste the time on the // attempted dynamic_cast throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } }
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr) { if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) { try { return detail::Cast_Helper<Type>::cast(bv, t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { } } if (t_conversions && (*t_conversions)->convertable_type<Type>()) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << '\n'; // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // either way, we are not responsible if it doesn't work return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions); } catch (...) { try { // std::cout << "trying a down conversion " << typeid(Type).name() << '\n'; // try going the other way - down the inheritance graph return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } } } else { // If it's not polymorphic, just throw the error, don't waste the time on the // attempted dynamic_cast throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } }
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) { try { return detail::Cast_Helper<Type>::cast(bv); } catch (const boost::bad_any_cast &) { #ifdef BOOST_MSVC //Thank you MSVC, yes we know that a constant value is being used in the if // statment in THIS VERSION of the template instantiation #pragma warning(push) #pragma warning(disable : 4127) #endif if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value) { try { // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // either way, we are not responsible if it doesn't work return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv)); } catch (const boost::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } } else { // If it's not polymorphic, just throw the error, don't waste the time on the // attempted dynamic_cast throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } #ifdef BOOST_MSVC #pragma warning(pop) #endif } }
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result)) { return static_cast<Result *>(throw_if_null(ob.get_ptr())); } else { throw chaiscript::detail::exception::bad_any_cast(); } }
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const { try { return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived); } catch (const std::out_of_range &) { throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion"); } catch (const std::bad_cast &) { throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation"); } }
static Boxed_Value cast(const Boxed_Value &t_from) { if (t_from.get_type_info().bare_equal(user_type<From>())) { if (t_from.is_pointer()) { // Dynamic cast out the contained boxed value, which we know is the type we want if (t_from.is_const()) { std::shared_ptr<const To> data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)); if (!data) { throw std::bad_cast(); } return Boxed_Value(data); } else { std::shared_ptr<To> data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)); if (!data) { throw std::bad_cast(); } return Boxed_Value(data); } } else { // Pull the reference out of the contained boxed value, which we know is the type we want if (t_from.is_const()) { const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr); const To &data = dynamic_cast<const To &>(d); return Boxed_Value(std::cref(data)); } else { From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr); To &data = dynamic_cast<To &>(d); return Boxed_Value(std::ref(data)); } } } else { throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion"); } }
virtual Boxed_Value convert(const Boxed_Value &t_derived) const { if (t_derived.get_type_info().bare_equal(user_type<Derived>())) { if (t_derived.is_pointer()) { // Dynamic cast out the contained boxed value, which we know is the type we want if (t_derived.is_const()) { boost::shared_ptr<const Base> data = boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived, 0)); if (!data) { throw std::bad_cast(); } return Boxed_Value(data); } else { boost::shared_ptr<Base> data = boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived, 0)); if (!data) { throw std::bad_cast(); } return Boxed_Value(data); } } else { // Pull the reference out of the contained boxed value, which we know is the type we want if (t_derived.is_const()) { const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived, 0); const Base &data = dynamic_cast<const Base &>(d); return Boxed_Value(boost::cref(data)); } else { Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived, 0); Base &data = dynamic_cast<Base &>(d); return Boxed_Value(boost::ref(data)); } } } else { throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion"); } }
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (!ob.get_type_info().is_const()) { return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >()); } else { return ob.get().cast<std::shared_ptr<const Result> >(); } }
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions) { if (ti.is_undef() || ti.bare_equal(user_type<Boxed_Value>()) || (!bv.get_type_info().is_undef() && (ti.bare_equal(user_type<Boxed_Number>()) || ti.bare_equal(bv.get_type_info()) || bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >()) || t_conversions.converts(ti, bv.get_type_info()) ) ) ) { return true; } else { return false; } }
static Result_Type cast(const Boxed_Value &ob) { if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) { return dispatch::functor<Signature>(ob); } else { return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob); } }
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { auto p = throw_if_null(ob.get_const_ptr()); return std::cref(*static_cast<const Result *>(p)); } else { throw chaiscript::detail::exception::bad_any_cast(); } }
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.is_ref()) { if (!ob.get_type_info().is_const()) { return &(ob.get().cast<std::reference_wrapper<Result> >()).get(); } else { return &(ob.get().cast<std::reference_wrapper<const Result> >()).get(); } } else { if (!ob.get_type_info().is_const()) { return (ob.get().cast<std::shared_ptr<Result> >()).get(); } else { return (ob.get().cast<std::shared_ptr<const Result> >()).get(); } } }
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr) { try { return detail::Cast_Helper<Type>::cast(bv, t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { #ifdef CHAISCRIPT_MSVC //Thank you MSVC, yes we know that a constant value is being used in the if // statment in THIS VERSION of the template instantiation #pragma warning(push) #pragma warning(disable : 4127) #endif if (t_conversions && t_conversions->convertable_type<Type>()) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << '\n'; // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // either way, we are not responsible if it doesn't work return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions); } catch (...) { try { // std::cout << "trying a down conversion " << typeid(Type).name() << '\n'; // try going the other way - down the inheritance graph return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } } } else { // If it's not polymorphic, just throw the error, don't waste the time on the // attempted dynamic_cast throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif } }
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name, const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const { if (bv.get_type_info().bare_equal(m_doti)) { try { const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions); return name == "Dynamic_Object" || d.get_type_name() == name; } catch (const std::bad_cast &) { return false; } } else { if (ti) { return bv.get_type_info().bare_equal(*ti); } else { return false; } } }
static Common_Types get_common_type(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); if (inp_ == typeid(int)) { return get_common_type(sizeof(int), true); } else if (inp_ == typeid(double)) { return Common_Types::t_double; } else if (inp_ == typeid(long double)) { return Common_Types::t_long_double; } else if (inp_ == typeid(float)) { return Common_Types::t_float; } else if (inp_ == typeid(char)) { return get_common_type(sizeof(char), std::is_signed<char>::value); } else if (inp_ == typeid(unsigned char)) { return get_common_type(sizeof(unsigned char), false); } else if (inp_ == typeid(unsigned int)) { return get_common_type(sizeof(unsigned int), false); } else if (inp_ == typeid(long)) { return get_common_type(sizeof(long), true); } else if (inp_ == typeid(long long)) { return get_common_type(sizeof(long long), true); } else if (inp_ == typeid(unsigned long)) { return get_common_type(sizeof(unsigned long), false); } else if (inp_ == typeid(unsigned long long)) { return get_common_type(sizeof(unsigned long long), false); } else if (inp_ == typeid(std::int8_t)) { return Common_Types::t_int8; } else if (inp_ == typeid(std::int16_t)) { return Common_Types::t_int16; } else if (inp_ == typeid(std::int32_t)) { return Common_Types::t_int32; } else if (inp_ == typeid(std::int64_t)) { return Common_Types::t_int64; } else if (inp_ == typeid(std::uint8_t)) { return Common_Types::t_uint8; } else if (inp_ == typeid(std::uint16_t)) { return Common_Types::t_uint16; } else if (inp_ == typeid(std::uint32_t)) { return Common_Types::t_uint32; } else if (inp_ == typeid(std::uint64_t)) { return Common_Types::t_uint64; } else if (inp_ == typeid(wchar_t)) { return get_common_type(sizeof(wchar_t), std::is_signed<wchar_t>::value); } else if (inp_ == typeid(char16_t)) { return get_common_type(sizeof(char16_t), std::is_signed<char16_t>::value); } else if (inp_ == typeid(char32_t)) { return get_common_type(sizeof(char32_t), std::is_signed<char32_t>::value); } else { throw chaiscript::detail::exception::bad_any_cast(); } }
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name, const boost::optional<Type_Info> &ti) { static Type_Info doti = user_type<Dynamic_Object>(); if (bv.get_type_info().bare_equal(doti)) { try { const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv); return name == "Dynamic_Object" || d.get_type_name() == name; } catch (const std::bad_cast &) { return false; } } else { if (ti) { return bv.get_type_info().bare_equal(*ti); } else { return false; } } }
bool test_type_conversion(const Boxed_Value &bv, bool expectedpass) { bool ret = run_test_type_conversion<To>(bv, expectedpass); if (!ret) { std::cerr << "Error with type conversion test. From: " << (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name() << " To: " << (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name() << " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not" << std::endl; } return ret; }