[ox] Cleanup Vector

This commit is contained in:
Gary Talent 2023-06-13 23:51:13 -05:00
parent 20e5b7e617
commit dde51151ff
5 changed files with 125 additions and 65 deletions

View File

@ -51,7 +51,7 @@ constexpr DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler
template<typename Reader, typename T> template<typename Reader, typename T>
constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept { constexpr Result<const DescriptorType*> DataWalker<Reader, T>::type() const noexcept {
oxRequire(out, m_typeStack.back()); oxRequire(out, m_typeStack.back());
return out; return *out;
} }
template<typename Reader, typename T> template<typename Reader, typename T>

View File

@ -271,7 +271,7 @@ constexpr ox::Error Preloader<PlatSpec>::endAlloc() noexcept {
if (m_allocStack.empty()) { if (m_allocStack.empty()) {
return m_writer.seekp(0, ox::ios_base::end); return m_writer.seekp(0, ox::ios_base::end);
} }
const auto &si = m_allocStack.back().unwrap(); const auto &si = *m_allocStack.back().unwrap();
oxReturnError(m_writer.seekp(si.restore, si.seekdir)); oxReturnError(m_writer.seekp(si.restore, si.seekdir));
m_allocStack.pop_back(); m_allocStack.pop_back();
return {}; return {};
@ -354,7 +354,7 @@ constexpr ox::Error Preloader<PlatSpec>::fieldVector(
template<typename PlatSpec> template<typename PlatSpec>
constexpr bool Preloader<PlatSpec>::unionCheckAndIt() noexcept { constexpr bool Preloader<PlatSpec>::unionCheckAndIt() noexcept {
auto &u = m_unionIdx.back().unwrap(); auto &u = *m_unionIdx.back().unwrap();
return u.checkAndIterate(); return u.checkAndIterate();
} }

View File

@ -528,7 +528,7 @@ constexpr void BasicString<SmallStringSize_v>::set(const BasicString<OtherSize>
std::size_t strBytes = src.bytes(); std::size_t strBytes = src.bytes();
m_buff.resize(strBytes); m_buff.resize(strBytes);
copy_n(src.begin(), strBytes, m_buff.data()); copy_n(src.begin(), strBytes, m_buff.data());
m_buff.back().value = 0; *m_buff.back().value = 0;
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
@ -536,7 +536,7 @@ constexpr void BasicString<SmallStringSize_v>::set(CRStringView str) noexcept {
std::size_t strBytes = str.bytes(); std::size_t strBytes = str.bytes();
m_buff.resize(strBytes + 1); m_buff.resize(strBytes + 1);
copy_n(str.data(), strBytes, m_buff.data()); copy_n(str.data(), strBytes, m_buff.data());
m_buff.back().value = 0; *m_buff.back().value = 0;
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
@ -544,7 +544,7 @@ constexpr void BasicString<SmallStringSize_v>::set(const char *str) noexcept {
std::size_t strBytes = ox_strlen(str) + 1; std::size_t strBytes = ox_strlen(str) + 1;
m_buff.resize(strBytes); m_buff.resize(strBytes);
copy_n(str, strBytes, m_buff.data()); copy_n(str, strBytes, m_buff.data());
m_buff.back().value = 0; *m_buff.back().value = 0;
} }
template<std::size_t SmallStringSize_v> template<std::size_t SmallStringSize_v>
@ -552,7 +552,7 @@ constexpr void BasicString<SmallStringSize_v>::set(const char8_t *str) noexcept
std::size_t strBytes = ox_strlen(str) + 1; std::size_t strBytes = ox_strlen(str) + 1;
m_buff.resize(strBytes); m_buff.resize(strBytes);
memcpy(m_buff.data(), str, strBytes); memcpy(m_buff.data(), str, strBytes);
m_buff.back().value = 0; *m_buff.back().value = 0;
} }
extern template class BasicString<8>; extern template class BasicString<8>;

View File

@ -20,8 +20,8 @@ static std::map<ox::String, ox::Error(*)()> tests = {
ox::heapmgr::initHeap(&buff[0], &buff[buff.size()-1]); ox::heapmgr::initHeap(&buff[0], &buff[buff.size()-1]);
auto a1 = static_cast<char*>(ox::heapmgr::malloc(5)); auto a1 = static_cast<char*>(ox::heapmgr::malloc(5));
auto a2 = static_cast<char*>(ox::heapmgr::malloc(5)); auto a2 = static_cast<char*>(ox::heapmgr::malloc(5));
oxAssert(a1 >= &buff.front().value && a1 < &buff.back().value, "malloc is broken"); oxAssert(a1 >= buff.front().unwrap() && a1 < buff.back().unwrap(), "malloc is broken");
oxAssert(a2 >= &buff.front().value && a2 < &buff.back().value && a2 > a1 + 5, "malloc is broken"); oxAssert(a2 >= buff.front().unwrap() && a2 < buff.back().unwrap() && a2 > a1 + 5, "malloc is broken");
return OxError(0); return OxError(0);
} }
}, },

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2022 gary@drinkingtea.net * Copyright 2015 - 2023 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -31,7 +31,7 @@ struct VectorAllocator {
private: private:
ox::Array<AllocAlias<T>, Size> m_data = {}; ox::Array<AllocAlias<T>, Size> m_data = {};
Allocator m_allocator; Allocator m_allocator;
public: protected:
constexpr VectorAllocator() noexcept = default; constexpr VectorAllocator() noexcept = default;
constexpr VectorAllocator(const VectorAllocator&) noexcept = default; constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
constexpr VectorAllocator(VectorAllocator&&) noexcept = default; constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
@ -45,7 +45,11 @@ struct VectorAllocator {
} }
} }
constexpr void moveConstructItemsFrom(T **items, VectorAllocator *src, const std::size_t count, const std::size_t cap) noexcept { constexpr void moveConstructItemsFrom(
T **items,
VectorAllocator *src,
const std::size_t count,
const std::size_t cap) noexcept {
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM, // this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
// try removing it later // try removing it later
if (cap <= m_data.size() && count <= m_data.size()) { if (cap <= m_data.size() && count <= m_data.size()) {
@ -58,7 +62,11 @@ struct VectorAllocator {
} }
} }
constexpr void moveItemsFrom(T **items, VectorAllocator *src, const std::size_t count, const std::size_t cap) noexcept { constexpr void moveItemsFrom(
T **items,
VectorAllocator *src,
const std::size_t count,
const std::size_t cap) noexcept {
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM, // this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
// try removing it later // try removing it later
if (cap <= m_data.size() && count <= m_data.size()) { if (cap <= m_data.size() && count <= m_data.size()) {
@ -84,7 +92,7 @@ template<typename T, typename Allocator>
struct VectorAllocator<T, Allocator, 0> { struct VectorAllocator<T, Allocator, 0> {
private: private:
Allocator m_allocator; Allocator m_allocator;
public: protected:
constexpr VectorAllocator() noexcept = default; constexpr VectorAllocator() noexcept = default;
constexpr VectorAllocator(const VectorAllocator&) noexcept = default; constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
constexpr VectorAllocator(VectorAllocator&&) noexcept = default; constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
@ -94,7 +102,11 @@ struct VectorAllocator<T, Allocator, 0> {
} }
[[maybe_unused]] [[maybe_unused]]
constexpr void moveConstructItemsFrom(T**, VectorAllocator*, const std::size_t, const std::size_t) noexcept { constexpr void moveConstructItemsFrom(
T**,
VectorAllocator*,
const std::size_t,
const std::size_t) noexcept {
} }
[[maybe_unused]] [[maybe_unused]]
@ -310,16 +322,16 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
constexpr const T &operator[](std::size_t i) const noexcept; constexpr const T &operator[](std::size_t i) const noexcept;
[[nodiscard]] [[nodiscard]]
Result<T&> front() noexcept; constexpr Result<T*> front() noexcept;
[[nodiscard]] [[nodiscard]]
Result<const T&> front() const noexcept; constexpr Result<const T*> front() const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr Result<T&> back() noexcept; constexpr Result<T*> back() noexcept;
[[nodiscard]] [[nodiscard]]
constexpr Result<const T&> back() const noexcept; constexpr Result<const T*> back() const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr std::size_t size() const noexcept; constexpr std::size_t size() const noexcept;
@ -382,13 +394,18 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
constexpr void reserve(std::size_t cap); constexpr void reserve(std::size_t cap);
private:
constexpr void reserveInsert(std::size_t cap, std::size_t pos, std::size_t offset = 1);
}; };
template<typename T, std::size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse> template<typename T, std::size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse>
using VectorIt = typename Vector<T, SmallVectorSize, Allocator>::template iterator<RefType, reverse>; using VectorIt = typename Vector<T, SmallVectorSize, Allocator>::template iterator<RefType, reverse>;
template<typename T, std::size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse> template<typename T, std::size_t SmallVectorSize, typename Allocator, typename RefType, bool reverse>
constexpr VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> operator+(std::size_t n, const VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> &a) { constexpr VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> operator+(
std::size_t n,
const VectorIt<T, SmallVectorSize, Allocator, RefType, reverse> &a) {
return a + n; return a + n;
} }
@ -451,7 +468,8 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::operator==(const Vector &o
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(const Vector &other) { constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(
const Vector &other) {
if (this != &other) { if (this != &other) {
clear(); clear();
this->deallocate(m_items, m_cap); this->deallocate(m_items, m_cap);
@ -467,7 +485,8 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(Vector &&other) noexcept { constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(
Vector &&other) noexcept {
if (this != &other) { if (this != &other) {
clear(); clear();
this->deallocate(m_items, m_cap); this->deallocate(m_items, m_cap);
@ -493,39 +512,35 @@ constexpr const T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
Result<T&> Vector<T, SmallVectorSize, Allocator>::front() noexcept { constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::front() noexcept {
if (!m_size) { if (!m_size) {
AllocAlias<T> v; return {nullptr, OxError(1)};
return {*reinterpret_cast<T*>(&v), OxError(1)};
} }
return m_items[0]; return &m_items[0];
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
Result<const T&> Vector<T, SmallVectorSize, Allocator>::front() const noexcept { constexpr Result<const T*> Vector<T, SmallVectorSize, Allocator>::front() const noexcept {
if (!m_size) { if (!m_size) {
AllocAlias<T> v; return {nullptr, OxError(1)};
return {*reinterpret_cast<T*>(&v), OxError(1)};
} }
return m_items[0]; return &m_items[0];
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Result<T&> Vector<T, SmallVectorSize, Allocator>::back() noexcept { constexpr Result<T*> Vector<T, SmallVectorSize, Allocator>::back() noexcept {
if (!m_size) { if (!m_size) {
AllocAlias<T> v; return {nullptr, OxError(1)};
return {*reinterpret_cast<T*>(&v), OxError(1)};
} }
return m_items[m_size - 1]; return &m_items[m_size - 1];
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Result<const T&> Vector<T, SmallVectorSize, Allocator>::back() const noexcept { constexpr Result<const T*> Vector<T, SmallVectorSize, Allocator>::back() const noexcept {
if (!m_size) { if (!m_size) {
AllocAlias<T> v; return {nullptr, OxError(1)};
return {*reinterpret_cast<T*>(&v), OxError(1)};
} }
return m_items[m_size - 1]; return &m_items[m_size - 1];
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
@ -578,18 +593,25 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<> constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<>
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, std::size_t cnt, const T &val) { Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, std::size_t cnt, const T &val) {
// TODO: insert should ideally have its own reserve
if (m_size + cnt > m_cap) { if (m_size + cnt > m_cap) {
reserve(m_cap ? m_size + cnt : initialSize); reserveInsert(m_cap ? m_size + cnt : initialSize, pos, cnt);
} if (pos < m_size) {
if (pos < m_size) { m_items[pos] = val;
for (auto i = m_size + cnt - 1; i > pos; --i) { } else {
std::construct_at(&m_items[i], std::move(m_items[i - cnt])); for (auto i = 0u; i < cnt; ++i) {
std::construct_at(&m_items[pos + i], val);
}
} }
m_items[pos] = val;
} else { } else {
for (auto i = 0u; i < cnt; ++i) { if (pos < m_size) {
std::construct_at(&m_items[pos + i], val); for (auto i = m_size + cnt - 1; i > pos; --i) {
std::construct_at(&m_items[i], std::move(m_items[i - cnt]));
}
m_items[pos] = val;
} else {
for (auto i = 0u; i < cnt; ++i) {
std::construct_at(&m_items[pos + i], val);
}
} }
} }
++m_size; ++m_size;
@ -599,17 +621,22 @@ Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, std::size_t cnt,
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<> constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<>
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, const T &val) { Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, const T &val) {
// TODO: insert should ideally have its own reserve
if (m_size == m_cap) { if (m_size == m_cap) {
reserve(m_cap ? m_cap * 2 : initialSize); reserveInsert(m_cap ? m_cap * 2 : initialSize, pos);
} if (pos < m_size) {
if (pos < m_size) { m_items[pos] = val;
for (auto i = m_size; i > pos; --i) { } else {
std::construct_at(&m_items[i], std::move(m_items[i - 1])); std::construct_at(&m_items[pos], val);
} }
m_items[pos] = val;
} else { } else {
std::construct_at(&m_items[pos], val); if (pos < m_size) {
for (auto i = m_size; i > pos; --i) {
std::construct_at(&m_items[i], std::move(m_items[i - 1]));
}
m_items[pos] = val;
} else {
std::construct_at(&m_items[pos], val);
}
} }
++m_size; ++m_size;
return begin() + pos; return begin() + pos;
@ -619,17 +646,21 @@ template<typename T, std::size_t SmallVectorSize, typename Allocator>
template<typename... Args> template<typename... Args>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<> constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<>
Vector<T, SmallVectorSize, Allocator>::emplace(std::size_t pos, Args&&... args) { Vector<T, SmallVectorSize, Allocator>::emplace(std::size_t pos, Args&&... args) {
// TODO: insert should ideally have its own reserve
if (m_size == m_cap) { if (m_size == m_cap) {
reserve(m_cap ? m_cap * 2 : initialSize); reserveInsert(m_cap ? m_cap * 2 : initialSize);
} if (pos < m_size) {
if (pos < m_size) { m_items[pos].~T();
for (auto i = m_size; i > pos; --i) {
std::construct_at(&m_items[i], std::move(m_items[i - 1]));
} }
m_items[pos].~T(); std::construct_at(&m_items[pos], ox::forward<Args>(args)...);
} else {
if (pos < m_size) {
for (auto i = m_size; i > pos; --i) {
std::construct_at(&m_items[i], std::move(m_items[i - 1]));
}
m_items[pos].~T();
}
std::construct_at(&m_items[pos], ox::forward<Args>(args)...);
} }
std::construct_at(&m_items[pos], ox::forward<Args>(args)...);
++m_size; ++m_size;
return begin() + pos; return begin() + pos;
} }
@ -661,12 +692,14 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::pop_back() {
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Result<typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>> Vector<T, SmallVectorSize, Allocator>::erase(const iterator<> &pos) { constexpr Result<typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>>
Vector<T, SmallVectorSize, Allocator>::erase(const iterator<> &pos) {
return erase(pos.offset()); return erase(pos.offset());
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Result<typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>> Vector<T, SmallVectorSize, Allocator>::erase(std::size_t pos) { constexpr Result<typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>>
Vector<T, SmallVectorSize, Allocator>::erase(std::size_t pos) {
if (pos >= m_size) { if (pos >= m_size) {
return OxError(1, "Vector::erase failed: pos is greater than Vector size"); return OxError(1, "Vector::erase failed: pos is greater than Vector size");
} }
@ -708,6 +741,33 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(std::size_t cap) {
} }
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveInsert(
std::size_t cap,
std::size_t pos,
std::size_t offset) {
if (cap <= m_cap) {
return;
}
const auto oldItems = m_items;
const auto oldCap = m_cap;
m_cap = cap;
this->allocate(&m_items, cap);
if (oldItems) { // move over old items
auto itRange = ox::min(m_size, pos);
for (std::size_t i = 0; i < itRange; ++i) {
std::construct_at(&m_items[i], std::move(oldItems[i]));
oldItems[i].~T();
}
itRange = m_size;
for (std::size_t i = pos; i < itRange; ++i) {
std::construct_at(&m_items[i + offset], std::move(oldItems[i]));
oldItems[i].~T();
}
this->deallocate(oldItems, oldCap);
}
}
template<typename PlatSpec, typename T> template<typename PlatSpec, typename T>
[[nodiscard]] [[nodiscard]]