mirror of
https://github.com/boostorg/python.git
synced 2026-01-30 20:12:37 +00:00
Initial revision
[SVN r1471]
This commit is contained in:
21
include/boost/python/suite/indexing/CONTENTS
Executable file
21
include/boost/python/suite/indexing/CONTENTS
Executable file
@@ -0,0 +1,21 @@
|
||||
|
||||
container_proxy.hpp Container wrapper with semi-transparent proxies
|
||||
shared_proxy_impl.hpp Component shared by proxies that refer to same element
|
||||
testcontprox.cpp Simple tests for container_proxy
|
||||
testindexing.py Test various instantiations of the indexing_suite
|
||||
indexing.cpp Python extensions required for testindexing.py
|
||||
vis.hpp.patch Simple vector_indexing_suite.hpp patch for indexing.cpp
|
||||
sample.out Sample output of testindexing.py
|
||||
vector_indexing_suite_ext.cpp Modified extension module from python/test
|
||||
vector_indexing_suite.py Python test script from python/test (unmodified)
|
||||
|
||||
|
||||
older stuff
|
||||
===========
|
||||
|
||||
container_suite.hpp Container traits
|
||||
iterator_suite.hpp Traits for iterator ranges
|
||||
suite_utils.hpp Traits utilities
|
||||
indexing_suite.cpp Traits tests
|
||||
containers.txt Analysis of Python sequence vs. C++ containers
|
||||
testlist.py Test behaviour of real Python lists
|
||||
576
include/boost/python/suite/indexing/container_proxy.hpp
Executable file
576
include/boost/python/suite/indexing/container_proxy.hpp
Executable file
@@ -0,0 +1,576 @@
|
||||
// -*- mode:c++; switch-modules-target: "testcontprox.cpp" -*-
|
||||
//
|
||||
// Header file container_proxy.hpp
|
||||
//
|
||||
// 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/ 8/26 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef container_proxy_rmg_20030826_included
|
||||
#define container_proxy_rmg_20030826_included
|
||||
|
||||
#include "shared_proxy_impl.hpp"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
template<typename T> struct identity {
|
||||
static T & get(T & obj) { return obj; }
|
||||
static T const & get(T const & obj) { return obj; }
|
||||
};
|
||||
|
||||
template<typename T> struct deref {
|
||||
template<typename U> static T & get (U & ptr) { return *ptr; }
|
||||
template<typename U> static T const & get (U const & ptr) { return *ptr; }
|
||||
};
|
||||
|
||||
template<class Container
|
||||
, typename HeldType = Container
|
||||
, class Accessor = identity<Container> >
|
||||
class container_proxy
|
||||
{
|
||||
typedef container_proxy<Container, HeldType, Accessor> self_type;
|
||||
typedef typename Container::iterator raw_iterator;
|
||||
typedef std::iterator_traits<raw_iterator> raw_iterator_traits;
|
||||
|
||||
public:
|
||||
typedef typename Container::size_type size_type;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
|
||||
typedef shared_proxy_impl<self_type> shared_proxy;
|
||||
|
||||
typedef typename Container::value_type raw_value_type;
|
||||
|
||||
struct const_element_proxy;
|
||||
|
||||
class element_proxy
|
||||
{
|
||||
friend class const_element_proxy;
|
||||
|
||||
typedef shared_proxy proxy_type;
|
||||
typedef boost::shared_ptr<proxy_type> proxy_pointer;
|
||||
|
||||
proxy_pointer mPtr;
|
||||
|
||||
public:
|
||||
typedef typename proxy_type::value_type value_type;
|
||||
typedef typename proxy_type::reference reference;
|
||||
typedef typename proxy_type::pointer pointer;
|
||||
typedef typename proxy_type::iterator_category iterator_category;
|
||||
typedef typename proxy_type::difference_type difference_type;
|
||||
|
||||
typedef value_type element_type; // Alias for register_ptr_to_python
|
||||
|
||||
element_proxy () : mPtr () { }
|
||||
explicit element_proxy (proxy_type *ptr) : mPtr (ptr) { }
|
||||
element_proxy (proxy_pointer const &ptr) : mPtr (ptr) { }
|
||||
|
||||
explicit element_proxy (raw_value_type const &val)
|
||||
: mPtr (new proxy_type(val))
|
||||
{
|
||||
// Create new standalone value (i.e. detached)
|
||||
}
|
||||
|
||||
reference operator* () const { return mPtr->operator*(); }
|
||||
pointer operator-> () const { return (*mPtr).operator->(); }
|
||||
pointer get () const { return operator->(); } // Alias for pointer_holder
|
||||
|
||||
// Implicit conversion to raw_value_type
|
||||
operator reference () const { return operator*(); }
|
||||
|
||||
// These are necessary (at least) while the indexing suite insists
|
||||
// on converting the real container's value_type to the proxy
|
||||
// container's value_type when going from Python to C++. If the
|
||||
// suite would just pass the real container's value_type through,
|
||||
// our implicit conversion to value_type might suffice.
|
||||
bool operator== (value_type const &other) { return (**this) == other; }
|
||||
bool operator!= (value_type const &other) { return (**this) != other; }
|
||||
bool operator< (value_type const &other) { return (**this) < other; }
|
||||
bool operator> (value_type const &other) { return (**this) > other; }
|
||||
|
||||
element_proxy &operator= (value_type const ©)
|
||||
{
|
||||
proxy_type &proxy (*mPtr);
|
||||
container_proxy *container = proxy.owner();
|
||||
size_type index = proxy.index();
|
||||
|
||||
if (container)
|
||||
{
|
||||
container->replace (index, copy);
|
||||
// Proxy was attached before, but is now detached. Make sure
|
||||
// we now refer to the new element, instead of the detached
|
||||
// copy of the old element
|
||||
mPtr = container->at (index).mPtr;
|
||||
|
||||
// Note: in the special case that this we and the container
|
||||
// proxy itself have the only references to the
|
||||
// shared_proxy_impl, it is not necessary to first detach
|
||||
// the proxy. Maybe best to implement when changing to
|
||||
// intrusive_ptr instead of shared_ptr.
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
*proxy = copy;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
element_proxy &operator= (element_proxy const ©)
|
||||
{
|
||||
// This is the most dubious bit of the fudge. The indexing_suite's
|
||||
// implementation of __setitem__ tries to pass us our value_type,
|
||||
// which is actually of type element_proxy
|
||||
return (*this) = *copy;
|
||||
}
|
||||
|
||||
size_t use_count() const { return mPtr.use_count(); } // For debugging
|
||||
};
|
||||
|
||||
struct const_element_proxy
|
||||
{
|
||||
typedef shared_proxy proxy_type;
|
||||
typedef boost::shared_ptr<proxy_type> proxy_pointer;
|
||||
|
||||
proxy_pointer mPtr;
|
||||
|
||||
public:
|
||||
typedef typename proxy_type::value_type const value_type;
|
||||
typedef value_type &reference;
|
||||
typedef value_type *pointer;
|
||||
typedef typename proxy_type::iterator_category iterator_category;
|
||||
typedef typename proxy_type::difference_type difference_type;
|
||||
|
||||
const_element_proxy () : mPtr () { }
|
||||
explicit const_element_proxy (proxy_type *ptr) : mPtr (ptr) { }
|
||||
const_element_proxy (proxy_pointer const &ptr) : mPtr (ptr) { }
|
||||
const_element_proxy (element_proxy const ©) : mPtr (copy.mPtr) { }
|
||||
|
||||
explicit const_element_proxy (raw_value_type const &val)
|
||||
: mPtr (new proxy_type(val))
|
||||
{
|
||||
// Create new standalone value (i.e. detached)
|
||||
}
|
||||
|
||||
reference operator* () const { return mPtr->operator*(); }
|
||||
pointer operator-> () const { return mPtr->operator->(); }
|
||||
|
||||
// Implicit conversion to raw_value_type
|
||||
operator reference () const { return operator*(); }
|
||||
|
||||
size_t use_count() const { return mPtr.use_count(); } // For debugging
|
||||
};
|
||||
|
||||
typedef element_proxy value_type;
|
||||
typedef element_proxy reference; // Already has reference semantics
|
||||
typedef const_element_proxy const_value_type;
|
||||
|
||||
public:
|
||||
struct iterator
|
||||
{
|
||||
typedef typename raw_iterator_traits::difference_type difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef element_proxy value_type;
|
||||
typedef element_proxy *pointer;
|
||||
typedef element_proxy reference; // Already has reference semantics
|
||||
|
||||
iterator (container_proxy *p, size_type i) : ptr (p), index (i) { }
|
||||
|
||||
iterator (container_proxy *p, raw_iterator iter)
|
||||
: ptr (p), index (iter - p->container().begin())
|
||||
{
|
||||
}
|
||||
|
||||
reference operator*() const { return ptr->at(index); }
|
||||
pointer operator->() const { return &ptr->at(index); }
|
||||
reference operator[](size_type s) { return ptr->at (index + s); }
|
||||
|
||||
iterator &operator++ () { ++index; return *this; }
|
||||
iterator &operator++ (int) { ++index; return *this; }
|
||||
iterator &operator+= (size_type s) { index += s; return *this; }
|
||||
|
||||
iterator &operator-- () { --index; return *this; }
|
||||
iterator &operator-- (int) { --index; return *this; }
|
||||
iterator &operator-= (size_type s) { index -= s; return *this; }
|
||||
|
||||
iterator operator+ (size_type s) const { return iterator(*this) += s; }
|
||||
iterator operator- (size_type s) const { return iterator(*this) -= s; }
|
||||
difference_type operator- (iterator i) const { return index - i.index; }
|
||||
|
||||
bool operator== (iterator const &other) const {
|
||||
return (ptr == other.ptr) && (index == other.index);
|
||||
}
|
||||
|
||||
bool operator!= (iterator const &other) const { return !(*this == other); }
|
||||
|
||||
// public:
|
||||
// Extensions to the normal iterator interface
|
||||
// void replace (value_type const ©) { ptr->replace (index, copy); }
|
||||
|
||||
public:
|
||||
friend class container_proxy;
|
||||
container_proxy *ptr;
|
||||
size_type index;
|
||||
};
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
container_proxy ();
|
||||
explicit container_proxy (HeldType const &h);
|
||||
template<typename Iter> container_proxy (Iter, Iter);
|
||||
|
||||
Container & container(); // Should be private?
|
||||
Container const &container() const; // Should be private?
|
||||
|
||||
element_proxy at (size_type index);
|
||||
const_element_proxy at (size_type index) const;
|
||||
|
||||
element_proxy operator[] (size_type index) { return at(index); }
|
||||
const_element_proxy operator[] (size_type index) const { return at(index); }
|
||||
|
||||
size_type size() const { return container().size(); }
|
||||
size_type capacity() const { return container().capacity(); }
|
||||
void reserve(size_type s) { container().reserve(s); }
|
||||
|
||||
public:
|
||||
iterator begin() { return iterator (this, 0); }
|
||||
iterator end() { return iterator (this, container().size()); }
|
||||
|
||||
iterator erase (iterator);
|
||||
iterator erase (iterator, iterator);
|
||||
iterator insert (iterator, raw_value_type const &);
|
||||
template<typename Iter> void insert (iterator, Iter, Iter);
|
||||
|
||||
void push_back (raw_value_type const ©) { insert (end(), copy); }
|
||||
|
||||
element_proxy pop_back () {
|
||||
element_proxy result = at (end() - 1);
|
||||
erase (end() - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
// Proxies for a given index must be detached before overwriting
|
||||
// that container element.
|
||||
void detach_proxy (size_type index);
|
||||
void detach_proxies (size_type from, size_type to);
|
||||
void detach_proxies (iterator from, iterator to);
|
||||
|
||||
public:
|
||||
// Convenient replacement of elements (automatic proxy detachment)
|
||||
void replace (size_type index, raw_value_type const &);
|
||||
template<typename Iter> void replace (size_type index, Iter, Iter);
|
||||
|
||||
private:
|
||||
// Overloads for insertions with/without useful std::distance
|
||||
template<typename Iter>
|
||||
void insert (iterator, Iter, Iter, std::forward_iterator_tag);
|
||||
|
||||
template<typename Iter>
|
||||
void insert (iterator, Iter, Iter, std::input_iterator_tag);
|
||||
|
||||
private:
|
||||
typedef boost::shared_ptr<shared_proxy> pointer_impl;
|
||||
typedef std::map<size_type, pointer_impl> MapType;
|
||||
typedef typename MapType::iterator MapIterator;
|
||||
typedef typename MapType::value_type MapEntry;
|
||||
|
||||
private:
|
||||
static void detach_if_shared (MapEntry const &);
|
||||
void adjustIndexes (MapIterator, MapIterator, long);
|
||||
|
||||
private:
|
||||
HeldType myHeldType;
|
||||
MapType myMap;
|
||||
};
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::container_proxy ()
|
||||
: myHeldType ()
|
||||
, myMap ()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::container_proxy (HeldType const &heldType)
|
||||
: myHeldType (heldType)
|
||||
, myMap ()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
template<typename Iter>
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::container_proxy (Iter start, Iter finish)
|
||||
: myHeldType ()
|
||||
, myMap ()
|
||||
{
|
||||
insert (begin(), start, finish);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
Container &
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::container ()
|
||||
{
|
||||
return Accessor::get (myHeldType);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
Container const &
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::container () const
|
||||
{
|
||||
return Accessor::get (myHeldType);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::element_proxy
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::at (size_type index)
|
||||
{
|
||||
pointer_impl &entry = myMap[index];
|
||||
|
||||
if (!entry.get())
|
||||
{
|
||||
entry.reset (new shared_proxy (this, index));
|
||||
}
|
||||
|
||||
return element_proxy (entry);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::const_element_proxy
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::at (size_type index) const
|
||||
{
|
||||
// const_cast allows insertion into map. Maybe this is wrong, and
|
||||
// there can be no const-version of at. Alternatively, maybe
|
||||
// the map member variable should be declared mutable.
|
||||
|
||||
container_proxy *mutable_this = const_cast<container_proxy *>(this);
|
||||
|
||||
return const_element_proxy (mutable_this->at (index));
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::replace (size_type index, raw_value_type const ©)
|
||||
{
|
||||
detach_proxy (index);
|
||||
container().at(index) = copy;
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::replace (size_type index, Iter from, Iter to)
|
||||
{
|
||||
while (from != to)
|
||||
{
|
||||
replace (index++, *from++);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::iterator
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::erase (iterator iter)
|
||||
{
|
||||
return erase (iter, iter + 1);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::iterator
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::erase (iterator from, iterator to)
|
||||
{
|
||||
assert (from.ptr == this);
|
||||
assert (to.ptr == this);
|
||||
|
||||
size_type deleting = to.index - from.index;
|
||||
MapIterator erase_begin = myMap.lower_bound (from.index);
|
||||
MapIterator erase_end = myMap.lower_bound (to.index);
|
||||
|
||||
// Detach any proxies for the soon-to-be-erased elements
|
||||
std::for_each (erase_begin, erase_end, detach_if_shared);
|
||||
myMap.erase (erase_begin, erase_end); // Note: erase_end remains valid
|
||||
|
||||
// Adjust the indexes of any following proxies
|
||||
adjustIndexes (erase_end, myMap.end(), -deleting);
|
||||
|
||||
// Erase the elements from the real container
|
||||
raw_iterator result = container().erase (container().begin() + from.index
|
||||
, container().begin() + to.index);
|
||||
|
||||
return iterator (this, result);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::iterator
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::insert (iterator iter, raw_value_type const ©)
|
||||
{
|
||||
assert (iter.ptr == this);
|
||||
|
||||
// Adjust indexes from iter.index, since insert will go before iter
|
||||
adjustIndexes (myMap.lower_bound (iter.index), myMap.end(), 1);
|
||||
|
||||
// Insert the element into the real container
|
||||
raw_iterator result = container().insert (container().begin() + iter.index
|
||||
, copy);
|
||||
|
||||
return iterator (this, result);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::insert (iterator iter, Iter from, Iter to)
|
||||
{
|
||||
// Forward insertion to the right overloaded version
|
||||
typedef typename std::iterator_traits<Iter>::iterator_category category;
|
||||
insert (iter, from, to, category());
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::insert (iterator iter, Iter from, Iter to, std::forward_iterator_tag)
|
||||
{
|
||||
// insert overload for iterators where we can get distance()
|
||||
|
||||
assert (iter.ptr == this);
|
||||
|
||||
// Adjust indexes from iter.index, since insert will go before iter
|
||||
adjustIndexes (myMap.lower_bound (iter.index)
|
||||
, myMap.end()
|
||||
, std::distance (from, to));
|
||||
|
||||
// Insert the element into the real container
|
||||
container().insert (container().begin() + iter.index, from, to);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::insert (iterator iter, Iter from, Iter to, std::input_iterator_tag)
|
||||
{
|
||||
// insert overload for iterators where we *can't* get distance()
|
||||
// so just insert elements one at a time
|
||||
while (from != to)
|
||||
{
|
||||
iter = insert (iter, *from++) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::detach_if_shared (MapEntry const &ent)
|
||||
{
|
||||
if (!ent.second.unique())
|
||||
{
|
||||
ent.second->detach();
|
||||
}
|
||||
// If the pointer isn't shared, don't bother causing a copy of the
|
||||
// container element, since the proxy is about to be deleted.
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::detach_proxy (size_type index)
|
||||
{
|
||||
MapIterator iter = myMap.find (index);
|
||||
|
||||
if (iter != myMap.end())
|
||||
{
|
||||
detach_if_shared (*iter);
|
||||
myMap.erase (iter);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::detach_proxies (size_type fromIndex, size_type toIndex)
|
||||
{
|
||||
MapIterator from = myMap.lower_bound (fromIndex);
|
||||
MapIterator to = myMap.lower_bound (toIndex);
|
||||
std::for_each (from, to, detach_if_shared);
|
||||
myMap.erase (from, to);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::detach_proxies (iterator from, iterator to)
|
||||
{
|
||||
assert (from.ptr == this);
|
||||
assert (to.ptr == this);
|
||||
detach_proxies (from.index, to.index);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
void
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::adjustIndexes (MapIterator from, MapIterator to, long offset)
|
||||
{
|
||||
// Adjust indexes in the given range of proxies by the given offset.
|
||||
// The adjustment is done by erasing and re-inserting the entries
|
||||
// in the map.
|
||||
//
|
||||
// Could provide a hint iterator to the map insertion calls, except
|
||||
// in the case that "from" is right at the start of the container
|
||||
// (the hint must be the element *before* the one to be inserted,
|
||||
// and there is no element before the first one). This would mean
|
||||
// additional complexity to deal with the special case somehow.
|
||||
|
||||
while (from != to)
|
||||
{
|
||||
MapIterator next (from);
|
||||
++next; // Find next element before invalidating the current one
|
||||
|
||||
pointer_impl ptr (from->second); // Copy the shared pointer
|
||||
myMap.erase (from); // Remove the map copy of it
|
||||
|
||||
if (!ptr.unique())
|
||||
{
|
||||
// Reinsert only if there are other pointers "out there"
|
||||
// referring to the shared proxy
|
||||
|
||||
ptr->myIndex += offset;
|
||||
myMap.insert (typename MapType::value_type (ptr->myIndex, ptr));
|
||||
}
|
||||
|
||||
from = next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // container_proxy_rmg_20030826_included
|
||||
349
include/boost/python/suite/indexing/container_suite.hpp
Executable file
349
include/boost/python/suite/indexing/container_suite.hpp
Executable file
@@ -0,0 +1,349 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file container_suite.hpp
|
||||
//
|
||||
// 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/ 8/23 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef container_suite_rmg_20030823_included
|
||||
#define container_suite_rmg_20030823_included
|
||||
|
||||
#include "suite_utils.hpp"
|
||||
#include "iterator_suite.hpp"
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
namespace indexing {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Iterator pair container emulation
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Iterator>
|
||||
class iterator_pair
|
||||
{
|
||||
private:
|
||||
typedef typename boost::call_traits<Iterator>::param_type iterator_param;
|
||||
typedef std::iterator_traits<Iterator> std_traits;
|
||||
|
||||
public:
|
||||
typedef typename std_traits::reference reference;
|
||||
typedef Iterator iterator;
|
||||
typedef typename std_traits::difference_type size_type;
|
||||
typedef typename std_traits::difference_type difference_type;
|
||||
typedef typename std_traits::value_type value_type;
|
||||
typedef typename std_traits::pointer pointer;
|
||||
|
||||
// Can't provide: const_iterator, allocator_type, reverse_iterator
|
||||
// or const_reverse_iterator. Could probably provide (but don't)
|
||||
// const_reference and const_pointer. These would be the same
|
||||
// as reference and pointer if Iterator is itself a const_iterator.
|
||||
|
||||
public:
|
||||
iterator_pair (iterator_param, iterator_param);
|
||||
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
|
||||
public:
|
||||
// Only sensible for random_access iterators
|
||||
size_type size () const;
|
||||
reference operator[] (size_type) const;
|
||||
|
||||
private:
|
||||
iterator myBegin;
|
||||
iterator myEnd;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
iterator_pair<Iterator>::iterator_pair (iterator_param begin
|
||||
, iterator_param end)
|
||||
: myBegin (begin)
|
||||
, myEnd (end)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
typename iterator_pair<Iterator>::iterator
|
||||
iterator_pair<Iterator>::begin() const
|
||||
{
|
||||
return myBegin;
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
typename iterator_pair<Iterator>::iterator
|
||||
iterator_pair<Iterator>::end() const
|
||||
{
|
||||
return myEnd;
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
typename iterator_pair<Iterator>::size_type
|
||||
iterator_pair<Iterator>::size() const
|
||||
{
|
||||
return std::distance (begin(), end());
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
typename iterator_pair<Iterator>::reference
|
||||
iterator_pair<Iterator>::operator[](size_type index) const
|
||||
{
|
||||
return *(begin() + index);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Container traits
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Traits for the iterator_pair container emulator
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename IteratorPair>
|
||||
struct iterator_pair_traits
|
||||
: public
|
||||
iterator_detail::traits_by_category<typename IteratorPair::iterator>::type
|
||||
{
|
||||
typedef IteratorPair container;
|
||||
typedef typename IteratorPair::size_type size_type;
|
||||
typedef typename IteratorPair::size_type index_type; // at()
|
||||
|
||||
static bool const has_insert = false;
|
||||
static bool const has_erase = false;
|
||||
static bool const has_pop_back = false;
|
||||
static bool const has_push_back = false;
|
||||
|
||||
// Default implementations of support functions
|
||||
typedef container_algorithms<iterator_pair_traits> algorithms;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Lowest common denominator (almost all "real" containers would
|
||||
// meet at least these requirements)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct default_container_traits
|
||||
{
|
||||
protected:
|
||||
static bool const is_mutable = ! boost::is_const<Container>::value;
|
||||
|
||||
public:
|
||||
typedef Container container;
|
||||
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::reference reference;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
typedef typename Container::size_type size_type;
|
||||
typedef typename Container::size_type index_type; // at()
|
||||
typedef value_type key_type; // find, count, ...
|
||||
|
||||
// Should probably select iterator or const_iterator on the
|
||||
// basis of is_mutable
|
||||
typedef typename Container::iterator iterator;
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
|
||||
static bool const has_copyable_iter = true;
|
||||
|
||||
static bool const has_random_access
|
||||
= ::indexing::iterator_traits<iterator>::has_random_access;
|
||||
|
||||
static bool const has_mutable_ref
|
||||
= is_mutable && is_mutable_ref<reference>::value;
|
||||
|
||||
// has_mutable_ref basically means that the container supports
|
||||
// in-place replacement of values (e.g. the associative containers
|
||||
// *don't*)
|
||||
|
||||
static bool const is_reversible = has_mutable_ref;
|
||||
|
||||
static bool const has_insert = is_mutable;
|
||||
static bool const has_erase = is_mutable;
|
||||
static bool const has_pop_back = false;
|
||||
static bool const has_push_back = false;
|
||||
|
||||
// Default implementations of support functions
|
||||
typedef container_algorithms<default_container_traits> algorithms;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sequences (list, deque, vector)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct default_sequence_traits : public default_container_traits<Container>
|
||||
{
|
||||
static bool const has_pop_back = is_mutable;
|
||||
static bool const has_push_back = is_mutable;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct list_traits : public default_sequence_traits<Container>
|
||||
{
|
||||
// Some special algo's for list (using member functions)
|
||||
typedef list_algorithms<list_traits> algorithms;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Associative containers set and multiset
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct set_traits : public default_container_traits<Container>
|
||||
{
|
||||
// Special algo's for set types (using member functions)
|
||||
typedef assoc_algorithms<set_traits> algorithms;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Associative containers map and multimap
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct map_traits : public default_container_traits<Container>
|
||||
{
|
||||
typedef typename Container::key_type key_type; // find, count, ...
|
||||
|
||||
// Special algo's for map types (using member functions)
|
||||
typedef assoc_algorithms<map_traits> algorithms;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Automated trait selection
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace container_details {
|
||||
template<typename Container> struct traits_by_type;
|
||||
|
||||
// traits_by_type instances should include two typedefs, one for
|
||||
// the non-const version of the container, and one for the
|
||||
// const version. This saves having to have two specializations
|
||||
// of traits_by_type for every kind of container.
|
||||
|
||||
// std::set
|
||||
template <class Key, class Compare, class Allocator>
|
||||
class traits_by_type<std::set<Key, Compare, Allocator> >
|
||||
{
|
||||
typedef std::set<Key, Compare, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef set_traits<Container> mutable_type;
|
||||
typedef set_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// std::multiset
|
||||
template <class Key, class Compare, class Allocator>
|
||||
class traits_by_type<std::multiset<Key, Compare, Allocator> >
|
||||
{
|
||||
typedef std::multiset<Key, Compare, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef set_traits<Container> mutable_type;
|
||||
typedef set_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// std::map
|
||||
template <class Key, class T, class Compare, class Allocator>
|
||||
class traits_by_type<std::map<Key, T, Compare, Allocator> >
|
||||
{
|
||||
typedef std::map<Key, T, Compare, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef map_traits<Container> mutable_type;
|
||||
typedef map_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// std::multimap
|
||||
template <class Key, class T, class Compare, class Allocator>
|
||||
class traits_by_type<std::multimap<Key, T, Compare, Allocator> >
|
||||
{
|
||||
typedef std::multimap<Key, T, Compare, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef map_traits<Container> mutable_type;
|
||||
typedef map_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// std::vector
|
||||
template <class T, class Allocator>
|
||||
class traits_by_type<std::vector<T, Allocator> >
|
||||
{
|
||||
typedef std::vector<T, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef default_sequence_traits<Container> mutable_type;
|
||||
typedef default_sequence_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// std::deque
|
||||
template <class T, class Allocator>
|
||||
class traits_by_type<std::deque<T, Allocator> >
|
||||
{
|
||||
typedef std::deque<T, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef default_sequence_traits<Container> mutable_type;
|
||||
typedef default_sequence_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// std::list
|
||||
template <class T, class Allocator>
|
||||
class traits_by_type<std::list<T, Allocator> >
|
||||
{
|
||||
typedef std::list<T, Allocator> Container;
|
||||
|
||||
public:
|
||||
typedef list_traits<Container> mutable_type;
|
||||
typedef list_traits<Container const> const_type;
|
||||
};
|
||||
|
||||
// Iterator ranges
|
||||
template <typename Iterator>
|
||||
class traits_by_type<indexing::iterator_pair<Iterator> >
|
||||
{
|
||||
typedef ::indexing::iterator_pair<Iterator> Container;
|
||||
|
||||
public:
|
||||
typedef iterator_pair_traits<Container> mutable_type;
|
||||
typedef iterator_pair_traits<Container const> const_type; // ?
|
||||
};
|
||||
}
|
||||
|
||||
// Select the right traits for each supported kind of container
|
||||
|
||||
// Generic version (mutable containers)
|
||||
template<class Container>
|
||||
struct container_traits
|
||||
: public container_details::traits_by_type<Container>::mutable_type
|
||||
{
|
||||
};
|
||||
|
||||
// Partial specialization for const containers
|
||||
template<class Container>
|
||||
struct container_traits<Container const>
|
||||
: public container_details::traits_by_type<Container>::const_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif // container_suite_rmg_20030823_included
|
||||
129
include/boost/python/suite/indexing/containers.txt
Executable file
129
include/boost/python/suite/indexing/containers.txt
Executable file
@@ -0,0 +1,129 @@
|
||||
|
||||
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 for any purpose is granted, provided the above notices are
|
||||
retained, and a notice that the material was modified is included with
|
||||
the above copyright notice.
|
||||
|
||||
$Id$
|
||||
|
||||
==============================================================================
|
||||
|
||||
This file contains information and comments about mapping Python
|
||||
sequence functionality onto STL containers or iterator pairs. Primary
|
||||
sources of information are the Python Library Reference, sections
|
||||
2.2.6 (Sequence types) and 2.2.6.4 (Mutable sequence types), the
|
||||
Python Reference Manual (aka Language Reference) sections 3.3 (Special
|
||||
method names), 3.3.4 (Emulating container types) and 3.3.6 (Eumlating
|
||||
numeric types) and the C++ standard (ISO/IEC 14882:1998(E)).
|
||||
|
||||
==============================================================================
|
||||
|
||||
Sequence functionality - Python expressions, the Python method used to
|
||||
implement the operation (in order of preference) and possible C++
|
||||
equivalents.
|
||||
|
||||
Python feature Implementation (preferential order) Possible C++ emulation
|
||||
============== =================================== ======================
|
||||
|
||||
x in s __contains__, __iter__, __getitem__ find algo/member fn
|
||||
x not in s __contains__, __iter__, __getitem__ find algo/member fn
|
||||
s + t __add__ or __radd__ constr., insert [1]
|
||||
s * n , n * s __mul__ or __rmul__ constr., insert [1]
|
||||
s[i] __getitem__ [] or *(iter + i)
|
||||
s[i:j] __getslice__ [3], __getitem__ constr(iter,iter)[2]
|
||||
len(s) __len__ distance/size memfn
|
||||
iter(s) __iter__ constr. iter pair
|
||||
min(s) __iter__, __getitem__ (?)
|
||||
max(s) __iter__, __getitem__ (?)
|
||||
|
||||
[1] have to construct new container (make vector from iterator pairs?)
|
||||
[2] construct copy of container contents or return iterator pair?
|
||||
[3] __getslice__, __setslice__ and __delslice__ are deprecated
|
||||
|
||||
|
||||
Mutable sequence functionality:
|
||||
|
||||
Python feature Implementation (preferential order) Possible C++ emulation
|
||||
============== =================================== ======================
|
||||
|
||||
s[i] = x __setitem__ s[i]=x or *(iter+i)=x
|
||||
s[i:j] = t __setslice__ [3], __setitem__ operator=,insert,erase
|
||||
del s[i:j] __delslice__ [3], __delitem__ erase
|
||||
del s[i] __delitem__ erase
|
||||
s += t __iadd__ insert(iter,iter)
|
||||
s *= t __imul__ insert(iter,iter)
|
||||
s.append(x) append insert(obj)
|
||||
s.extend(x) extend [ python list type only ] insert(iter,iter)
|
||||
s.count(x) count count algo/mem fn
|
||||
s.index(x) index find algo/mem fn
|
||||
s.insert(i, x) insert insert
|
||||
s.pop([i]) pop pop_back/erase?
|
||||
s.remove(x) remove remove_if and erase?
|
||||
s.reverse() reverse reverse
|
||||
s.sort([cmpfunc]) sort sort algo?
|
||||
|
||||
[3] __getslice__, __setslice__ and __delslice__ are deprecated
|
||||
|
||||
==============================================================================
|
||||
|
||||
Cross-reference. C++ functions for the various types of iterator-pair
|
||||
ranges and the python methods that they can implement.
|
||||
|
||||
C++ functions Minimum iterator type Python function(s)
|
||||
============= ===================== ==================
|
||||
|
||||
++, * input_iterator[4] next
|
||||
copyable iterator forward_iterator[5] __iter__
|
||||
std::distance forward_iterator[5] __len__
|
||||
std::find forward_iterator[5] __contains__, index
|
||||
std::count forward_iterator[5] count
|
||||
std::reverse bidirectional_iter[6] reverse
|
||||
+, * random_access_iter[4] __getitem__ [7]
|
||||
+, non-const * random_access_iter[6] __setitem__(index)[8]
|
||||
std::sort random_access_iter[6] sort([cmpfunc])
|
||||
|
||||
[4] iterator_traits<iterator>::reference can be reference to const
|
||||
[5] input_iterator is unsuitable because copies aren't independant
|
||||
[6] iterator_traits<iterator>::reference must not be reference to const
|
||||
[7] maybe return an iterator pair if step is 1 or -1 (reverse_iterator)
|
||||
[8] support slices where replacement sequence is of equal length?
|
||||
|
||||
Continued cross-reference. C++ functions for the various types of STL
|
||||
containers and the python methods that they can implement.
|
||||
|
||||
C++ functions Minimum container type Python function(s)
|
||||
============= ====================== ==================
|
||||
|
||||
insert any insert
|
||||
member function size any(?) __len__
|
||||
nonconst [] any except list __setitem__(index/key)
|
||||
pop_back non-associative pop()
|
||||
push_back non-associative append, __iadd__, __imul__
|
||||
std::find, erase non-associative remove(value)
|
||||
member function find associative __contains__
|
||||
find, erase associative pop(key)
|
||||
erase associative remove, __delitem__(key)
|
||||
nonconst [], insert, erase vector, deque __setitem__(slice)
|
||||
erase vector, deque pop(index), __delitem__
|
||||
insert multimap, multiset __iadd__, __imul__
|
||||
member function sort list sort
|
||||
member function reverse list reverse
|
||||
|
||||
=============================================================================
|
||||
|
||||
random notes
|
||||
============
|
||||
|
||||
What about __lt__, __le__, __ne__, __eq__, __ge__ and __gt__ ?
|
||||
|
||||
What about debugging? Maybe the traits classes need to identify
|
||||
themselves, so that traits-clients could trace information about what
|
||||
traits were used. Otherwise, if expected features aren't available,
|
||||
how would the programmer figure out why not?
|
||||
222
include/boost/python/suite/indexing/indexing.cpp
Executable file
222
include/boost/python/suite/indexing/indexing.cpp
Executable file
@@ -0,0 +1,222 @@
|
||||
// -*- mode:c++; switch-modules-target: "testindexing.py" -*-
|
||||
//
|
||||
// Module indexing.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 software for any non-commercial purpose
|
||||
// is hereby granted without fee, provided the above notices are retained
|
||||
// on all copies. Permission to modify the code and to distribute
|
||||
// modified code for non-commercial purposes is granted, provided the
|
||||
// above notices are retained, and a notice that the code was modified is
|
||||
// included with the above copyright notice.
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 8/18 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#include "container_proxy.hpp"
|
||||
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include <boost/python/suite/indexing/indexing_suite.hpp>
|
||||
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
bool gIntWrapperTrace = true;
|
||||
}
|
||||
|
||||
struct IntWrapper {
|
||||
static unsigned ourObjectCounter;
|
||||
int mObjNumber;
|
||||
int mI;
|
||||
|
||||
IntWrapper ()
|
||||
: mObjNumber (ourObjectCounter++)
|
||||
, mI (0)
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("IntWrapper %u ()\n", mObjNumber);
|
||||
}
|
||||
}
|
||||
|
||||
explicit IntWrapper (int i)
|
||||
: mObjNumber (ourObjectCounter++)
|
||||
, mI (i)
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("IntWrapper %u (%d)\n"
|
||||
, mObjNumber
|
||||
, mI);
|
||||
}
|
||||
}
|
||||
|
||||
IntWrapper (IntWrapper const &other)
|
||||
: mObjNumber (ourObjectCounter++)
|
||||
, mI (other.mI)
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("IntWrapper %u (IntWrapper %u)\n"
|
||||
, mObjNumber
|
||||
, other.mObjNumber);
|
||||
}
|
||||
}
|
||||
|
||||
IntWrapper &operator= (IntWrapper const &other)
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("IntWrapper %u = IntWrapper %u\n"
|
||||
, mObjNumber
|
||||
, other.mObjNumber);
|
||||
}
|
||||
|
||||
mI = other.mI;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~IntWrapper ()
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("~IntWrapper %u\n", mObjNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("IntWrapper %u::increment\n", mObjNumber);
|
||||
}
|
||||
|
||||
++mI;
|
||||
}
|
||||
|
||||
operator boost::shared_ptr<IntWrapper> () const
|
||||
{
|
||||
if (gIntWrapperTrace)
|
||||
{
|
||||
printf ("IntWrapper %u shared_ptr conversion\n", mObjNumber);
|
||||
}
|
||||
|
||||
return boost::shared_ptr<IntWrapper> (new IntWrapper (*this));
|
||||
}
|
||||
};
|
||||
|
||||
unsigned IntWrapper::ourObjectCounter = 0;
|
||||
|
||||
bool operator== (IntWrapper const &lhs, IntWrapper const &rhs)
|
||||
{
|
||||
return lhs.mI == rhs.mI;
|
||||
}
|
||||
|
||||
bool operator< (IntWrapper const &lhs, IntWrapper const &rhs)
|
||||
{
|
||||
return lhs.mI < rhs.mI;
|
||||
}
|
||||
|
||||
std::ostream &operator<< (std::ostream &strm, IntWrapper const &iw)
|
||||
{
|
||||
strm << iw.mI;
|
||||
return strm;
|
||||
}
|
||||
|
||||
template<typename ContainerProxy>
|
||||
std::string proxy_repr (typename ContainerProxy::value_type const &proxy)
|
||||
{
|
||||
return boost::lexical_cast<std::string, IntWrapper> (*proxy);
|
||||
}
|
||||
|
||||
template<typename ContainerProxy>
|
||||
void proxy_increment (typename ContainerProxy::value_type const &proxy)
|
||||
{
|
||||
(*proxy).increment();
|
||||
}
|
||||
|
||||
std::string pointer_repr (boost::shared_ptr<IntWrapper> const &ptr)
|
||||
{
|
||||
return boost::lexical_cast<std::string, IntWrapper> (*ptr);
|
||||
}
|
||||
|
||||
void pointer_increment (boost::shared_ptr<IntWrapper> const &ptr)
|
||||
{
|
||||
(*ptr).increment();
|
||||
}
|
||||
|
||||
void setTrace (int onoff)
|
||||
{
|
||||
gIntWrapperTrace = onoff;
|
||||
}
|
||||
|
||||
IntWrapper *get_pointer (container_proxy<std::vector<IntWrapper> >::value_type const &proxy)
|
||||
{
|
||||
return &(*proxy);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE (indexing)
|
||||
{
|
||||
boost::python::def ("trace", &setTrace);
|
||||
|
||||
typedef std::vector<IntWrapper> Container;
|
||||
typedef container_proxy<Container> ProxyContainer;
|
||||
typedef boost::shared_ptr<IntWrapper> Pointer;
|
||||
typedef std::vector<Pointer> PointerContainer;
|
||||
|
||||
using boost::python::vector_indexing_suite;
|
||||
|
||||
// typedef vector_indexing_suite<Container, true> Suite;
|
||||
typedef vector_indexing_suite<Container, false> ProxySuite;
|
||||
typedef vector_indexing_suite<ProxyContainer, true> ProxyContainerSuite;
|
||||
typedef vector_indexing_suite<PointerContainer, true> PointerContainerSuite;
|
||||
|
||||
boost::python::class_<Container> ("Vector")
|
||||
.def (ProxySuite())
|
||||
.def ("reserve", &Container::reserve);
|
||||
|
||||
boost::python::class_<ProxyContainer> ("ProxyVector")
|
||||
.def (ProxyContainerSuite())
|
||||
.def ("reserve", &ProxyContainer::reserve);
|
||||
|
||||
boost::python::class_<PointerContainer> ("PointerVector")
|
||||
.def (PointerContainerSuite())
|
||||
.def ("reserve", &PointerContainer::reserve);
|
||||
|
||||
boost::python::implicitly_convertible <IntWrapper, ProxyContainer::value_type>();
|
||||
|
||||
boost::python::class_<IntWrapper> ("IntWrapper", boost::python::init<int>())
|
||||
.def ("increment", &IntWrapper::increment)
|
||||
.def ("__repr__", &boost::lexical_cast<std::string, IntWrapper>)
|
||||
;
|
||||
|
||||
// Ultimately, all of the value_type's properties should be provided
|
||||
// via something like register_ptr_to_python with double-dereferencing.
|
||||
// boost::python::class_<ProxyContainer::value_type> ("Container__value_type", boost::python::init<IntWrapper>())
|
||||
// .def ("increment", proxy_increment<ProxyContainer>)
|
||||
// .def ("__repr__", proxy_repr<ProxyContainer>)
|
||||
// ;
|
||||
boost::python::register_ptr_to_python<ProxyContainer::value_type>();
|
||||
|
||||
boost::python::implicitly_convertible <IntWrapper, Pointer>();
|
||||
|
||||
boost::python::class_<Pointer> ("Pointer", boost::python::no_init)
|
||||
.def ("increment", pointer_increment)
|
||||
.def ("__repr__", pointer_repr)
|
||||
;
|
||||
}
|
||||
165
include/boost/python/suite/indexing/indexing_suite.cpp
Executable file
165
include/boost/python/suite/indexing/indexing_suite.cpp
Executable file
@@ -0,0 +1,165 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Module indexing_suite.cc
|
||||
//
|
||||
// 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/ 8/22 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#include "container_suite.hpp"
|
||||
#include "iterator_suite.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <typeinfo>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <cxxabi.h>
|
||||
static int DEMANGLE_STATUS = 0;
|
||||
# define TYPENAME(t) \
|
||||
abi::__cxa_demangle(typeid(t).name(), 0, 0, &DEMANGLE_STATUS)
|
||||
#else
|
||||
# define TYPENAME(t) \
|
||||
typeid(t).name()
|
||||
#endif // __GXX__
|
||||
|
||||
template<typename Traits>
|
||||
void test ()
|
||||
{
|
||||
std::cout
|
||||
<< TYPENAME(Traits)
|
||||
<< "\n"
|
||||
|
||||
<< Traits::has_copyable_iter
|
||||
<< " iterator_traits<T>::has_copyable_iter\n"
|
||||
|
||||
<< Traits::is_reversible
|
||||
<< " iterator_traits<T>::is_reversible\n"
|
||||
|
||||
<< Traits::has_random_access
|
||||
<< " iterator_traits<T>::has_random_access\n"
|
||||
|
||||
<< Traits::has_mutable_ref
|
||||
<< " iterator_traits<T>::has_mutable_ref\n"
|
||||
|
||||
<< Traits::has_insert
|
||||
<< " iterator_traits<T>::has_insert\n"
|
||||
|
||||
<< Traits::has_erase
|
||||
<< " iterator_traits<T>::has_erase\n"
|
||||
|
||||
<< Traits::has_pop_back
|
||||
<< " iterator_traits<T>::has_pop_back\n"
|
||||
|
||||
<< Traits::has_push_back
|
||||
<< " iterator_traits<T>::has_push_back\n"
|
||||
|
||||
<< "=====================================\n"
|
||||
;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
using indexing::iterator_traits;
|
||||
using indexing::container_traits;
|
||||
using indexing::iterator_pair;
|
||||
|
||||
test<container_traits <iterator_pair<std::istream_iterator<int> > > >();
|
||||
test<container_traits <iterator_pair<std::set<int>::const_iterator> > >();
|
||||
test<container_traits <iterator_pair<std::set<int>::iterator> > >();
|
||||
test<container_traits <iterator_pair<std::list<int>::const_iterator> > >();
|
||||
test<container_traits <iterator_pair<std::list<int>::iterator> > >();
|
||||
test<container_traits <iterator_pair<std::deque<int>::const_iterator> > >();
|
||||
test<container_traits <iterator_pair<std::deque<int>::iterator> > >();
|
||||
test<container_traits <iterator_pair<std::vector<int>::const_iterator> > >();
|
||||
test<container_traits <iterator_pair<std::vector<int>::iterator> > >();
|
||||
test<container_traits <iterator_pair<int const *> > >();
|
||||
test<container_traits <iterator_pair<int *> > >();
|
||||
|
||||
test<container_traits <std::list<int> > >();
|
||||
test<container_traits <std::list<int> const> >();
|
||||
test<container_traits <std::deque<int> > >();
|
||||
test<container_traits <std::deque<int> const> >();
|
||||
test<container_traits <std::vector<int> > >();
|
||||
test<container_traits <std::vector<int> const> >();
|
||||
test<container_traits <std::set<int> > >();
|
||||
test<container_traits <std::set<int> const> >();
|
||||
|
||||
typedef iterator_pair<int *> Range;
|
||||
int array[16] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
Range range (array, array + 16);
|
||||
|
||||
container_traits<Range>::algorithms::reverse (range);
|
||||
|
||||
std::cout
|
||||
<< *container_traits<Range>::algorithms::at (range, 0) << " "
|
||||
<< *container_traits<Range>::algorithms::at (range, 1) << " "
|
||||
<< *container_traits<Range>::algorithms::at (range, 2) << " "
|
||||
<< "\n";
|
||||
|
||||
container_traits<Range>::algorithms::sort (range);
|
||||
|
||||
std::cout
|
||||
<< *container_traits<Range>::algorithms::at (range, 3) << " "
|
||||
<< *container_traits<Range>::algorithms::at (range, 4) << " "
|
||||
<< *container_traits<Range>::algorithms::at (range, 5) << " "
|
||||
<< "\n";
|
||||
|
||||
std::cout
|
||||
<< container_traits<Range>::algorithms::size (range)
|
||||
<< "\n"
|
||||
<< container_traits<Range>::algorithms::find (range, 8) - array
|
||||
<< "\n"
|
||||
<< container_traits<Range>::algorithms::count (range, 0)
|
||||
<< "\n"
|
||||
;
|
||||
|
||||
typedef std::list<int> List;
|
||||
List l (array, array + 16);
|
||||
|
||||
container_traits<List>::algorithms::reverse (l);
|
||||
std::copy (l.begin(), l.end(), std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << "\n";
|
||||
|
||||
container_traits<List>::algorithms::sort (l);
|
||||
std::copy (l.begin(), l.end(), std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << "\n";
|
||||
|
||||
typedef std::set<int> Set;
|
||||
Set s (l.begin(), l.end());
|
||||
std::cout
|
||||
<< container_traits<Set>::algorithms::count (s, 0)
|
||||
<< "\n"
|
||||
<< *container_traits<Set>::algorithms::find (s, 8)
|
||||
<< "\n"
|
||||
;
|
||||
|
||||
typedef std::multiset<int> Multiset;
|
||||
Multiset multi_s (l.begin(), l.end());
|
||||
std::cout
|
||||
<< container_traits<Multiset>::algorithms::count (multi_s, 0)
|
||||
<< "\n"
|
||||
<< *container_traits<Multiset>::algorithms::find (multi_s, 8)
|
||||
<< "\n"
|
||||
;
|
||||
}
|
||||
143
include/boost/python/suite/indexing/iterator_suite.hpp
Executable file
143
include/boost/python/suite/indexing/iterator_suite.hpp
Executable file
@@ -0,0 +1,143 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file iterator_suite.hpp
|
||||
//
|
||||
// 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/ 8/23 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef iterator_suite_rmg_20030823_included
|
||||
#define iterator_suite_rmg_20030823_included
|
||||
|
||||
#include "suite_utils.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
namespace indexing {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Indexing traits for containers based on iterator pairs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Iterator>
|
||||
struct input_iterator_traits
|
||||
{
|
||||
private:
|
||||
typedef std::iterator_traits<Iterator> std_traits;
|
||||
|
||||
public:
|
||||
typedef Iterator iterator;
|
||||
typedef typename std_traits::value_type value_type;
|
||||
typedef typename std_traits::reference reference;
|
||||
typedef typename std_traits::difference_type difference_type;
|
||||
typedef typename std_traits::difference_type index_type;
|
||||
typedef value_type key_type; // find, count, ...
|
||||
|
||||
static bool const has_copyable_iter = false;
|
||||
static bool const is_reversible = false;
|
||||
static bool const has_random_access = false;
|
||||
static bool const has_mutable_ref = is_mutable_ref<reference>::value;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct forward_iterator_traits
|
||||
: public input_iterator_traits<Iterator>
|
||||
{
|
||||
static bool const has_copyable_iter = true;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct bidirectional_iterator_traits
|
||||
: public forward_iterator_traits<Iterator>
|
||||
{
|
||||
static bool const is_reversible = has_mutable_ref;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct random_access_iterator_traits
|
||||
: public bidirectional_iterator_traits<Iterator>
|
||||
{
|
||||
static bool const has_random_access = true;
|
||||
};
|
||||
|
||||
namespace iterator_detail {
|
||||
typedef char input_iter_sizer[1];
|
||||
typedef char forward_iter_sizer[2];
|
||||
typedef char bidirectional_iter_sizer[3];
|
||||
typedef char random_access_iter_sizer[4];
|
||||
|
||||
input_iter_sizer &sizer (std::input_iterator_tag const &);
|
||||
forward_iter_sizer &sizer (std::forward_iterator_tag const &);
|
||||
bidirectional_iter_sizer &sizer (std::bidirectional_iterator_tag const &);
|
||||
random_access_iter_sizer &sizer (std::random_access_iterator_tag const &);
|
||||
|
||||
template<size_t Size> struct traits_by_size { };
|
||||
|
||||
template<>
|
||||
struct traits_by_size<sizeof(input_iter_sizer)> {
|
||||
template<typename Iterator>
|
||||
struct traits {
|
||||
typedef input_iterator_traits<Iterator> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct traits_by_size<sizeof(forward_iter_sizer)> {
|
||||
template<typename Iterator>
|
||||
struct traits {
|
||||
typedef forward_iterator_traits<Iterator> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct traits_by_size<sizeof(bidirectional_iter_sizer)> {
|
||||
template<typename Iterator>
|
||||
struct traits {
|
||||
typedef bidirectional_iterator_traits<Iterator> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct traits_by_size<sizeof(random_access_iter_sizer)> {
|
||||
template<typename Iterator>
|
||||
struct traits {
|
||||
typedef random_access_iterator_traits<Iterator> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
class traits_by_category {
|
||||
typedef typename std::iterator_traits<Iterator>::iterator_category
|
||||
iterator_category;
|
||||
|
||||
static size_t const size = sizeof(sizer(iterator_category()));
|
||||
|
||||
public:
|
||||
typedef typename traits_by_size<size>::traits<Iterator>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
struct iterator_traits
|
||||
: public iterator_detail::traits_by_category<Iterator>::type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif // iterator_suite_rmg_20030823_included
|
||||
44
include/boost/python/suite/indexing/sample.out
Normal file
44
include/boost/python/suite/indexing/sample.out
Normal file
@@ -0,0 +1,44 @@
|
||||
<indexing.Vector object at 0x007B57E0>
|
||||
1 2 3
|
||||
1 2 3
|
||||
copy is 2, v[1] is 2
|
||||
copy is 3, v[1] is 3
|
||||
copy is 5, v[1] is 5
|
||||
slice[0] is 5, copy is 5, v[1] is 5
|
||||
slice[0] is 5, copy is 5, v[1] is 6
|
||||
slice[0] is 5, copy is 5, v[1] is 7
|
||||
slice[0] is 9, copy is 9, v[1] is 7
|
||||
=============
|
||||
<indexing.ProxyVector object at 0x007B57E0>
|
||||
1 2 3
|
||||
1 2 3
|
||||
copy is 2, v[1] is 2
|
||||
copy is 3, v[1] is 3
|
||||
copy is 3, v[1] is 5
|
||||
slice[0] is 5, copy is 5, v[1] is 5
|
||||
slice[0] is 5, copy is 5, v[1] is 6
|
||||
slice[0] is 5, copy is 5, v[1] is 7
|
||||
slice[0] is 9, copy is 5, v[1] is 7
|
||||
=============
|
||||
<indexing.PointerVector object at 0x007B57E0>
|
||||
1 2 3
|
||||
1 2 3
|
||||
copy is 2, v[1] is 2
|
||||
copy is 3, v[1] is 3
|
||||
copy is 3, v[1] is 5
|
||||
slice[0] is 5, copy is 5, v[1] is 5
|
||||
slice[0] is 6, copy is 6, v[1] is 6
|
||||
slice[0] is 6, copy is 6, v[1] is 7
|
||||
slice[0] is 9, copy is 6, v[1] is 7
|
||||
=============
|
||||
[]
|
||||
1 2 3
|
||||
1 2 3
|
||||
copy is 2, v[1] is 2
|
||||
copy is 3, v[1] is 3
|
||||
copy is 3, v[1] is 5
|
||||
slice[0] is 5, copy is 5, v[1] is 5
|
||||
slice[0] is 6, copy is 6, v[1] is 6
|
||||
slice[0] is 6, copy is 6, v[1] is 7
|
||||
slice[0] is 9, copy is 6, v[1] is 7
|
||||
=============
|
||||
103
include/boost/python/suite/indexing/shared_proxy_impl.hpp
Executable file
103
include/boost/python/suite/indexing/shared_proxy_impl.hpp
Executable file
@@ -0,0 +1,103 @@
|
||||
// -*- mode:c++; switch-modules-target: "container_proxy.hpp" -*-
|
||||
//
|
||||
// Header file shared_proxy_impl.hpp
|
||||
//
|
||||
// The shared implementation of the element proxy (const and non-const
|
||||
// versions). Multiple proxy pointers can refer to the same shared
|
||||
// implementation, meaning that only one object requires updating to
|
||||
// affect all proxy pointers that ultimately refer to the same index
|
||||
// in the container.
|
||||
//
|
||||
// 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/ 8/29 rmg File creation from container_proxy.hh
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef shared_proxy_impl_rmg_20030829_included
|
||||
#define shared_proxy_impl_rmg_20030829_included
|
||||
|
||||
#include <memory>
|
||||
|
||||
template<class ContainerProxy>
|
||||
class shared_proxy_impl
|
||||
{
|
||||
public:
|
||||
typedef typename ContainerProxy::raw_value_type value_type;
|
||||
typedef value_type &reference;
|
||||
typedef value_type *pointer;
|
||||
typedef void iterator_category; // Fudge for boost::indirect_iterator
|
||||
typedef void difference_type; // Fudge for boost::indirect_iterator
|
||||
|
||||
reference operator*() const;
|
||||
pointer operator->() const { return &(**this); }
|
||||
|
||||
ContainerProxy *owner() const { return myOwnerPtr; }
|
||||
size_t index() const { return myIndex; }
|
||||
|
||||
shared_proxy_impl (value_type const ©);
|
||||
// Creates value-only (detached) proxy
|
||||
|
||||
private:
|
||||
template<class C, typename H, class A> friend class container_proxy;
|
||||
|
||||
shared_proxy_impl (ContainerProxy *, size_t);
|
||||
void detach ();
|
||||
|
||||
private:
|
||||
ContainerProxy *myOwnerPtr; // When attached
|
||||
size_t myIndex; // When attached
|
||||
std::auto_ptr<value_type> myElementPtr; // When detached
|
||||
|
||||
private:
|
||||
// Not implemented
|
||||
shared_proxy_impl (shared_proxy_impl const &);
|
||||
shared_proxy_impl &operator= (shared_proxy_impl const &);
|
||||
};
|
||||
|
||||
template<class ContainerProxy>
|
||||
shared_proxy_impl<ContainerProxy>::shared_proxy_impl (ContainerProxy *ownerPtr
|
||||
, size_t index)
|
||||
: myOwnerPtr (ownerPtr)
|
||||
, myIndex (index)
|
||||
, myElementPtr ()
|
||||
{
|
||||
}
|
||||
|
||||
template<class ContainerProxy>
|
||||
shared_proxy_impl<ContainerProxy>::shared_proxy_impl (value_type const &val)
|
||||
: myOwnerPtr (0)
|
||||
, myIndex (-1)
|
||||
, myElementPtr (new value_type (val))
|
||||
{
|
||||
}
|
||||
|
||||
template<class ContainerProxy>
|
||||
typename shared_proxy_impl<ContainerProxy>::reference
|
||||
shared_proxy_impl<ContainerProxy>::operator* () const
|
||||
{
|
||||
return myOwnerPtr ? myOwnerPtr->container().at (myIndex) : *myElementPtr;
|
||||
}
|
||||
|
||||
template<class ContainerProxy>
|
||||
void shared_proxy_impl<ContainerProxy>::detach ()
|
||||
{
|
||||
myElementPtr.reset (new value_type (**this));
|
||||
myOwnerPtr = 0;
|
||||
myIndex = static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
#endif // shared_proxy_impl_rmg_20030829_included
|
||||
211
include/boost/python/suite/indexing/suite_utils.hpp
Executable file
211
include/boost/python/suite/indexing/suite_utils.hpp
Executable file
@@ -0,0 +1,211 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file suite_utils.hpp
|
||||
//
|
||||
// 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/ 8/23 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef suite_utils_rmg_20030823_included
|
||||
#define suite_utils_rmg_20030823_included
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace indexing {
|
||||
template<typename T>
|
||||
class is_mutable_ref
|
||||
{
|
||||
typedef typename boost::remove_reference<T>::type maybe_const;
|
||||
|
||||
public:
|
||||
static bool const value = ! boost::is_const<maybe_const>::value;
|
||||
};
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct container_algorithms
|
||||
{
|
||||
typedef typename ContainerTraits::container container;
|
||||
typedef typename ContainerTraits::iterator iterator;
|
||||
typedef typename ContainerTraits::key_type key_type;
|
||||
typedef typename ContainerTraits::size_type size_type;
|
||||
typedef typename ContainerTraits::index_type index_type;
|
||||
|
||||
typedef typename boost::call_traits<key_type>::param_type key_param;
|
||||
typedef typename boost::call_traits<index_type>::param_type index_param;
|
||||
|
||||
static size_type size (container &);
|
||||
static iterator find (container &, key_param);
|
||||
static size_type count (container &, key_param);
|
||||
static void reverse (container &);
|
||||
static iterator at (container&, index_param);
|
||||
static void sort (container &);
|
||||
// static void sort (container &, PyObject *);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Get the size of a container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename container_algorithms<ContainerTraits>::size_type
|
||||
container_algorithms<ContainerTraits>::size (container &c)
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename container_algorithms<ContainerTraits>::iterator
|
||||
container_algorithms<ContainerTraits>::find (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return std::find (c.begin(), c.end(), key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename container_algorithms<ContainerTraits>::size_type
|
||||
container_algorithms<ContainerTraits>::count (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return std::count (c.begin(), c.end(), key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (iterator version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename container_algorithms<ContainerTraits>::iterator
|
||||
container_algorithms<ContainerTraits>::at (container &c, index_param ix)
|
||||
{
|
||||
return c.begin() + ix;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Reverse the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void container_algorithms<ContainerTraits>::reverse (container &c)
|
||||
{
|
||||
std::reverse (c.begin(), c.end());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sort the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void container_algorithms<ContainerTraits>::sort (container &c)
|
||||
{
|
||||
std::sort (c.begin(), c.end());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Special cases for std::list
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct list_algorithms : public container_algorithms<ContainerTraits>
|
||||
{
|
||||
private:
|
||||
typedef container_algorithms<ContainerTraits> Parent;
|
||||
|
||||
public:
|
||||
typedef typename Parent::container container;
|
||||
|
||||
// Use member functions for the following (hiding base class versions)
|
||||
static void reverse (container &);
|
||||
static void sort (container &);
|
||||
// static void sort (container &, PyObject *);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Reverse the contents of a list (member function version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void list_algorithms<ContainerTraits>::reverse (container &c)
|
||||
{
|
||||
c.reverse();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sort the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void list_algorithms<ContainerTraits>::sort (container &c)
|
||||
{
|
||||
c.sort();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Special cases for associative containers
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct assoc_algorithms : public container_algorithms<ContainerTraits>
|
||||
{
|
||||
private:
|
||||
typedef container_algorithms<ContainerTraits> Parent;
|
||||
|
||||
public:
|
||||
typedef typename Parent::iterator iterator;
|
||||
typedef typename Parent::size_type size_type;
|
||||
typedef typename Parent::container container;
|
||||
typedef typename Parent::key_param key_param;
|
||||
|
||||
// Use member functions for the following (hiding base class versions)
|
||||
static iterator find (container &, key_param);
|
||||
static size_type count (container &, key_param);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in an associative container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::iterator
|
||||
assoc_algorithms<ContainerTraits>::find (container &c, key_param key)
|
||||
{
|
||||
return c.find (key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::size_type
|
||||
assoc_algorithms<ContainerTraits>::count (container &c, key_param key)
|
||||
{
|
||||
return c.count (key);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // suite_utils_rmg_20030823_included
|
||||
145
include/boost/python/suite/indexing/testcontprox.cpp
Executable file
145
include/boost/python/suite/indexing/testcontprox.cpp
Executable file
@@ -0,0 +1,145 @@
|
||||
// -*- mode:c++; switch-modules-target: "container_proxy.hpp" -*-
|
||||
//
|
||||
// Module testcontprox.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/ 8/26 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#include "container_proxy.hpp"
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
|
||||
int unique_int() {
|
||||
static int counter = 400;
|
||||
|
||||
return counter++;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
int i = unique_int();
|
||||
typedef std::vector<int> Container;
|
||||
typedef container_proxy<Container, Container *, deref<Container> > ContainerProxy;
|
||||
|
||||
Container raw_container;
|
||||
raw_container.push_back (i);
|
||||
|
||||
ContainerProxy proxy (&raw_container);
|
||||
|
||||
std::cout
|
||||
<< proxy.container().front() // Should be first element
|
||||
<< " "
|
||||
<< *proxy.at (0) // Should be the same
|
||||
<< "\n";
|
||||
|
||||
ContainerProxy::value_type ptr (proxy.at (0));
|
||||
|
||||
std::cout
|
||||
<< *ptr // Should be first element
|
||||
<< " "
|
||||
<< ptr.use_count(); // Should be 2 (internal map has a ref)
|
||||
|
||||
{
|
||||
ContainerProxy::const_value_type
|
||||
const_ptr (const_cast<ContainerProxy const &>(proxy).at(0));
|
||||
|
||||
std::cout
|
||||
<< ", "
|
||||
<< *const_ptr // Should also be first element
|
||||
<< " "
|
||||
<< ptr.use_count(); // Should be 3 (two proxies and internal)
|
||||
}
|
||||
|
||||
proxy.replace (0, unique_int());
|
||||
|
||||
std::cout
|
||||
<< ", "
|
||||
<< *ptr // Should be *original* first element
|
||||
<< " "
|
||||
<< ptr.use_count() // Should be 1 (detached)
|
||||
<< ", "
|
||||
<< proxy.at (0) // Should be new first element
|
||||
<< "\n";
|
||||
|
||||
ptr = proxy.at (0); // Proxy to new first element (attached)
|
||||
|
||||
proxy.insert (proxy.begin(), unique_int());
|
||||
proxy.insert (proxy.begin(), unique_int());
|
||||
|
||||
int array[4];
|
||||
for (int count = 0; count < 4; ++count) array[count] = unique_int();
|
||||
|
||||
proxy.insert (proxy.begin(), array, array + 4);
|
||||
|
||||
std::cout << "(" << *ptr << ", " << ptr.use_count() << ") ";
|
||||
std::copy (raw_container.begin(), raw_container.end()
|
||||
, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << "\n";
|
||||
|
||||
proxy.erase (proxy.begin());
|
||||
proxy.erase (proxy.begin(), proxy.begin() + 3);
|
||||
|
||||
std::cout << "(" << *ptr << ", " << ptr.use_count() << ") ";
|
||||
std::copy (raw_container.begin(), raw_container.end()
|
||||
, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << "\n";
|
||||
|
||||
std::stringstream strm;
|
||||
strm << unique_int();
|
||||
strm << " " << unique_int();
|
||||
proxy.insert (proxy.begin()
|
||||
, std::istream_iterator<int> (strm)
|
||||
, std::istream_iterator<int> ());
|
||||
|
||||
std::cout << "(" << *ptr << ", " << ptr.use_count() << ") ";
|
||||
std::copy (raw_container.begin(), raw_container.end()
|
||||
, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << "\n";
|
||||
|
||||
// Example set_item implementation - replacing the slice [1:4] with a
|
||||
// single element
|
||||
proxy.detach_proxy (1);
|
||||
proxy.at(1) = unique_int(); // Replace with new element
|
||||
proxy.erase (proxy.begin() + 2, proxy.begin() + 4);
|
||||
|
||||
std::cout << "(" << *ptr << ", " << ptr.use_count() << ") ";
|
||||
|
||||
|
||||
// Try indirect_iterator just for fun, but this creates proxies for
|
||||
// every element in the container!
|
||||
|
||||
using boost::make_indirect_iterator;
|
||||
|
||||
std::copy (make_indirect_iterator(proxy.begin())
|
||||
, make_indirect_iterator(proxy.end())
|
||||
, std::ostream_iterator<int>(std::cout, " "));
|
||||
|
||||
std::cout << "\n";
|
||||
|
||||
// Try erasing the whole container, make sure proxy has value and is unique
|
||||
proxy.erase (proxy.begin(), proxy.end());
|
||||
std::cout
|
||||
<< "(" << *ptr << ", " << ptr.use_count() << ") "
|
||||
<< proxy.size() << "\n";
|
||||
}
|
||||
70
include/boost/python/suite/indexing/testindexing.py
Executable file
70
include/boost/python/suite/indexing/testindexing.py
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/python
|
||||
# -*- mode:python; switch-modules-target: "indexing.cpp" -*-
|
||||
#
|
||||
# Python module testindexing.py
|
||||
#
|
||||
# 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 software for any non-commercial purpose
|
||||
# is hereby granted without fee, provided the above notices are retained
|
||||
# on all copies. Permission to modify the code and to distribute
|
||||
# modified code for non-commercial purposes is granted, provided the
|
||||
# above notices are retained, and a notice that the code was modified is
|
||||
# included with the above copyright notice.
|
||||
#
|
||||
# History
|
||||
# =======
|
||||
# 2003/ 8/19 rmg File creation
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
from indexing import *
|
||||
|
||||
trace(0)
|
||||
|
||||
def test_from_empty(v):
|
||||
# v.reserve (10);
|
||||
|
||||
print v
|
||||
|
||||
v.append (IntWrapper (1))
|
||||
v.append (IntWrapper (2))
|
||||
v.append (IntWrapper (3))
|
||||
|
||||
print v[0], v[1], v[2]
|
||||
|
||||
try:
|
||||
print v[0], v[1:][0], v[-1:][0]
|
||||
|
||||
except Exception, e:
|
||||
print e
|
||||
pass
|
||||
|
||||
copy = v[1]
|
||||
|
||||
print "copy is %s, v[1] is %s" % (copy, v[1])
|
||||
v[1].increment()
|
||||
print "copy is %s, v[1] is %s" % (copy, v[1])
|
||||
v[1] = IntWrapper (5)
|
||||
print "copy is %s, v[1] is %s" % (copy, v[1])
|
||||
|
||||
slice = v[1:2]
|
||||
copy = slice[0]
|
||||
print "slice[0] is %s, copy is %s, v[1] is %s" % (slice[0], copy, v[1])
|
||||
v[1].increment()
|
||||
print "slice[0] is %s, copy is %s, v[1] is %s" % (slice[0], copy, v[1])
|
||||
v[1] = IntWrapper (7)
|
||||
print "slice[0] is %s, copy is %s, v[1] is %s" % (slice[0], copy, v[1])
|
||||
slice[0] = IntWrapper (9)
|
||||
print "slice[0] is %s, copy is %s, v[1] is %s" % (slice[0], copy, v[1])
|
||||
|
||||
print "============="
|
||||
|
||||
test_from_empty (Vector())
|
||||
test_from_empty (ProxyVector())
|
||||
test_from_empty (PointerVector())
|
||||
test_from_empty ([])
|
||||
158
include/boost/python/suite/indexing/testlist.py
Executable file
158
include/boost/python/suite/indexing/testlist.py
Executable file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/python
|
||||
# -*- mode:python -*-
|
||||
#
|
||||
# Python module testlist.py
|
||||
#
|
||||
# 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/ 8/20 rmg File creation
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
from types import SliceType
|
||||
|
||||
class ListIter:
|
||||
def __init__(self, l):
|
||||
self.myList = l
|
||||
self.myIndex = 0
|
||||
|
||||
def next(self):
|
||||
print "next(ListIter)",
|
||||
try:
|
||||
result = self.myList[self.myIndex]
|
||||
self.myIndex += 1
|
||||
print "ok"
|
||||
return result
|
||||
|
||||
except IndexError:
|
||||
print "StopIteration"
|
||||
raise StopIteration
|
||||
|
||||
class MyList:
|
||||
def __init__(self, l = None):
|
||||
print "__init__(MyList)"
|
||||
|
||||
if l == None:
|
||||
self.myList = list()
|
||||
else:
|
||||
self.myList = l
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
print "__setitem__(MyList, %s, %s)" % (key, value)
|
||||
if isinstance (key, SliceType):
|
||||
if key.step != None:
|
||||
raise TypeError ("Invalid slice for list")
|
||||
self.myList.__setslice__ (key.start, key.stop, value)
|
||||
|
||||
else:
|
||||
self.myList.__setitem__(key, value)
|
||||
|
||||
def __iter__(self):
|
||||
print "__iter__(MyList)"
|
||||
return ListIter(self.myList)
|
||||
|
||||
def __getitem__(self, key):
|
||||
print "__getitem__(MyList, %s)" % key
|
||||
if isinstance (key, SliceType):
|
||||
if key.step != None:
|
||||
raise TypeError ("Invalid slice for list")
|
||||
return self.myList.__getslice__ (key.start, key.stop)
|
||||
return self.myList.__getitem__(key)
|
||||
|
||||
def __delitem__(self, key):
|
||||
print "__delitem__(MyList, %s)" % key
|
||||
if isinstance (key, SliceType):
|
||||
if key.step != None:
|
||||
raise TypeError ("Invalid slice for list")
|
||||
self.myList.__delslice__ (key.start, key.stop)
|
||||
|
||||
else:
|
||||
self.myList.__delitem__(key)
|
||||
|
||||
def __len__(self):
|
||||
print "__len__(MyList)"
|
||||
return self.myList.__len__()
|
||||
|
||||
def __add__(self, value):
|
||||
print "__add__(MyList, %s)" % value
|
||||
return MyList(self.myList.__add__(value))
|
||||
|
||||
def __mul__(self, value):
|
||||
print "__mul__(MyList, %s)" % value
|
||||
return MyList(self.myList.__mul__(value))
|
||||
|
||||
# def __imul__(self, value):
|
||||
# print "__imul__(MyList, %s)" % value
|
||||
# self.myList.__imul__(value)
|
||||
|
||||
# def __contains__(self, value):
|
||||
# print "__contains__(MyList, %s)" % value
|
||||
# return self.myList.__contains__(value)
|
||||
|
||||
def append(self, value):
|
||||
print "append(MyList, %s)" % value
|
||||
self.myList.append(value)
|
||||
|
||||
def __insert__(self, key, value):
|
||||
print "__insert__(MyList, %s, %s)" % (key, value)
|
||||
self.myList.__insert__(key, value)
|
||||
|
||||
# def __setslice__(self, start, end, value):
|
||||
# print "__setslice__(MyList, %s, %s, %s)" % (start, end, value)
|
||||
# self.myList.__setslice__(start, end, value)
|
||||
|
||||
# def __getslice__(self, start, end):
|
||||
# print "__getslice__(MyList, %s, %s)" % (start, end)
|
||||
# self.myList.__getslice__(start, end)
|
||||
|
||||
# def __delslice__(self, start, end):
|
||||
# print "__delslice__(MyList, %s, %s)" % (start, end)
|
||||
# self.myList.__delslice__(start, end)
|
||||
|
||||
def __repr__(self):
|
||||
return self.myList.__repr__()
|
||||
|
||||
x = MyList()
|
||||
|
||||
x.append(4)
|
||||
x.append(5)
|
||||
x.append(6)
|
||||
|
||||
print 4 in x
|
||||
print 7 in x
|
||||
|
||||
x[1] = 0
|
||||
x[2:3]=[7, 8, 9]
|
||||
print x + [10]
|
||||
print x[2:]
|
||||
|
||||
del x[2:3]
|
||||
del x[0]
|
||||
|
||||
print x
|
||||
|
||||
x[1:2] = []
|
||||
|
||||
print x
|
||||
|
||||
x *= 2
|
||||
|
||||
print x
|
||||
|
||||
x[0:3][0:1] = [1]
|
||||
|
||||
print x
|
||||
|
||||
344
include/boost/python/suite/indexing/vector_indexing_suite.py
Executable file
344
include/boost/python/suite/indexing/vector_indexing_suite.py
Executable file
@@ -0,0 +1,344 @@
|
||||
'''
|
||||
|
||||
#####################################################################
|
||||
# Check an object that we will use as container element
|
||||
#####################################################################
|
||||
|
||||
>>> from vector_indexing_suite_ext import *
|
||||
>>> x = X('hi')
|
||||
>>> x
|
||||
hi
|
||||
>>> x.reset() # a member function that modifies X
|
||||
>>> x
|
||||
reset
|
||||
>>> x.foo() # another member function that modifies X
|
||||
>>> x
|
||||
foo
|
||||
|
||||
# test that a string is implicitly convertible
|
||||
# to an X
|
||||
>>> x_value('bochi bochi')
|
||||
'gotya bochi bochi'
|
||||
|
||||
#####################################################################
|
||||
# Iteration
|
||||
#####################################################################
|
||||
>>> def print_xvec(xvec):
|
||||
... s = '[ '
|
||||
... for x in xvec:
|
||||
... s += repr(x)
|
||||
... s += ' '
|
||||
... s += ']'
|
||||
... print s
|
||||
|
||||
#####################################################################
|
||||
# Replace all the contents using slice syntax
|
||||
#####################################################################
|
||||
|
||||
>>> v = XVec()
|
||||
>>> v[:] = [X('a'),X('b'),X('c'),X('d'),X('e')]
|
||||
>>> print_xvec(v)
|
||||
[ a b c d e ]
|
||||
|
||||
#####################################################################
|
||||
# Indexing
|
||||
#####################################################################
|
||||
>>> len(v)
|
||||
5
|
||||
>>> v[0]
|
||||
a
|
||||
>>> v[1]
|
||||
b
|
||||
>>> v[2]
|
||||
c
|
||||
>>> v[3]
|
||||
d
|
||||
>>> v[4]
|
||||
e
|
||||
>>> v[-1]
|
||||
e
|
||||
>>> v[-2]
|
||||
d
|
||||
>>> v[-3]
|
||||
c
|
||||
>>> v[-4]
|
||||
b
|
||||
>>> v[-5]
|
||||
a
|
||||
|
||||
#####################################################################
|
||||
# Deleting an element
|
||||
#####################################################################
|
||||
|
||||
>>> del v[0]
|
||||
>>> v[0] = 'yaba' # must do implicit conversion
|
||||
>>> print_xvec(v)
|
||||
[ yaba c d e ]
|
||||
|
||||
#####################################################################
|
||||
# Calling a mutating function of a container element
|
||||
#####################################################################
|
||||
>>> v[3].reset()
|
||||
>>> v[3]
|
||||
reset
|
||||
|
||||
#####################################################################
|
||||
# Copying a container element
|
||||
#####################################################################
|
||||
>>> x = X(v[3])
|
||||
>>> x
|
||||
reset
|
||||
>>> x.foo()
|
||||
>>> x
|
||||
foo
|
||||
>>> v[3] # should not be changed to 'foo'
|
||||
reset
|
||||
|
||||
#####################################################################
|
||||
# Referencing a container element
|
||||
#####################################################################
|
||||
>>> x = v[3]
|
||||
>>> x
|
||||
reset
|
||||
>>> x.foo()
|
||||
>>> x
|
||||
foo
|
||||
>>> v[3] # should be changed to 'foo'
|
||||
foo
|
||||
|
||||
#####################################################################
|
||||
# Slice
|
||||
#####################################################################
|
||||
|
||||
>>> sl = v[0:2]
|
||||
>>> print_xvec(sl)
|
||||
[ yaba c ]
|
||||
>>> sl[0].reset()
|
||||
>>> sl[0]
|
||||
reset
|
||||
|
||||
#####################################################################
|
||||
# Reset the container again
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e'] # perform implicit conversion to X
|
||||
>>> print_xvec(v)
|
||||
[ a b c d e ]
|
||||
|
||||
#####################################################################
|
||||
# Slice: replace [1:3] with an element
|
||||
#####################################################################
|
||||
>>> v[1:3] = X('z')
|
||||
>>> print_xvec(v)
|
||||
[ a z d e ]
|
||||
|
||||
#####################################################################
|
||||
# Slice: replace [0:2] with a list
|
||||
#####################################################################
|
||||
>>> v[0:2] = ['1','2','3','4'] # perform implicit conversion to X
|
||||
>>> print_xvec(v)
|
||||
[ 1 2 3 4 d e ]
|
||||
|
||||
#####################################################################
|
||||
# Slice: delete [3:4]
|
||||
#####################################################################
|
||||
>>> del v[3:4]
|
||||
>>> print_xvec(v)
|
||||
[ 1 2 3 d e ]
|
||||
|
||||
#####################################################################
|
||||
# Slice: set [3:] to a list
|
||||
#####################################################################
|
||||
>>> v[3:] = [X('trailing'), X('stuff')] # a list
|
||||
>>> print_xvec(v)
|
||||
[ 1 2 3 trailing stuff ]
|
||||
|
||||
#####################################################################
|
||||
# Slice: delete [:3]
|
||||
#####################################################################
|
||||
>>> del v[:3]
|
||||
>>> print_xvec(v)
|
||||
[ trailing stuff ]
|
||||
|
||||
#####################################################################
|
||||
# Slice: insert a tuple to [0:0]
|
||||
#####################################################################
|
||||
>>> v[0:0] = ('leading','stuff') # can also be a tuple
|
||||
>>> print_xvec(v)
|
||||
[ leading stuff trailing stuff ]
|
||||
|
||||
#####################################################################
|
||||
# Reset the container again
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e']
|
||||
|
||||
#####################################################################
|
||||
# Some references to the container elements
|
||||
#####################################################################
|
||||
>>> z0 = v[0]
|
||||
>>> z1 = v[1]
|
||||
>>> z2 = v[2]
|
||||
>>> z3 = v[3]
|
||||
>>> z4 = v[4]
|
||||
|
||||
>>> z0 # proxy
|
||||
a
|
||||
>>> z1 # proxy
|
||||
b
|
||||
>>> z2 # proxy
|
||||
c
|
||||
>>> z3 # proxy
|
||||
d
|
||||
>>> z4 # proxy
|
||||
e
|
||||
|
||||
#####################################################################
|
||||
# Delete a container element
|
||||
#####################################################################
|
||||
|
||||
>>> del v[2]
|
||||
>>> print_xvec(v)
|
||||
[ a b d e ]
|
||||
|
||||
#####################################################################
|
||||
# Show that the references are still valid
|
||||
#####################################################################
|
||||
>>> z0 # proxy
|
||||
a
|
||||
>>> z1 # proxy
|
||||
b
|
||||
>>> z2 # proxy detached
|
||||
c
|
||||
>>> z3 # proxy index adjusted
|
||||
d
|
||||
>>> z4 # proxy index adjusted
|
||||
e
|
||||
|
||||
#####################################################################
|
||||
# Delete all container elements
|
||||
#####################################################################
|
||||
>>> del v[:]
|
||||
>>> print_xvec(v)
|
||||
[ ]
|
||||
|
||||
#####################################################################
|
||||
# Show that the references are still valid
|
||||
#####################################################################
|
||||
>>> z0 # proxy detached
|
||||
a
|
||||
>>> z1 # proxy detached
|
||||
b
|
||||
>>> z2 # proxy detached
|
||||
c
|
||||
>>> z3 # proxy detached
|
||||
d
|
||||
>>> z4 # proxy detached
|
||||
e
|
||||
|
||||
#####################################################################
|
||||
# Reset the container again
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e']
|
||||
|
||||
#####################################################################
|
||||
# renew the references to the container elements
|
||||
#####################################################################
|
||||
>>> z0 = v[0]
|
||||
>>> z1 = v[1]
|
||||
>>> z2 = v[2]
|
||||
>>> z3 = v[3]
|
||||
>>> z4 = v[4]
|
||||
|
||||
>>> z0 # proxy
|
||||
a
|
||||
>>> z1 # proxy
|
||||
b
|
||||
>>> z2 # proxy
|
||||
c
|
||||
>>> z3 # proxy
|
||||
d
|
||||
>>> z4 # proxy
|
||||
e
|
||||
|
||||
#####################################################################
|
||||
# Set [2:4] to a list such that there will be more elements
|
||||
#####################################################################
|
||||
>>> v[2:4] = ['x','y','v']
|
||||
>>> print_xvec(v)
|
||||
[ a b x y v e ]
|
||||
|
||||
#####################################################################
|
||||
# Show that the references are still valid
|
||||
#####################################################################
|
||||
>>> z0 # proxy
|
||||
a
|
||||
>>> z1 # proxy
|
||||
b
|
||||
>>> z2 # proxy detached
|
||||
c
|
||||
>>> z3 # proxy detached
|
||||
d
|
||||
>>> z4 # proxy index adjusted
|
||||
e
|
||||
|
||||
#####################################################################
|
||||
# Contains
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e'] # reset again
|
||||
|
||||
>>> assert 'a' in v
|
||||
>>> assert 'b' in v
|
||||
>>> assert 'c' in v
|
||||
>>> assert 'd' in v
|
||||
>>> assert 'e' in v
|
||||
>>> assert not 'X' in v
|
||||
>>> assert not 12345 in v
|
||||
|
||||
#####################################################################
|
||||
# Show that iteration allows mutable access to the elements
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e'] # reset again
|
||||
>>> for x in v:
|
||||
... x.reset()
|
||||
>>> print_xvec(v)
|
||||
[ reset reset reset reset reset ]
|
||||
|
||||
#####################################################################
|
||||
# append
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e'] # reset again
|
||||
>>> v.append('f')
|
||||
>>> print_xvec(v)
|
||||
[ a b c d e f ]
|
||||
|
||||
#####################################################################
|
||||
# extend
|
||||
#####################################################################
|
||||
>>> v[:] = ['a','b','c','d','e'] # reset again
|
||||
>>> v.extend(['f','g','h','i','j'])
|
||||
>>> print_xvec(v)
|
||||
[ a b c d e f g h i j ]
|
||||
|
||||
#####################################################################
|
||||
# END....
|
||||
#####################################################################
|
||||
|
||||
'''
|
||||
|
||||
|
||||
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])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
61
include/boost/python/suite/indexing/vector_indexing_suite_ext.cpp
Executable file
61
include/boost/python/suite/indexing/vector_indexing_suite_ext.cpp
Executable file
@@ -0,0 +1,61 @@
|
||||
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include "container_proxy.hpp"
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct X // a container element
|
||||
{
|
||||
std::string s;
|
||||
X():s("default") {}
|
||||
X(std::string s):s(s) {}
|
||||
std::string repr() const { return s; }
|
||||
void reset() { s = "reset"; }
|
||||
void foo() { s = "foo"; }
|
||||
bool operator==(X const& x) const { return s == x.s; }
|
||||
bool operator!=(X const& x) const { return s != x.s; }
|
||||
};
|
||||
|
||||
std::string x_value(X const& x)
|
||||
{
|
||||
return "gotya " + x.s;
|
||||
}
|
||||
|
||||
X *get_pointer (container_proxy<std::vector<X> >::value_type const &proxy)
|
||||
{
|
||||
return &(*proxy);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(vector_indexing_suite_ext)
|
||||
{
|
||||
class_<X>("X")
|
||||
.def(init<>())
|
||||
.def(init<X>())
|
||||
.def(init<std::string>())
|
||||
.def("__repr__", &X::repr)
|
||||
.def("reset", &X::reset)
|
||||
.def("foo", &X::foo)
|
||||
;
|
||||
|
||||
def("x_value", x_value);
|
||||
implicitly_convertible<std::string, X>();
|
||||
|
||||
typedef std::vector<X> RawContainer;
|
||||
typedef container_proxy<RawContainer> Container;
|
||||
|
||||
boost::python::register_ptr_to_python<Container::value_type>();
|
||||
|
||||
implicitly_convertible<X, Container::value_type>();
|
||||
|
||||
class_<Container>("XVec")
|
||||
.def(vector_indexing_suite<Container, true>())
|
||||
;
|
||||
|
||||
// Compile check only...
|
||||
class_<std::vector<float> >("FloatVec")
|
||||
.def(vector_indexing_suite<std::vector<float> >())
|
||||
;
|
||||
}
|
||||
|
||||
33
include/boost/python/suite/indexing/vis.hpp.patch
Normal file
33
include/boost/python/suite/indexing/vis.hpp.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
Index: vector_indexing_suite.hpp
|
||||
===================================================================
|
||||
RCS file: /cvsroot/boost/boost/boost/python/suite/indexing/vector_indexing_suite.hpp,v
|
||||
retrieving revision 1.4
|
||||
diff -w -d -u -r1.4 vector_indexing_suite.hpp
|
||||
--- vector_indexing_suite.hpp 14 Aug 2003 12:14:25 -0000 1.4
|
||||
+++ vector_indexing_suite.hpp 30 Aug 2003 11:47:22 -0000
|
||||
@@ -52,6 +52,7 @@
|
||||
public:
|
||||
|
||||
typedef typename Container::value_type data_type;
|
||||
+ typedef typename Container::reference reference_type;
|
||||
typedef typename Container::value_type key_type;
|
||||
typedef typename Container::size_type index_type;
|
||||
typedef typename Container::size_type size_type;
|
||||
@@ -67,7 +68,7 @@
|
||||
;
|
||||
}
|
||||
|
||||
- static data_type&
|
||||
+ static reference_type
|
||||
get_item(Container& container, index_type i)
|
||||
{
|
||||
return container[i];
|
||||
@@ -185,7 +186,7 @@
|
||||
static void
|
||||
base_append(Container& container, PyObject* v)
|
||||
{
|
||||
- extract<data_type&> elem(v);
|
||||
+ extract<reference_type> elem(v);
|
||||
// try if elem is an exact Data
|
||||
if (elem.check())
|
||||
{
|
||||
Reference in New Issue
Block a user