179 lines
4.3 KiB
C++
179 lines
4.3 KiB
C++
/*
|
|
* Copyright 2015 - 2025 gary@drinkingtea.net
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "def.hpp"
|
|
#include "error.hpp"
|
|
#include "math.hpp"
|
|
|
|
#if !__has_include(<iterator>)
|
|
#include "stddef.hpp"
|
|
|
|
namespace std {
|
|
|
|
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 {
|
|
};
|
|
|
|
struct contiguous_iterator_tag: public random_access_iterator_tag {
|
|
};
|
|
|
|
}
|
|
#else
|
|
#include <iterator>
|
|
#endif
|
|
|
|
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
|
|
|
namespace ox {
|
|
|
|
template<typename Category, typename T, typename DiffType = std::ptrdiff_t,
|
|
typename PointerType = T*, typename ReferenceType = T&>
|
|
struct Iterator {
|
|
using iterator_category = Category;
|
|
using value_type = T;
|
|
using pointer = T*;
|
|
using reference = T&;
|
|
using difference_type = DiffType;
|
|
};
|
|
|
|
|
|
template<typename T, typename RefType, typename PtrType, bool reverse = false>
|
|
struct SpanIterator {
|
|
public:
|
|
using iterator_category = std::bidirectional_iterator_tag;
|
|
using value_type = T;
|
|
using pointer = T*;
|
|
using reference = T&;
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
private:
|
|
PtrType m_t = nullptr;
|
|
std::size_t m_offset = 0;
|
|
std::size_t m_max = 0;
|
|
|
|
public:
|
|
constexpr SpanIterator() noexcept = default;
|
|
|
|
constexpr SpanIterator(PtrType t, std::size_t offset, std::size_t max) noexcept:
|
|
m_t(t),
|
|
m_offset(offset),
|
|
m_max(max) {
|
|
}
|
|
|
|
constexpr auto offset() const noexcept {
|
|
return m_offset;
|
|
}
|
|
|
|
constexpr SpanIterator operator+(std::size_t s) const noexcept {
|
|
if constexpr(reverse) {
|
|
return SpanIterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
|
} else {
|
|
return SpanIterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
|
}
|
|
}
|
|
|
|
constexpr auto operator-(const SpanIterator &other) const noexcept {
|
|
if constexpr(reverse) {
|
|
return m_offset + other.m_offset;
|
|
} else {
|
|
return m_offset - other.m_offset;
|
|
}
|
|
}
|
|
|
|
constexpr SpanIterator operator-(std::size_t s) const noexcept {
|
|
if constexpr(reverse) {
|
|
return SpanIterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
|
} else {
|
|
return SpanIterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
|
}
|
|
}
|
|
|
|
constexpr SpanIterator &operator+=(std::size_t s) noexcept {
|
|
if constexpr(reverse) {
|
|
m_offset = max<std::size_t>(m_offset - s, 0);
|
|
} else {
|
|
m_offset = min(m_offset + s, m_max);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
constexpr SpanIterator &operator-=(std::size_t s) noexcept {
|
|
if constexpr(reverse) {
|
|
m_offset = min(m_offset + s, m_max);
|
|
} else {
|
|
m_offset = max<std::size_t>(m_offset - s, 0);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
constexpr SpanIterator &operator++() noexcept {
|
|
return operator+=(1);
|
|
}
|
|
|
|
constexpr SpanIterator &operator--() noexcept {
|
|
return operator-=(1);
|
|
}
|
|
|
|
constexpr PtrType operator->() const noexcept {
|
|
ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow");
|
|
return &m_t[m_offset];
|
|
}
|
|
|
|
constexpr RefType operator*() const noexcept {
|
|
ox::primitiveAssert(__FILE__, __LINE__, m_offset < m_max, "SpanIterator access overflow");
|
|
return m_t[m_offset];
|
|
}
|
|
|
|
constexpr RefType operator[](std::size_t s) const noexcept {
|
|
ox::primitiveAssert(__FILE__, __LINE__, s < m_max, "SpanIterator access overflow");
|
|
return m_t[s];
|
|
}
|
|
|
|
constexpr bool operator<(const SpanIterator &other) const noexcept {
|
|
return m_offset < other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator>(const SpanIterator &other) const noexcept {
|
|
return m_offset > other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator<=(const SpanIterator &other) const noexcept {
|
|
return m_offset <= other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator>=(const SpanIterator &other) const noexcept {
|
|
return m_offset >= other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator==(const SpanIterator &other) const noexcept {
|
|
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
|
}
|
|
|
|
constexpr bool operator!=(const SpanIterator &other) const noexcept {
|
|
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
OX_CLANG_NOWARN_END
|