Program Listing for File iterator.h#
↰ Return to documentation for file (support\iterator.h
)
#ifndef SDV_ITERATOR_H
#define SDV_ITERATOR_H
#include <iterator>
#ifndef DONT_LOAD_CORE_TYPES
#include "../interfaces/core_types.h"
#endif
namespace sdv
{
namespace internal
{
template <class TContainer, bool bConstIterator, bool bReverseIterator>
class index_iterator
{
friend index_iterator<TContainer, !bConstIterator, bReverseIterator>;
public:
using container_reference = std::conditional_t<bConstIterator, const TContainer&, TContainer&>;
using container_pointer = std::conditional_t<bConstIterator, const TContainer*, TContainer*>;
using iterator_category = std::random_access_iterator_tag;
using value_type = typename TContainer::value_type;
using difference_type = size_t;
using pointer = std::conditional_t<bConstIterator, const value_type*, value_type*>;
using reference = std::conditional_t<bConstIterator, const value_type&, value_type&>;
index_iterator() {}
index_iterator(container_pointer pContainer) : m_pContainer(pContainer)
{}
index_iterator(const index_iterator& rit) : m_pContainer(rit.m_pContainer), m_nIndex(rit.m_nIndex)
{}
index_iterator(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit) :
m_pContainer(const_cast<container_pointer>(rit.m_pContainer)), m_nIndex(rit.m_nIndex)
{}
index_iterator(index_iterator&& rit) noexcept : m_pContainer(rit.m_pContainer), m_nIndex(rit.m_nIndex)
{
rit.m_pContainer = nullptr;
rit.m_nIndex = 0;
}
index_iterator& operator=(const index_iterator& rit)
{
m_pContainer = rit.m_pContainer;
m_nIndex = rit.m_nIndex;
return *this;
}
index_iterator& operator=(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit)
{
m_pContainer = rit.m_pContainer;
m_nIndex = rit.m_nIndex;
return *this;
}
index_iterator& operator=(index_iterator&& rit) noexcept
{
m_pContainer = rit.m_pContainer;
m_nIndex = rit.m_nIndex;
rit.m_pContainer = nullptr;
rit.m_nIndex = 0;
return *this;
}
bool is_valid(container_reference rContainer) const
{
return m_pContainer == &rContainer;
}
bool operator==(const index_iterator& rit) const
{
return m_pContainer == rit.m_pContainer && m_nIndex == rit.m_nIndex;
}
bool operator==(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit) const
{
return m_pContainer == rit.m_pContainer && m_nIndex == rit.m_nIndex;
}
bool operator!=(const index_iterator& rit) const
{
return !(*this == rit);
}
bool operator!=(const index_iterator<TContainer, !bConstIterator, bReverseIterator>& rit) const
{
return !(*this == rit);
}
reference operator*() const
{
size_t nIndex = m_nIndex;
if (!m_pContainer || m_nIndex >= m_pContainer->size())
{
XIndexOutOfRange exception;
exception.uiIndex = static_cast<uint32_t>(nIndex);
exception.uiSize = static_cast<uint32_t>(m_pContainer ? m_pContainer->size() : 0);
throw exception;
}
if constexpr (bReverseIterator)
nIndex = m_pContainer->size() - m_nIndex - 1;
return (*m_pContainer)[nIndex];
}
pointer operator->() const
{
return std::pointer_traits<pointer>::pointer_to(**this);
}
index_iterator& operator++()
{
if (m_pContainer && m_nIndex < m_pContainer->size())
m_nIndex++;
return *this;
}
index_iterator operator++(int)
{
index_iterator itCopy = *this;
operator++();
return itCopy;
}
index_iterator& operator--() noexcept
{
if (m_pContainer && m_nIndex > 0)
m_nIndex--;
return *this;
}
index_iterator operator--(int) noexcept
{
index_iterator itCopy = *this;
operator--();
return itCopy;
}
index_iterator& operator+=(size_t nOffset) noexcept
{
if (!m_pContainer) return *this;
if (nOffset > m_pContainer->size() - m_nIndex)
m_nIndex = m_pContainer->size();
else
m_nIndex += nOffset;
return *this;
}
index_iterator operator+(size_t nOffset) const noexcept
{
index_iterator itCopy = *this;
itCopy += nOffset;
return itCopy;
}
index_iterator& operator-=(size_t nOffset) noexcept
{
if (!m_pContainer) return *this;
if (m_nIndex > nOffset)
m_nIndex -= nOffset;
else if (m_nIndex)
m_nIndex = 0;
return *this;
}
index_iterator operator-(size_t nOffset) const noexcept
{
index_iterator itCopy = *this;
itCopy -= nOffset;
return itCopy;
}
difference_type operator-(index_iterator it) const
{
if (m_pContainer != it.m_pContainer) return 0;
if (m_nIndex > it.m_nIndex)
return m_nIndex - it.m_nIndex;
else
return it.m_nIndex - m_nIndex;
}
reference operator[](size_t nOffset) const
{
if (!m_pContainer || m_pContainer->empty())
{
XIndexOutOfRange exception;
exception.uiIndex = static_cast<uint32_t>(nOffset + m_nIndex);
exception.uiSize = static_cast<uint32_t>(0);
throw exception;
}
return *(operator+(nOffset));
}
private:
container_pointer m_pContainer = nullptr;
size_t m_nIndex = 0;
};
} // namespace internal
} // namespace sdv
#endif // !defined SDV_ITERATOR_H