General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

270 lines
6.3 KiB

#pragma once
#include <gp/utils/iterators/iterator_properties.hpp>
#include <cstddef>
#include <cstdint>
// TODO: Specify the concept of an iterator
namespace gp {
/**
* @brief An abstraction of a pointer to iterate against, in both normal and reverse order
*
* @tparam T The type of data pointed by the iterator
* @tparam sign the direction in which data is scrutinized, should be either 1 or -1, behaviour for other value is left undefined
*/
template<typename T, int sign = 1>
struct pointer_iterator final
{
T* data; /**< the only data field of the class */
typedef T value_type; /**< The type of which a reference will be returned on dereferencing */
typedef std::intptr_t difference_type; /**< The type of the substraction of two pointers */
static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; /**< @see iterator_type_t */
/**
* @brief Generates an empty iterator
*/
constexpr pointer_iterator()
: data{nullptr}
{}
constexpr pointer_iterator(const pointer_iterator& oth)
: data{oth.data}
{}
/**
* @brief Generates an iterator from any pointer
*/
constexpr pointer_iterator(T* ptr)
: data{ptr}
{}
/**
* @brief Dereference unary operator
*
* @return constexpr T& returns a reference to the pointed value
*/
constexpr T& operator*() const
{
return *data;
}
constexpr pointer_iterator& operator++()
{
data += sign;
return *this;
}
constexpr pointer_iterator operator++(int)
{
auto p = *this;
data += sign;
return p;
}
constexpr pointer_iterator& operator--()
{
data -= sign;
return *this;
}
constexpr pointer_iterator operator--(int)
{
auto p = *this;
data -= sign;
return p;
}
constexpr pointer_iterator operator+(const std::size_t offset) const
{
return pointer_iterator{data+sign*offset};
}
constexpr pointer_iterator operator+(const difference_type offset) const
{
return pointer_iterator{data+sign*offset};
}
constexpr pointer_iterator operator+(const int offset) const
{
return pointer_iterator{data+sign*offset};
}
constexpr pointer_iterator operator-(const std::size_t offset) const
{
return pointer_iterator{data-sign*offset};
}
constexpr pointer_iterator operator-(const difference_type offset) const
{
return pointer_iterator{data-sign*offset};
}
constexpr pointer_iterator operator-(const int offset) const
{
return pointer_iterator{data-sign*offset};
}
constexpr difference_type operator-(const pointer_iterator& oth) const
{
return (data-oth.data)*sign;
}
constexpr bool operator==(const pointer_iterator oth) const
{
return data==oth.data;
}
constexpr bool operator!=(pointer_iterator oth) const
{
return data!=oth.data;
}
constexpr bool before_or_equal(const pointer_iterator oth) const
{
return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool after_or_equal(const pointer_iterator oth) const
{
return reinterpret_cast<std::intptr_t>(data) >= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool operator<=(const pointer_iterator oth) const
{
return before_or_equal(oth);
}
constexpr bool operator>=(const pointer_iterator oth) const
{
return after_or_equal(oth);
}
};
/**
* @brief An identical twin to the pointer_iterator, but which dereference to a const reference
*
* @see pointer_iterator
* @tparam T @see pointer_iterator
* @tparam sign @see pointer_iterator
*/
template<typename T, int sign = 1>
struct const_pointer_iterator final
{
const T* data; /**< @see pointer_iterator */
typedef T value_type; /**< @see pointer_iterator */
typedef std::intptr_t difference_type; /**< @see pointer_iterator */
static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; /**< @see pointer_iterator */
constexpr const_pointer_iterator(const const_pointer_iterator& oth)
: data{oth.data}
{}
/**
* @brief @see pointer_iterator
*/
constexpr const_pointer_iterator(const T* ptr)
: data{ptr}
{}
/**
* @brief Dereferencing returns a const version of what a pointer_iterator would return
*/
constexpr const T& operator*() const
{
return *data;
}
constexpr const_pointer_iterator& operator++()
{
data += sign;
return *this;
}
constexpr const_pointer_iterator operator++(int)
{
auto p = data;
data += sign;
return const_pointer_iterator{p};
}
constexpr const_pointer_iterator& operator--()
{
data -= sign;
return *this;
}
constexpr const_pointer_iterator operator--(int)
{
auto p = data;
data -= sign;
return const_pointer_iterator{p};
}
constexpr const_pointer_iterator operator+(const std::size_t offset) const
{
return const_pointer_iterator{data+sign*offset};
}
constexpr const_pointer_iterator operator+(const difference_type offset) const
{
return const_pointer_iterator{data+sign*offset};
}
constexpr const_pointer_iterator operator+(const int offset) const
{
return const_pointer_iterator{data+sign*offset};
}
constexpr const_pointer_iterator operator-(const difference_type offset) const
{
return const_pointer_iterator{data-sign*offset};
}
constexpr const_pointer_iterator operator-(const std::size_t offset) const
{
return const_pointer_iterator{data-sign*offset};
}
constexpr const_pointer_iterator operator-(const int offset)
{
return const_pointer_iterator{data-sign*offset};
}
constexpr difference_type operator-(const const_pointer_iterator& oth) const
{
return ((T*)data-(T*)oth.data)*sign;
}
constexpr bool operator==(const const_pointer_iterator oth) const
{
return data==oth.data;
}
constexpr bool operator!=(const_pointer_iterator oth) const
{
return data!=oth.data;
}
constexpr bool before_or_equal(const const_pointer_iterator oth) const
{
return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool after_or_equal(const const_pointer_iterator oth) const
{
return reinterpret_cast<std::intptr_t>(data) >= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool operator<=(const const_pointer_iterator oth) const
{
return before_or_equal(oth);
}
constexpr bool operator>=(const const_pointer_iterator oth) const
{
return after_or_equal(oth);
}
};
}