// Header file slice.hpp // // Copyright (c) 2003 Raoul M. Gough // // Use, modification and distribution is subject to 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) // // History // ======= // 2003/ 9/10 rmg File creation // 2008/12/08 Roman Change indexing suite layout // // $Id: slice.hpp,v 1.1.2.10 2003/11/24 14:28:31 raoulgough Exp $ // // 2008 November 27 Roman Yakovenko // implementation of the member functions was moved from cpp to header. // this was done to simplify "installation" procedure. #ifndef BOOST_PYTHON_INDEXING_SLICE_HPP #define BOOST_PYTHON_INDEXING_SLICE_HPP #include <boost/python/object.hpp> #include <boost/python/errors.hpp> #include <boost/python/converter/pytype_object_mgr_traits.hpp> #include <algorithm> namespace boost { namespace python { namespace indexing { struct /*BOOST_PYTHON_DECL*/ slice : public boost::python::object { // This is just a thin wrapper around boost::python::object // so that it is possible to register a special converter for // PySlice_Type and overload C++ functions on slice #if defined (BOOST_NO_MEMBER_TEMPLATES) // MSVC6 doesn't seem to be able to invoke the templated // constructor, so provide explicit overloads to match the // (currently) known boost::python::object constructors explicit slice (::boost::python::handle<> const& p) : object (p) {} explicit slice (::boost::python::detail::borrowed_reference p) : object (p) {} explicit slice (::boost::python::detail::new_reference p) : object (p) {} explicit slice (::boost::python::detail::new_non_null_reference p) : object (p) {} #else // Better compilers make life easier template<typename T> inline slice (T const &ref); #endif slice (slice const & copy) // Copy constructor : object (copy) {} }; struct /*BOOST_PYTHON_DECL*/ integer_slice { // This class provides a convenient interface to Python slice // objects that contain integer bound and stride values. #if PY_VERSION_HEX < 0x02050000 typedef int index_type; #else typedef Py_ssize_t index_type; #endif integer_slice (slice const & sl, index_type length) : m_slice (sl) // Leave index members uninitialized { PySlice_GetIndices( reinterpret_cast<PyObject *> (m_slice.ptr()), length, &m_start, &m_stop, &m_step); if (m_step == 0) { // Can happen with Python prior to 2.3 PyErr_SetString (PyExc_ValueError, "slice step cannot be zero"); boost::python::throw_error_already_set (); } m_start = std::max (static_cast<index_type> (0), std::min (length, m_start)); m_stop = std::max (static_cast<index_type> (0), std::min (length, m_stop)); m_direction = (m_step > 0) ? 1 : -1; } // integer_slice must know how big the container is so it can // adjust for negative indexes, etc... index_type start() const { return m_start; } index_type step() const { return m_step; } index_type stop() const { return m_stop; } index_type size() const { return (m_stop - m_start) / m_step; } bool in_range (index_type index) { return ((m_stop - index) * m_direction) > 0; } private: slice m_slice; index_type m_start; index_type m_step; index_type m_stop; index_type m_direction; }; } } } #if !defined (BOOST_NO_MEMBER_TEMPLATES) template<typename T> boost::python::indexing::slice::slice (T const &ref) : boost::python::object (ref) { if (!PySlice_Check (this->ptr())) { PyErr_SetString( PyExc_TypeError, "slice constructor: passed a non-slice object"); boost::python::throw_error_already_set(); } } #endif namespace boost { namespace python { namespace converter { // Specialized converter to handle PySlice_Type objects template<> struct object_manager_traits<boost::python::indexing::slice> : pytype_object_manager_traits< &PySlice_Type, ::boost::python::indexing::slice> { }; }}} #endif // BOOST_PYTHON_INDEXING_SLICE_HPP