[ox/std] Add ox::Array
This commit is contained in:
parent
7459d687b0
commit
27f5523e70
369
deps/ox/src/ox/std/array.hpp
vendored
Normal file
369
deps/ox/src/ox/std/array.hpp
vendored
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 - 2022 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "bit.hpp"
|
||||||
|
#include "error.hpp"
|
||||||
|
#include "initializerlist.hpp"
|
||||||
|
#include "iterator.hpp"
|
||||||
|
#include "math.hpp"
|
||||||
|
#include "memory.hpp"
|
||||||
|
#include "new.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace ox {
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
class Array {
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
|
||||||
|
template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
|
||||||
|
struct iterator: public std::iterator<std::bidirectional_iterator_tag, T> {
|
||||||
|
private:
|
||||||
|
PtrType m_t = nullptr;
|
||||||
|
size_type m_offset = 0;
|
||||||
|
size_type m_max = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr iterator() noexcept = default;
|
||||||
|
|
||||||
|
constexpr iterator(PtrType t, size_type offset, size_type max) noexcept {
|
||||||
|
m_t = t;
|
||||||
|
m_offset = offset;
|
||||||
|
m_max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto offset() const noexcept {
|
||||||
|
return m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator operator+(size_type s) const noexcept {
|
||||||
|
if constexpr(reverse) {
|
||||||
|
return iterator(m_t, max<size_type>(m_offset - s, 0), m_max);
|
||||||
|
} else {
|
||||||
|
return iterator(m_t, min<size_type>(m_offset + s, m_max), m_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr typename std::iterator<std::bidirectional_iterator_tag, T>::difference_type
|
||||||
|
operator-(const iterator &other) const noexcept {
|
||||||
|
if constexpr(reverse) {
|
||||||
|
return m_offset + other.m_offset;
|
||||||
|
} else {
|
||||||
|
return m_offset - other.m_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator operator-(size_type s) const noexcept {
|
||||||
|
if constexpr(reverse) {
|
||||||
|
return iterator(m_t, min<size_type>(m_offset + s, m_max), m_max);
|
||||||
|
} else {
|
||||||
|
return iterator(m_t, max<size_type>(m_offset - s, 0), m_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator &operator+=(size_type s) noexcept {
|
||||||
|
if constexpr(reverse) {
|
||||||
|
m_offset = max<size_type>(m_offset - s, 0);
|
||||||
|
} else {
|
||||||
|
m_offset = min(m_offset + s, m_max);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator &operator-=(size_type s) noexcept {
|
||||||
|
if constexpr(reverse) {
|
||||||
|
m_offset = min(m_offset + s, m_max);
|
||||||
|
} else {
|
||||||
|
m_offset = max<size_type>(m_offset - s, 0);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator &operator++() noexcept {
|
||||||
|
return operator+=(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator &operator--() noexcept {
|
||||||
|
return operator-=(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr RefType operator*() const noexcept {
|
||||||
|
return m_t[m_offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr RefType operator[](size_type s) const noexcept {
|
||||||
|
return m_t[s];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<(const iterator &other) const noexcept {
|
||||||
|
return m_offset < other.m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator>(const iterator &other) const noexcept {
|
||||||
|
return m_offset > other.m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<=(const iterator &other) const noexcept {
|
||||||
|
return m_offset <= other.m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator>=(const iterator &other) const noexcept {
|
||||||
|
return m_offset >= other.m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const iterator &other) const noexcept {
|
||||||
|
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const iterator &other) const noexcept {
|
||||||
|
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
T m_items[ArraySize];
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr Array() noexcept = default;
|
||||||
|
|
||||||
|
explicit constexpr Array(std::size_t size) noexcept;
|
||||||
|
|
||||||
|
constexpr Array(std::initializer_list<T> list) noexcept;
|
||||||
|
|
||||||
|
constexpr Array(const Array &other);
|
||||||
|
|
||||||
|
constexpr Array(Array &&other) noexcept;
|
||||||
|
|
||||||
|
~Array();
|
||||||
|
|
||||||
|
constexpr iterator<> begin() noexcept {
|
||||||
|
return iterator<>(&m_items[0], 0, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<> end() noexcept {
|
||||||
|
return iterator<>(&m_items[0], ArraySize, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<const T&, const T*> begin() const noexcept {
|
||||||
|
return iterator<const T&, const T*>(&m_items[0], 0, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<const T&, const T*> end() const noexcept {
|
||||||
|
return iterator<const T&, const T*>(&m_items[0], ArraySize, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<T&, T*, true> rbegin() noexcept {
|
||||||
|
return iterator<T&, T*, true>(&m_items[0], ArraySize - 1, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<T&, T*, true> rend() noexcept {
|
||||||
|
return iterator<T&, T*, true>(&m_items[0], MaxValue<size_type>, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<const T&, const T*, true> rbegin() const noexcept {
|
||||||
|
return iterator<const T&, const T*, true>(m_items, ArraySize - 1, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator<const T&, const T*, true> rend() const noexcept {
|
||||||
|
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, ArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const Array &other) const;
|
||||||
|
|
||||||
|
constexpr Array &operator=(const Array &other);
|
||||||
|
|
||||||
|
constexpr Array &operator=(Array &&other) noexcept;
|
||||||
|
|
||||||
|
constexpr T &operator[](std::size_t i) noexcept;
|
||||||
|
|
||||||
|
constexpr const T &operator[](std::size_t i) const noexcept;
|
||||||
|
|
||||||
|
Result<T&> front() noexcept;
|
||||||
|
|
||||||
|
Result<const T&> front() const noexcept;
|
||||||
|
|
||||||
|
Result<T&> back() noexcept;
|
||||||
|
|
||||||
|
Result<const T&> back() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr std::size_t size() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr bool empty() const noexcept;
|
||||||
|
|
||||||
|
constexpr void clear();
|
||||||
|
|
||||||
|
constexpr void resize(std::size_t size);
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr T *data() noexcept {
|
||||||
|
return m_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr const T *data() const noexcept {
|
||||||
|
return m_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr bool contains(const T&) const;
|
||||||
|
|
||||||
|
constexpr void insert(std::size_t pos, const T &val);
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
constexpr T &emplace_back(Args&&... args);
|
||||||
|
|
||||||
|
constexpr void push_back(const T &item);
|
||||||
|
|
||||||
|
constexpr void pop_back();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an item from the Array.
|
||||||
|
* @param pos iterator at the point to remove
|
||||||
|
* @return Error if index is out of bounds
|
||||||
|
*/
|
||||||
|
constexpr Result<iterator<>> erase(const iterator<> &pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an item from the Array.
|
||||||
|
* @param pos position of item to remove
|
||||||
|
* @return Error if index is out of bounds
|
||||||
|
*/
|
||||||
|
constexpr Result<iterator<>> erase(std::size_t pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the last item in the Array to position pos and decrements the
|
||||||
|
* size by 1.
|
||||||
|
* @param pos position of item to remove
|
||||||
|
* @return Error if index is out of bounds
|
||||||
|
*/
|
||||||
|
constexpr Error unordered_erase(std::size_t pos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr void expandCap(std::size_t cap);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize, typename RefType, bool reverse>
|
||||||
|
using ArrayIt = typename Array<T, ArraySize>::template iterator<RefType, reverse>;
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize, typename RefType, bool reverse>
|
||||||
|
constexpr ArrayIt<T, ArraySize, RefType, reverse> operator+(std::size_t n, const ArrayIt<T, ArraySize, RefType, reverse> &a) {
|
||||||
|
return a + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr Array<T, ArraySize>::Array(std::size_t size) noexcept {
|
||||||
|
for (std::size_t i = 0; i < size; ++i) {
|
||||||
|
m_items[i] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr Array<T, ArraySize>::Array(std::initializer_list<T> list) noexcept {
|
||||||
|
for (auto &item : list) {
|
||||||
|
emplace_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr Array<T, ArraySize>::Array(const Array &other) {
|
||||||
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
||||||
|
new (&m_items[i]) T(other.m_items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr Array<T, ArraySize>::Array(Array &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
||||||
|
new (&m_items[i]) T(std::move(other.m_items[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
Array<T, ArraySize>::~Array() {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr bool Array<T, ArraySize>::operator==(const Array &other) const {
|
||||||
|
for (std::size_t i = 0; i < ArraySize; i++) {
|
||||||
|
if (!(m_items[i] == other.m_items[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(const Array &other) {
|
||||||
|
if (this != &other) {
|
||||||
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
||||||
|
m_items[i] = other.m_items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
||||||
|
m_items[i] = std::move(other.m_items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
|
||||||
|
return m_items[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
|
||||||
|
return m_items[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr std::size_t Array<T, ArraySize>::size() const noexcept {
|
||||||
|
return ArraySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr bool Array<T, ArraySize>::contains(const T &v) const {
|
||||||
|
for (std::size_t i = 0; i < ArraySize; i++) {
|
||||||
|
if (m_items[i] == v) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t ArraySize>
|
||||||
|
constexpr void Array<T, ArraySize>::expandCap(std::size_t cap) {
|
||||||
|
auto oldItems = m_items;
|
||||||
|
if (oldItems) { // move over old items
|
||||||
|
const auto itRange = ox::min(cap, ArraySize);
|
||||||
|
for (std::size_t i = 0; i < itRange; ++i) {
|
||||||
|
new (&m_items[i]) T(std::move(oldItems[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1
deps/ox/src/ox/std/std.hpp
vendored
1
deps/ox/src/ox/std/std.hpp
vendored
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "array.hpp"
|
||||||
#include "assert.hpp"
|
#include "assert.hpp"
|
||||||
#include "bit.hpp"
|
#include "bit.hpp"
|
||||||
#include "bstring.hpp"
|
#include "bstring.hpp"
|
||||||
|
8
deps/ox/src/ox/std/string.hpp
vendored
8
deps/ox/src/ox/std/string.hpp
vendored
@ -52,12 +52,12 @@ class BasicString {
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto cbegin() const noexcept {
|
constexpr auto cbegin() const noexcept {
|
||||||
return m_buff.cbegin();
|
return m_buff.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto cend() const noexcept {
|
constexpr auto cend() const noexcept {
|
||||||
return m_buff.cend();
|
return m_buff.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -72,12 +72,12 @@ class BasicString {
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto crbegin() const noexcept {
|
constexpr auto crbegin() const noexcept {
|
||||||
return m_buff.crbegin();
|
return m_buff.rbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto crend() const noexcept {
|
constexpr auto crend() const noexcept {
|
||||||
return m_buff.crend();
|
return m_buff.rend();
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicString &operator=(const char *str) noexcept;
|
BasicString &operator=(const char *str) noexcept;
|
||||||
|
16
deps/ox/src/ox/std/vector.hpp
vendored
16
deps/ox/src/ox/std/vector.hpp
vendored
@ -233,35 +233,35 @@ class Vector: detail::SmallVector<T, SmallVectorSize> {
|
|||||||
|
|
||||||
~Vector();
|
~Vector();
|
||||||
|
|
||||||
constexpr iterator<> begin() const noexcept {
|
constexpr iterator<> begin() noexcept {
|
||||||
return iterator<>(m_items, 0, m_size);
|
return iterator<>(m_items, 0, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<> end() const noexcept {
|
constexpr iterator<> end() noexcept {
|
||||||
return iterator<>(m_items, m_size, m_size);
|
return iterator<>(m_items, m_size, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<const T&, const T*> cbegin() const noexcept {
|
constexpr iterator<const T&, const T*> begin() const noexcept {
|
||||||
return iterator<const T&, const T*>(m_items, 0, m_size);
|
return iterator<const T&, const T*>(m_items, 0, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<const T&, const T*> cend() const noexcept {
|
constexpr iterator<const T&, const T*> end() const noexcept {
|
||||||
return iterator<const T&, const T*>(m_items, m_size, m_size);
|
return iterator<const T&, const T*>(m_items, m_size, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<T&, T*, true> rbegin() const noexcept {
|
constexpr iterator<T&, T*, true> rbegin() noexcept {
|
||||||
return iterator<T&, T*, true>(m_items, m_size - 1, m_size);
|
return iterator<T&, T*, true>(m_items, m_size - 1, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<T&, T*, true> rend() const noexcept {
|
constexpr iterator<T&, T*, true> rend() noexcept {
|
||||||
return iterator<T&, T*, true>(m_items, MaxValue<size_type>, m_size);
|
return iterator<T&, T*, true>(m_items, MaxValue<size_type>, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<const T&, const T*, true> crbegin() const noexcept {
|
constexpr iterator<const T&, const T*, true> rbegin() const noexcept {
|
||||||
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
|
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator<const T&, const T*, true> crend() const noexcept {
|
constexpr iterator<const T&, const T*, true> rend() const noexcept {
|
||||||
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
|
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user