diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp new file mode 100644 index 0000000..a6cce3d --- /dev/null +++ b/include/chaiscript/dispatchkit/any.hpp @@ -0,0 +1,162 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com) +// and Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +#ifndef CHAISCRIPT_ANY_HPP_ +#define CHAISCRIPT_ANY_HPP_ + +namespace chaiscript { + namespace detail { + namespace exception + { + /// \brief Thrown in the event that an Any cannot be cast to the desired type + /// + /// It is used internally during function dispatch. + /// + /// \sa chaiscript::detail::Any + class bad_any_cast : public std::bad_cast + { + public: + bad_any_cast() throw() + : m_what("bad any cast") + { + } + + virtual ~bad_any_cast() throw() {} + + /// \brief Description of what error occured + virtual const char * what() const throw() + { + return m_what.c_str(); + } + + private: + std::string m_what; + }; + } + + + class Any { + private: + struct Data + { + virtual void *data() = 0; + virtual const std::type_info &type() const = 0; + virtual std::shared_ptr clone() const = 0; + }; + + template + struct Data_Impl : Data + { + Data_Impl(const T &t_type) + : m_type(typeid(T)), + m_data(t_type) + { + } + + virtual void *data() + { + return &m_data; + } + + const std::type_info &type() const + { + return m_type; + } + + std::shared_ptr clone() const + { + return std::shared_ptr(new Data_Impl(m_data)); + } + + const std::type_info &m_type; + T m_data; + }; + + std::shared_ptr m_data; + + public: + // construct/copy/destruct + Any() {} + + Any(const Any &t_any) + { + if (!t_any.empty()) + { + m_data = t_any.m_data->clone(); + } else { + m_data.reset(); + } + } + + template + Any(const ValueType &t_value) + { + m_data = std::shared_ptr(new Data_Impl(t_value)); + } + + Any & operator=(const Any &t_any) + { + Any copy(t_any); + swap(copy); + return *this; + } + + template + Any & operator=(const ValueType &t_value) + { + m_data = std::shared_ptr(new Data_Impl(t_value)); + return *this; + } + + template + ToType &cast() const + { + if (typeid(ToType) == m_data->type()) + { + return *static_cast(m_data->data()); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + + } + + + ~Any() + { + } + + // modifiers + Any & swap(Any &t_other) + { + std::shared_ptr data = t_other.m_data; + t_other.m_data = m_data; + m_data = data; + return *this; + } + + // queries + bool empty() const + { + return !bool(m_data); + } + + const std::type_info & type() const + { + if (m_data) + { + return m_data->type(); + } else { + return typeid(void); + } + } + }; + + } +} + +#endif + + diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index c10aa72..c8b8e76 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -13,7 +13,6 @@ #include "dynamic_cast_conversion.hpp" #include "../chaiscript_threading.hpp" -#include namespace chaiscript { @@ -65,7 +64,7 @@ namespace chaiscript { try { return detail::Cast_Helper::cast(bv); - } catch (const boost::bad_any_cast &) { + } catch (const chaiscript::detail::exception::bad_any_cast &) { #ifdef BOOST_MSVC //Thank you MSVC, yes we know that a constant value is being used in the if @@ -80,7 +79,7 @@ namespace chaiscript // 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::cast(detail::boxed_dynamic_cast(bv)); - } catch (const boost::bad_any_cast &) { + } catch (const chaiscript::detail::exception::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } } else { diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index ae23556..aec80df 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -10,7 +10,6 @@ #include "type_info.hpp" #include "boxed_value.hpp" -#include namespace chaiscript { @@ -32,16 +31,16 @@ namespace chaiscript { if (!ob.get_type_info().is_const()) { - return std::cref((boost::any_cast >(ob.get())).get()); + return std::cref((ob.get().cast >()).get()); } else { - return boost::any_cast >(ob.get()); + return ob.get().cast >(); } } else { if (!ob.get_type_info().is_const()) { - return std::cref(*(boost::any_cast >(ob.get()))); + return std::cref(*(ob.get().cast >())); } else { - return std::cref(*(boost::any_cast >(ob.get()))); + return std::cref(*(ob.get().cast >())); } } } @@ -74,16 +73,16 @@ namespace chaiscript { if (!ob.get_type_info().is_const()) { - return &(boost::any_cast >(ob.get())).get(); + return &(ob.get().cast >()).get(); } else { - return &(boost::any_cast >(ob.get())).get(); + return &(ob.get().cast >()).get(); } } else { if (!ob.get_type_info().is_const()) { - return (boost::any_cast >(ob.get())).get(); + return (ob.get().cast >()).get(); } else { - return (boost::any_cast >(ob.get())).get(); + return (ob.get().cast >()).get(); } } } @@ -101,9 +100,9 @@ namespace chaiscript { if (ob.is_ref()) { - return &(boost::any_cast >(ob.get())).get(); + return &(ob.get().cast >()).get(); } else { - return (boost::any_cast >(ob.get())).get(); + return (ob.get().cast >()).get(); } } }; @@ -120,9 +119,9 @@ namespace chaiscript { if (ob.is_ref()) { - return boost::any_cast >(ob.get()); + return ob.get().cast >(); } else { - Result &r = *(boost::any_cast >(ob.get())); + Result &r = *(ob.get().cast >()); return r; } } @@ -138,7 +137,7 @@ namespace chaiscript static Result_Type cast(const Boxed_Value &ob) { - return boost::any_cast >(ob.get()); + return ob.get().cast >(); } }; @@ -154,9 +153,9 @@ namespace chaiscript { if (!ob.get_type_info().is_const()) { - return std::const_pointer_cast(boost::any_cast >(ob.get())); + return std::const_pointer_cast(ob.get().cast >()); } else { - return boost::any_cast >(ob.get()); + return ob.get().cast >(); } } }; diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index f593e62..0241c5b 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -38,9 +38,9 @@ namespace chaiscript case Operators::not_equal: return const_var(t != u); default: - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } }; @@ -73,7 +73,7 @@ namespace chaiscript t -= u; break; default: - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; @@ -106,7 +106,7 @@ namespace chaiscript t ^= u; break; default: - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } @@ -134,9 +134,9 @@ namespace chaiscript case Operators::bitwise_complement: return const_var(~t); default: - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } }; @@ -160,9 +160,9 @@ namespace chaiscript case Operators::unary_plus: return const_var(+t); default: - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } }; @@ -183,7 +183,7 @@ namespace chaiscript } else if (t_oper > Operators::const_flag) { return const_binary::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); } else { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } } }; @@ -199,13 +199,13 @@ namespace chaiscript } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) { return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_flag) { return const_binary::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); } else { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } } }; @@ -248,7 +248,7 @@ namespace chaiscript } else if (inp_ == typeid(std::uint64_t)) { return Go::go(t_oper, t_lhs, t_rhs); } else { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } } @@ -289,7 +289,7 @@ namespace chaiscript } else if (inp_ == typeid(std::uint64_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } } @@ -302,12 +302,12 @@ namespace chaiscript const Type_Info &inp_ = v.get_type_info(); if (inp_ == typeid(bool)) { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } if (!inp_.is_arithmetic()) { - throw boost::bad_any_cast(); + throw chaiscript::detail::exception::bad_any_cast(); } } diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 76a785f..c7b6ca7 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -12,7 +12,7 @@ #include "../chaiscript_threading.hpp" #include -#include +#include "any.hpp" namespace chaiscript { @@ -36,7 +36,7 @@ namespace chaiscript struct Data { Data(const Type_Info &ti, - const boost::any &to, + const chaiscript::detail::Any &to, bool tr, const void *t_void_ptr) : m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?0:const_cast(t_void_ptr)), m_const_data_ptr(t_void_ptr), @@ -60,7 +60,7 @@ namespace chaiscript } Type_Info m_type_info; - boost::any m_obj; + chaiscript::detail::Any m_obj; void *m_data_ptr; const void *m_const_data_ptr; bool m_is_ref; @@ -73,7 +73,7 @@ namespace chaiscript { return std::shared_ptr (new Data( detail::Get_Type_Info::get(), - boost::any(), + chaiscript::detail::Any(), false, 0) ); @@ -90,7 +90,7 @@ namespace chaiscript { return std::shared_ptr(new Data( detail::Get_Type_Info::get(), - boost::any(obj), + chaiscript::detail::Any(obj), false, obj.get()) ); @@ -107,7 +107,7 @@ namespace chaiscript { return std::shared_ptr(new Data( detail::Get_Type_Info::get(), - boost::any(obj), + chaiscript::detail::Any(obj), true, &obj.get()) ); @@ -119,7 +119,7 @@ namespace chaiscript std::shared_ptr p(new T(t)); return std::shared_ptr(new Data( detail::Get_Type_Info::get(), - boost::any(p), + chaiscript::detail::Any(p), false, p.get()) ); @@ -129,7 +129,7 @@ namespace chaiscript { return std::shared_ptr (new Data( Type_Info(), - boost::any(), + chaiscript::detail::Any(), false, 0) ); @@ -220,7 +220,7 @@ namespace chaiscript return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0); } - const boost::any & get() const + const chaiscript::detail::Any & get() const { return m_data->m_obj; } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index ecb4de4..04936be 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -100,7 +100,7 @@ namespace chaiscript { if (!t_bv.is_const()) { - throw exception::global_non_const(); + throw chaiscript::exception::global_non_const(); } m_globals.push_back(std::make_pair(t_bv, t_name)); @@ -421,7 +421,7 @@ namespace chaiscript validate_object_name(name); if (!obj.is_const()) { - throw exception::global_non_const(); + throw chaiscript::exception::global_non_const(); } chaiscript::detail::threading::unique_lock l(m_global_object_mutex); @@ -928,7 +928,7 @@ namespace chaiscript if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end()) { - throw exception::reserved_word_error(name); + throw chaiscript::exception::reserved_word_error(name); } } diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 1bb5447..c024563 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -117,7 +117,7 @@ namespace chaiscript } } } else { - throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion"); + throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion"); } } }; @@ -272,9 +272,9 @@ namespace chaiscript try { return detail::Dynamic_Conversions::get().get_conversion(user_type(), 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"); + throw chaiscript::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"); + throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation"); } } } diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index ff169c3..0f08cdc 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -21,7 +21,7 @@ namespace chaiscript template void throw_type(const Boxed_Value &bv) { - try { T t = boxed_cast(bv); throw t; } catch (const exception::bad_boxed_cast &) {} + try { T t = boxed_cast(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {} } }; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 4b91239..e0816b7 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -57,7 +57,7 @@ namespace chaiscript { if (!m_data) { - throw exception::load_module_error(dlerror()); + throw chaiscript::exception::load_module_error(dlerror()); } } @@ -80,7 +80,7 @@ namespace chaiscript { if (!m_symbol) { - throw exception::load_module_error(dlerror()); + throw chaiscript::exception::load_module_error(dlerror()); } } @@ -180,7 +180,7 @@ namespace chaiscript { if (!m_data) { - throw exception::load_module_error(GetErrorMessage(GetLastError())); + throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError())); } } @@ -200,7 +200,7 @@ namespace chaiscript { if (!m_symbol) { - throw exception::load_module_error(GetErrorMessage(GetLastError())); + throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError())); } } @@ -223,7 +223,7 @@ namespace chaiscript { Loadable_Module(const std::string &, const std::string &) { - throw exception::load_module_error("Loadable module support not available for your platform"); + throw chaiscript::exception::load_module_error("Loadable module support not available for your platform"); } ModulePtr m_moduleptr; @@ -302,10 +302,10 @@ namespace chaiscript l2.unlock(); eval_file(appendedpath); } - } catch (const exception::file_not_found_error &) { + } catch (const chaiscript::exception::file_not_found_error &) { if (i == m_usepaths.size() - 1) { - throw exception::file_not_found_error(t_filename); + throw chaiscript::exception::file_not_found_error(t_filename); } // failed to load, try the next path @@ -378,7 +378,7 @@ namespace chaiscript std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary ); if (!infile.is_open()) { - throw exception::file_not_found_error(t_filename); + throw chaiscript::exception::file_not_found_error(t_filename); } std::streampos size = infile.tellg(); @@ -420,7 +420,7 @@ namespace chaiscript /// \brief Adds a constant object that is available in all contexts and to all threads /// \param[in] t_bv Boxed_Value to add as a global /// \param[in] t_name Name of the value to add - /// \throw exception::global_non_const If t_bv is not a constant object + /// \throw chaiscript::exception::global_non_const If t_bv is not a constant object /// \sa Boxed_Value::is_const ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) { @@ -536,7 +536,7 @@ namespace chaiscript /// If no file can be found matching the search criteria and containing the appropriate entry point /// (the symbol mentioned above), an exception is thrown. /// - /// \throw exception::load_module_error In the event that no matching module can be found. + /// \throw chaiscript::exception::load_module_error In the event that no matching module can be found. void load_module(const std::string &t_module_name) { std::vector errors; @@ -560,7 +560,7 @@ namespace chaiscript std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k]; load_module(t_module_name, name); return; - } catch (const exception::load_module_error &e) { + } catch (const chaiscript::exception::load_module_error &e) { errors.push_back(e); // Try next set } @@ -582,7 +582,7 @@ namespace chaiscript errstring += itr->what(); } - throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring); + throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring); } /// \brief Load a binary module from a dynamic library. Works on platforms that support @@ -616,7 +616,7 @@ namespace chaiscript /// /// \return result of the script execution /// - /// \throw exception::eval_error In the case that evaluation fails. + /// \throw chaiscript::exception::eval_error In the case that evaluation fails. Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler()) { try { @@ -637,8 +637,8 @@ namespace chaiscript /// /// \return result of the script execution /// - /// \throw exception::eval_error In the case that evaluation fails. - /// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted + /// \throw chaiscript::exception::eval_error In the case that evaluation fails. + /// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted /// to the requested type. template T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler()) @@ -660,7 +660,7 @@ namespace chaiscript /// /// \return result of the script execution /// - /// \throw exception::eval_error In the case that evaluation fails. + /// \throw chaiscript::exception::eval_error In the case that evaluation fails. Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler()) { try { @@ -677,7 +677,7 @@ namespace chaiscript /// \param[in] t_filename File to load and parse. /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \return result of the script execution - /// \throw exception::eval_error In the case that evaluation fails. + /// \throw chaiscript::exception::eval_error In the case that evaluation fails. Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { try { return do_eval(load_file(t_filename), t_filename); @@ -694,8 +694,8 @@ namespace chaiscript /// \param[in] t_filename File to load and parse. /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \return result of the script execution - /// \throw exception::eval_error In the case that evaluation fails. - /// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted + /// \throw chaiscript::exception::eval_error In the case that evaluation fails. + /// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted /// to the requested type. template T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {