mirror of
https://github.com/boostorg/python.git
synced 2026-01-30 20:12:37 +00:00
Version 2 of the python indexing suite
[SVN r20288]
This commit is contained in:
195
include/boost/python/suite/indexing/algo_selector.hpp
Executable file
195
include/boost/python/suite/indexing/algo_selector.hpp
Executable file
@@ -0,0 +1,195 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file algo_selector.hpp
|
||||
//
|
||||
// Automatic selection of container algorithms (and traits) for known
|
||||
// container types (basically, all STL container instances, as well as
|
||||
// iterator_pair instances).
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/11 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef algo_selector_rmg_20030911_included
|
||||
#define algo_selector_rmg_20030911_included
|
||||
|
||||
#include <boost/python/suite/indexing/container_traits.hpp>
|
||||
#include <boost/python/suite/indexing/algorithms.hpp>
|
||||
|
||||
// Definitions of supported types
|
||||
#include <boost/python/suite/indexing/iterator_pair.hpp>
|
||||
#include <boost/python/suite/indexing/container_proxy.hpp>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Automated algorithm and trait selection
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
template<typename Container> struct selector_impl;
|
||||
|
||||
// selector_impl instances should include *two* publically
|
||||
// accessible typedefs, one for the non-const version of the
|
||||
// container, and one for the const version. This saves having to
|
||||
// have two specializations of selector_impl for every kind of
|
||||
// container.
|
||||
|
||||
// std::set
|
||||
template <class Key, class Compare, class Allocator>
|
||||
class selector_impl<std::set<Key, Compare, Allocator> >
|
||||
{
|
||||
typedef std::set<Key, Compare, Allocator> Container;
|
||||
|
||||
typedef set_traits<Container> mutable_traits;
|
||||
typedef set_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef set_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef set_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// std::multiset
|
||||
template <class Key, class Compare, class Allocator>
|
||||
class selector_impl<std::multiset<Key, Compare, Allocator> >
|
||||
{
|
||||
typedef std::multiset<Key, Compare, Allocator> Container;
|
||||
|
||||
typedef set_traits<Container> mutable_traits;
|
||||
typedef set_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef set_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef set_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// std::map
|
||||
template <class Key, class T, class Compare, class Allocator>
|
||||
class selector_impl<std::map<Key, T, Compare, Allocator> >
|
||||
{
|
||||
typedef std::map<Key, T, Compare, Allocator> Container;
|
||||
|
||||
typedef map_traits<Container> mutable_traits;
|
||||
typedef map_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef map_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef map_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// std::multimap
|
||||
template <class Key, class T, class Compare, class Allocator>
|
||||
class selector_impl<std::multimap<Key, T, Compare, Allocator> >
|
||||
{
|
||||
typedef std::multimap<Key, T, Compare, Allocator> Container;
|
||||
|
||||
typedef map_traits<Container> mutable_traits;
|
||||
typedef map_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef map_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef map_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// std::vector
|
||||
template <class T, class Allocator>
|
||||
class selector_impl<std::vector<T, Allocator> >
|
||||
{
|
||||
typedef std::vector<T, Allocator> Container;
|
||||
|
||||
typedef default_sequence_traits<Container> mutable_traits;
|
||||
typedef default_sequence_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef default_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef default_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// std::deque
|
||||
template <class T, class Allocator>
|
||||
class selector_impl<std::deque<T, Allocator> >
|
||||
{
|
||||
typedef std::deque<T, Allocator> Container;
|
||||
|
||||
typedef default_sequence_traits<Container> mutable_traits;
|
||||
typedef default_sequence_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef default_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef default_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// std::list
|
||||
template <class T, class Allocator>
|
||||
class selector_impl<std::list<T, Allocator> >
|
||||
{
|
||||
typedef std::list<T, Allocator> Container;
|
||||
|
||||
typedef default_sequence_traits<Container> mutable_traits;
|
||||
typedef default_sequence_traits<Container const> const_traits;
|
||||
|
||||
public:
|
||||
typedef list_algorithms<mutable_traits> mutable_algorithms;
|
||||
typedef list_algorithms<const_traits> const_algorithms;
|
||||
};
|
||||
|
||||
// Iterator ranges
|
||||
template <typename Iterator>
|
||||
class selector_impl<iterator_pair<Iterator> >
|
||||
{
|
||||
typedef iterator_pair<Iterator> Container;
|
||||
|
||||
typedef iterator_pair_traits<Container> mutable_traits;
|
||||
typedef iterator_pair_traits<Container const> const_traits; // ?
|
||||
|
||||
public:
|
||||
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
|
||||
|
||||
// Generic version (mutable containers)
|
||||
template<class Container>
|
||||
struct algo_selector
|
||||
: public detail::selector_impl<Container>::mutable_algorithms
|
||||
{
|
||||
};
|
||||
|
||||
// Partial specialization for const containers
|
||||
template<class Container>
|
||||
struct algo_selector<Container const>
|
||||
: public detail::selector_impl<Container>::const_algorithms
|
||||
{
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif // algo_selector_rmg_20030911_included
|
||||
602
include/boost/python/suite/indexing/algorithms.hpp
Executable file
602
include/boost/python/suite/indexing/algorithms.hpp
Executable file
@@ -0,0 +1,602 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file algorithms.hpp
|
||||
//
|
||||
// Uniform interface layer for all containers.
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/11 rmg File creation from suite_utils.hpp
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef algorithms_rmg_20030823_included
|
||||
#define algorithms_rmg_20030823_included
|
||||
|
||||
#include <boost/python/suite/indexing/suite_utils.hpp>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
template<typename ContainerTraits>
|
||||
struct default_algorithms
|
||||
{
|
||||
typedef ContainerTraits container_traits;
|
||||
|
||||
// Import typedefs from the container_traits for convenience
|
||||
typedef typename ContainerTraits::container container;
|
||||
typedef typename ContainerTraits::iterator iterator;
|
||||
typedef typename ContainerTraits::reference reference;
|
||||
typedef typename ContainerTraits::size_type size_type;
|
||||
typedef typename ContainerTraits::value_type value_type;
|
||||
typedef typename ContainerTraits::value_param value_param;
|
||||
typedef typename ContainerTraits::index_param index_param;
|
||||
typedef typename ContainerTraits::key_param key_param;
|
||||
|
||||
static size_type size (container &);
|
||||
static iterator find (container &, key_param);
|
||||
static size_type get_index (container &, key_param);
|
||||
static size_type count (container &, key_param);
|
||||
static bool contains (container &, key_param);
|
||||
static void reverse (container &);
|
||||
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_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
|
||||
, bool truncate = false);
|
||||
// Throws std::out_of_range if necessary. If one_past is set, then
|
||||
// indexes up to container.size() *inclusive* are allowed. If
|
||||
// truncate is set, then out of bounds values are reset to the
|
||||
// nearest in-bound value (and if none exists, throws an
|
||||
// exception). If truncate is *not* set, then negative values index
|
||||
// from the upper bound backwards and are bounds-checked.
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Special cases for std::list
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct list_algorithms : public default_algorithms<ContainerTraits>
|
||||
{
|
||||
private:
|
||||
typedef default_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 *);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Base class for associative containers
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct assoc_algorithms : public default_algorithms<ContainerTraits>
|
||||
{
|
||||
private:
|
||||
typedef default_algorithms<ContainerTraits> Parent;
|
||||
|
||||
public:
|
||||
typedef typename Parent::iterator iterator;
|
||||
typedef typename Parent::size_type size_type;
|
||||
typedef typename Parent::container container;
|
||||
typedef typename Parent::reference reference;
|
||||
typedef typename Parent::key_param key_param;
|
||||
typedef typename Parent::value_param value_param;
|
||||
typedef typename Parent::index_param index_param;
|
||||
|
||||
static reference get (container &, index_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);
|
||||
static bool contains (container &, key_param);
|
||||
|
||||
protected:
|
||||
static iterator find_or_throw (container &, index_param);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Special case for sets
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct set_algorithms : public assoc_algorithms<ContainerTraits>
|
||||
{
|
||||
private:
|
||||
typedef assoc_algorithms<ContainerTraits> Parent;
|
||||
|
||||
public:
|
||||
typedef typename Parent::container container;
|
||||
typedef typename Parent::value_param value_param;
|
||||
typedef typename Parent::index_param index_param;
|
||||
|
||||
static void assign (container &, index_param, value_param);
|
||||
static void insert (container &, index_param);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Special case for map
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
struct map_algorithms : public assoc_algorithms<ContainerTraits>
|
||||
{
|
||||
private:
|
||||
typedef assoc_algorithms<ContainerTraits> Parent;
|
||||
|
||||
public:
|
||||
typedef typename Parent::container container;
|
||||
typedef typename Parent::reference reference;
|
||||
typedef typename Parent::index_param index_param;
|
||||
typedef typename Parent::value_param value_param;
|
||||
|
||||
static reference get (container &, index_param);
|
||||
// Version to return only the mapped type
|
||||
|
||||
static void assign (container &, index_param, value_param);
|
||||
static void insert (container &, index_param, value_param);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Get the size of a container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::size_type
|
||||
default_algorithms<ContainerTraits>::size (container &c)
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Range check an index and throw out_of_range if necessary
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::size_type
|
||||
default_algorithms<ContainerTraits>::bounds_check (container &c
|
||||
, index_param ix
|
||||
, char const *msg
|
||||
, bool one_past
|
||||
, bool truncate)
|
||||
{
|
||||
size_type bound = size(c) + (one_past ? 1 : 0);
|
||||
size_type result;
|
||||
|
||||
if (truncate)
|
||||
{
|
||||
if (ix < 0)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
result = ix;
|
||||
|
||||
if ((result >= bound) && (bound > 0))
|
||||
{
|
||||
result = bound - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (ix < 0)
|
||||
{
|
||||
if (size_type(-ix) > bound)
|
||||
{
|
||||
throw std::out_of_range (msg);
|
||||
}
|
||||
|
||||
result = bound + ix;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
result = ix;
|
||||
}
|
||||
|
||||
if (result >= bound)
|
||||
{
|
||||
throw std::out_of_range (msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element and return its index (std algorithm version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename default_algorithms<ContainerTraits>::size_type
|
||||
default_algorithms<ContainerTraits>::get_index (container &c
|
||||
, key_param key)
|
||||
{
|
||||
iterator temp (find (c, key));
|
||||
|
||||
if (temp == end(c))
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "get_index: element not found");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
|
||||
return std::distance (begin (c), temp);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Check whether a container contains the given element (std algo ver)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
bool
|
||||
default_algorithms<ContainerTraits>::contains (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return find (c, key) != end(c);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// 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[bounds_check (c, ix, "get")];
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// 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[bounds_check (c, ix, "assign")] = 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)
|
||||
{
|
||||
iterator insert_pos (c.begin());
|
||||
|
||||
// Index may range up to c.size() inclusive to allow inserting at end
|
||||
std::advance (insert_pos, bounds_check (c, i, "insert", true, true));
|
||||
c.insert (insert_pos, v);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Erase between given indexes in the container (generic version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
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
|
||||
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 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));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Visitor helper function (default version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
template<typename PythonClass, typename Policy>
|
||||
void
|
||||
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 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();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::reference
|
||||
assoc_algorithms<ContainerTraits>::get (container &c, index_param ix)
|
||||
{
|
||||
return *find_or_throw (c, ix);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Index into a container (map version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename map_algorithms<ContainerTraits>::reference
|
||||
map_algorithms<ContainerTraits>::get (container &c, index_param ix)
|
||||
{
|
||||
return find_or_throw (c, ix)->second;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Erase elements with the given key (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
assoc_algorithms<ContainerTraits>::erase_one (container &c
|
||||
, key_param key)
|
||||
{
|
||||
if (c.erase (key) == 0)
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "Container does not hold value to be erased");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Assign a value at a particular index (set version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
set_algorithms<ContainerTraits>::assign (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
insert (c, ix); // Ignore dummy value parameter
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Insert an element into a set
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
set_algorithms<ContainerTraits>::insert (container &c
|
||||
, index_param ix)
|
||||
{
|
||||
if (!c.insert (ix).second)
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "Set already holds value for insertion");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Assign a value at a particular index (map version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
map_algorithms<ContainerTraits>::assign (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
c[ix] = val; // Handles overwrite and insert
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Insert a new key, value pair into a map
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
void
|
||||
map_algorithms<ContainerTraits>::insert (container &c
|
||||
, index_param ix
|
||||
, value_param val)
|
||||
{
|
||||
typedef std::pair
|
||||
<typename container_traits::index_type
|
||||
, typename container_traits::value_type>
|
||||
pair_type;
|
||||
|
||||
// Can't use std::make_pair, because param types may be references
|
||||
|
||||
if (!c.insert (pair_type (ix, val)).second)
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "Map already holds value for insertion");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in an associative container
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
bool
|
||||
assoc_algorithms<ContainerTraits>::contains (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return find (c, key) != end(c);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Find an element in an associative container - throw an exception if
|
||||
// not found
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::iterator
|
||||
assoc_algorithms<ContainerTraits>::find_or_throw (container &c
|
||||
, index_param ix)
|
||||
{
|
||||
iterator iter = find (c, ix);
|
||||
|
||||
if (iter == end(c))
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "associative container: key not found");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Count occurances of an element in a container (associative version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ContainerTraits>
|
||||
typename assoc_algorithms<ContainerTraits>::size_type
|
||||
assoc_algorithms<ContainerTraits>::count (container &c
|
||||
, key_param key)
|
||||
{
|
||||
return c.count (key);
|
||||
}
|
||||
} } }
|
||||
|
||||
#endif // algorithms_rmg_20030823_included
|
||||
543
include/boost/python/suite/indexing/container_proxy.hpp
Executable file
543
include/boost/python/suite/indexing/container_proxy.hpp
Executable file
@@ -0,0 +1,543 @@
|
||||
// -*- mode:c++; switch-modules-target: "testcontprox.cpp" -*-
|
||||
//
|
||||
// Header file container_proxy.hpp
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 8/26 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef container_proxy_rmg_20030826_included
|
||||
#define container_proxy_rmg_20030826_included
|
||||
|
||||
#include <boost/python/suite/indexing/shared_proxy_impl.hpp>
|
||||
#include <boost/python/suite/indexing/element_proxy.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
template<typename T> struct identity {
|
||||
typedef T held_type;
|
||||
|
||||
static T & get(T & obj) { return obj; }
|
||||
static T const & get(T const & obj) { return obj; }
|
||||
|
||||
static T create () { return T(); }
|
||||
static T copy (T const ©) { return copy; }
|
||||
static void assign (T &to, T const &from) { to = from; }
|
||||
static void pre_destruction (T &) { }
|
||||
};
|
||||
|
||||
template<typename P> struct deref {
|
||||
typedef P held_type;
|
||||
|
||||
typedef typename boost::iterator_value<P>::type value;
|
||||
|
||||
static value & get (P & ptr) { return *ptr; }
|
||||
static value const & get (P const & ptr) { return *ptr; }
|
||||
|
||||
static P create () { return P(); }
|
||||
static P copy (P const ©) { return copy; }
|
||||
static void assign (P &to, P const &from) { to = from; }
|
||||
static void pre_destruction (P &) { }
|
||||
};
|
||||
|
||||
template<class Container
|
||||
, class Holder = identity<Container> >
|
||||
class container_proxy
|
||||
{
|
||||
typedef container_proxy<Container, Holder> self_type;
|
||||
typedef typename Container::iterator raw_iterator;
|
||||
typedef std::iterator_traits<raw_iterator> raw_iterator_traits;
|
||||
|
||||
template<class C> friend class shared_proxy_impl;
|
||||
|
||||
public:
|
||||
typedef typename Holder::held_type held_type;
|
||||
|
||||
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;
|
||||
|
||||
typedef element_proxy<self_type> value_type;
|
||||
typedef value_type reference; // Already has ref. semantics
|
||||
|
||||
typedef const_element_proxy<self_type> const_value_type;
|
||||
typedef const_value_type const_reference; // Ref. semantics
|
||||
|
||||
public:
|
||||
struct iterator
|
||||
{
|
||||
typedef typename raw_iterator_traits::difference_type difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
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) { }
|
||||
|
||||
iterator (container_proxy *p, raw_iterator iter)
|
||||
: ptr (p), index (iter - p->raw_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) { iterator temp(*this); ++index; return temp; }
|
||||
iterator &operator+= (size_type s) { index += s; return *this; }
|
||||
|
||||
iterator &operator-- () { --index; return *this; }
|
||||
iterator operator-- (int) { iterator temp(*this); --index; return temp; }
|
||||
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); }
|
||||
|
||||
bool operator< (iterator const &other) const {
|
||||
return index < other.index;
|
||||
}
|
||||
|
||||
bool operator> (iterator const &other) const {
|
||||
return index > other.index;
|
||||
}
|
||||
|
||||
// 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 (held_type const &h);
|
||||
template<typename Iter> container_proxy (Iter, Iter);
|
||||
|
||||
container_proxy (container_proxy const &);
|
||||
container_proxy &operator= (container_proxy const &);
|
||||
~container_proxy ();
|
||||
|
||||
Container const &raw_container() const; // OK to expose const reference
|
||||
|
||||
reference at (size_type index);
|
||||
const_reference at (size_type index) const;
|
||||
|
||||
reference operator[] (size_type index) { return at(index); }
|
||||
const_reference operator[] (size_type index) const { return at(index); }
|
||||
|
||||
size_type size() const { return raw_container().size(); }
|
||||
size_type capacity() const { return raw_container().capacity(); }
|
||||
void reserve(size_type s) { raw_container().reserve(s); }
|
||||
|
||||
public:
|
||||
iterator begin() { return iterator (this, 0); }
|
||||
iterator end() { return iterator (this, raw_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); }
|
||||
|
||||
value_type pop_back () {
|
||||
value_type 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::reverse_iterator ReverseIterator;
|
||||
typedef typename MapType::value_type MapEntry;
|
||||
|
||||
private:
|
||||
Container &raw_container();
|
||||
|
||||
static void detach_if_shared (MapEntry const &);
|
||||
|
||||
template<typename Iter>
|
||||
void adjustIndexes (Iter, Iter, long offset);
|
||||
|
||||
void erase_helper (MapIterator);
|
||||
void erase_helper (ReverseIterator);
|
||||
|
||||
private:
|
||||
held_type myHeldObj;
|
||||
MapType myMap;
|
||||
};
|
||||
|
||||
template<class Container, class Holder>
|
||||
container_proxy<Container, Holder>
|
||||
::container_proxy ()
|
||||
: myHeldObj ()
|
||||
, myMap ()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
container_proxy<Container, Holder>
|
||||
::container_proxy (held_type const &heldType)
|
||||
: myHeldObj (heldType)
|
||||
, myMap ()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
template<typename Iter>
|
||||
container_proxy<Container, Holder>
|
||||
::container_proxy (Iter start, Iter finish)
|
||||
: myHeldObj (Holder::create())
|
||||
, myMap ()
|
||||
{
|
||||
insert (begin(), start, finish);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
container_proxy<Container, Holder>
|
||||
::container_proxy (container_proxy const ©)
|
||||
: myHeldObj (Holder::copy (copy.myHeldObj))
|
||||
, myMap () // Do *not* duplicate map
|
||||
{
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
container_proxy<Container, Holder> &
|
||||
container_proxy<Container, Holder>
|
||||
::operator= (container_proxy const ©)
|
||||
{
|
||||
// All of our contained values are about to be dis-owned
|
||||
std::for_each (myMap.begin(), myMap.end(), detach_if_shared);
|
||||
myMap.clear();
|
||||
Holder::assign (myHeldObj, copy.myHeldObj);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
container_proxy<Container, Holder>
|
||||
::~container_proxy ()
|
||||
{
|
||||
// All of our contained values are about to be dis-owned
|
||||
std::for_each (myMap.begin(), myMap.end(), detach_if_shared);
|
||||
Holder::pre_destruction (myHeldObj);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
Container &
|
||||
container_proxy<Container, Holder>
|
||||
::raw_container ()
|
||||
{
|
||||
return Holder::get (myHeldObj);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
Container const &
|
||||
container_proxy<Container, Holder>
|
||||
::raw_container () const
|
||||
{
|
||||
return Holder::get (myHeldObj);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
typename container_proxy<Container, Holder>::reference
|
||||
container_proxy<Container, Holder>
|
||||
::at (size_type index)
|
||||
{
|
||||
pointer_impl &entry = myMap[index];
|
||||
|
||||
if (!entry.get())
|
||||
{
|
||||
entry.reset (new shared_proxy (this, index));
|
||||
}
|
||||
|
||||
return reference (entry);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
typename container_proxy<Container, Holder>::const_reference
|
||||
container_proxy<Container, Holder>
|
||||
::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_reference (mutable_this->at (index));
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::replace (size_type index, raw_value_type const ©)
|
||||
{
|
||||
detach_proxy (index);
|
||||
raw_container().at(index) = copy;
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::replace (size_type index, Iter from, Iter to)
|
||||
{
|
||||
while (from != to)
|
||||
{
|
||||
replace (index++, *from++);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
typename container_proxy<Container, Holder>::iterator
|
||||
container_proxy<Container, Holder>
|
||||
::erase (iterator iter)
|
||||
{
|
||||
return erase (iter, iter + 1);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
typename container_proxy<Container, Holder>::iterator
|
||||
container_proxy<Container, Holder>
|
||||
::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
|
||||
= raw_container().erase (raw_container().begin() + from.index
|
||||
, raw_container().begin() + to.index);
|
||||
|
||||
return iterator (this, result);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
typename container_proxy<Container, Holder>::iterator
|
||||
container_proxy<Container, Holder>
|
||||
::insert (iterator iter, raw_value_type const ©)
|
||||
{
|
||||
assert (iter.ptr == this);
|
||||
|
||||
// Adjust indexes (backwards) down to iter.index
|
||||
adjustIndexes (myMap.rbegin()
|
||||
, ReverseIterator (myMap.lower_bound (iter.index))
|
||||
, 1);
|
||||
|
||||
// Insert the element into the real container
|
||||
raw_iterator result
|
||||
= raw_container().insert (raw_container().begin() + iter.index, copy);
|
||||
|
||||
return iterator (this, result);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::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, class Holder>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::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 (backwards) down to iter.index
|
||||
adjustIndexes (myMap.rbegin()
|
||||
, ReverseIterator (myMap.lower_bound (iter.index))
|
||||
, std::distance (from, to));
|
||||
|
||||
// Insert the element into the real container
|
||||
raw_container().insert (raw_container().begin() + iter.index, from, to);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::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, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::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, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::detach_proxy (size_type index)
|
||||
{
|
||||
MapIterator iter = myMap.find (index);
|
||||
|
||||
if (iter != myMap.end())
|
||||
{
|
||||
detach_if_shared (*iter);
|
||||
myMap.erase (iter);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::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, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::detach_proxies (iterator from, iterator to)
|
||||
{
|
||||
assert (from.ptr == this);
|
||||
assert (to.ptr == this);
|
||||
detach_proxies (from.index, to.index);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
template<typename Iter>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::adjustIndexes (Iter from, Iter 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)
|
||||
{
|
||||
Iter next (from);
|
||||
++next; // Find next element before invalidating the current one
|
||||
|
||||
pointer_impl ptr (from->second); // Copy the shared pointer
|
||||
erase_helper (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;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::erase_helper (MapIterator iter)
|
||||
{
|
||||
myMap.erase (iter);
|
||||
}
|
||||
|
||||
template<class Container, class Holder>
|
||||
void
|
||||
container_proxy<Container, Holder>
|
||||
::erase_helper (ReverseIterator iter)
|
||||
{
|
||||
++iter;
|
||||
myMap.erase (iter.base());
|
||||
}
|
||||
} } }
|
||||
|
||||
#endif // container_proxy_rmg_20030826_included
|
||||
46
include/boost/python/suite/indexing/container_suite.hpp
Executable file
46
include/boost/python/suite/indexing/container_suite.hpp
Executable file
@@ -0,0 +1,46 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file container_suite.hpp
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 8/23 rmg File creation
|
||||
// 2003/ 9/ 8 rmg Extracted trait facilities into container_traits.hpp
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef container_suite_rmg_20030823_included
|
||||
#define container_suite_rmg_20030823_included
|
||||
|
||||
#include <boost/python/suite/indexing/algo_selector.hpp>
|
||||
#include <boost/python/suite/indexing/visitor.hpp>
|
||||
|
||||
#include <boost/python/return_by_value.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
typedef boost::python::return_value_policy<boost::python::return_by_value>
|
||||
default_container_policies;
|
||||
|
||||
template<class Container, class Algorithms = algo_selector<Container> >
|
||||
struct container_suite
|
||||
: public visitor<Algorithms, default_container_policies>
|
||||
{
|
||||
typedef Algorithms algorithms;
|
||||
|
||||
template<typename Policy>
|
||||
static visitor<Algorithms, Policy> with_policies (Policy const &policy)
|
||||
{
|
||||
return visitor <Algorithms, Policy> (policy);
|
||||
}
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif // container_suite_rmg_20030823_included
|
||||
196
include/boost/python/suite/indexing/container_traits.hpp
Executable file
196
include/boost/python/suite/indexing/container_traits.hpp
Executable file
@@ -0,0 +1,196 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 8/23 rmg File creation as container_suite.hpp
|
||||
// 2003/ 9/ 8 rmg Renamed container_traits.hpp
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef container_traits_rmg_20030823_included
|
||||
#define container_traits_rmg_20030823_included
|
||||
|
||||
#include <boost/python/suite/indexing/suite_utils.hpp>
|
||||
#include <boost/python/suite/indexing/iterator_traits.hpp>
|
||||
#include <boost/python/suite/indexing/value_traits.hpp>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { 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 base_type::value_type value_type; // insert, etc.
|
||||
typedef typename base_type::value_type key_type; // find, count, ...
|
||||
|
||||
typedef typename make_signed<size_type>::type index_type;
|
||||
// at(), operator[]. Signed to support Python -ve indexes
|
||||
|
||||
typedef typename boost::call_traits<value_type>::param_type value_param;
|
||||
typedef typename boost::call_traits<key_type>::param_type key_param;
|
||||
typedef typename boost::call_traits<index_type>::param_type index_param;
|
||||
|
||||
// *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 base_container_traits<IteratorPair>
|
||||
{
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Default container traits - almost all "real" containers would meet
|
||||
// at least these requirements
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct default_container_traits : public base_container_traits<Container>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT (bool, has_insert = is_mutable);
|
||||
BOOST_STATIC_CONSTANT (bool, has_erase = is_mutable);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Sequences (list, deque, vector)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct default_sequence_traits : public default_container_traits<Container>
|
||||
{
|
||||
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 typename boost::call_traits<value_type>::param_type value_param;
|
||||
typedef typename boost::call_traits<key_type>::param_type key_param;
|
||||
|
||||
typedef value_traits<reference> value_traits_;
|
||||
// Get value_traits for the reference type (i.e. element_proxy)
|
||||
// to get the custom visitor_helper
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Associative containers set and multiset
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct set_traits : public default_container_traits<Container>
|
||||
{
|
||||
// *FIXME* handle const sets
|
||||
|
||||
typedef void value_type; // index_type only (?)
|
||||
typedef typename Container::key_type index_type; // operator[]
|
||||
typedef typename Container::key_type key_type; // find, count, ...
|
||||
|
||||
typedef void * value_param;
|
||||
typedef typename boost::call_traits<key_type>::param_type key_param;
|
||||
typedef typename boost::call_traits<index_type>::param_type index_param;
|
||||
|
||||
BOOST_STATIC_CONSTANT (IndexStyle, index_style = index_style_nonlinear);
|
||||
BOOST_STATIC_CONSTANT (bool, has_find = true);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Associative containers map and multimap
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
struct map_traits : public default_container_traits<Container>
|
||||
{
|
||||
// *FIXME* handle const maps
|
||||
typedef typename Container::mapped_type value_type;
|
||||
typedef value_type & reference;
|
||||
typedef typename Container::key_type index_type; // operator[]
|
||||
typedef typename Container::key_type key_type; // find, count, ...
|
||||
|
||||
typedef typename boost::call_traits<value_type>::param_type value_param;
|
||||
typedef typename boost::call_traits<key_type>::param_type key_param;
|
||||
typedef typename boost::call_traits<index_type>::param_type index_param;
|
||||
|
||||
BOOST_STATIC_CONSTANT (IndexStyle, index_style = index_style_nonlinear);
|
||||
BOOST_STATIC_CONSTANT (bool, has_find = true);
|
||||
BOOST_STATIC_CONSTANT (bool, is_reorderable = false);
|
||||
};
|
||||
} } }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Visitor helper function (foward to value_traits_ version)
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Container>
|
||||
template<typename PythonClass, typename Policy>
|
||||
void
|
||||
boost::python::indexing::base_container_traits<Container>
|
||||
::visitor_helper (PythonClass &pyClass, Policy const &policy)
|
||||
{
|
||||
value_traits_::visitor_helper (pyClass, policy);
|
||||
}
|
||||
|
||||
#endif // container_suite_rmg_20030823_included
|
||||
191
include/boost/python/suite/indexing/element_proxy.hpp
Executable file
191
include/boost/python/suite/indexing/element_proxy.hpp
Executable file
@@ -0,0 +1,191 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file element_proxy.hpp
|
||||
//
|
||||
// Proxy objects for invidivual elements in a container wrapped by
|
||||
// container_proxy
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/15 rmg File creation from container_proxy.hpp
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef element_proxy_rmg_20030915_included
|
||||
#define element_proxy_rmg_20030915_included
|
||||
|
||||
#include <boost/python/suite/indexing/shared_proxy_impl.hpp>
|
||||
#include <boost/python/suite/indexing/value_traits.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include <boost/python/register_ptr_to_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
template<typename ContainerProxy>
|
||||
class element_proxy
|
||||
{
|
||||
template<typename T> friend struct const_element_proxy;
|
||||
|
||||
typedef ContainerProxy container_proxy;
|
||||
typedef typename container_proxy::shared_proxy proxy_type;
|
||||
typedef boost::shared_ptr<proxy_type> proxy_pointer;
|
||||
typedef typename container_proxy::raw_value_type raw_value_type;
|
||||
typedef typename container_proxy::size_type size_type;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
template<typename ContainerProxy>
|
||||
struct const_element_proxy
|
||||
{
|
||||
typedef ContainerProxy container_proxy;
|
||||
typedef typename container_proxy::shared_proxy proxy_type;
|
||||
typedef boost::shared_ptr<proxy_type> proxy_pointer;
|
||||
typedef typename container_proxy::raw_value_type raw_value_type;
|
||||
|
||||
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<container_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
|
||||
};
|
||||
} } }
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename ContainerProxy>
|
||||
typename ContainerProxy::raw_value_type *
|
||||
get_pointer (python::indexing::element_proxy<ContainerProxy> const &proxy)
|
||||
{
|
||||
return &(*proxy);
|
||||
}
|
||||
}
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
template<typename ContainerProxy>
|
||||
struct value_traits<element_proxy<ContainerProxy> >
|
||||
: public value_traits<typename ContainerProxy::raw_value_type>
|
||||
{
|
||||
template<typename PythonClass, typename Policy>
|
||||
static void visitor_helper (PythonClass &, Policy const &)
|
||||
{
|
||||
typedef element_proxy<ContainerProxy> element_proxy_;
|
||||
typedef typename ContainerProxy::raw_value_type raw_value_type;
|
||||
|
||||
boost::python::register_ptr_to_python<element_proxy_>();
|
||||
boost::python::implicitly_convertible<raw_value_type, element_proxy_>();
|
||||
}
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif // element_proxy_rmg_20030915_included
|
||||
132
include/boost/python/suite/indexing/iterator_pair.hpp
Executable file
132
include/boost/python/suite/indexing/iterator_pair.hpp
Executable file
@@ -0,0 +1,132 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file iterator_pair.hpp
|
||||
//
|
||||
// Emulate an STL container using a pair of iterators. Doesn't support
|
||||
// insertion or deletion, for the obvious reasons.
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/ 9 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef iterator_pair_rmg_20030909_included
|
||||
#define iterator_pair_rmg_20030909_included
|
||||
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
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;
|
||||
reference at (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
|
||||
{
|
||||
iterator temp (begin());
|
||||
std::advance (temp, index);
|
||||
return *temp;
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
typename iterator_pair<Iterator>::reference
|
||||
iterator_pair<Iterator>::at (size_type index) const
|
||||
{
|
||||
if (index >= size())
|
||||
{
|
||||
throw std::out_of_range
|
||||
(std::string ("iterator_pair: index out of range"));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return (*this)[index];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
T *begin (T(&array)[N]) {
|
||||
return array;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
T *end (T(&array)[N]) {
|
||||
return array + N;
|
||||
}
|
||||
} } }
|
||||
|
||||
#endif // iterator_pair_rmg_20030909_included
|
||||
148
include/boost/python/suite/indexing/iterator_traits.hpp
Executable file
148
include/boost/python/suite/indexing/iterator_traits.hpp
Executable file
@@ -0,0 +1,148 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file iterator_traits.hpp
|
||||
//
|
||||
// Traits information about iterators for use in determining what
|
||||
// Python methods to support for a container.
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 8/23 rmg File creation as iterator_suite.hpp
|
||||
// 2003/ 9/12 rmg Renamed iterator_traits.hpp
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef iterator_traits_rmg_20030823_included
|
||||
#define iterator_traits_rmg_20030823_included
|
||||
|
||||
#include <boost/python/suite/indexing/suite_utils.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
enum IndexStyle {
|
||||
index_style_none // No random access (iteration only)
|
||||
, index_style_nonlinear // Random access by key (no slicing)
|
||||
, index_style_linear // Random access by integer index (allows slicing)
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
BOOST_STATIC_CONSTANT (bool, has_copyable_iter = false);
|
||||
BOOST_STATIC_CONSTANT (bool, is_reorderable = false);
|
||||
BOOST_STATIC_CONSTANT (bool, has_mutable_ref
|
||||
= is_mutable_ref<reference>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT (IndexStyle, index_style = index_style_none);
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct forward_iterator_traits
|
||||
: public input_iterator_traits<Iterator>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT (bool, has_copyable_iter = true);
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct bidirectional_iterator_traits
|
||||
: public forward_iterator_traits<Iterator>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT (bool, is_reorderable = has_mutable_ref);
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct random_access_iterator_traits
|
||||
: public bidirectional_iterator_traits<Iterator>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT (IndexStyle, index_style = index_style_linear);
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
BOOST_STATIC_CONSTANT (size_t, 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_traits_rmg_20030823_included
|
||||
65
include/boost/python/suite/indexing/python_iterator.hpp
Executable file
65
include/boost/python/suite/indexing/python_iterator.hpp
Executable file
@@ -0,0 +1,65 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file python_iterator.hpp
|
||||
//
|
||||
// Handy Python iterable iterators
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/10 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef python_iterator_rmg_20030910_included
|
||||
#define python_iterator_rmg_20030910_included
|
||||
|
||||
#include <boost/python/object.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
struct python_iterator
|
||||
{
|
||||
virtual ~python_iterator ();
|
||||
virtual bool next () = 0;
|
||||
virtual boost::python::object current() const = 0;
|
||||
};
|
||||
|
||||
std::auto_ptr<python_iterator> make_iterator (boost::python::object);
|
||||
// Returns null auto_ptr if object does not provide __iter__ nor
|
||||
// __getitem__, otherwise a pointer to a suitable implementation of
|
||||
// python_iterator
|
||||
|
||||
struct python_getitem_iterator : public python_iterator
|
||||
{
|
||||
public:
|
||||
python_getitem_iterator (boost::python::object);
|
||||
virtual bool next ();
|
||||
virtual boost::python::object current() const;
|
||||
|
||||
private:
|
||||
boost::python::object mGetitemMethod;
|
||||
int mIndex;
|
||||
boost::python::object mCurrent;
|
||||
};
|
||||
|
||||
struct python_iter_iterator : public python_iterator
|
||||
{
|
||||
public:
|
||||
python_iter_iterator (boost::python::object);
|
||||
virtual bool next ();
|
||||
virtual boost::python::object current() const;
|
||||
|
||||
private:
|
||||
boost::python::object mNextMethod;
|
||||
boost::python::object mCurrent;
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif // python_iterator_rmg_20030910_included
|
||||
101
include/boost/python/suite/indexing/shared_proxy_impl.hpp
Executable file
101
include/boost/python/suite/indexing/shared_proxy_impl.hpp
Executable file
@@ -0,0 +1,101 @@
|
||||
// -*- 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
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
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, 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->raw_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
|
||||
83
include/boost/python/suite/indexing/slice.hpp
Executable file
83
include/boost/python/suite/indexing/slice.hpp
Executable file
@@ -0,0 +1,83 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file slice.hpp
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/10 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef slice_rmg_20030910_included
|
||||
#define slice_rmg_20030910_included
|
||||
|
||||
#include <boost/python/object.hpp>
|
||||
#include <boost/python/converter/pytype_object_mgr_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
struct slice : public boost::python::object
|
||||
{
|
||||
//
|
||||
// *** WARNING ***
|
||||
//
|
||||
// A newly constructed slice object is useless until setLength is called
|
||||
//
|
||||
|
||||
template<typename T> slice (T const &ref);
|
||||
|
||||
void setLength (int sequenceLength);
|
||||
|
||||
int start() const { validate(); return mStart; }
|
||||
int step() const { validate(); return mStep; }
|
||||
int stop() const { validate(); return mStop; }
|
||||
|
||||
int size() const { validate(); return (mStop - mStart) / mStep; }
|
||||
|
||||
bool inRange (int index);
|
||||
|
||||
private:
|
||||
void validate () const; // throws unless setLength has been called
|
||||
|
||||
int mStart;
|
||||
int mStep;
|
||||
int mStop;
|
||||
int mDirection;
|
||||
};
|
||||
} } }
|
||||
|
||||
template<typename T>
|
||||
boost::python::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<>
|
||||
struct object_manager_traits<boost::python::indexing::slice>
|
||||
: pytype_object_manager_traits<&PySlice_Type, ::boost::python::indexing::slice>
|
||||
{
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif // slice_rmg_20030910_included
|
||||
395
include/boost/python/suite/indexing/slice_handler.hpp
Executable file
395
include/boost/python/suite/indexing/slice_handler.hpp
Executable file
@@ -0,0 +1,395 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file slice_handler.hpp
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/ 9 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef slice_handler_rmg_20030909_included
|
||||
#define slice_handler_rmg_20030909_included
|
||||
|
||||
#include <boost/python/object.hpp>
|
||||
#include <boost/python/list.hpp>
|
||||
#include <boost/python/extract.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/python/suite/indexing/slice.hpp>
|
||||
#include <boost/python/suite/indexing/python_iterator.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
template<class Algorithms, class Policy>
|
||||
struct slice_handler
|
||||
{
|
||||
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;
|
||||
typedef typename Algorithms::reference reference;
|
||||
|
||||
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
|
||||
{
|
||||
// This class overrides our Policy's postcall function and
|
||||
// result_conveter to handle the list returned from get_slice.
|
||||
// The Policy's result_converter is removed, since it gets
|
||||
// applied within get_slice. Our postcall override applies the
|
||||
// original postcall to each element of the Python list returned
|
||||
// from get_slice.
|
||||
|
||||
typedef boost::python::default_result_converter result_converter;
|
||||
typedef typename Policy::argument_package argument_package; // ?
|
||||
|
||||
postcall_override (Policy const &p);
|
||||
|
||||
bool precall (PyObject *args);
|
||||
PyObject* postcall (PyObject *args, PyObject *result);
|
||||
|
||||
private:
|
||||
Policy mBase;
|
||||
};
|
||||
};
|
||||
|
||||
template<bool doit> struct maybe_insert {
|
||||
template<class Algorithms>
|
||||
static void apply (typename Algorithms::container &
|
||||
, typename Algorithms::index_param
|
||||
, typename Algorithms::value_param)
|
||||
{
|
||||
PyErr_SetString (PyExc_TypeError
|
||||
, "container does not support item insertion");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct maybe_insert<true> {
|
||||
template<class Algorithms>
|
||||
static void apply (typename Algorithms::container &c
|
||||
, typename Algorithms::index_param i
|
||||
, typename Algorithms::value_param v)
|
||||
{
|
||||
Algorithms::insert (c, i, v);
|
||||
}
|
||||
};
|
||||
|
||||
template<bool doit> struct maybe_erase {
|
||||
template<class Algorithms>
|
||||
static void apply (typename Algorithms::container &
|
||||
, typename Algorithms::index_param
|
||||
, typename Algorithms::index_param)
|
||||
{
|
||||
PyErr_SetString (PyExc_TypeError
|
||||
, "container does not support item deletion");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct maybe_erase<true> {
|
||||
template<class Algorithms>
|
||||
static void apply (typename Algorithms::container &c
|
||||
, typename Algorithms::index_param from
|
||||
, typename Algorithms::index_param to)
|
||||
{
|
||||
Algorithms::erase_range (c, from, to);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// postcall_override constructor
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
slice_handler<Algorithms, Policy>
|
||||
::postcall_override::postcall_override (Policy const &p)
|
||||
: mBase (p)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// precall forwarder
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
bool
|
||||
slice_handler<Algorithms, Policy>
|
||||
::postcall_override::precall (PyObject *args)
|
||||
{
|
||||
return mBase.precall (args);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Apply base postcall to each element of the list returend by get_slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
PyObject *
|
||||
slice_handler<Algorithms, Policy>
|
||||
::postcall_override::postcall (PyObject *args, PyObject *result)
|
||||
{
|
||||
int size = PyList_Size (result);
|
||||
|
||||
for (int count = 0; count < size; ++count)
|
||||
{
|
||||
mBase.postcall (args, PyList_GetItem (result, count));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Return a function object that implements the slice version of __getitem__
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
boost::python::object
|
||||
slice_handler<Algorithms, Policy>
|
||||
::make_getitem (Policy const &policy)
|
||||
{
|
||||
return
|
||||
boost::python::make_function (get_slice, postcall_override (policy));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Return a function object that implements the slice version of __setitem__
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
boost::python::object
|
||||
slice_handler<Algorithms, Policy>
|
||||
::make_setitem (Policy const &policy)
|
||||
{
|
||||
// should we try to get funky with policy::precall?
|
||||
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
|
||||
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
|
||||
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__
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
boost::python::list
|
||||
slice_handler<Algorithms, Policy>
|
||||
::get_slice (container &c, slice sl)
|
||||
{
|
||||
typedef typename Policy::result_converter converter_type;
|
||||
typedef typename Algorithms::reference reference;
|
||||
typename boost::mpl::apply1<converter_type, reference>::type converter;
|
||||
|
||||
boost::python::list result;
|
||||
|
||||
sl.setLength (Algorithms::size(c));
|
||||
|
||||
for (int index = sl.start(); sl.inRange (index); index += sl.step())
|
||||
{
|
||||
// Apply the result converter (only) to each element before
|
||||
// appending. postcall is done in postcall_override
|
||||
|
||||
result.append
|
||||
(boost::python::handle<>
|
||||
(converter (Algorithms::get (c, index))));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implementation for the slice version of __setitem__
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
void
|
||||
slice_handler<Algorithms, Policy>
|
||||
::set_slice (container &c, slice sl, boost::python::object values)
|
||||
{
|
||||
std::auto_ptr<python_iterator> iterPtr (make_iterator (values));
|
||||
|
||||
if (!iterPtr.get())
|
||||
{
|
||||
PyErr_SetString (PyExc_TypeError
|
||||
, "Type assigned to slice must be a sequence");
|
||||
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
|
||||
typedef typename Algorithms::container_traits traits;
|
||||
|
||||
// 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
|
||||
// replacement sequence is of a different length to the original
|
||||
// slice and the container does not support insertion/deletion.
|
||||
// This could be prevented if the length of the replacement sequence
|
||||
// is known in advance (via __len__, for example) but not otherwise.
|
||||
|
||||
sl.setLength (Algorithms::size (c)); // Current length of our container
|
||||
int index = sl.start(); // Index in our container for update
|
||||
|
||||
// Overwrite and/or insert elements
|
||||
while (iterPtr->next())
|
||||
{
|
||||
if (sl.inRange (index))
|
||||
{
|
||||
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)
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "attempt to insert via extended slice");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Could optimize this in some cases (i.e. if the length of
|
||||
// the replacement sequence is known)
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// Erase any remaining elements in the slice
|
||||
if (sl.inRange(index))
|
||||
{
|
||||
if (sl.step() != 1)
|
||||
{
|
||||
PyErr_SetString (PyExc_ValueError
|
||||
, "attempt to erase via extended slice");
|
||||
|
||||
boost::python::throw_error_already_set ();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
maybe_erase<traits::has_erase>
|
||||
::template apply<Algorithms> (c, index, sl.stop());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implementation for the slice version of __delitem__
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
void
|
||||
slice_handler<Algorithms, Policy>
|
||||
::del_slice (container &c, slice sl)
|
||||
{
|
||||
typename Algorithms::size_type length (Algorithms::size (c));
|
||||
|
||||
// avoid bounds check problems with deleting [0..0) when length==0
|
||||
if (length)
|
||||
{
|
||||
sl.setLength (length);
|
||||
Algorithms::erase_range (c, sl.start(), sl.stop());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of extend
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Algorithms, class Policy>
|
||||
void
|
||||
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)))));
|
||||
|
||||
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
|
||||
75
include/boost/python/suite/indexing/suite_utils.hpp
Executable file
75
include/boost/python/suite/indexing/suite_utils.hpp
Executable file
@@ -0,0 +1,75 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file suite_utils.hpp
|
||||
//
|
||||
// Shared utilities for the indexing suite.
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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>
|
||||
|
||||
namespace boost { namespace python { 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;
|
||||
};
|
||||
|
||||
// make_signed attempts to identify the signed version of any
|
||||
// numeric type (useful in this case because Python container
|
||||
// indexes can be negative).
|
||||
template<typename T> struct make_signed {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<> struct make_signed<char> {
|
||||
// Raw "char" could be signed or unsigned. "signed char"
|
||||
// guarantess signedness
|
||||
typedef signed char type;
|
||||
};
|
||||
|
||||
template<> struct make_signed<unsigned char> {
|
||||
typedef signed char type;
|
||||
};
|
||||
|
||||
template<> struct make_signed<unsigned short> {
|
||||
typedef short type;
|
||||
};
|
||||
|
||||
template<> struct make_signed<unsigned int> {
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template<> struct make_signed<unsigned long> {
|
||||
typedef long type;
|
||||
};
|
||||
|
||||
#if defined (BOOST_HAS_LONG_LONG)
|
||||
template<> struct make_signed<unsigned long long> {
|
||||
typedef long long type;
|
||||
};
|
||||
#elif defined (BOOST_HAS_MS_INT64)
|
||||
template<> struct make_signed<unsigned __int64> {
|
||||
typedef __int64 type;
|
||||
};
|
||||
#endif
|
||||
} } }
|
||||
|
||||
#endif // suite_utils_rmg_20030823_included
|
||||
41
include/boost/python/suite/indexing/value_traits.hpp
Executable file
41
include/boost/python/suite/indexing/value_traits.hpp
Executable file
@@ -0,0 +1,41 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file value_traits.hpp
|
||||
//
|
||||
// Traits information about container element types for use in
|
||||
// determining which Python methods to support for a container.
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/12 rmg File creation
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef value_traits_rmg_20030912_included
|
||||
#define value_traits_rmg_20030912_included
|
||||
|
||||
namespace boost { namespace python { namespace indexing {
|
||||
template<typename T>
|
||||
struct value_traits {
|
||||
static bool const equality_comparable = true;
|
||||
// Meaning from C++98 standard section 20.1.1
|
||||
|
||||
static bool const lessthan_comparable = true;
|
||||
|
||||
// static bool const has_less = true;
|
||||
// etc...
|
||||
|
||||
// Default, do-nothing, version of visitor_helper
|
||||
template<typename PythonClass, typename Policy>
|
||||
static void visitor_helper (PythonClass &, Policy const &) { }
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif // value_traits_rmg_20030912_included
|
||||
520
include/boost/python/suite/indexing/visitor.hpp
Executable file
520
include/boost/python/suite/indexing/visitor.hpp
Executable file
@@ -0,0 +1,520 @@
|
||||
// -*- mode:c++ -*-
|
||||
//
|
||||
// Header file visitor.hpp
|
||||
//
|
||||
// Copyright (c) 2003 Raoul M. Gough
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
||||
// at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// History
|
||||
// =======
|
||||
// 2003/ 9/11 rmg File creation from container_suite.hpp
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
#ifndef visitor_rmg_20030823_included
|
||||
#define visitor_rmg_20030823_included
|
||||
|
||||
#include <boost/python/suite/indexing/slice_handler.hpp>
|
||||
|
||||
#include <boost/python/def_visitor.hpp>
|
||||
#include <boost/python/iterator.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace boost { namespace python { 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>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__getitem__", &Algorithms::get, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __getitem__ with slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_getitem<index_style_linear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__getitem__", &Algorithms::get, policy);
|
||||
pyClass.def ("__getitem__"
|
||||
, slice_handler<Algorithms, Policy>::make_getitem (policy));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __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>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__setitem__", &Algorithms::assign, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __setitem__ with slice
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_setitem<index_style_linear> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("__setitem__", &Algorithms::assign, policy);
|
||||
pyClass.def ("__setitem__"
|
||||
, slice_handler<Algorithms, Policy>::make_setitem (policy));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// __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>
|
||||
static void apply (PythonClass &pyClass
|
||||
, 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));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// sort dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit, bool lessthan_comparable>
|
||||
struct maybe_add_sort {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// sort real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_sort<true, true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("sort", &Algorithms::sort, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reverse dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_reverse {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reverse real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_reverse<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("reverse", &Algorithms::reverse, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 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>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("append", &Algorithms::push_back, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// extend dummy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool doit>
|
||||
struct maybe_add_insert {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &, Algorithms const &, Policy const &) { }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// insert real
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct maybe_add_insert<true> {
|
||||
template<class PythonClass, class Algorithms, class Policy>
|
||||
static void apply (PythonClass &pyClass
|
||||
, Algorithms const &
|
||||
, Policy const &policy)
|
||||
{
|
||||
pyClass.def ("insert", Algorithms::insert, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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", Algorithms::get_index, 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);
|
||||
pyClass.def ("contains", Algorithms::contains, 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);
|
||||
pyClass.def ("__contains__", Algorithms::contains, policy);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// count real (associative containers). add has_key
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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", Algorithms::contains, policy);
|
||||
pyClass.def ("__contains__", Algorithms::contains, 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 > >
|
||||
{
|
||||
Policy mPolicy;
|
||||
|
||||
public:
|
||||
typedef Algorithms algorithms;
|
||||
typedef typename algorithms::container_traits traits;
|
||||
typedef typename traits::value_traits_ value_traits_;
|
||||
|
||||
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_sort<traits::is_reorderable
|
||||
, value_traits_::lessthan_comparable>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_reverse<traits::is_reorderable>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_append<traits::has_push_back>
|
||||
::apply (pyClass, algorithms(), precallPolicy);
|
||||
|
||||
maybe_add_insert<traits::has_insert>
|
||||
::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);
|
||||
}
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif // visitor_rmg_20030823_included
|
||||
Reference in New Issue
Block a user