mirror of
https://github.com/boostorg/python.git
synced 2026-01-30 20:12:37 +00:00
Synchronize with local work
[SVN r1564]
This commit is contained in:
@@ -121,6 +121,24 @@ bool operator< (IntWrapper const &lhs, IntWrapper const &rhs)
|
||||
return lhs.mI < rhs.mI;
|
||||
}
|
||||
|
||||
int compare (IntWrapper const &lhs, IntWrapper const &rhs)
|
||||
{
|
||||
if (lhs < rhs)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
else if (rhs < lhs)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream &operator<< (std::ostream &strm, IntWrapper const &iw)
|
||||
{
|
||||
strm << iw.mI;
|
||||
|
||||
@@ -48,6 +48,7 @@ struct IntWrapper {
|
||||
|
||||
bool operator== (IntWrapper const &lhs, IntWrapper const &rhs);
|
||||
bool operator< (IntWrapper const &lhs, IntWrapper const &rhs);
|
||||
int compare (IntWrapper const &lhs, IntWrapper const &rhs);
|
||||
std::ostream &operator<< (std::ostream &strm, IntWrapper const &iw);
|
||||
|
||||
#endif // IntWrapper_rmg_20030910_included
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
// Definitions of supported types
|
||||
#include "iterator_pair.hpp"
|
||||
#include "container_proxy.hpp"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
@@ -164,6 +165,20 @@ namespace indexing {
|
||||
typedef default_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef default_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// Container proxies
|
||||
template <typename RawContainer>
|
||||
class selector_impl<container_proxy<RawContainer> >
|
||||
{
|
||||
typedef container_proxy<RawContainer> Container;
|
||||
|
||||
typedef container_proxy_traits<Container> mutable_traits;
|
||||
typedef container_proxy_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef default_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef default_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
}
|
||||
|
||||
// Select the right algorithms for each supported kind of container
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
namespace indexing {
|
||||
@@ -44,8 +45,8 @@ namespace indexing {
|
||||
typedef typename ContainerTraits::reference reference;
|
||||
typedef typename ContainerTraits::key_type key_type;
|
||||
typedef typename ContainerTraits::size_type size_type;
|
||||
typedef typename ContainerTraits::index_type index_type;
|
||||
typedef typename ContainerTraits::value_type value_type;
|
||||
typedef long index_type; // Ignore container traits (need signed repr.)
|
||||
|
||||
typedef typename boost::call_traits<value_type>::param_type value_param;
|
||||
typedef typename boost::call_traits<key_type>::param_type key_param;
|
||||
@@ -58,132 +59,26 @@ namespace indexing {
|
||||
static reference get (container &, index_param);
|
||||
static void assign (container &, index_param, value_param);
|
||||
static void insert (container &, index_param, value_param);
|
||||
static void erase (container &, index_param, index_param);
|
||||
static void erase_one (container &, index_param);
|
||||
static void erase_range(container &, index_param, index_param);
|
||||
static void push_back (container &, value_param);
|
||||
static void sort (container &);
|
||||
// static void sort (container &, PyObject *);
|
||||
|
||||
static iterator begin (container &c) { return c.begin(); }
|
||||
static iterator end (container &c) { return c.end(); }
|
||||
|
||||
template<typename PythonClass, typename Policy>
|
||||
static void visitor_helper (PythonClass &, Policy const &);
|
||||
|
||||
private:
|
||||
static size_type bounds_check (container &, index_param, char const *msg
|
||||
, bool one_past = false);
|
||||
// Throws std::out_of_range if necessary. If one_past is set, then
|
||||
// indexes up to container.size() *inclusive* are allowed. Otherwise
|
||||
// returns a normalized index.
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Get the size of a container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::size_type
|
||||
default_algorithms<ContainerTraits>::size (container &c)
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::iterator
|
||||
default_algorithms<ContainerTraits>::find (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return std::find (begin(c), end(c), key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::size_type
|
||||
default_algorithms<ContainerTraits>::count (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return std::count (begin(c), end(c), key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::reference
|
||||
default_algorithms<ContainerTraits>::get (container &c, index_param ix)
|
||||
{
|
||||
return c.at (ix);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Assign a value at a particular index (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
default_algorithms<ContainerTraits>::assign (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
c.at(ix) = val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Insert at end of a container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
default_algorithms<ContainerTraits>::push_back (container &c
|
||||
, value_param v)
|
||||
{
|
||||
c.push_back (v);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Insert at an index in the container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
default_algorithms<ContainerTraits>::insert (container &c
|
||||
, index_param i
|
||||
, value_param v)
|
||||
{
|
||||
c.insert (c.begin() + i, v);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Erase between given indexes in the container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
default_algorithms<ContainerTraits>::erase (container &c
|
||||
, index_param from
|
||||
, index_param to)
|
||||
{
|
||||
c.erase (c.begin() + from, c.begin() + to);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Reverse the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void default_algorithms<ContainerTraits>::reverse (container &c)
|
||||
{
|
||||
std::reverse (begin(c), end(c));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sort the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void default_algorithms<ContainerTraits>::sort (container &c)
|
||||
{
|
||||
std::sort (begin(c), end(c));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Special cases for std::list
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -203,26 +98,6 @@ namespace indexing {
|
||||
// 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
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -239,73 +114,300 @@ namespace indexing {
|
||||
typedef typename Parent::container container;
|
||||
typedef typename Parent::reference reference;
|
||||
typedef typename Parent::key_param key_param;
|
||||
typedef typename Parent::index_param index_param;
|
||||
typedef typename Parent::value_param value_param;
|
||||
|
||||
// Use the trait's index type information to support non-integer indexes
|
||||
typedef typename ContainerTraits::index_type index_type;
|
||||
typedef typename boost::call_traits<index_type>::param_type index_param;
|
||||
|
||||
static reference get (container &, index_param);
|
||||
static void assign (container &, index_param, value_param);
|
||||
|
||||
// Use member functions for the following (hiding base class versions)
|
||||
static void erase_one (container &, key_param);
|
||||
static iterator find (container &, key_param);
|
||||
static size_type count (container &, key_param);
|
||||
};
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Get the size of a container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::reference
|
||||
assoc_algorithms<ContainerTraits>::get (container &c, index_param ix)
|
||||
{
|
||||
iterator iter = find (c, ix);
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::default_algorithms<ContainerTraits>::size_type
|
||||
indexing::default_algorithms<ContainerTraits>::size (container &c)
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
if (iter == end(c))
|
||||
{
|
||||
throw std::domain_error
|
||||
(std::string ("associative container: key not found"));
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Range check an index and throw out_of_range if necessary
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
else
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::default_algorithms<ContainerTraits>::size_type
|
||||
indexing::default_algorithms<ContainerTraits>::bounds_check (container &c
|
||||
, index_param ix
|
||||
, char const *msg
|
||||
, bool one_past)
|
||||
{
|
||||
size_type bound = size(c) + (one_past ? 1 : 0);
|
||||
size_type result;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Assign a value at a particular index (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
if (ix < 0)
|
||||
{
|
||||
if (size_type(-ix) > bound)
|
||||
{
|
||||
throw std::out_of_range (msg);
|
||||
}
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
assoc_algorithms<ContainerTraits>::assign (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
c[ix] = val;
|
||||
}
|
||||
result = bound + ix;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in an associative container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
else
|
||||
{
|
||||
result = ix;
|
||||
}
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::iterator
|
||||
assoc_algorithms<ContainerTraits>::find (container &c, key_param key)
|
||||
{
|
||||
return c.find (key);
|
||||
}
|
||||
if (result >= bound)
|
||||
{
|
||||
throw std::out_of_range (msg);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::size_type
|
||||
assoc_algorithms<ContainerTraits>::count (container &c, key_param key)
|
||||
{
|
||||
return c.count (key);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::default_algorithms<ContainerTraits>::iterator
|
||||
indexing::default_algorithms<ContainerTraits>::find (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return std::find (begin(c), end(c), key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::default_algorithms<ContainerTraits>::size_type
|
||||
indexing::default_algorithms<ContainerTraits>::count (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return std::count (begin(c), end(c), key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::default_algorithms<ContainerTraits>::reference
|
||||
indexing::default_algorithms<ContainerTraits>::get (container &c
|
||||
, index_param ix)
|
||||
{
|
||||
return c[bounds_check (c, ix, "get")];
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Assign a value at a particular index (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::default_algorithms<ContainerTraits>::assign (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
c[bounds_check (c, ix, "assign")] = val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Insert at end of a container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::default_algorithms<ContainerTraits>::push_back (container &c
|
||||
, value_param v)
|
||||
{
|
||||
c.push_back (v);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Insert at an index in the container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::default_algorithms<ContainerTraits>::insert (container &c
|
||||
, index_param i
|
||||
, value_param v)
|
||||
{
|
||||
// Index may range up to c.size() inclusive to allow inserting at end
|
||||
c.insert (c.begin() + bounds_check (c, i, "insert", true), v);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Erase between given indexes in the container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::default_algorithms<ContainerTraits>::erase_range (container &c
|
||||
, index_param from
|
||||
, index_param to)
|
||||
{
|
||||
// End index is one-past-the-end, so may range up to c.size() inclusive
|
||||
|
||||
c.erase (c.begin() + bounds_check (c, from, "erase_range (from)")
|
||||
, c.begin() + bounds_check (c, to, "erase_range (to)", true));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Erase one element at the given index in the container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::default_algorithms<ContainerTraits>::erase_one (container &c
|
||||
, index_param ix)
|
||||
{
|
||||
c.erase (c.begin() + bounds_check (c, ix, "erase_one"));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Reverse the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void indexing::default_algorithms<ContainerTraits>::reverse (container &c)
|
||||
{
|
||||
std::reverse (begin(c), end(c));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sort the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void indexing::default_algorithms<ContainerTraits>::sort (container &c)
|
||||
{
|
||||
std::sort (begin(c), end(c));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Visitor helper function (default version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
template<typename PythonClass, typename Policy>
|
||||
void
|
||||
indexing::default_algorithms<ContainerTraits>
|
||||
::visitor_helper (PythonClass &pyClass, Policy const &policy)
|
||||
{
|
||||
container_traits::visitor_helper (pyClass, policy);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Reverse the contents of a list (member function version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void indexing::list_algorithms<ContainerTraits>::reverse (container &c)
|
||||
{
|
||||
c.reverse();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sort the contents of a container (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void indexing::list_algorithms<ContainerTraits>::sort (container &c)
|
||||
{
|
||||
c.sort();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::assoc_algorithms<ContainerTraits>::reference
|
||||
indexing::assoc_algorithms<ContainerTraits>::get (container &c, index_param ix)
|
||||
{
|
||||
iterator iter = find (c, ix);
|
||||
|
||||
if (iter == end(c))
|
||||
{
|
||||
// ? Is domain_error appropriate here?
|
||||
throw std::domain_error
|
||||
(std::string ("associative container get: key not found"));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Erase elements with the given key (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::assoc_algorithms<ContainerTraits>::erase_one (container &c
|
||||
, key_param key)
|
||||
{
|
||||
if (c.erase (key) == 0)
|
||||
{
|
||||
// ? Is domain_error appropriate here?
|
||||
throw std::domain_error
|
||||
(std::string ("associative container erase: key not found"));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Assign a value at a particular index (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
indexing::assoc_algorithms<ContainerTraits>::assign (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
c[ix] = val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in an associative container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::assoc_algorithms<ContainerTraits>::iterator
|
||||
indexing::assoc_algorithms<ContainerTraits>::find (container &c, key_param key)
|
||||
{
|
||||
return c.find (key);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename indexing::assoc_algorithms<ContainerTraits>::size_type
|
||||
indexing::assoc_algorithms<ContainerTraits>::count (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return c.count (key);
|
||||
}
|
||||
|
||||
#endif // algorithms_rmg_20030823_included
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define container_proxy_rmg_20030826_included
|
||||
|
||||
#include "shared_proxy_impl.hpp"
|
||||
#include "element_proxy.hpp"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
@@ -60,139 +61,20 @@ public:
|
||||
|
||||
typedef typename Container::value_type raw_value_type;
|
||||
|
||||
struct const_element_proxy;
|
||||
typedef element_proxy<self_type> value_type;
|
||||
typedef value_type reference; // Already has ref. semantics
|
||||
|
||||
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;
|
||||
typedef const_element_proxy<self_type> const_value_type;
|
||||
typedef const_value_type const_reference; // Has ref. semantics
|
||||
|
||||
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
|
||||
typedef container_proxy::value_type value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef value_type reference; // Already has reference semantics
|
||||
|
||||
iterator (container_proxy *p, size_type i) : ptr (p), index (i) { }
|
||||
|
||||
@@ -246,11 +128,11 @@ public:
|
||||
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;
|
||||
reference at (size_type index);
|
||||
const_reference 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); }
|
||||
reference operator[] (size_type index) { return at(index); }
|
||||
const_reference operator[] (size_type index) const { return at(index); }
|
||||
|
||||
size_type size() const { return container().size(); }
|
||||
size_type capacity() const { return container().capacity(); }
|
||||
@@ -267,8 +149,8 @@ public:
|
||||
|
||||
void push_back (raw_value_type const ©) { insert (end(), copy); }
|
||||
|
||||
element_proxy pop_back () {
|
||||
element_proxy result = at (end() - 1);
|
||||
value_type pop_back () {
|
||||
value_type result = at (end() - 1);
|
||||
erase (end() - 1);
|
||||
return result;
|
||||
}
|
||||
@@ -378,7 +260,7 @@ container_proxy<Container, HeldType, Accessor>
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::element_proxy
|
||||
typename container_proxy<Container, HeldType, Accessor>::reference
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::at (size_type index)
|
||||
{
|
||||
@@ -389,11 +271,11 @@ container_proxy<Container, HeldType, Accessor>
|
||||
entry.reset (new shared_proxy (this, index));
|
||||
}
|
||||
|
||||
return element_proxy (entry);
|
||||
return reference (entry);
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
typename container_proxy<Container, HeldType, Accessor>::const_element_proxy
|
||||
typename container_proxy<Container, HeldType, Accessor>::const_reference
|
||||
container_proxy<Container, HeldType, Accessor>
|
||||
::at (size_type index) const
|
||||
{
|
||||
@@ -403,7 +285,7 @@ container_proxy<Container, HeldType, Accessor>
|
||||
|
||||
container_proxy *mutable_this = const_cast<container_proxy *>(this);
|
||||
|
||||
return const_element_proxy (mutable_this->at (index));
|
||||
return const_reference (mutable_this->at (index));
|
||||
}
|
||||
|
||||
template<class Container, typename HeldType, class Accessor>
|
||||
|
||||
@@ -35,12 +35,14 @@ namespace indexing {
|
||||
template<class Container, class Algorithms = algo_selector<Container> >
|
||||
struct container_suite
|
||||
{
|
||||
typedef Algorithms algorithms;
|
||||
|
||||
typedef boost::python::return_value_policy<boost::python::return_by_value>
|
||||
default_policies;
|
||||
|
||||
static visitor<Algorithms, default_policies> generate ()
|
||||
{
|
||||
return visitor <Algorithms, default_policies> (default_policies());
|
||||
return visitor <Algorithms, default_policies> ();
|
||||
}
|
||||
|
||||
template<typename Policy>
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
//
|
||||
// Header file container_traits.hpp
|
||||
//
|
||||
// Traits information about entire containers for use in determining
|
||||
// what Python methods to support for a container.
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
@@ -26,75 +29,77 @@
|
||||
#define container_traits_rmg_20030823_included
|
||||
|
||||
#include "suite_utils.hpp"
|
||||
#include "iterator_suite.hpp"
|
||||
#include "iterator_traits.hpp"
|
||||
#include "value_traits.hpp"
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
namespace indexing {
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Lowest common denominator traits - applicable to real containers
|
||||
// and iterator pairs
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct base_container_traits
|
||||
: public iterator_detail::traits_by_category<typename Container::iterator>
|
||||
::type
|
||||
{
|
||||
protected:
|
||||
typedef typename
|
||||
iterator_detail::traits_by_category<typename Container::iterator>
|
||||
::type base_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT (bool, is_mutable
|
||||
= ! boost::is_const<Container>::value);
|
||||
|
||||
public:
|
||||
typedef Container container;
|
||||
|
||||
typedef typename container::size_type size_type;
|
||||
typedef typename container::size_type index_type; // at(), operator[]
|
||||
typedef typename base_type::value_type key_type; // find, count, ...
|
||||
|
||||
// *FIXME* should probably override the typedefs for iterator,
|
||||
// value_type and reference with the const versions if !is_mutable
|
||||
|
||||
typedef value_traits<typename base_type::value_type> value_traits_;
|
||||
|
||||
BOOST_STATIC_CONSTANT (bool, has_mutable_ref
|
||||
= base_type::has_mutable_ref && is_mutable);
|
||||
|
||||
BOOST_STATIC_CONSTANT (bool, has_find
|
||||
= value_traits_::equality_comparable);
|
||||
|
||||
// Assume the worst for everything else
|
||||
BOOST_STATIC_CONSTANT (bool, has_insert = false);
|
||||
BOOST_STATIC_CONSTANT (bool, has_erase = false);
|
||||
BOOST_STATIC_CONSTANT (bool, has_pop_back = false);
|
||||
BOOST_STATIC_CONSTANT (bool, has_push_back = false);
|
||||
|
||||
// Forward visitor_helper to value_traits_
|
||||
template<typename PythonClass, typename Policy>
|
||||
static void visitor_helper (PythonClass &, Policy const &);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Traits for the iterator_pair container emulator
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename IteratorPair>
|
||||
struct iterator_pair_traits
|
||||
: public
|
||||
iterator_detail::traits_by_category<typename IteratorPair::iterator>::type
|
||||
struct iterator_pair_traits : public base_container_traits<IteratorPair>
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Lowest common denominator (almost all "real" containers would
|
||||
// meet at least these requirements)
|
||||
// Default container traits - almost all "real" containers would meet
|
||||
// at least these requirements
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct default_container_traits
|
||||
struct default_container_traits : public base_container_traits<Container>
|
||||
{
|
||||
protected:
|
||||
static bool const is_mutable = ! boost::is_const<Container>::value;
|
||||
|
||||
public:
|
||||
typedef Container container;
|
||||
|
||||
// *FIXME* should use value_type const and const_reference if !is_mutable
|
||||
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 IndexStyle const index_style
|
||||
= ::indexing::iterator_traits<iterator>::index_style;
|
||||
|
||||
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;
|
||||
BOOST_STATIC_CONSTANT (bool, has_insert = is_mutable);
|
||||
BOOST_STATIC_CONSTANT (bool, has_erase = is_mutable);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -104,8 +109,25 @@ namespace indexing {
|
||||
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;
|
||||
BOOST_STATIC_CONSTANT (bool, has_pop_back = is_mutable);
|
||||
BOOST_STATIC_CONSTANT (bool, has_push_back = is_mutable);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sequences within a container_proxy
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct container_proxy_traits : public default_sequence_traits<Container>
|
||||
{
|
||||
typedef Container container;
|
||||
typedef typename container::raw_value_type value_type; // insert, ...
|
||||
typedef typename container::raw_value_type key_type; // find, count, ...
|
||||
typedef typename container::reference reference; // return values
|
||||
|
||||
typedef value_traits<reference> value_traits_;
|
||||
// Get value_traits for the reference type (i.e. element_proxy)
|
||||
// to get the custom visitor_helper
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -115,7 +137,8 @@ namespace indexing {
|
||||
template<typename Container>
|
||||
struct set_traits : public default_container_traits<Container>
|
||||
{
|
||||
static IndexStyle const index_style = index_style_nonlinear;
|
||||
BOOST_STATIC_CONSTANT (IndexStyle, index_style = index_style_nonlinear);
|
||||
BOOST_STATIC_CONSTANT (bool, has_find = true);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -131,8 +154,22 @@ namespace indexing {
|
||||
typedef typename Container::key_type index_type; // at()
|
||||
typedef typename Container::key_type key_type; // find, count, ...
|
||||
|
||||
static IndexStyle const index_style = index_style_nonlinear;
|
||||
BOOST_STATIC_CONSTANT (IndexStyle, index_style = index_style_nonlinear);
|
||||
BOOST_STATIC_CONSTANT (bool, has_find = true);
|
||||
};
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Visitor helper function (foward to value_traits_ version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
template<typename PythonClass, typename Policy>
|
||||
void
|
||||
indexing::base_container_traits<Container>
|
||||
::visitor_helper (PythonClass &pyClass, Policy const &policy)
|
||||
{
|
||||
value_traits_::visitor_helper (pyClass, policy);
|
||||
}
|
||||
|
||||
#endif // container_suite_rmg_20030823_included
|
||||
|
||||
@@ -21,15 +21,27 @@
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef NEWSTYLE
|
||||
# define NEWSTYLE 1
|
||||
#endif
|
||||
|
||||
#include "container_proxy.hpp"
|
||||
#include "IntWrapper.hpp"
|
||||
|
||||
#if NEWSTYLE
|
||||
#include "container_suite.hpp"
|
||||
#endif
|
||||
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
|
||||
#if !NEWSTYLE
|
||||
#include <boost/python/suite/indexing/indexing_suite.hpp>
|
||||
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <string>
|
||||
@@ -57,27 +69,47 @@ void pointer_increment (boost::shared_ptr<IntWrapper> const &ptr)
|
||||
(*ptr).increment();
|
||||
}
|
||||
|
||||
IntWrapper *get_pointer (container_proxy<std::vector<IntWrapper> >::value_type const &proxy)
|
||||
{
|
||||
return &(*proxy);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE (indexing)
|
||||
{
|
||||
boost::python::def ("trace", &IntWrapper::setTrace);
|
||||
boost::python::def ("setTrace", &IntWrapper::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;
|
||||
boost::python::implicitly_convertible <int, IntWrapper>();
|
||||
|
||||
// typedef vector_indexing_suite<Container, true> Suite;
|
||||
#if NEWSTYLE
|
||||
typedef boost::python::return_value_policy<boost::python::return_by_value>
|
||||
default_policies;
|
||||
|
||||
// Not really the same thing - returning internal references
|
||||
typedef indexing::visitor
|
||||
<indexing::container_suite<Container>::algorithms
|
||||
, boost::python::return_internal_reference<> > ProxySuite;
|
||||
|
||||
typedef indexing::visitor
|
||||
<indexing::container_suite<ProxyContainer>::algorithms
|
||||
, default_policies> ProxyContainerSuite;
|
||||
|
||||
typedef indexing::visitor
|
||||
<indexing::container_suite<PointerContainer>::algorithms
|
||||
, default_policies> PointerContainerSuite;
|
||||
|
||||
#else
|
||||
using boost::python::vector_indexing_suite;
|
||||
|
||||
typedef vector_indexing_suite<Container, false> ProxySuite;
|
||||
typedef vector_indexing_suite<ProxyContainer, true> ProxyContainerSuite;
|
||||
typedef vector_indexing_suite<PointerContainer, true> PointerContainerSuite;
|
||||
|
||||
boost::python::implicitly_convertible <IntWrapper, ProxyContainer::value_type>();
|
||||
|
||||
boost::python::register_ptr_to_python<ProxyContainer::value_type>();
|
||||
#endif
|
||||
|
||||
boost::python::class_<Container> ("Vector")
|
||||
.def (ProxySuite())
|
||||
.def ("reserve", &Container::reserve);
|
||||
@@ -90,21 +122,11 @@ BOOST_PYTHON_MODULE (indexing)
|
||||
.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)
|
||||
|
||||
@@ -37,28 +37,6 @@ void indexing::slice::validate () const
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Slice constructor
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
indexing::slice::slice (boost::python::detail::borrowed_reference ref)
|
||||
: boost::python::object (ref)
|
||||
, mStart (0)
|
||||
, mStep (0)
|
||||
, mStop (0)
|
||||
, mDirection (0)
|
||||
{
|
||||
if (!PySlice_Check (this->ptr()))
|
||||
{
|
||||
PyErr_SetString (PyExc_TypeError
|
||||
, "slice constructor: passed a non-slice object");
|
||||
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
|
||||
// This slice object is useless until setLength is called
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Set up our member variables for a sequence of a given length
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#ifndef slice_rmg_20030910_included
|
||||
#define slice_rmg_20030910_included
|
||||
|
||||
#include <Python.h>
|
||||
#include <boost/python/object.hpp>
|
||||
#include <boost/python/converter/pytype_object_mgr_traits.hpp>
|
||||
|
||||
@@ -38,7 +37,8 @@ namespace indexing
|
||||
// A newly constructed slice object is useless until setLength is called
|
||||
//
|
||||
|
||||
slice (boost::python::detail::borrowed_reference ref);
|
||||
template<typename T> slice (T const &ref);
|
||||
|
||||
void setLength (int sequenceLength);
|
||||
|
||||
int start() const { validate(); return mStart; }
|
||||
@@ -59,6 +59,25 @@ namespace indexing
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
indexing::slice::slice (T const &ref)
|
||||
: boost::python::object (ref)
|
||||
, mStart (0)
|
||||
, mStep (0)
|
||||
, mStop (0)
|
||||
, mDirection (0)
|
||||
{
|
||||
if (!PySlice_Check (this->ptr()))
|
||||
{
|
||||
PyErr_SetString (PyExc_TypeError
|
||||
, "slice constructor: passed a non-slice object");
|
||||
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
|
||||
// This slice object is still useless until setLength is called
|
||||
}
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
// Specialized converter to handle PySlice_Type objects
|
||||
template<>
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace indexing
|
||||
{
|
||||
static boost::python::object make_getitem (Policy const &);
|
||||
static boost::python::object make_setitem (Policy const &);
|
||||
static boost::python::object make_delitem (Policy const &);
|
||||
static boost::python::object make_extend (Policy const &);
|
||||
|
||||
private:
|
||||
typedef typename Algorithms::container container;
|
||||
@@ -47,6 +49,8 @@ namespace indexing
|
||||
|
||||
static boost::python::list get_slice (container &, slice);
|
||||
static void set_slice (container &, slice, boost::python::object);
|
||||
static void del_slice (container &, slice);
|
||||
static void extend (container &, boost::python::object);
|
||||
|
||||
struct postcall_override
|
||||
{
|
||||
@@ -111,7 +115,7 @@ namespace indexing
|
||||
, typename Algorithms::index_param from
|
||||
, typename Algorithms::index_param to)
|
||||
{
|
||||
Algorithms::erase (c, from, to);
|
||||
Algorithms::erase_range (c, from, to);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -183,6 +187,32 @@ indexing::slice_handler<Algorithms, Policy>
|
||||
return boost::python::make_function (set_slice, policy);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Return a function object that implements the slice version of __delitem__
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
boost::python::object
|
||||
indexing::slice_handler<Algorithms, Policy>
|
||||
::make_delitem (Policy const &policy)
|
||||
{
|
||||
// should we try to get funky with policy::precall?
|
||||
return boost::python::make_function (del_slice, policy);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Return a function object that implements extend
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
boost::python::object
|
||||
indexing::slice_handler<Algorithms, Policy>
|
||||
::make_extend (Policy const &policy)
|
||||
{
|
||||
// should we try to get funky with policy::precall?
|
||||
return boost::python::make_function (extend, policy);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation for the slice version of __getitem__
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -233,7 +263,12 @@ indexing::slice_handler<Algorithms, Policy>
|
||||
}
|
||||
|
||||
typedef typename Algorithms::container_traits traits;
|
||||
typedef boost::python::extract<typename Algorithms::value_param> extractor;
|
||||
|
||||
// Try two kinds of extractors - the first is more efficient (using
|
||||
// a reference to existing object, if possible and sensible) and the
|
||||
// second allowing implicit conversions.
|
||||
typedef boost::python::extract<typename Algorithms::value_param> extractor1;
|
||||
typedef boost::python::extract<typename Algorithms::value_type> extractor2;
|
||||
|
||||
// Note: any error during this operation will probably leave the
|
||||
// container partially updated. This can occur (for example) if the
|
||||
@@ -250,7 +285,17 @@ indexing::slice_handler<Algorithms, Policy>
|
||||
{
|
||||
if (sl.inRange (index))
|
||||
{
|
||||
Algorithms::assign (c, index, extractor (iterPtr->current()));
|
||||
extractor1 ex1 (iterPtr->current());
|
||||
|
||||
if (ex1.check())
|
||||
{
|
||||
Algorithms::assign (c, index, ex1);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Algorithms::assign (c, index, extractor2 (iterPtr->current()));
|
||||
}
|
||||
}
|
||||
|
||||
else if (sl.step() != 1)
|
||||
@@ -266,9 +311,22 @@ indexing::slice_handler<Algorithms, Policy>
|
||||
// Could optimize this in some cases (i.e. if the length of
|
||||
// the replacement sequence is known)
|
||||
|
||||
maybe_insert<traits::has_insert>
|
||||
::template apply<Algorithms> (c, index
|
||||
, extractor (iterPtr->current()));
|
||||
extractor1 ex1 (iterPtr->current());
|
||||
|
||||
if (ex1.check())
|
||||
{
|
||||
maybe_insert<traits::has_insert>
|
||||
::template apply<Algorithms> (c, index, ex1);
|
||||
|
||||
Algorithms::assign (c, index, ex1);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
maybe_insert<traits::has_insert>
|
||||
::template apply<Algorithms>
|
||||
(c, index, extractor2 (iterPtr->current()));
|
||||
}
|
||||
}
|
||||
|
||||
index += sl.step();
|
||||
@@ -293,4 +351,41 @@ indexing::slice_handler<Algorithms, Policy>
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation for the slice version of __delitem__
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
void
|
||||
indexing::slice_handler<Algorithms, Policy>
|
||||
::del_slice (container &c, slice sl)
|
||||
{
|
||||
sl.setLength (Algorithms::size (c)); // Current length of our container
|
||||
|
||||
Algorithms::erase_range (c, sl.start(), sl.stop());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of extend
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
void
|
||||
indexing::slice_handler<Algorithms, Policy>
|
||||
::extend (container &c, boost::python::object values)
|
||||
{
|
||||
boost::python::object length
|
||||
((boost::python::detail::new_reference
|
||||
(PyInt_FromLong (Algorithms::size (c)))));
|
||||
|
||||
indexing::slice sl
|
||||
((boost::python::detail::new_reference
|
||||
(PySlice_New
|
||||
(length.ptr()
|
||||
, boost::python::object().ptr()
|
||||
, boost::python::object().ptr()))));
|
||||
|
||||
set_slice (c, sl, values);
|
||||
}
|
||||
|
||||
#endif // slice_handler_rmg_20030909_included
|
||||
|
||||
@@ -22,14 +22,43 @@
|
||||
# $Id$
|
||||
#
|
||||
|
||||
from testsuite import Array, getArray
|
||||
from testsuite import Array, getArray, IntWrapper, setTrace
|
||||
|
||||
setTrace (0)
|
||||
|
||||
a = getArray()
|
||||
|
||||
print a[0], a[1], a[2], [x for x in a], a[0:-2], a[-1:-3:-1], a[0:54:0]
|
||||
print a[0], a[1], a[2], [x for x in a], a[0:-2], a[-1:-3:-1]
|
||||
|
||||
try:
|
||||
a[0:54:0]
|
||||
|
||||
except ValueError, e:
|
||||
print "Got expected ValueError:", e
|
||||
pass
|
||||
|
||||
a[1] = 4
|
||||
|
||||
print a[0], a[1], a[2], [x for x in a], a[0:-2], a[-1:-3:-1]
|
||||
|
||||
print a[0:43]
|
||||
print a[0:43] # Try index beyond length
|
||||
|
||||
# Try slice assignment with correct length
|
||||
a[0:2] = [IntWrapper(-1), IntWrapper(-2)]
|
||||
print [x for x in a]
|
||||
|
||||
# Try slice assignment with overlong sequence
|
||||
try:
|
||||
a[0:1] = [IntWrapper(-1), IntWrapper(-2)]
|
||||
|
||||
except TypeError, e:
|
||||
print "Got expected TypeError:", e
|
||||
pass
|
||||
|
||||
# Try slice assignment with short sequence
|
||||
try:
|
||||
a[0:3] = [IntWrapper(-1), IntWrapper(-2)]
|
||||
|
||||
except TypeError, e:
|
||||
print "Got expected TypeError:", e
|
||||
pass
|
||||
|
||||
@@ -23,48 +23,89 @@
|
||||
#
|
||||
|
||||
from indexing import *
|
||||
import sys
|
||||
|
||||
trace(0)
|
||||
setTrace(0)
|
||||
|
||||
def test_from_empty(v):
|
||||
if hasattr(sys, "gettotalrefcount"):
|
||||
def dumper() : print "refcount:", sys.gettotalrefcount()
|
||||
|
||||
maybe_dump_refcount = dumper
|
||||
else:
|
||||
def dumper() : pass
|
||||
|
||||
maybe_dump_refcount = dumper
|
||||
|
||||
def test_from_empty(v, outfile = sys.stdout):
|
||||
# v.reserve (10);
|
||||
|
||||
print v
|
||||
print >> outfile, v
|
||||
|
||||
v.append (IntWrapper (1))
|
||||
v.append (IntWrapper (2))
|
||||
v.append (IntWrapper (3))
|
||||
|
||||
print v[0], v[1], v[2]
|
||||
print >> outfile, v[0], v[1], v[2]
|
||||
|
||||
try:
|
||||
print v[0], v[1:][0], v[-1:][0]
|
||||
print >> outfile, v[0], v[1:][0], v[-1:][0]
|
||||
|
||||
except Exception, e:
|
||||
print e
|
||||
print >> outfile, e
|
||||
pass
|
||||
|
||||
copy = v[1]
|
||||
|
||||
print "copy is %s, v[1] is %s" % (copy, v[1])
|
||||
print >> outfile, "copy is %s, v[1] is %s" % (copy, v[1])
|
||||
v[1].increment()
|
||||
print "copy is %s, v[1] is %s" % (copy, v[1])
|
||||
print >> outfile, "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])
|
||||
print >> outfile, "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])
|
||||
print >> outfile, "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])
|
||||
print >> outfile, "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])
|
||||
print >> outfile, "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 >> outfile, "slice[0] is %s, copy is %s, v[1] is %s" % (slice[0], copy, v[1])
|
||||
|
||||
print "============="
|
||||
# if hasattr(sys, "gettotalrefcount"):
|
||||
# for x in range(20):
|
||||
# v[:] = [1,2,3,4]
|
||||
# maybe_dump_refcount()
|
||||
|
||||
# for x in range(9):
|
||||
# v[:] = [1,2,3,4]
|
||||
# maybe_dump_refcount()
|
||||
|
||||
print >> outfile, "============="
|
||||
|
||||
#test_from_empty (Vector_proxy())
|
||||
|
||||
class write_eater:
|
||||
def write (self, str):
|
||||
pass
|
||||
|
||||
# Run everything through once to settle reference counters
|
||||
test_from_empty (Vector(), write_eater())
|
||||
test_from_empty (ProxyVector(), write_eater())
|
||||
test_from_empty (PointerVector(), write_eater())
|
||||
test_from_empty ([], write_eater())
|
||||
|
||||
# Run again with output (and ref-count dumping, if possible)
|
||||
maybe_dump_refcount()
|
||||
|
||||
test_from_empty (Vector())
|
||||
maybe_dump_refcount()
|
||||
|
||||
test_from_empty (ProxyVector())
|
||||
maybe_dump_refcount()
|
||||
|
||||
test_from_empty (PointerVector())
|
||||
maybe_dump_refcount()
|
||||
|
||||
test_from_empty ([])
|
||||
maybe_dump_refcount()
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <boost/python/implicit.hpp>
|
||||
|
||||
#include "iterator_pair.hpp"
|
||||
#include "container_proxy.hpp"
|
||||
|
||||
indexing::iterator_pair<IntWrapper *> getArray()
|
||||
{
|
||||
@@ -63,7 +64,8 @@ BOOST_PYTHON_MODULE(testsuite)
|
||||
|
||||
boost::python::class_<IntWrapper> ("IntWrapper", boost::python::init<int>())
|
||||
.def ("increment", &IntWrapper::increment)
|
||||
.def ("__repr__", repr);
|
||||
.def ("__repr__", repr)
|
||||
.def ("__cmp__", compare)
|
||||
;
|
||||
|
||||
typedef std::vector<int> Container1;
|
||||
@@ -96,4 +98,9 @@ BOOST_PYTHON_MODULE(testsuite)
|
||||
// deletes!
|
||||
boost::python::class_<Container5>("Vector_ref")
|
||||
.def (indexing::container_suite<Container5>::generate (boost::python::return_internal_reference<>()));
|
||||
|
||||
typedef container_proxy<std::vector<IntWrapper> > Container6;
|
||||
|
||||
boost::python::class_<Container6>("Vector_proxy")
|
||||
.def (indexing::container_suite<Container6>::generate ());
|
||||
}
|
||||
|
||||
@@ -22,18 +22,60 @@
|
||||
# $Id$
|
||||
#
|
||||
|
||||
from testsuite import Vector
|
||||
from testsuite import Vector, Vector_ref, setTrace
|
||||
|
||||
v = Vector()
|
||||
def test_vector(v):
|
||||
v.append(1)
|
||||
v.append(2)
|
||||
v.append(3)
|
||||
|
||||
v.append(1)
|
||||
v.append(2)
|
||||
v.append(3)
|
||||
print v[0], v[1], v[2], [x for x in v]
|
||||
|
||||
print v[0], v[1], v[2], [x for x in v]
|
||||
v[1] = 4
|
||||
|
||||
v[1] = 4
|
||||
print v[0], v[1], v[2], [x for x in v], v[0:2]
|
||||
|
||||
print v[0], v[1], v[2], [x for x in v]
|
||||
# Try slice assignment with equal lengths
|
||||
v[0:2] = [9, 8]
|
||||
print [x for x in v]
|
||||
|
||||
print v[0:2]
|
||||
# Try slice assignment with shorter replacement
|
||||
v[0:2] = [7]
|
||||
print [x for x in v]
|
||||
|
||||
# Try slice assignment with longer replacement
|
||||
v[0:1] = [6, 5, 4]
|
||||
print [x for x in v]
|
||||
|
||||
# Try element deletion
|
||||
del v[0]
|
||||
print [x for x in v]
|
||||
|
||||
# Try slice deletion
|
||||
del v[0:2]
|
||||
print [x for x in v]
|
||||
|
||||
try:
|
||||
del v[3]
|
||||
|
||||
except IndexError, e:
|
||||
print "Got expected exception:", e
|
||||
|
||||
print [x for x in v]
|
||||
|
||||
del v[0:999]
|
||||
print [x for x in v]
|
||||
|
||||
v.append (3)
|
||||
print v[0]
|
||||
del v[:]
|
||||
print [x for x in v]
|
||||
|
||||
print "Plain vector:"
|
||||
print "============="
|
||||
test_vector (Vector())
|
||||
|
||||
print "Ref vector:"
|
||||
print "==========="
|
||||
setTrace(0)
|
||||
test_vector (Vector_ref())
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include "container_proxy.hpp"
|
||||
#include "container_suite.hpp"
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -23,11 +23,6 @@ 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")
|
||||
@@ -35,6 +30,7 @@ BOOST_PYTHON_MODULE(vector_indexing_suite_ext)
|
||||
.def(init<X>())
|
||||
.def(init<std::string>())
|
||||
.def("__repr__", &X::repr)
|
||||
.def("__eq__", &X::operator==)
|
||||
.def("reset", &X::reset)
|
||||
.def("foo", &X::foo)
|
||||
;
|
||||
@@ -45,12 +41,8 @@ BOOST_PYTHON_MODULE(vector_indexing_suite_ext)
|
||||
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>())
|
||||
.def(indexing::container_suite<Container>::generate())
|
||||
;
|
||||
|
||||
// Compile check only...
|
||||
|
||||
@@ -28,14 +28,68 @@
|
||||
|
||||
#include <boost/python/def_visitor.hpp>
|
||||
#include <boost/python/iterator.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace indexing {
|
||||
namespace detail {
|
||||
template<typename PrecallPolicy>
|
||||
struct precall_only : public boost::python::default_call_policies
|
||||
{
|
||||
// This policies struct uses default policies for everything
|
||||
// except precall, which must be provided by the template
|
||||
// argument.
|
||||
|
||||
precall_only () : mPrecall () { }
|
||||
explicit precall_only (PrecallPolicy const ©) : mPrecall (copy) { }
|
||||
|
||||
bool precall (PyObject *args) { return mPrecall.precall (args); }
|
||||
bool precall (PyObject *args) const { return mPrecall.precall (args); }
|
||||
|
||||
private:
|
||||
PrecallPolicy mPrecall;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __len__ dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_len {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __len__ real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_len<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__len__", &Algorithms::size, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __getitem__ dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<IndexStyle>
|
||||
struct maybe_add_getitem {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __getitem__ no-slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_getitem<index_style_nonlinear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
@@ -47,6 +101,10 @@ namespace indexing {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __getitem__ with slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_getitem<index_style_linear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
@@ -60,12 +118,20 @@ namespace indexing {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __setitem__ dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<IndexStyle>
|
||||
struct maybe_add_setitem {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __setitem__ no-slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_setitem<index_style_nonlinear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
@@ -77,6 +143,10 @@ namespace indexing {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __setitem__ with slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_setitem<index_style_linear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
@@ -90,12 +160,62 @@ namespace indexing {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __delitem__ dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit, IndexStyle syle>
|
||||
struct maybe_add_delitem {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __delitem__ no-slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_delitem<true, index_style_nonlinear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__delitem__", &Algorithms::erase_one, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __delitem__ with slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_delitem<true, index_style_linear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__delitem__", &Algorithms::erase_one, policy);
|
||||
pyClass.def ("__delitem__"
|
||||
, slice_handler<Algorithms, Policy>::make_delitem (policy));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __iter__ dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_iter {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __iter__ real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_iter<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
@@ -103,18 +223,29 @@ namespace indexing {
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
// *FIXME* seperate precall and postcall portions of the
|
||||
// policy (precall when generating the range object, postcall
|
||||
// when returing from range.next())
|
||||
pyClass.def ("__iter__"
|
||||
, boost::python::range<Policy> (Algorithms::begin
|
||||
, Algorithms::end));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// append dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_append {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// append real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_append<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
@@ -126,6 +257,155 @@ namespace indexing {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// extend dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_extend {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// extend real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_extend<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("extend"
|
||||
, slice_handler<Algorithms, Policy>::make_extend (policy));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// index dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_index {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// index real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
template<typename Algorithms>
|
||||
typename Algorithms::index_type
|
||||
get_index (typename Algorithms::container &c
|
||||
, typename Algorithms::key_param key)
|
||||
{
|
||||
typename Algorithms::iterator temp (Algorithms::find (c, key));
|
||||
|
||||
if (temp == Algorithms::end(c))
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "get_index: element not found");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
|
||||
return std::distance (Algorithms::begin (c), temp);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
struct maybe_add_index<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("index", detail::get_index<Algorithms>, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// count dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit, IndexStyle>
|
||||
struct maybe_add_count {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// count real (sequences without indexing)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_count<true, index_style_none> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("count", Algorithms::count, policy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// count real (sequences with indexing)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_count<true, index_style_linear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
// This is identical to the index_style_none version. Doing it
|
||||
// this way avoids using a partial specialization for
|
||||
// <true, *>
|
||||
pyClass.def ("count", Algorithms::count, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// count real (associative containers). add has_key
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
template<typename Algorithms>
|
||||
bool has_key (typename Algorithms::container &c
|
||||
, typename Algorithms::key_param key)
|
||||
{
|
||||
return Algorithms::find (c, key) != Algorithms::end (c);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
struct maybe_add_count<true, index_style_nonlinear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
// Nearest equivalent is has_key, since Python dictionaries
|
||||
// have at most one value for a key.
|
||||
pyClass.def ("has_key", detail::has_key<Algorithms>, policy);
|
||||
|
||||
// Maybe this makes sense for multimap or multiset. Then again,
|
||||
// maybe they should always return a list of elements for a key?
|
||||
pyClass.def ("count", Algorithms::count, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Do-all visitor
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
class visitor
|
||||
: public boost::python::def_visitor< visitor< Algorithms, Policy > >
|
||||
@@ -136,23 +416,49 @@ namespace indexing {
|
||||
typedef Algorithms algorithms;
|
||||
typedef typename algorithms::container_traits traits;
|
||||
|
||||
visitor (Policy const &policy) : mPolicy (policy) { }
|
||||
explicit visitor (Policy const &policy = Policy()) : mPolicy (policy) { }
|
||||
|
||||
template <class PythonClass>
|
||||
void visit (PythonClass &pyClass) const
|
||||
{
|
||||
detail::precall_only<Policy> precallPolicy (mPolicy);
|
||||
|
||||
// Note - this will add __len__ for anything that can determine
|
||||
// its size, even if that might be inefficient (e.g. have linear
|
||||
// time complexity). It might be better to add a new feature
|
||||
// selection flag to the container_traits to make this
|
||||
// configurable.
|
||||
maybe_add_len<traits::has_copyable_iter>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_getitem<traits::index_style>
|
||||
::apply (pyClass, algorithms(), mPolicy);
|
||||
|
||||
maybe_add_setitem<traits::index_style>
|
||||
::apply (pyClass, algorithms(), mPolicy);
|
||||
|
||||
maybe_add_delitem<traits::has_erase, traits::index_style>
|
||||
::apply (pyClass, algorithms(), mPolicy);
|
||||
|
||||
maybe_add_iter<((traits::index_style != index_style_linear)
|
||||
&& traits::has_copyable_iter)>
|
||||
::apply (pyClass, algorithms(), mPolicy);
|
||||
|
||||
maybe_add_append<traits::has_push_back>
|
||||
::apply (pyClass, algorithms(), mPolicy);
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_extend<(traits::has_insert
|
||||
&& traits::index_style == index_style_linear)>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_index<(traits::has_find
|
||||
&& (traits::index_style == index_style_linear))>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_count<traits::has_find, traits::index_style>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
Algorithms::visitor_helper (pyClass, mPolicy);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user