2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-28 07:22:31 +00:00

added the cursor feature

[SVN r8368]
This commit is contained in:
Ullrich Köthe
2000-11-30 16:13:12 +00:00
parent 7e672720f1
commit f6b99ede25
3 changed files with 133 additions and 1 deletions

View File

@@ -144,7 +144,27 @@ class class_builder
reference<detail::extension_class<T, U> > m_class;
};
// The bug mentioned at the top of this file is that on certain compilers static
namespace detail
{
// helper function that does the actual work of creating a cursor for a n
// STL conforming container. called by module_builder::def_cursor_for()
template <class T, class U>
void wrap_cursor_class(module_builder & module,
class_builder<T, U> & wrapped_container)
{
std::string cursor_name(wrapped_container.get_extension_class()->tp_name);
cursor_name += "_cursor";
class_builder<cursor<T> > cursor_class(module, cursor_name.c_str());
cursor_class.def(&cursor<T>::get_item, "__getitem__");
cursor_class.def(&cursor<T>::set_item, "__setitem__");
cursor_class.def(&cursor<T>::len, "__len__");
wrapped_container.def(&extension_class_cursor_factory<T>::get, "cursor");
}
} // namespace detail
// global functions declared within the body of a class template will only be
// generated when the class template is constructed, and when (for some reason)
// the construction does not occur via a new-expression. Otherwise, we could

View File

@@ -319,6 +319,98 @@ class read_only_setattr_function : public function
string m_name;
};
/* helper class to wrap STL conforming iterators.
Given a wrapped container ("FooList", say), this template is used to create
an auxiliary class "FooList_cursor" that wraps the container's iterator.
The cursor can be used in Python loops likes this:
>>> for i in foo_list.cursor():
... print i.get_data()
The auxiliary cursor class can be created for any STL conforming
container. It implements random access functions (get_item() and
set_item()) for any iterator, but these will only be as efficient as the
underlying iterator allows. However, this is not a problem because
the above Python loop accesses the items in forward order anyway.
*/
template <class Container>
struct cursor
{
typedef typename Container::iterator iterator;
typedef typename Container::value_type value_type;
cursor(Container & c, ref python_object)
: m_python_object(python_object),
m_begin(c.begin()),
m_iter(c.begin()),
m_size(c.size()),
m_index(0)
{}
void advance(int index, std::forward_iterator_tag)
{
if(index < 0 || index >= m_size)
{
PyErr_SetObject(PyExc_KeyError, BOOST_PYTHON_CONVERSION::to_python(index));
throw python::error_already_set();
}
int delta = index - m_index;
if(delta < 0)
{
m_iter = m_begin;
delta = index;
}
std::advance(m_iter, delta);
m_index = index;
}
void advance(int index, std::bidirectional_iterator_tag)
{
if(index < 0 || index >= m_size)
{
PyErr_SetObject(PyExc_KeyError, BOOST_PYTHON_CONVERSION::to_python(index));
throw python::error_already_set();
}
int delta = index - m_index;
std::advance(m_iter, delta);
m_index = index;
}
value_type const & get_item(int index)
{
advance(index, std::iterator_category(m_iter));
return *m_iter;
}
void set_item(int index, value_type const & v)
{
advance(index, std::iterator_category(m_iter));
*m_iter = v;
}
int len() const
{ return m_size; }
ref m_python_object;
iterator m_begin, m_iter;
int m_index, m_size;
};
/* create a cursor for an STL conforming container */
template <class T>
struct extension_class_cursor_factory
{
static cursor<T> get(ref container)
{
return cursor<T>(
BOOST_PYTHON_CONVERSION::from_python(container.get(), type<T&>()),
container);
}
};
template <class From, class To>
struct define_conversion
{

View File

@@ -16,6 +16,17 @@
namespace boost { namespace python {
class module_builder;
template <class T, class U> class class_builder;
namespace detail {
template <class T, class U>
void wrap_cursor_class(module_builder & module,
class_builder<T, U> & wrapped_container);
} // namspace detail
class module_builder
{
public:
@@ -39,6 +50,15 @@ class module_builder
{
add(detail::new_wrapped_function(fn), name);
}
// wrapped_container must wrap an STL conforming container;
// this function creates a cursor that wraps this container's iterator
// and adds the factory function "cursor()" to the wrapped container
template <class T, class U>
void def_cursor_for(class_builder<T, U> & wrapped_container)
{
detail::wrap_cursor_class(*this, wrapped_container);
}
// Return true iff a module is currently being built.
static bool initializing();