2
0
mirror of https://github.com/boostorg/python.git synced 2026-02-01 20:52:13 +00:00

C++ interface to iterable Python objects

[SVN r1524]
This commit is contained in:
Raoul Gough
2003-09-10 15:36:45 +00:00
parent ea5fa8ab3e
commit a8d2e3cc26
2 changed files with 243 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
// -*- mode:c++ -*-
//
// Module python_iterator.cpp
//
// Copyright (c) 2003 Raoul M. Gough
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this material for any purpose is hereby
// granted without fee, provided the above notices are retained on all
// copies. Permission to modify the material and to distribute modified
// versions is granted, provided the above notices are retained, and a
// notice that the material was modified is included with the above
// copyright notice.
//
// History
// =======
// 2003/ 9/10 rmg File creation
//
// $Id$
//
#include "python_iterator.hpp"
////////////////////////////////////////////////////////////////////////////
// python_iterator factory
///////////////////////////////////////////////////////////////////////////
std::auto_ptr<indexing::python_iterator>
indexing::make_iterator (boost::python::object temp)
{
std::auto_ptr<python_iterator> result;
try
{
result.reset (new python_iter_iterator (temp));
}
catch (boost::python::error_already_set const &)
{
PyErr_Clear ();
try
{
result.reset (new python_getitem_iterator (temp));
}
catch (boost::python::error_already_set const &)
{
PyErr_Clear ();
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////
// Base class (virtual) destructor
///////////////////////////////////////////////////////////////////////////
indexing::python_iterator::~python_iterator ()
{
}
////////////////////////////////////////////////////////////////////////////
// python_getitem_iterator constructor
///////////////////////////////////////////////////////////////////////////
indexing::python_getitem_iterator
::python_getitem_iterator (boost::python::object obj)
: mGetitemMethod (obj.attr ("__getitem__"))
, mIndex (0)
, mCurrent()
{
}
////////////////////////////////////////////////////////////////////////////
// Get our next item (if any)
///////////////////////////////////////////////////////////////////////////
bool indexing::python_getitem_iterator::next ()
{
bool result = true; // Assume success
try
{
mCurrent = mGetitemMethod (mIndex);
++mIndex;
}
catch (boost::python::error_already_set const &)
{
if (PyErr_ExceptionMatches (PyExc_IndexError))
{
// Eat this exception
PyErr_Clear ();
mCurrent = boost::python::object ();
result = false;
}
else
{
// Pass it up the line
throw;
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////
// Return our current item
///////////////////////////////////////////////////////////////////////////
boost::python::object indexing::python_getitem_iterator::current () const
{
return mCurrent;
}
////////////////////////////////////////////////////////////////////////////
// python_iter_iterator constructor
///////////////////////////////////////////////////////////////////////////
indexing::python_iter_iterator
::python_iter_iterator (boost::python::object obj)
: mNextMethod (obj.attr ("__iter__")().attr ("next"))
, mCurrent()
{
}
////////////////////////////////////////////////////////////////////////////
// Get our next item (if any)
///////////////////////////////////////////////////////////////////////////
bool indexing::python_iter_iterator::next ()
{
bool result = true; // Assume success
try
{
mCurrent = mNextMethod ();
}
catch (boost::python::error_already_set const &)
{
if (PyErr_ExceptionMatches (PyExc_StopIteration))
{
// Eat this exception
PyErr_Clear ();
mCurrent = boost::python::object ();
result = false;
}
else
{
// Pass it up the line
throw;
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////
// Return our current item
///////////////////////////////////////////////////////////////////////////
boost::python::object indexing::python_iter_iterator::current () const
{
return mCurrent;
}

View File

@@ -0,0 +1,71 @@
// -*- mode:c++ -*-
//
// Header file python_iterator.hpp
//
// Handy Python iterable iterators
//
// Copyright (c) 2003 Raoul M. Gough
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this material for any purpose is hereby
// granted without fee, provided the above notices are retained on all
// copies. Permission to modify the material and to distribute modified
// versions is granted, provided the above notices are retained, and a
// notice that the material was modified is included with the above
// copyright notice.
//
// History
// =======
// 2003/ 9/10 rmg File creation
//
// $Id$
//
#ifndef python_iterator_rmg_20030910_included
#define python_iterator_rmg_20030910_included
#include <boost/python/object.hpp>
#include <memory>
namespace indexing {
struct python_iterator
{
virtual ~python_iterator ();
virtual bool next () = 0;
virtual boost::python::object current() const = 0;
};
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
struct python_getitem_iterator : public python_iterator
{
public:
python_getitem_iterator (boost::python::object);
virtual bool next ();
virtual boost::python::object current() const;
private:
boost::python::object mGetitemMethod;
int mIndex;
boost::python::object mCurrent;
};
struct 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 mNextMethod;
boost::python::object mCurrent;
};
}
#endif // python_iterator_rmg_20030910_included