mirror of
https://github.com/boostorg/python.git
synced 2026-01-22 05:22:45 +00:00
Switch to a non-virtual interface by relying on PyObject_GetIter
[SVN r20939]
This commit is contained in:
@@ -21,46 +21,24 @@
|
||||
#define BOOST_PYTHON_INDEXING_PYTHON_ITERATOR_HPP
|
||||
|
||||
#include <boost/python/object.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
struct BOOST_PYTHON_DECL python_iterator
|
||||
{
|
||||
virtual ~python_iterator ();
|
||||
virtual bool next () = 0;
|
||||
virtual boost::python::object current() const = 0;
|
||||
};
|
||||
python_iterator (boost::python::object);
|
||||
// Sets a python type exception and calls throw_error_already_set if
|
||||
// the passed object is not iterable via PyObject_GetIter
|
||||
|
||||
BOOST_PYTHON_DECL
|
||||
std::auto_ptr<python_iterator>
|
||||
make_iterator (boost::python::object);
|
||||
// Returns null auto_ptr if object does not provide __iter__ nor
|
||||
// __getitem__, otherwise a pointer to a suitable implementation of
|
||||
// python_iterator
|
||||
bool next ();
|
||||
// Get the next item from the iterator, returning true for success
|
||||
|
||||
struct BOOST_PYTHON_DECL python_getitem_iterator : public python_iterator
|
||||
{
|
||||
public:
|
||||
python_getitem_iterator (boost::python::object);
|
||||
virtual bool next ();
|
||||
virtual boost::python::object current() const;
|
||||
boost::python::object current() const;
|
||||
// Callable only after a successful next()
|
||||
|
||||
private:
|
||||
boost::python::object m_getitem_method;
|
||||
int m_index;
|
||||
boost::python::object m_current;
|
||||
};
|
||||
|
||||
struct BOOST_PYTHON_DECL python_iter_iterator : public python_iterator
|
||||
{
|
||||
public:
|
||||
python_iter_iterator (boost::python::object);
|
||||
virtual bool next ();
|
||||
virtual boost::python::object current() const;
|
||||
|
||||
private:
|
||||
boost::python::object m_next_method;
|
||||
boost::python::object m_current;
|
||||
::boost::python::object m_iter_obj;
|
||||
::boost::python::object m_next_method;
|
||||
::boost::python::object m_current;
|
||||
};
|
||||
} } }
|
||||
|
||||
|
||||
@@ -16,60 +16,17 @@
|
||||
//
|
||||
|
||||
#include <boost/python/suite/indexing/python_iterator.hpp>
|
||||
#include <boost/python/suite/indexing/workaround.hpp>
|
||||
#include <boost/python/handle.hpp>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// python_iterator factory
|
||||
// python_iterator constructor
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::auto_ptr<boost::python::indexing::python_iterator>
|
||||
boost::python::indexing::make_iterator (boost::python::object temp)
|
||||
{
|
||||
typedef std::auto_ptr<python_iterator> ptr_type;
|
||||
ptr_type result;
|
||||
|
||||
try
|
||||
{
|
||||
BOOST_PYTHON_INDEXING_RESET_AUTO_PTR(
|
||||
result, (python_iterator *) new python_iter_iterator (temp));
|
||||
}
|
||||
|
||||
catch (boost::python::error_already_set const &)
|
||||
{
|
||||
PyErr_Clear ();
|
||||
|
||||
try
|
||||
{
|
||||
BOOST_PYTHON_INDEXING_RESET_AUTO_PTR(
|
||||
result, (python_iterator *) new python_getitem_iterator (temp));
|
||||
}
|
||||
|
||||
catch (boost::python::error_already_set const &)
|
||||
{
|
||||
PyErr_Clear ();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Base class (virtual) destructor
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
boost::python::indexing::python_iterator::~python_iterator ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// python_getitem_iterator constructor
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
boost::python::indexing::python_getitem_iterator
|
||||
::python_getitem_iterator (boost::python::object obj)
|
||||
: m_getitem_method (obj.attr ("__getitem__")),
|
||||
m_index (0),
|
||||
m_current()
|
||||
boost::python::indexing::python_iterator
|
||||
::python_iterator (boost::python::object obj)
|
||||
: m_iter_obj (handle<> (PyObject_GetIter (obj.ptr()))),
|
||||
m_next_method (m_iter_obj.attr ("next")),
|
||||
m_current()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -77,62 +34,7 @@ boost::python::indexing::python_getitem_iterator
|
||||
// Get our next item (if any)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool boost::python::indexing::python_getitem_iterator::next ()
|
||||
{
|
||||
bool result = true; // Assume success
|
||||
|
||||
try
|
||||
{
|
||||
m_current = m_getitem_method (m_index);
|
||||
++m_index;
|
||||
}
|
||||
|
||||
catch (boost::python::error_already_set const &)
|
||||
{
|
||||
if (PyErr_ExceptionMatches (PyExc_IndexError))
|
||||
{
|
||||
// Eat this exception
|
||||
PyErr_Clear ();
|
||||
m_current = boost::python::object ();
|
||||
result = false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Pass it up the line
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Return our current item
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
boost::python::object
|
||||
boost::python::indexing::python_getitem_iterator::current () const
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// python_iter_iterator constructor
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
boost::python::indexing::python_iter_iterator
|
||||
::python_iter_iterator (boost::python::object obj)
|
||||
: m_next_method (obj.attr ("__iter__")().attr ("next")),
|
||||
m_current()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Get our next item (if any)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool boost::python::indexing::python_iter_iterator::next ()
|
||||
bool boost::python::indexing::python_iterator::next ()
|
||||
{
|
||||
bool result = true; // Assume success
|
||||
|
||||
@@ -147,8 +49,8 @@ bool boost::python::indexing::python_iter_iterator::next ()
|
||||
{
|
||||
// Eat this exception
|
||||
PyErr_Clear ();
|
||||
m_current = boost::python::object ();
|
||||
result = false;
|
||||
m_current = boost::python::object (); // No current object
|
||||
result = false; // Report failure via return value only
|
||||
}
|
||||
|
||||
else
|
||||
@@ -166,7 +68,7 @@ bool boost::python::indexing::python_iter_iterator::next ()
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
boost::python::object
|
||||
boost::python::indexing::python_iter_iterator::current () const
|
||||
boost::python::indexing::python_iterator::current () const
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user