Subversion

logrus

[/] [TemplateLibrary/] [InterleavedArrayIterator/] [InterleavedArrayIterator.h] - Rev 678

Compare with Previous - Blame


//InterleavedArrayIterator.h
//Provides iterator classes for accesing arbitrary arrays of interleaved components
//Primary uses are to allow STL-like generalised algorithms to iterate over any data
//that can be used as OpenGL vertex attribute data, and to allow image processing algorithms to be written 
//without relying on a specific format/layout in memory .
//That being the case, it will operate on any sequential block of memory (e.g. plain arrays, std::vector)
//Given a compound class it provides an interface to iterate over some or all of the components as
//if they were a plain array of the component type. The pointer to member operator is also implemented,
//so the dereferenceable component type can itself be a compound type. 

//see the tests for examples

#include <iterator>

//Models the stl concept of Random Access Iterator
//dereference is not range checked, for speed

template<typename dereftype>
class InterleavedArrayIterator : public std::iterator<std::random_access_iterator_tag,dereftype>
//note: implicit distance type is platform int, at least on ms compiler
//ms stl and alloc stuff assumes that if you can alloc it, you can index it with an int. Fair enough.
//I use distance_type instead of int, so hopefully the compiler and stl implementation should always sort it
//Still, it's worth checking the platform distance_type before using on 64bit platforms where mem can be > 2GB
{
        distance_type m_stridebytes; //full element size in bytes
        distance_type m_size; //number of adjacent dereferenceable elements
        const void * m_pointer;
        
        distance_type full_pos;
        distance_type derefable_pos;

public:
        //copy constructor
        InterleavedArrayIterator(const InterleavedArrayIterator<dereftype>& r)
        {
                //copy vals
                m_size = r.m_size;
                m_stridebytes = r.m_stridebytes;
                m_pointer = r.m_pointer;
                full_pos = r.full_pos;
                derefable_pos=r.derefable_pos;
        }
        //same params as gl*Pointer
        InterleavedArrayIterator(const unsigned int& size, const unsigned int& stride, const void* ptr)
        {
                m_size =size; //change to use param list for speed
                m_stridebytes = stride;
                m_pointer = ptr;
                full_pos=0;
                derefable_pos=0;
        }

        ///assignment operator
        InterleavedArrayIterator<dereftype>&
        operator=(const InterleavedArrayIterator<dereftype>& r)
        {
                if(this == &r)
                {
                        return *this;
                }
                //copy vals
                m_size = r.m_size;
                m_stridebytes = r.m_stridebytes;
                m_pointer = r.m_pointer;
                full_pos = r.full_pos;
                derefable_pos=r.derefable_pos;
                return *this;		
        }
        ///preincrement operator; to model ForwardIterator; returns incremented value
        const InterleavedArrayIterator<dereftype>&
        operator++()
        {
                derefable_pos++;
                if(derefable_pos >= m_size)
                {
                        derefable_pos -=m_size;
                        full_pos++;
                }
                return *this;
        }
        ///postincrement operator; to model ForwardIterator, returns the value before increment
        const InterleavedArrayIterator<dereftype>
        operator++(int a)
        {
        InterleavedArrayIterator<dereftype>before(*this);
                ++(*this);
                return before;
        }

        ///predecrement operator; to model Bidirectional Iterator; returns incremented value
        const InterleavedArrayIterator<dereftype>&
        operator--()
        {
                derefable_pos--;
                if(derefable_pos < 0)
                {
                        derefable_pos += m_size;
                        full_pos--;
                }
                return *this;
        }

        ///postdecrement operator; to model Bidirectional Iterator; returns the value before increment
        const InterleavedArrayIterator<dereftype>
        operator--(int a)
        {
                InterleavedArrayIterator<dereftype>before(*this);
                --(*this);
                return before;
        }

        ///iterator addition & ; to model RandomAccessIterator
        InterleavedArrayIterator<dereftype>&
        operator+=(const distance_type& right)
        {
                distance_type m = right%m_size;
                derefable_pos += m;
                full_pos += (right-m)/m_size;
                if(derefable_pos >= m_size)
                {
                        full_pos++;
                        derefable_pos -= m_size;
                }
                return *this;
        }

        ///iterator addition; to model RandomAccessIterator
        //make this friend func? makes more sense
        const InterleavedArrayIterator<dereftype>
        operator+ (const distance_type& right) const
        {
                InterleavedArrayIterator<dereftype>r(*this);
                r+=right;
                return r;
        }
        
        ///iterator subtraction & ; to model RandomAccessIterator
        InterleavedArrayIterator<dereftype>&
        operator-=(const distance_type& right)
        {
                distance_type m = right%m_size;
                derefable_pos -= m;
                full_pos -= (right-m)/m_size;
                if(derefable_pos < 0)
                {
                        full_pos--;
                        derefable_pos += m_size;
                }
                return *this;
        }

        ///iterator subtraction ; to model RandomAccessIterator
        const InterleavedArrayIterator<dereftype>
        operator- (const distance_type& right) const
        {
                InterleavedArrayIterator<dereftype>r(*this);
                r-=right;
                return r;
        }

        ///difference ; to model RandomAccessIterator
        const difference_type operator-(const InterleavedArrayIterator<dereftype>& right) const
        {
                return ((full_pos - right.full_pos)*m_size) + (derefable_pos - right.derefable_pos);
        }

        ///element access operator ; to model RandomAccessIterator
        dereftype& operator[](const distance_type& x) const
        {
                InterleavedArrayIterator<dereftype>r(*this);
                r+=x;
                return * r;
        }

        ///operator lessthan; to model LessThan Comparable for RandomAccessIterator
        bool operator<(const InterleavedArrayIterator<dereftype>&right)const 
        {
                return ((full_pos*m_size)+derefable_pos)
                        < ( (right.full_pos*right.m_size)+right.derefable_pos);
        }

        ///dereference ; to model TrivialIterator etc 
        dereftype& operator*() const
        {
                unsigned char * ptr = (unsigned char*)m_pointer + (full_pos*m_stridebytes) + (derefable_pos*sizeof(dereftype));
                return *(dereftype*)ptr;
        }

        ////dereference ; to model TrivialIterator etc 
        dereftype* operator->() const
        {
                unsigned char * ptr = (unsigned char*)m_pointer + (full_pos*m_stridebytes) + (derefable_pos*sizeof(dereftype));
                return (dereftype*)ptr;
        }
        
        ///comparison ; to model Equality Comparable
        bool operator==(const InterleavedArrayIterator<dereftype>&right)const
        {
                if(right.derefable_pos != derefable_pos)
                {
                        return false;
                }
                if(right.full_pos != full_pos)
                {
                        return false;
                }
                if(right.m_pointer != m_pointer)
                {
                        return false;
                }
                if(right.m_stridebytes != m_stridebytes)
                {
                        return false;
                }
                if(right.m_size != m_size)
                {
                        return false;
                }
                return true;
                
        }
        ///comparison ; to model Equality Comparable
        bool operator!=(const InterleavedArrayIterator<dereftype>&right)
        {
                return ! (*this == right);
        }
};

Powered by WebSVN v1.61