IteratorRange.h

// IteratorRange.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2010

#pragma once
#ifndef Ceda_cxUtils_IteratorRange_H
#define Ceda_cxUtils_IteratorRange_H

#include "CedaAssert.h"
#include "cxUtils.h"

namespace ceda
{

///////////////////////////////////////////////////////////////////////////////////////////////////
// IteratorRange<T>

// Represents a range [p1,p2) using a pair of iterators.  No ownership semantics is implied.

template <typename It>
class IteratorRange
{
public:
    typedef It iterator;
    typedef typename It::iterator_category iterator_category;
    typedef typename It::value_type value_type;
    typedef typename It::difference_type difference_type;
    typedef typename It::pointer pointer;
    typedef typename It::reference reference;

    // Warning: A default constructed iterator cannot be read (according to the standard reading
    // is undefined).
    IteratorRange() {}

    IteratorRange(It p1, It p2) : m_p1(p1), m_p2(p2) {}
    
    template <typename C>
    explicit IteratorRange(C& c) : m_p1(c.begin()), m_p2(c.end()) {}

    explicit operator bool() const { return m_p1 != m_p2; }

    void clear() { m_p1 = m_p2; }

    ssize_t size() const { return m_p2 - m_p1; }
    bool empty() const { return m_p2 == m_p1; }

    reference operator*() const { cxAssert(m_p1 != m_p2); return *m_p1; }
    pointer operator->() const { &**this; }

    It begin() const { return m_p1; }
    It end() const { return m_p2; }

    void setbegin(It p1) { m_p1 = p1; }
    void setend(It p2) { m_p2 = p2; }

    IteratorRange& operator++() { cxAssert(m_p1 != m_p2); ++m_p1; return *this; }
    const IteratorRange operator++(int) { IteratorRange s = *this; ++(*this); return s; }
    IteratorRange& operator--() { --m_p1; return *this; }
    const IteratorRange operator--(int) { IteratorRange s = *this; --(*this); return s; }

    reference operator[](ssize_t i) const 
    { 
        cxAssert(0 <= i && i < size());
        return m_p1[i]; 
    }

    IteratorRange& operator+=(difference_type i) 
    { 
        m_p1 += i; 
        return *this; 
    }
    IteratorRange& operator-=(difference_type i) 
    { 
        m_p1 -= i; 
        return *this; 
    }

private:
    It m_p1;
    It m_p2;
};

} // namespace ceda

#endif // include guard