2
0
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:
Raoul Gough
2003-11-24 16:35:19 +00:00
parent 182d9e9447
commit dfcce0f2a9
2 changed files with 21 additions and 141 deletions

View File

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

View File

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