Remove boost::any requirement by providing our own implementation

This commit is contained in:
Jason Turner
2011-09-11 19:51:37 -06:00
parent a3c3b8683b
commit 194001f9a1
9 changed files with 230 additions and 70 deletions

View File

@@ -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<Data> clone() const = 0;
};
template<typename T>
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<Data> clone() const
{
return std::shared_ptr<Data>(new Data_Impl<T>(m_data));
}
const std::type_info &m_type;
T m_data;
};
std::shared_ptr<Data> 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<typename ValueType>
Any(const ValueType &t_value)
{
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
}
Any & operator=(const Any &t_any)
{
Any copy(t_any);
swap(copy);
return *this;
}
template<typename ValueType>
Any & operator=(const ValueType &t_value)
{
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
return *this;
}
template<typename ToType>
ToType &cast() const
{
if (typeid(ToType) == m_data->type())
{
return *static_cast<ToType *>(m_data->data());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
~Any()
{
}
// modifiers
Any & swap(Any &t_other)
{
std::shared_ptr<Data> 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

View File

@@ -13,7 +13,6 @@
#include "dynamic_cast_conversion.hpp"
#include "../chaiscript_threading.hpp"
#include <boost/any.hpp>
namespace chaiscript
{
@@ -65,7 +64,7 @@ namespace chaiscript
{
try {
return detail::Cast_Helper<Type>::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<Type>::cast(detail::boxed_dynamic_cast<Type>(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 {

View File

@@ -10,7 +10,6 @@
#include "type_info.hpp"
#include "boxed_value.hpp"
#include <boost/any.hpp>
namespace chaiscript
{
@@ -32,16 +31,16 @@ namespace chaiscript
{
if (!ob.get_type_info().is_const())
{
return std::cref((boost::any_cast<std::reference_wrapper<Result> >(ob.get())).get());
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
} else {
return boost::any_cast<std::reference_wrapper<const Result> >(ob.get());
return ob.get().cast<std::reference_wrapper<const Result> >();
}
} else {
if (!ob.get_type_info().is_const())
{
return std::cref(*(boost::any_cast<std::shared_ptr<Result> >(ob.get())));
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
} else {
return std::cref(*(boost::any_cast<std::shared_ptr<const Result> >(ob.get())));
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
}
}
}
@@ -74,16 +73,16 @@ namespace chaiscript
{
if (!ob.get_type_info().is_const())
{
return &(boost::any_cast<std::reference_wrapper<Result> >(ob.get())).get();
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else {
return &(boost::any_cast<std::reference_wrapper<const Result> >(ob.get())).get();
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
}
} else {
if (!ob.get_type_info().is_const())
{
return (boost::any_cast<std::shared_ptr<Result> >(ob.get())).get();
return (ob.get().cast<std::shared_ptr<Result> >()).get();
} else {
return (boost::any_cast<std::shared_ptr<const Result> >(ob.get())).get();
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
}
}
}
@@ -101,9 +100,9 @@ namespace chaiscript
{
if (ob.is_ref())
{
return &(boost::any_cast<std::reference_wrapper<Result> >(ob.get())).get();
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else {
return (boost::any_cast<std::shared_ptr<Result> >(ob.get())).get();
return (ob.get().cast<std::shared_ptr<Result> >()).get();
}
}
};
@@ -120,9 +119,9 @@ namespace chaiscript
{
if (ob.is_ref())
{
return boost::any_cast<std::reference_wrapper<Result> >(ob.get());
return ob.get().cast<std::reference_wrapper<Result> >();
} else {
Result &r = *(boost::any_cast<std::shared_ptr<Result> >(ob.get()));
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
return r;
}
}
@@ -138,7 +137,7 @@ namespace chaiscript
static Result_Type cast(const Boxed_Value &ob)
{
return boost::any_cast<std::shared_ptr<Result> >(ob.get());
return ob.get().cast<std::shared_ptr<Result> >();
}
};
@@ -154,9 +153,9 @@ namespace chaiscript
{
if (!ob.get_type_info().is_const())
{
return std::const_pointer_cast<const Result>(boost::any_cast<std::shared_ptr<Result> >(ob.get()));
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
} else {
return boost::any_cast<std::shared_ptr<const Result> >(ob.get());
return ob.get().cast<std::shared_ptr<const Result> >();
}
}
};

View File

@@ -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<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(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<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(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<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(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<LHS, std::uint64_t, Float>::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<std::uint64_t, false>(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();
}
}

View File

@@ -12,7 +12,7 @@
#include "../chaiscript_threading.hpp"
#include <map>
#include <boost/any.hpp>
#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<void *>(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<Data> (new Data(
detail::Get_Type_Info<void>::get(),
boost::any(),
chaiscript::detail::Any(),
false,
0)
);
@@ -90,7 +90,7 @@ namespace chaiscript
{
return std::shared_ptr<Data>(new Data(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
chaiscript::detail::Any(obj),
false,
obj.get())
);
@@ -107,7 +107,7 @@ namespace chaiscript
{
return std::shared_ptr<Data>(new Data(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
chaiscript::detail::Any(obj),
true,
&obj.get())
);
@@ -119,7 +119,7 @@ namespace chaiscript
std::shared_ptr<T> p(new T(t));
return std::shared_ptr<Data>(new Data(
detail::Get_Type_Info<T>::get(),
boost::any(p),
chaiscript::detail::Any(p),
false,
p.get())
);
@@ -129,7 +129,7 @@ namespace chaiscript
{
return std::shared_ptr<Data> (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;
}

View File

@@ -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<chaiscript::detail::threading::shared_mutex> 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);
}
}

View File

@@ -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<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");
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");
}
}
}

View File

@@ -21,7 +21,7 @@ namespace chaiscript
template<typename T>
void throw_type(const Boxed_Value &bv)
{
try { T t = boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
}
};

View File

@@ -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<exception::load_module_error> 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<typename T>
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<typename T>
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {