blob: 23d409f645f5c1116c51cd9351749f37ecaa7995 [file] [log] [blame]
/* -*- c++ -*- */
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef ANDROID_ASTL_ITERATOR__
#define ANDROID_ASTL_ITERATOR__
#include <cstddef>
// Iterators are a generalization of pointers to allow programs to
// work with different data structures (containers) in a uniform
// manner.
namespace std {
// Tags for the various iterator categories. Only input and forward
// iterators are supported.
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
template<typename _Category, typename _T, typename _Distance = ptrdiff_t,
typename _Pointer = _T*, typename _Reference = _T&>
struct iterator
{
typedef _Category iterator_category; // See tags above.
typedef _T value_type;
typedef _Distance difference_type; // Distance between iterators.
typedef _Pointer pointer;
typedef _Reference reference;
};
// Generic version, simply forward the typedef to the iterator
// template argument.
template<typename _Iterator>
struct iterator_traits
{
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
// Specialization for pointers and const pointers. These are random
// access iterators.
template<typename _T>
struct iterator_traits<_T*>
{
typedef random_access_iterator_tag iterator_category;
typedef _T value_type;
typedef ptrdiff_t difference_type;
typedef _T* pointer;
typedef _T& reference;
};
template<typename _T>
struct iterator_traits<const _T*>
{
typedef random_access_iterator_tag iterator_category;
typedef _T value_type;
typedef ptrdiff_t difference_type;
typedef const _T* pointer;
typedef const _T& reference;
};
// Wrap an interator that is not a class (e.g pointer) into an
// iterator that is a class.
template<typename _Iterator, typename _Container>
class __wrapper_iterator
{
public:
typedef typename iterator_traits<_Iterator>::iterator_category
iterator_category;
typedef typename iterator_traits<_Iterator>::value_type value_type;
typedef typename iterator_traits<_Iterator>::difference_type
difference_type;
typedef typename iterator_traits<_Iterator>::reference reference;
typedef typename iterator_traits<_Iterator>::pointer pointer;
__wrapper_iterator() : mCurrent(_Iterator()) { }
explicit __wrapper_iterator(const _Iterator& i) : mCurrent(i) { }
// Allow iterator to const_iterator conversion
template<typename _Iter>
__wrapper_iterator(const __wrapper_iterator<_Iter, _Container>& i)
: mCurrent(i.base()) { }
// Forward iterator requirements
reference operator*() const { return *mCurrent; }
pointer operator->() const { return mCurrent; }
__wrapper_iterator& operator++() {
++mCurrent;
return *this;
}
__wrapper_iterator operator++(int) {
return __wrapper_iterator(mCurrent++);
}
// Bidirectional iterator requirements
__wrapper_iterator& operator--() {
--mCurrent;
return *this;
}
__wrapper_iterator operator--(int) {
return __wrapper_iterator(mCurrent--);
}
// Random access iterator requirements
reference operator[](const difference_type& n) const {
return mCurrent[n];
}
__wrapper_iterator& operator+=(const difference_type& n) {
mCurrent += n;
return *this;
}
__wrapper_iterator operator+(const difference_type& n) const {
return __wrapper_iterator(mCurrent + n);
}
__wrapper_iterator& operator-=(const difference_type& n) {
mCurrent -= n; return *this;
}
__wrapper_iterator operator-(const difference_type& n) const {
return __wrapper_iterator(mCurrent - n);
}
const _Iterator& base() const {
return mCurrent;
}
private:
_Iterator mCurrent;
};
// Forward iterator requirements
template<typename _IteratorL, typename _IteratorR, typename _Container>
inline bool
operator==(const __wrapper_iterator<_IteratorL, _Container>& lhs,
const __wrapper_iterator<_IteratorR, _Container>& rhs)
{ return lhs.base() == rhs.base(); }
template<typename _Iterator, typename _Container>
inline bool
operator==(const __wrapper_iterator<_Iterator, _Container>& lhs,
const __wrapper_iterator<_Iterator, _Container>& rhs)
{ return lhs.base() == rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Container>
inline bool
operator!=(const __wrapper_iterator<_IteratorL, _Container>& lhs,
const __wrapper_iterator<_IteratorR, _Container>& rhs)
{ return lhs.base() != rhs.base(); }
template<typename _Iterator, typename _Container>
inline bool
operator!=(const __wrapper_iterator<_Iterator, _Container>& lhs,
const __wrapper_iterator<_Iterator, _Container>& rhs)
{ return lhs.base() != rhs.base(); }
// operator+ so we support 100 + iterator<>.
template<typename _Iterator, typename _Container>
inline __wrapper_iterator<_Iterator, _Container>
operator+(typename __wrapper_iterator<_Iterator, _Container>::difference_type n,
const __wrapper_iterator<_Iterator, _Container>& i)
{ return __wrapper_iterator<_Iterator, _Container>(i.base() + n); }
// operator- : diff is supported on iterators.
template<typename _Iterator, typename _Container>
inline typename __wrapper_iterator<_Iterator, _Container>::difference_type
operator-(const __wrapper_iterator<_Iterator, _Container>& lhs,
const __wrapper_iterator<_Iterator, _Container>& rhs)
{ return lhs.base() - rhs.base(); }
} // namespace std
namespace android {
// Shorthand to return the catogory of an iterator. Not part of the
// STL -> android namespace.
template<typename _Iterator>
inline typename std::iterator_traits<_Iterator>::iterator_category
iterator_category(const _Iterator&)
{ return typename std::iterator_traits<_Iterator>::iterator_category(); }
} // namespace android
namespace std {
// Utilities: distance().
template<typename _InputIterator>
inline typename iterator_traits<_InputIterator>::difference_type
distance(_InputIterator first, _InputIterator last,
input_iterator_tag) // Match input iterators.
{
typename iterator_traits<_InputIterator>::difference_type dist = 0;
while (first != last) {
++first;
++dist;
}
return dist;
}
// Random access iterator: equivalent to mem pointer arithmetic.
template<typename _RandomAccessIterator>
inline typename iterator_traits<_RandomAccessIterator>::difference_type
distance(_RandomAccessIterator first, _RandomAccessIterator last,
random_access_iterator_tag) // Match random access iterators.
{
return last - first;
}
/**
* Iterator arithmetic.
* @param first An input iterator.
* @param last An input iterator.
* @return The distance between them.
*/
template<typename _InputIterator>
inline typename iterator_traits<_InputIterator>::difference_type
distance(_InputIterator first, _InputIterator last)
{
// The correct implementation (above) will be called based on the
// iterator's category.
return distance(first, last, android::iterator_category(first));
}
} // namespace std
#endif // ANDROID_ASTL_ITERATOR__