diff --git a/src/object/iterator.cpp b/src/object/iterator.cpp new file mode 100644 index 00000000..6a927726 --- /dev/null +++ b/src/object/iterator.cpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +#include +#include +#include +#include + +namespace boost { namespace python { namespace objects { + +static PyObject* identity(PyObject* args_, PyObject*) +{ + PyObject* x = PyTuple_GET_ITEM(args_,0); + Py_INCREF(x); + return x; +} + +BOOST_PYTHON_DECL ref identity_function() +{ + static ref result(new objects::function(py_function(&identity), 1)); + return result; +} + +void set_stop_iteration_error() +{ + PyErr_SetObject(PyExc_StopIteration, Py_None); +} + +}}} // namespace boost::python::objects diff --git a/test/iterator.cpp b/test/iterator.cpp new file mode 100644 index 00000000..1ea2196b --- /dev/null +++ b/test/iterator.cpp @@ -0,0 +1,128 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace boost::python; + +typedef std::list list_int; +typedef std::list list_list; + +void push_back(list_int& x, int y) +{ + x.push_back(y); +} + +void push_list_back(list_list& x, list_int const& y) +{ + x.push_back(y); +} + +int back(list_int& x) +{ + return x.back(); +} + +typedef std::pair list_range; + +list_range range(list_int& x) +{ + return list_range(x.begin(), x.end()); +} + +struct two_lists +{ + two_lists() + { + int primes[] = { 2, 3, 5, 7, 11, 13 }; + std::copy(primes, primes + sizeof(primes)/sizeof(*primes), std::back_inserter(one)); + int evens[] = { 2, 4, 6, 8, 10, 12 }; + std::copy(evens, evens + sizeof(evens)/sizeof(*evens), std::back_inserter(two)); + } + + struct two_start + { + typedef list_int::iterator result_type; + result_type operator()(two_lists& ll) const { return ll.two.begin(); } + }; + friend struct two_start; + + list_int::iterator one_begin() { return one.begin(); } + list_int::iterator two_begin() { return two.begin(); } + + list_int::iterator one_end() { return one.end(); } + list_int::iterator two_end() { return two.end(); } + +private: + list_int one; + list_int two; +}; + +BOOST_PYTHON_MODULE_INIT(iterator_ext) +{ + module("iterator_ext") + .def("range", &::range) + .add( + class_("list_int") + .def_init() + .def("push_back", push_back) + .def("back", back) + .def("__iter__", iterator()) + ) + .add( + class_("list_range") + + // We can specify data members + .def("__iter__" + , range(&list_range::first, &list_range::second)) + ) + .add( + class_("two_lists") + .def_init() + + // We can spcify member functions + .add_property( + "primes" + , range(&two_lists::one_begin, &two_lists::one_end)) + + // Prove that we can explicitly specify call policies + .add_property( + "evens" + , range >( + &two_lists::two_begin, &two_lists::two_end)) + + // Prove that we can specify call policies and target + .add_property( + "twosies" + , range, two_lists>( + // And we can use adaptable function objects when + // partial specialization is available. +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + two_lists::two_start() +# else + &two_lists::two_begin +# endif + , &two_lists::two_end)) + ) + .add( + class_("list_list") + .def_init() + .def("push_back", push_list_back) + .def("__iter__", iterator >()) + ) + ; +} + +#include "module_tail.cpp" diff --git a/test/iterator.py b/test/iterator.py new file mode 100644 index 00000000..4e6366ad --- /dev/null +++ b/test/iterator.py @@ -0,0 +1,60 @@ +''' +>>> from iterator_ext import * +>>> x = list_int() +>>> x.push_back(1) +>>> x.back() +1 +>>> x.push_back(3) +>>> x.push_back(5) +>>> for y in x: +... print y +1 +3 +5 +>>> z = range(x) +>>> for y in z: +... print y +1 +3 +5 +>>> l2 = two_lists() +>>> for y in l2.primes: +... print y +2 +3 +5 +7 +11 +13 +>>> for y in l2.evens: +... print y +2 +4 +6 +8 +10 +12 +>>> ll = list_list() +>>> ll.push_back(x) +>>> x.push_back(7) +>>> ll.push_back(x) +>>> for a in ll: +... for b in a: +... print b, +... print +... +1 3 5 +1 3 5 7 +''' +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0])