diff options
Diffstat (limited to 'libs/python/src/errors.cpp')
-rw-r--r-- | libs/python/src/errors.cpp | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/libs/python/src/errors.cpp b/libs/python/src/errors.cpp new file mode 100644 index 000000000..34ea22f43 --- /dev/null +++ b/libs/python/src/errors.cpp @@ -0,0 +1,105 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PYTHON_SOURCE +# define BOOST_PYTHON_SOURCE +#endif + +#include <boost/python/errors.hpp> +#include <boost/cast.hpp> +#include <boost/python/detail/exception_handler.hpp> + +namespace boost { namespace python { + +error_already_set::~error_already_set() {} + +// IMPORTANT: this function may only be called from within a catch block! +BOOST_PYTHON_DECL bool handle_exception_impl(function0<void> f) +{ + try + { + if (detail::exception_handler::chain) + return detail::exception_handler::chain->handle(f); + f(); + return false; + } + catch(const boost::python::error_already_set&) + { + // The python error reporting has already been handled. + } + catch(const std::bad_alloc&) + { + PyErr_NoMemory(); + } + catch(const bad_numeric_cast& x) + { + PyErr_SetString(PyExc_OverflowError, x.what()); + } + catch(const std::out_of_range& x) + { + PyErr_SetString(PyExc_IndexError, x.what()); + } + catch(const std::invalid_argument& x) + { + PyErr_SetString(PyExc_ValueError, x.what()); + } + catch(const std::exception& x) + { + PyErr_SetString(PyExc_RuntimeError, x.what()); + } + catch(...) + { + PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception"); + } + return true; +} + +void BOOST_PYTHON_DECL throw_error_already_set() +{ + throw error_already_set(); +} + +namespace detail { + +bool exception_handler::operator()(function0<void> const& f) const +{ + if (m_next) + { + return m_next->handle(f); + } + else + { + f(); + return false; + } +} + +exception_handler::exception_handler(handler_function const& impl) + : m_impl(impl) + , m_next(0) +{ + if (chain != 0) + tail->m_next = this; + else + chain = this; + tail = this; +} + +exception_handler* exception_handler::chain; +exception_handler* exception_handler::tail; + +BOOST_PYTHON_DECL void register_exception_handler(handler_function const& f) +{ + // the constructor links the new object into a handler chain, so + // this object isn't actaully leaked (until, of course, the + // interpreter exits). + new exception_handler(f); +} + +} // namespace boost::python::detail + +}} // namespace boost::python + + |