// 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)
//
// Header file iterator_range.hpp
//
// Emulate an STL container using a pair of iterators. Doesn't support
// insertion or deletion, for the obvious reasons.
//
// History
// =======
// 2003/ 9/ 9 rmg File creation as iterator_pair.hpp
// 2003/10/27 rmg Renamed iterator_range.hpp
// 2008/12/08 Roman Change indexing suite layout
//
// $Id: iterator_range.hpp,v 1.1.2.7 2004/02/08 18:57:42 raoulgough Exp $
//
#ifndef BOOST_PYTHON_INDEXING_ITERATOR_RANGE_HPP
#define BOOST_PYTHON_INDEXING_ITERATOR_RANGE_HPP
#include <stdexcept>
#include <algorithm>
#include <utility>
#include <boost/type_traits.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <indexing_suite/container_traits.hpp>
#include <indexing_suite/container_suite.hpp>
#include <indexing_suite/algorithms.hpp>
#include <indexing_suite/iterator_traits.hpp>
namespace boost { namespace python { namespace indexing {
template<typename Iterator>
class iterator_range
{
private:
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <Iterator>::param_type
iterator_param;
typedef ::boost::detail::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;
typedef iterator const_iterator;
// Can't tell what the const version of our iterator should
// be. The client code will have to instantiate iterator_range
// directly with a const_iterator if that's what it wants.
// Also can't provide: 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_range (iterator_param, iterator_param);
iterator_range (std::pair<iterator, iterator> const &);
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 m_begin;
iterator m_end;
};
// Array support function(s).
template<typename T> iterator_range<T *> make_iterator_range (T *, T*);
#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
template<typename T, std::size_t N> iterator_range<T *> make_iterator_range(
T (&array)[N]);
template<typename T, std::size_t N> T *begin (T (&array)[N]);
template<typename T, std::size_t N> T *end (T (&array)[N]);
# define BOOST_MAKE_ITERATOR_RANGE \
::boost::python::indexing::make_iterator_range
#else
// For compilers that can't deduce template argument array bounds
# define BOOST_MAKE_ITERATOR_RANGE(array) \
::boost::python::indexing::make_iterator_range ( \
(array), ((array) + sizeof(array) / sizeof((array)[0])))
#endif
template<typename Iterator>
iterator_range<Iterator>::iterator_range(
iterator_param begin, iterator_param end)
: m_begin (begin),
m_end (end)
{
}
template<typename Iterator>
iterator_range<Iterator>
::iterator_range (std::pair<iterator, iterator> const &pair)
: m_begin (pair.first),
m_end (pair.second)
{
}
template<typename Iterator>
typename iterator_range<Iterator>::iterator
iterator_range<Iterator>::begin() const
{
return m_begin;
}
template<typename Iterator>
typename iterator_range<Iterator>::iterator
iterator_range<Iterator>::end() const
{
return m_end;
}
template<typename Iterator>
typename iterator_range<Iterator>::size_type
iterator_range<Iterator>::size() const
{
return std::distance (begin(), end());
}
template<typename Iterator>
typename iterator_range<Iterator>::reference
iterator_range<Iterator>::operator[](size_type index) const
{
iterator temp (begin());
std::advance (temp, index);
return *temp;
}
template<typename Iterator>
typename iterator_range<Iterator>::reference
iterator_range<Iterator>::at (size_type index) const
{
if (index >= size())
{
throw std::out_of_range
(std::string ("iterator_range: index out of range"));
}
else
{
return (*this)[index];
}
}
template<typename T> iterator_range<T *> make_iterator_range (T *p1, T* p2)
{
return iterator_range<T *> (p1, p2);
}
#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
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;
}
template<typename T, std::size_t N>
iterator_range<T *> make_iterator_range (T (&array)[N]) {
return iterator_range<T *>(begin (array), end (array));
}
#endif
template<typename Container, typename ValueTraits = detail::no_override>
class iterator_range_traits
: public base_container_traits<Container, ValueTraits>
{
typedef base_container_traits<Container, ValueTraits> base_class;
typedef ::boost::python::indexing::iterator_traits<
typename Container::iterator
> iterator_traits_type;
public:
typedef typename base_class::value_traits_type value_traits_type;
private:
// Methods that we *can't* support because of our value type
BOOST_STATIC_CONSTANT(
method_set_type,
disabled_methods = (
detail::method_set_if<
type_traits::ice_not<
value_traits_type::equality_comparable
>::value,
method_index // Impossible if !equality_comparable
| method_contains // Impossible if !equality_comparable
| method_count // Impossible if !equality_comparable
>::value
| detail::method_set_if<
type_traits::ice_not<
value_traits_type::less_than_comparable
>::value,
method_sort // Impossible if !less_than_comparable
>::value
));
public:
BOOST_STATIC_CONSTANT(
method_set_type,
supported_methods =
iterator_traits_type::supported_methods & ~disabled_methods);
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algorithms support for iterator_range instances
///////////////////////////////////////////////////////////////////////
template <typename Iterator>
class algorithms_selector<iterator_range<Iterator> >
{
typedef iterator_range<Iterator> Container;
typedef iterator_range_traits<Container> mutable_traits;
typedef iterator_range_traits<Container const> const_traits; // ?
public:
typedef default_algorithms<mutable_traits> mutable_algorithms;
typedef default_algorithms<const_traits> const_algorithms;
};
}
#endif
template<
class Container,
method_set_type MethodMask = all_methods,
class Traits = iterator_range_traits<Container>
>
struct iterator_range_suite
: container_suite<Container, MethodMask, default_algorithms<Traits> >
{
};
} } }
#endif // BOOST_PYTHON_INDEXING_ITERATOR_RANGE_HPP