flatten 20260225
This commit is contained in:
13
tjp/core/containers/Align.h
Executable file
13
tjp/core/containers/Align.h
Executable file
@@ -0,0 +1,13 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ALIGN( X, __Declaration__ ) __Declaration__ __attribute__((aligned(X)))
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ALIGN( __Declaration__ ) __pragma( align(push, 4) ) __Declaration__ __pragma( pack(pop))
|
||||
#endif
|
||||
36
tjp/core/containers/Array+IO.hpp
Executable file
36
tjp/core/containers/Array+IO.hpp
Executable file
@@ -0,0 +1,36 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Array.hpp"
|
||||
#include "../assert/debug_assert.h"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename IO, typename T, size_t Size>
|
||||
void io_r(IO &io, std::array<T, Size> &t)
|
||||
{
|
||||
auto size = io.array_begin();
|
||||
debug_assert(size == Size);
|
||||
|
||||
for (auto &v: t)
|
||||
io.on_vector_value(v);
|
||||
|
||||
io.array_end();
|
||||
}
|
||||
|
||||
//template<typename IO, typename T, size_t Size>
|
||||
//void io_w(IO &io, std::array<T, Size> &t)
|
||||
//{
|
||||
// io.array_begin(t.size());
|
||||
// debug_assert(size == Size);
|
||||
//
|
||||
// for (auto &v: t)
|
||||
// io.on_vector_value(v);
|
||||
//
|
||||
// io.array_end();
|
||||
//}
|
||||
|
||||
} // namespace
|
||||
14
tjp/core/containers/Array.h
Executable file
14
tjp/core/containers/Array.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, int N>
|
||||
using Array = std::array<T, N>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Array.hpp
Executable file
7
tjp/core/containers/Array.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Array.h"
|
||||
34
tjp/core/containers/ByF.hpp
Executable file
34
tjp/core/containers/ByF.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
struct ByF {
|
||||
typedef bool is_transparent;
|
||||
|
||||
[[no_unique_address]]
|
||||
F f;
|
||||
|
||||
bool operator() (const T &lhs, const T &rhs) const
|
||||
{
|
||||
return f(lhs) < f(rhs);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const T &lhs, const R &rhs) const
|
||||
{
|
||||
return f(lhs) < f(rhs);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const R &lhs, const T &rhs) const
|
||||
{
|
||||
return f(lhs) < f(rhs);
|
||||
}
|
||||
} ;
|
||||
|
||||
}
|
||||
31
tjp/core/containers/ById.hpp
Executable file
31
tjp/core/containers/ById.hpp
Executable file
@@ -0,0 +1,31 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct ById {
|
||||
typedef bool is_transparent;
|
||||
|
||||
bool operator() (const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs.id < rhs.id;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const T &lhs, const R &rhs) const
|
||||
{
|
||||
return lhs.id < rhs;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const R &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs < rhs.id;
|
||||
}
|
||||
} ;
|
||||
|
||||
}
|
||||
31
tjp/core/containers/ByPtr.hpp
Executable file
31
tjp/core/containers/ByPtr.hpp
Executable file
@@ -0,0 +1,31 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../ptr/Ptr.h"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct ByPtr {
|
||||
typedef bool is_transparent;
|
||||
|
||||
bool operator() (const StrongPtr<T> &lhs, const StrongPtr<T> &rhs) const
|
||||
{
|
||||
return ptr_of(lhs) < ptr_of(rhs);
|
||||
}
|
||||
|
||||
bool operator() (const StrongPtr<T> &lhs, const T *rhs) const
|
||||
{
|
||||
return ptr_of(lhs) < rhs;
|
||||
}
|
||||
|
||||
bool operator() (const T *lhs, const StrongPtr<T> &rhs) const
|
||||
{
|
||||
return lhs < ptr_of(rhs);
|
||||
}
|
||||
} ;
|
||||
|
||||
}
|
||||
42
tjp/core/containers/ByPtrId.hpp
Executable file
42
tjp/core/containers/ByPtrId.hpp
Executable file
@@ -0,0 +1,42 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tjp/core/ptr/Ptr.hpp>
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct ByPtrId {
|
||||
typedef bool is_transparent;
|
||||
|
||||
bool operator() (const T *lhs, const T *rhs) const
|
||||
{
|
||||
debug_assert(lhs);
|
||||
debug_assert(rhs);
|
||||
return lhs->id < rhs->id;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const T *lhs, const R &rhs) const
|
||||
{
|
||||
debug_assert(lhs);
|
||||
debug_assert(rhs);
|
||||
|
||||
return lhs->id < rhs;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const R &lhs, const T *rhs) const
|
||||
{
|
||||
debug_assert(lhs);
|
||||
debug_assert(rhs);
|
||||
|
||||
return lhs < rhs->id;
|
||||
}
|
||||
} ;
|
||||
|
||||
}
|
||||
34
tjp/core/containers/ByStrongPtrId.hpp
Executable file
34
tjp/core/containers/ByStrongPtrId.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tjp/core/ptr/Ptr.hpp>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct ByStrongPtrId {
|
||||
typedef bool is_transparent;
|
||||
|
||||
bool operator() (const StrongPtr<T> &lhs, const StrongPtr<T> &rhs) const
|
||||
{
|
||||
return lhs->id < rhs->id;
|
||||
}
|
||||
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const StrongPtr<T> &lhs, const R &rhs) const
|
||||
{
|
||||
return lhs->id < rhs;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool operator() (const R &lhs, const StrongPtr<T> &rhs) const
|
||||
{
|
||||
return lhs < rhs->id;
|
||||
}
|
||||
} ;
|
||||
|
||||
}
|
||||
18
tjp/core/containers/FilledArray.h
Executable file
18
tjp/core/containers/FilledArray.h
Executable file
@@ -0,0 +1,18 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
* std list and vector and set are too slow for some reason, need fast allocation, with
|
||||
*/
|
||||
template<typename T, int N=32>
|
||||
struct FilledArray;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
66
tjp/core/containers/FilledArray.hpp
Executable file
66
tjp/core/containers/FilledArray.hpp
Executable file
@@ -0,0 +1,66 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FilledArray.h"
|
||||
#include "StackArray.hpp"
|
||||
|
||||
#include "../debug/Debug.h"
|
||||
#include "../assert/debug_assert.h"
|
||||
#include <memory>
|
||||
#include <cstring> // memcpy
|
||||
#include "../threads/TestCollision.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T, int N>
|
||||
struct FilledArray : StackArray<T, N>
|
||||
{
|
||||
using Super = StackArray<T, N>;
|
||||
using iterator = typename Super::iterator;
|
||||
using const_iterator = typename Super::const_iterator;
|
||||
|
||||
void insert(const T &element)
|
||||
{
|
||||
this->push_back(element);
|
||||
}
|
||||
|
||||
void erase (typename Super::iterator i)
|
||||
{
|
||||
if (i == this->end())
|
||||
return;
|
||||
|
||||
auto &back = this->back();
|
||||
if (i != &back)
|
||||
*i = std::move(back);
|
||||
|
||||
this->pop_back();
|
||||
}
|
||||
|
||||
void erase (const T &element)
|
||||
{
|
||||
erase(find(element));
|
||||
}
|
||||
|
||||
iterator find (const T &element)
|
||||
{
|
||||
// now iterator all except for what used to be the end element
|
||||
for (auto i=this->begin(); i!=this->end(); ++i)
|
||||
{
|
||||
if (*i == element)
|
||||
{
|
||||
// the end element was the last element
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return this->end();
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
20
tjp/core/containers/FilledArrayThreadSafe.h
Executable file
20
tjp/core/containers/FilledArrayThreadSafe.h
Executable file
@@ -0,0 +1,20 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../threads/Lock.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
* std list and vector and set are too slow for some reason, need fast allocation, with
|
||||
*/
|
||||
template<typename T, int N=32, typename M = Mutex>
|
||||
class FilledArrayThreadSafe;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
34
tjp/core/containers/FilledArrayThreadSafe.hpp
Executable file
34
tjp/core/containers/FilledArrayThreadSafe.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FilledArrayThreadSafe.h"
|
||||
#include "FilledArray.hpp"
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
* std list and vector and set are too slow for some reason, need fast allocation, with
|
||||
*/
|
||||
template<typename T, int N, typename M>
|
||||
struct FilledArrayThreadSafe : FilledArray<T,N>
|
||||
{
|
||||
typedef FilledArray<T,N> Super;
|
||||
typedef M Mutex;
|
||||
Mutex m;
|
||||
|
||||
template<typename ... U>
|
||||
FilledArrayThreadSafe(U&& ...u) :
|
||||
Super(std::forward<U>(u)...)
|
||||
{
|
||||
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
14
tjp/core/containers/Function.h
Executable file
14
tjp/core/containers/Function.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename V>
|
||||
using Function = std::function<V>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Function.hpp
Executable file
7
tjp/core/containers/Function.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Function.h"
|
||||
64
tjp/core/containers/InPlaceArray+iterator.inl
Executable file
64
tjp/core/containers/InPlaceArray+iterator.inl
Executable file
@@ -0,0 +1,64 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../assert/debug_assert.h"
|
||||
#include "../assert/handle_assert.hpp"
|
||||
#include "../algorithm/mem_copy.hpp"
|
||||
|
||||
#include <cstring> // for memcpy
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto rbegin(InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.rbegin();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto rend(InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.rend();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto rbegin(const InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.rbegin();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto rend(const InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.rend();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto begin(InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.begin();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto end(InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.end();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto begin(const InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.begin();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto end(const InPlaceArray<T, N> &t)
|
||||
{
|
||||
return t.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
17
tjp/core/containers/InPlaceArray.h
Executable file
17
tjp/core/containers/InPlaceArray.h
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T, size_t N=32>
|
||||
class InPlaceArray;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
137
tjp/core/containers/InPlaceArray.hpp
Executable file
137
tjp/core/containers/InPlaceArray.hpp
Executable file
@@ -0,0 +1,137 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "InPlaceArray.h"
|
||||
#include "Array.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
#include "../types/Types.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T, size_t N>
|
||||
class InPlaceArray
|
||||
{
|
||||
public:
|
||||
static constexpr size_t MaxLength = N;
|
||||
|
||||
private:
|
||||
using Array = std::array<T, N>;
|
||||
using Block = char;
|
||||
using Size = u32;
|
||||
|
||||
union Static {
|
||||
Block block;
|
||||
Array array;
|
||||
|
||||
Static() : block(0) {}
|
||||
~Static () {}
|
||||
} ;
|
||||
|
||||
Static v;
|
||||
Size length = 0;
|
||||
|
||||
typedef std::allocator<T> Allocator;
|
||||
Allocator allocator;
|
||||
|
||||
public:
|
||||
using value_type = typename Array::value_type;
|
||||
using iterator = typename Array::iterator;
|
||||
using const_iterator = typename Array::const_iterator;
|
||||
using pointer = typename Array::pointer;
|
||||
using reference = typename Array::reference;
|
||||
using const_reference = typename Array::const_reference;
|
||||
|
||||
inline auto data() { return v.array.data(); }
|
||||
inline auto data() const { return v.array.data(); }
|
||||
|
||||
inline auto begin() { return v.array.begin(); }
|
||||
inline auto end () { return v.array.begin() + length; }
|
||||
|
||||
inline auto begin() const { return v.array.begin(); }
|
||||
inline auto end () const { return v.array.begin() + length; }
|
||||
|
||||
inline auto rbegin() { return v.array.rbegin() + (v.array.size() - length); }
|
||||
inline auto rend () { return v.array.rend(); }
|
||||
|
||||
inline auto rbegin() const { return v.array.rbegin() + (v.array.size() - length); }
|
||||
inline auto rend () const { return v.array.rend(); }
|
||||
|
||||
inline const_reference front () const { return v.array.front(); }
|
||||
inline const_reference back () const { return *(v.array.data() + (length - 1)); }
|
||||
inline reference front () { return v.array.front(); }
|
||||
inline reference back () { return *(v.array.data() + (length - 1)); }
|
||||
|
||||
private:
|
||||
template<typename ... Args>
|
||||
void construct(T *t, Args&& ...args)
|
||||
{
|
||||
std::allocator_traits<Allocator>::construct(allocator, t, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void destruct(T *t)
|
||||
{
|
||||
std::allocator_traits<Allocator>::destroy(allocator, t);
|
||||
}
|
||||
|
||||
protected:
|
||||
void shorten_block(size_t length_);
|
||||
void shorten_items(size_t length_);
|
||||
void shorten(size_t length_);
|
||||
void append_block(const T *begin, const T *end);
|
||||
void append_items(const T *begin, const T *end);
|
||||
void emplace_items(T *begin, T *end);
|
||||
|
||||
public:
|
||||
InPlaceArray ();
|
||||
InPlaceArray(size_t length_, T t=T());
|
||||
|
||||
// InPlaceArray(InPlaceArray &&rhs);
|
||||
|
||||
// template<size_t N2>
|
||||
InPlaceArray(const InPlaceArray<T, N> &rhs);
|
||||
InPlaceArray(const std::initializer_list<T> &rhs);
|
||||
InPlaceArray(const T *begin, const T *end);
|
||||
InPlaceArray(const T *begin, size_t size);
|
||||
|
||||
// template<size_t N2>
|
||||
InPlaceArray &operator =(const InPlaceArray<T, N> &rhs);
|
||||
InPlaceArray &operator =(const Array &rhs);
|
||||
~InPlaceArray ();
|
||||
|
||||
void resize(size_t length_, T t=T());
|
||||
void append(const T *begin, const T *end);
|
||||
void emplace(T *begin, T *end);
|
||||
|
||||
void push_back_();
|
||||
void push_back (const T &element);
|
||||
void push_back (T &&element);
|
||||
void pop_back ();
|
||||
|
||||
template<typename ... Args>
|
||||
T &emplace_back (Args&& ...args);
|
||||
|
||||
const T &at(size_t i) const;
|
||||
T &at(size_t i);
|
||||
|
||||
const T &operator[] (size_t i) const;
|
||||
T &operator[] (size_t i);
|
||||
|
||||
size_t size () const;
|
||||
void clear ();
|
||||
|
||||
bool empty () const;
|
||||
} ;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
#include "InPlaceArray.inl"
|
||||
#include "InPlaceArray+iterator.inl"
|
||||
333
tjp/core/containers/InPlaceArray.inl
Executable file
333
tjp/core/containers/InPlaceArray.inl
Executable file
@@ -0,0 +1,333 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../assert/debug_assert.h"
|
||||
#include "../assert/handle_assert.hpp"
|
||||
#include "../algorithm/mem_copy.hpp"
|
||||
|
||||
#include "../exception/OutOfBounds.hpp"
|
||||
|
||||
#include <cstring> // for memcpy
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T, size_t N>
|
||||
InPlaceArray<T, N>::InPlaceArray (size_t size, T t)
|
||||
{
|
||||
resize(size, t);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
InPlaceArray<T, N>::InPlaceArray ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
//template<size_t N2>
|
||||
InPlaceArray<T, N>::InPlaceArray(const InPlaceArray<T, N> &rhs)
|
||||
{
|
||||
append(rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
//template<size_t N2>
|
||||
InPlaceArray<T, N>::InPlaceArray(const T *begin, const T *end)
|
||||
{
|
||||
append(begin, end);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
//template<size_t N2>
|
||||
InPlaceArray<T, N>::InPlaceArray(const T *data, size_t size)
|
||||
{
|
||||
append(data, data + size);
|
||||
}
|
||||
|
||||
|
||||
//template<typename T, size_t N>
|
||||
//InPlaceArray<T, N>::InPlaceArray(InPlaceArray<T, N> &&rhs)
|
||||
//{
|
||||
// append(rhs.begin(), rhs.end());
|
||||
//}
|
||||
|
||||
template<typename T, size_t N>
|
||||
//template<size_t N2>
|
||||
InPlaceArray<T,N> &InPlaceArray<T, N>::operator =(const InPlaceArray<T, N> &rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
append(rhs.begin(), rhs.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
//template<size_t N2>
|
||||
InPlaceArray<T,N> &InPlaceArray<T, N>::operator =(const Array &rhs)
|
||||
{
|
||||
if (&v.array != &rhs)
|
||||
v.array = rhs;
|
||||
|
||||
length = N;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
InPlaceArray<T, N>::InPlaceArray(const std::initializer_list<T> &rhs)
|
||||
{
|
||||
for (auto &element: rhs)
|
||||
push_back(element);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::append_block(const T *begin_, const T *end_)
|
||||
{
|
||||
auto size = (end_ - begin_);
|
||||
|
||||
handle_assert(length + size <= N) {
|
||||
throw exceptions::OutOfBounds();
|
||||
}
|
||||
|
||||
mem_copy((char *)end(), (char *)begin_, size * sizeof(T));
|
||||
length += size;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::append_items(const T *begin_, const T *end_)
|
||||
{
|
||||
for (auto i = begin_; i!=end_; ++i)
|
||||
push_back(*i);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::emplace_items(T *begin_, T *end_)
|
||||
{
|
||||
for (auto i = begin_; i!=end_; ++i)
|
||||
emplace_back(std::move(*i));
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::append(const T *begin, const T *end)
|
||||
{
|
||||
if constexpr (std::is_trivially_copyable<T>::value)
|
||||
return append_block(begin, end);
|
||||
else
|
||||
return append_items(begin, end);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::emplace(T *begin, T *end)
|
||||
{
|
||||
if constexpr (std::is_trivially_copyable<T>::value)
|
||||
return append_block(begin, end);
|
||||
else
|
||||
return emplace_items(begin, end);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
InPlaceArray<T, N>::~InPlaceArray ()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::shorten_items(size_t length_)
|
||||
{
|
||||
while (length > length_)
|
||||
pop_back();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::shorten_block(size_t length_)
|
||||
{
|
||||
if (length > length_)
|
||||
length = (Size)length_;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::shorten(size_t length_)
|
||||
{
|
||||
if constexpr (std::is_trivially_destructible<T>::value)
|
||||
return shorten_block(length_);
|
||||
else
|
||||
return shorten_items(length_);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::resize(size_t length_, T t)
|
||||
{
|
||||
shorten(length_);
|
||||
|
||||
handle_assert(length_ <= N) {
|
||||
throw exceptions::OutOfBounds();
|
||||
}
|
||||
|
||||
if constexpr (std::is_trivially_copyable<T>::value)
|
||||
{
|
||||
if (length < length_)
|
||||
{
|
||||
auto *data_ = data();
|
||||
auto *begin = data_ + length;
|
||||
auto *end = data_ + length_;
|
||||
|
||||
std::fill(begin, end, t);
|
||||
length = (Size)length_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (length < length_)
|
||||
push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::push_back (const T &element)
|
||||
{
|
||||
handle_assert(length < N) {
|
||||
throw exceptions::OutOfBounds();
|
||||
}
|
||||
|
||||
++length;
|
||||
|
||||
if constexpr (std::is_trivially_copyable<T>::value)
|
||||
{
|
||||
back() = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
construct(&back(), element);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::push_back (T &&element)
|
||||
{
|
||||
handle_assert(length < N) {
|
||||
throw exceptions::OutOfBounds();
|
||||
}
|
||||
|
||||
++length;
|
||||
construct(&back(), std::move(element));
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::pop_back ()
|
||||
{
|
||||
debug_assert (length > 0);
|
||||
|
||||
// decrease length
|
||||
if (length > 0)
|
||||
{
|
||||
--length;
|
||||
destruct(&v.array[length]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
template<typename ... Args>
|
||||
T &InPlaceArray<T, N>::emplace_back (Args&& ...element)
|
||||
{
|
||||
handle_assert(length < N) {
|
||||
throw exceptions::OutOfBounds();
|
||||
}
|
||||
|
||||
++length;
|
||||
auto &t = back();
|
||||
construct(&t, std::forward<Args>(element)...);
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const T &InPlaceArray<T, N>::at(size_t i) const
|
||||
{
|
||||
return v.array[i];
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
T &InPlaceArray<T, N>::at(size_t i)
|
||||
{
|
||||
return v.array[i];
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const T &InPlaceArray<T, N>::operator[] (size_t i) const
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
T &InPlaceArray<T, N>::operator[] (size_t i)
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
size_t InPlaceArray<T, N>::size () const
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void InPlaceArray<T, N>::clear ()
|
||||
{
|
||||
shorten(0);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool InPlaceArray<T, N>::empty () const
|
||||
{
|
||||
return length == 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator <(const InPlaceArray<T, N> &lhs, const InPlaceArray<T, N> &rhs)
|
||||
{
|
||||
auto max = std::min(lhs.size(), rhs.size());
|
||||
|
||||
for (auto i=0; i<max; ++i)
|
||||
{
|
||||
auto &l = lhs.at(i);
|
||||
auto &r = rhs.at(i);
|
||||
|
||||
if (l != r)
|
||||
return l < r;
|
||||
}
|
||||
|
||||
return lhs.size() < rhs.size();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator ==(const InPlaceArray<T, N> &lhs, const InPlaceArray<T, N> &rhs)
|
||||
{
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
|
||||
for (auto i=0; i<lhs.size(); ++i)
|
||||
{
|
||||
auto &l = lhs.at(i);
|
||||
auto &r = rhs.at(i);
|
||||
|
||||
if (l != r)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator !=(const InPlaceArray<T, N> &lhs, const InPlaceArray<T, N> &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
|
||||
14
tjp/core/containers/List.h
Executable file
14
tjp/core/containers/List.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename V>
|
||||
using List = std::list<V>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/List.hpp
Executable file
7
tjp/core/containers/List.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "List.h"
|
||||
14
tjp/core/containers/Map.h
Executable file
14
tjp/core/containers/Map.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename K, typename V, typename L=std::less<K>, typename A=std::allocator<std::pair<const K, V>>>
|
||||
using Map = std::map<K, V, L, A>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Map.hpp
Executable file
7
tjp/core/containers/Map.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Map.h"
|
||||
23
tjp/core/containers/MemoryArray.h
Executable file
23
tjp/core/containers/MemoryArray.h
Executable file
@@ -0,0 +1,23 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector.h"
|
||||
|
||||
namespace tjp::core {
|
||||
namespace memory_array {
|
||||
|
||||
template<typename T>
|
||||
struct MemoryArrayIterator;
|
||||
|
||||
template<typename T>
|
||||
struct MemoryArray;
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace memory_array;
|
||||
|
||||
} // namespace
|
||||
|
||||
170
tjp/core/containers/MemoryArray.hpp
Executable file
170
tjp/core/containers/MemoryArray.hpp
Executable file
@@ -0,0 +1,170 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MemoryArray.h"
|
||||
#include "Vector.h"
|
||||
#include "../assert/debug_assert.h"
|
||||
|
||||
namespace tjp::core {
|
||||
namespace memory_array {
|
||||
|
||||
template<typename T>
|
||||
struct MemoryArrayIterator
|
||||
{
|
||||
char *ptr_;
|
||||
size_t stride_;
|
||||
size_t offset_;
|
||||
|
||||
void operator ++()
|
||||
{
|
||||
ptr_ += stride_;
|
||||
}
|
||||
|
||||
T &operator *()
|
||||
{
|
||||
return *(T *)(ptr_ + offset_);
|
||||
}
|
||||
|
||||
bool operator !=(const MemoryArrayIterator<T> &rhs)
|
||||
{
|
||||
return ptr_ != rhs.ptr_;
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct MemoryArray
|
||||
{
|
||||
char *begin_;
|
||||
size_t size_;
|
||||
size_t stride_;
|
||||
size_t offset_;
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
MemoryArray(char *begin, size_t size, size_t stride, size_t offset) :
|
||||
begin_(begin),
|
||||
size_(size),
|
||||
stride_(stride),
|
||||
offset_(offset)
|
||||
{}
|
||||
|
||||
MemoryArray(const Vector<T> &v) :
|
||||
begin_((char *)(v.data())),
|
||||
size_(v.size()),
|
||||
stride_(sizeof(T)),
|
||||
offset_(0)
|
||||
{}
|
||||
|
||||
T &at(size_t index) const
|
||||
{
|
||||
char *ptr = (begin_ + stride_*index) + offset_;
|
||||
return *(T *)ptr;
|
||||
}
|
||||
|
||||
auto &operator[](size_t index) const
|
||||
{
|
||||
return at(index);
|
||||
}
|
||||
|
||||
auto begin () const
|
||||
{
|
||||
return MemoryArrayIterator<T> { begin_, stride_, offset_ };
|
||||
}
|
||||
|
||||
auto end () const
|
||||
{
|
||||
return MemoryArrayIterator<T> { (begin_ + stride_*size_), stride_, offset_ };
|
||||
}
|
||||
|
||||
auto &front () const
|
||||
{
|
||||
return at(0);
|
||||
}
|
||||
|
||||
auto &back () const
|
||||
{
|
||||
return at(size()-1);
|
||||
}
|
||||
|
||||
auto size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
auto recast() const
|
||||
{
|
||||
return MemoryArray<U> { begin_, size_, stride_, offset_ };
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename R>
|
||||
MemoryArray<R> memoryArray()
|
||||
{
|
||||
return MemoryArray<R> { nullptr, 0, 0, 0 };
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
MemoryArray<R> memoryArray(void *begin, size_t size, size_t stride, size_t offset)
|
||||
{
|
||||
return MemoryArray<R> { (char *)begin, size, stride, offset };
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
template<typename R, typename T>
|
||||
MemoryArray<R> memoryArray(const T *begin, size_t size)
|
||||
{
|
||||
static_assert(sizeof(R) <= sizeof(T));
|
||||
return memoryArray<R>((void *)begin, size, sizeof(T), 0);
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
MemoryArray<R> memoryArray(const T *begin, size_t size, size_t offset)
|
||||
{
|
||||
static_assert(sizeof(R) <= sizeof(T));
|
||||
return memoryArray<R>((void *)begin, size, sizeof(T), offset * sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
MemoryArray<T> memoryArray(const T *begin, size_t size)
|
||||
{
|
||||
return memoryArray<T, T>(begin, size);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
MemoryArray<T> memoryArray(const T *begin, size_t size, size_t offset)
|
||||
{
|
||||
return memoryArray<T, T>(begin, size, offset);
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
||||
template<typename R, typename T>
|
||||
MemoryArray<R> memoryArray(const Vector<T> &data)
|
||||
{
|
||||
return memoryArray<R, T>(data.data(), data.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MemoryArray<T> memoryArray(const Vector<T> &data)
|
||||
{
|
||||
return memoryArray<T, T>(data);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace memory_array;
|
||||
|
||||
} // namespace
|
||||
|
||||
13
tjp/core/containers/MemorySegment.h
Executable file
13
tjp/core/containers/MemorySegment.h
Executable file
@@ -0,0 +1,13 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core::containers {
|
||||
|
||||
template<typename T>
|
||||
struct MemorySegment;
|
||||
|
||||
} // namespace
|
||||
|
||||
75
tjp/core/containers/MemorySegment.hpp
Executable file
75
tjp/core/containers/MemorySegment.hpp
Executable file
@@ -0,0 +1,75 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MemorySegment.h"
|
||||
#include <stddef.h>
|
||||
|
||||
namespace tjp::core::containers {
|
||||
|
||||
template<typename T>
|
||||
struct MemorySegment
|
||||
{
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
|
||||
T *data_ = nullptr;
|
||||
size_t size_ = 0;
|
||||
|
||||
using iterator = T *;
|
||||
using const_iterator = T *;
|
||||
|
||||
iterator begin() { return data_; }
|
||||
iterator end() { return data_ + size_; }
|
||||
|
||||
const_iterator begin() const { return data_; }
|
||||
const_iterator end() const { return data_ + size_; }
|
||||
|
||||
T *data() { return data_; }
|
||||
const T *data() const { return data_; }
|
||||
|
||||
size_t size() const { return size_; }
|
||||
|
||||
T &operator[](size_t i)
|
||||
{
|
||||
return data_[i];
|
||||
}
|
||||
|
||||
const T &operator[](size_t i) const
|
||||
{
|
||||
return data_[i];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
MemorySegment<T> memory_segment(T *t, size_t size)
|
||||
{
|
||||
return MemorySegment<T> { t, size };
|
||||
}
|
||||
|
||||
template<typename C, typename T>
|
||||
inline
|
||||
MemorySegment<C> memory_segment(T *t, size_t size)
|
||||
{
|
||||
return MemorySegment<C> { (C *)t, size * sizeof(T) / sizeof(C) };
|
||||
}
|
||||
|
||||
template<typename C, typename T>
|
||||
inline
|
||||
MemorySegment<C> memory_segment_vector(const T &t)
|
||||
{
|
||||
return { (C *)t.data(), t.size() * sizeof(typename T::value_type) / sizeof(C) };
|
||||
}
|
||||
|
||||
template<typename C, typename T>
|
||||
inline
|
||||
MemorySegment<C> memory_segment_value(const T &t)
|
||||
{
|
||||
return MemorySegment<C> { (C *)&t, sizeof(T) / sizeof(C) };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
232
tjp/core/containers/MultiContainer.hpp
Executable file
232
tjp/core/containers/MultiContainer.hpp
Executable file
@@ -0,0 +1,232 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray.hpp"
|
||||
#include "../exception/OutOfBounds.hpp"
|
||||
#include "../algorithm/vector_erase_if_value.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
using MultiContainer_ = StackArray<T *>;
|
||||
|
||||
template<typename T, typename I, typename J>
|
||||
struct MultiIterator
|
||||
{
|
||||
using Self = MultiIterator<T,I,J>;
|
||||
using value_type = typename T::value_type;
|
||||
using reference = typename T::reference;
|
||||
|
||||
I end;
|
||||
I i;
|
||||
J j;
|
||||
bool ended;
|
||||
|
||||
MultiIterator()
|
||||
{
|
||||
}
|
||||
|
||||
MultiIterator(I &&end_, I &&i_, J &&j_, bool ended_) :
|
||||
end(end_),
|
||||
i(i_),
|
||||
j(j_),
|
||||
ended(ended_)
|
||||
{
|
||||
validate();
|
||||
}
|
||||
|
||||
auto &deref ()
|
||||
{
|
||||
return *j;
|
||||
}
|
||||
|
||||
auto &operator *() { return deref(); }
|
||||
auto &operator ->() { return deref(); }
|
||||
|
||||
void validate()
|
||||
{
|
||||
while (!ended && j == (*i)->end())
|
||||
{
|
||||
++i;
|
||||
|
||||
if (i == end)
|
||||
ended = true;
|
||||
else
|
||||
j = (*i)->begin();
|
||||
}
|
||||
}
|
||||
|
||||
void next()
|
||||
{
|
||||
if (ended)
|
||||
return;
|
||||
|
||||
++j;
|
||||
validate();
|
||||
}
|
||||
|
||||
auto &operator++(int)
|
||||
{
|
||||
next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator++()
|
||||
{
|
||||
auto v = *this;
|
||||
next();
|
||||
return v;
|
||||
}
|
||||
|
||||
bool operator ==(const Self &rhs) const
|
||||
{
|
||||
return
|
||||
(ended && rhs.ended) ||
|
||||
(i == rhs.i && j == rhs.j);
|
||||
}
|
||||
|
||||
bool operator !=(const Self &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T, typename C=MultiContainer_<T>>
|
||||
struct MultiContainer {
|
||||
C c;
|
||||
|
||||
using Self = MultiContainer<T, C>;
|
||||
using iterator = MultiIterator<T,typename C::iterator,typename T::iterator>;
|
||||
using const_iterator = MultiIterator<T,typename C::const_iterator,typename T::const_iterator>;
|
||||
using value_type = typename T::value_type;
|
||||
using reference = typename T::reference;
|
||||
|
||||
MultiContainer()
|
||||
{}
|
||||
|
||||
template<typename ... Args>
|
||||
MultiContainer(Args ... args)
|
||||
{
|
||||
(add(args),...);
|
||||
}
|
||||
|
||||
template<typename CI, typename TI, typename U>
|
||||
static auto begin(U &self)
|
||||
{
|
||||
auto &c = self.c;
|
||||
|
||||
CI end = c.end();
|
||||
CI i = c.begin();
|
||||
TI j;
|
||||
|
||||
auto ended = c.empty();
|
||||
if (!ended)
|
||||
{
|
||||
j = (*i)->begin();
|
||||
}
|
||||
|
||||
return MultiIterator<T,CI,TI>(
|
||||
std::move(end),
|
||||
std::move(i),
|
||||
std::move(j),
|
||||
ended
|
||||
);
|
||||
}
|
||||
|
||||
template<typename CI, typename TI, typename U>
|
||||
static auto end(U &self)
|
||||
{
|
||||
auto &c = self.c;
|
||||
|
||||
CI end = c.end();
|
||||
CI i = c.end();
|
||||
TI j;
|
||||
|
||||
return MultiIterator<T,CI,TI>(
|
||||
std::move(end),
|
||||
std::move(i),
|
||||
std::move(j),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
auto begin()
|
||||
{
|
||||
return begin<typename C::iterator, typename T::iterator>(*this);
|
||||
}
|
||||
|
||||
auto end()
|
||||
{
|
||||
return end<typename C::iterator, typename T::iterator>(*this);
|
||||
}
|
||||
|
||||
auto begin() const
|
||||
{
|
||||
return begin<typename C::const_iterator, typename T::const_iterator>(*this);
|
||||
}
|
||||
|
||||
auto end() const
|
||||
{
|
||||
return end<typename C::const_iterator, typename T::const_iterator>(*this);
|
||||
}
|
||||
|
||||
void add(T *t)
|
||||
{
|
||||
c.push_back(t);
|
||||
}
|
||||
|
||||
void remove(T *t)
|
||||
{
|
||||
auto i = std::find(c.begin(), c.end(), t);
|
||||
if (i != c.end())
|
||||
{
|
||||
std::swap(*i, c.back());
|
||||
c.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
auto container_size() const
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
auto size() const
|
||||
{
|
||||
size_t size_ = 0;
|
||||
for (auto *v : c)
|
||||
size_ += v->size();
|
||||
|
||||
return size_;
|
||||
}
|
||||
|
||||
auto empty() const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
auto &at(size_t i) const
|
||||
{
|
||||
for (auto *v : c)
|
||||
{
|
||||
size_t size_ = v->size();
|
||||
if (i < size_)
|
||||
return v->at(i);
|
||||
|
||||
i -= size_;
|
||||
}
|
||||
|
||||
debug_assert(false);
|
||||
throw exceptions::OutOfBounds();
|
||||
}
|
||||
|
||||
auto &operator[](size_t i)
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
|
||||
17
tjp/core/containers/Optional+IO.hpp
Executable file
17
tjp/core/containers/Optional+IO.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Optional.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename T>
|
||||
auto logOf(const std::optional<T> &v)
|
||||
{
|
||||
return tjp::core::logOfRef(v ? &*v : nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
14
tjp/core/containers/Optional.h
Executable file
14
tjp/core/containers/Optional.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
using Optional = std::optional<T>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Optional.hpp
Executable file
7
tjp/core/containers/Optional.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Optional.h"
|
||||
13
tjp/core/containers/Pack.h
Executable file
13
tjp/core/containers/Pack.h
Executable file
@@ -0,0 +1,13 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
|
||||
#endif
|
||||
14
tjp/core/containers/Pair.h
Executable file
14
tjp/core/containers/Pair.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename A, typename B>
|
||||
using Pair = std::pair<A, B>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Pair.hpp
Executable file
7
tjp/core/containers/Pair.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Pair.h"
|
||||
14
tjp/core/containers/PtrOnly.h
Executable file
14
tjp/core/containers/PtrOnly.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct PtrOnly;
|
||||
|
||||
} // namespace
|
||||
59
tjp/core/containers/PtrOnly.hpp
Executable file
59
tjp/core/containers/PtrOnly.hpp
Executable file
@@ -0,0 +1,59 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PtrOrValue.h"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct PtrOnly {
|
||||
const T *p = nullptr;
|
||||
|
||||
const T *get() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
PtrOnly(const T *p_) :
|
||||
p(p_)
|
||||
{}
|
||||
|
||||
PtrOnly(const PtrOnly &rhs) :
|
||||
p(rhs.p)
|
||||
{}
|
||||
|
||||
PtrOnly(PtrOnly &&rhs) :
|
||||
p(std::move(rhs.p))
|
||||
{}
|
||||
|
||||
auto *operator ->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
const T &operator *() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
operator const T&() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
PtrOnly<T> makePtrOnly(const T *t)
|
||||
{
|
||||
return PtrOnly<T>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
PtrOnly<T> makePtrOnly(const T &t)
|
||||
{
|
||||
return PtrOnly<T>(t);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
14
tjp/core/containers/PtrOrValue.h
Executable file
14
tjp/core/containers/PtrOrValue.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct PtrOrValue;
|
||||
|
||||
} // namespace
|
||||
70
tjp/core/containers/PtrOrValue.hpp
Executable file
70
tjp/core/containers/PtrOrValue.hpp
Executable file
@@ -0,0 +1,70 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PtrOrValue.h"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
struct PtrOrValue {
|
||||
Optional<T> v;
|
||||
const T *p = nullptr;
|
||||
|
||||
const T *get() const {
|
||||
return v ?
|
||||
&*v :
|
||||
p;
|
||||
}
|
||||
|
||||
PtrOrValue(const T &v_) :
|
||||
v(v_) {}
|
||||
|
||||
PtrOrValue(T &&v_) :
|
||||
v(std::move(v_)) {}
|
||||
|
||||
PtrOrValue(const T *p_) :
|
||||
p(p_)
|
||||
{}
|
||||
|
||||
PtrOrValue(const PtrOrValue &rhs) :
|
||||
v(rhs.v),
|
||||
p(rhs.p)
|
||||
{}
|
||||
|
||||
PtrOrValue(PtrOrValue &&rhs) :
|
||||
v(std::move(rhs.v)),
|
||||
p(std::move(rhs.p))
|
||||
{}
|
||||
|
||||
auto *operator ->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
const T &operator *() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
operator const T&() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
PtrOrValue<T> makePtrOrValue(const T *t)
|
||||
{
|
||||
return PtrOrValue<T>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
PtrOrValue<T> makePtrOrValue(const T &t)
|
||||
{
|
||||
return PtrOrValue<T>(t);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
16
tjp/core/containers/Queue.h
Executable file
16
tjp/core/containers/Queue.h
Executable file
@@ -0,0 +1,16 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T>
|
||||
using Queue = std::queue<T>;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
80
tjp/core/containers/QueueThreadSafe.hpp
Executable file
80
tjp/core/containers/QueueThreadSafe.hpp
Executable file
@@ -0,0 +1,80 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "List.h"
|
||||
#include "../threads/Lock.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
// this container is used in asio queue operations -
|
||||
// where the front is always popped and read from the same thread
|
||||
// this needs to be worked on, maybe a with_front(F &&f)
|
||||
|
||||
template<typename T, typename MutexType = Mutex>
|
||||
class QueueThreadSafe
|
||||
{
|
||||
public:
|
||||
List<T> queue;
|
||||
mutable MutexType mutex;
|
||||
|
||||
public:
|
||||
T &front()
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
return queue.front();
|
||||
}
|
||||
|
||||
size_t push_back(const T &t)
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
queue.push_back(t);
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
size_t push_back(T &&t)
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
queue.emplace_back(std::move(t));
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
template<typename ... Args>
|
||||
size_t emplace_back(Args&& ...args)
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
queue.emplace_back(std::forward<Args>(args)...);
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
size_t pop_front()
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
debug_assert(!queue.empty());
|
||||
queue.pop_front();
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
auto lk = lock_of(mutex);
|
||||
return queue.empty();
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
auto with(F &&f) {
|
||||
auto lk = lock_of(mutex);
|
||||
return f(queue);
|
||||
}
|
||||
} ;
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
17
tjp/core/containers/Reversed.h
Executable file
17
tjp/core/containers/Reversed.h
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T>
|
||||
T reversed (T &&t);
|
||||
|
||||
template<typename T>
|
||||
struct Reversed;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
67
tjp/core/containers/Reversed.hpp
Executable file
67
tjp/core/containers/Reversed.hpp
Executable file
@@ -0,0 +1,67 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Reversed.h"
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
template<typename T>
|
||||
T reversed (T &&t)
|
||||
{
|
||||
T c(std::move(t));
|
||||
for (auto i=0; i<c.size()/2; ++i)
|
||||
std::swap(c[i], c[c.size()-(i+1)]);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Reversed : T
|
||||
{
|
||||
typedef T Super;
|
||||
typedef T Unreversed;
|
||||
|
||||
template<typename ...U>
|
||||
Reversed(U&& ...u) : Super(u...)
|
||||
{}
|
||||
|
||||
typedef typename Super::reverse_iterator iterator;
|
||||
typedef typename Super::iterator reverse_iterator;
|
||||
typedef typename Super::const_reverse_iterator const_iterator;
|
||||
typedef typename Super::const_iterator const_reverse_iterator;
|
||||
|
||||
auto begin() { return Super::rbegin(); }
|
||||
auto begin() const { return Super::rbegin(); }
|
||||
auto end() { return Super::rend(); }
|
||||
auto end() const { return Super::rend(); }
|
||||
|
||||
auto rbegin() { return Super::begin(); }
|
||||
auto rbegin() const { return Super::begin(); }
|
||||
auto rend() { return Super::end(); }
|
||||
auto rend() const { return Super::end(); }
|
||||
|
||||
auto &back() { return Super::front(); }
|
||||
auto &back() const { return Super::front(); }
|
||||
auto &front() { return Super::back(); }
|
||||
auto &front() const { return Super::back(); }
|
||||
|
||||
auto &operator[](size_t i)
|
||||
{
|
||||
return Super::operator[](Super::size()-1-i);
|
||||
}
|
||||
|
||||
auto &operator[] (size_t i) const
|
||||
{
|
||||
return Super::operator[](Super::size()-1-i);
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
17
tjp/core/containers/SafeIteration+IO.h
Executable file
17
tjp/core/containers/SafeIteration+IO.h
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SafeIteration.h"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename IO, typename T>
|
||||
void io_(IO &io, SafeIteration<T> &t)
|
||||
{
|
||||
io.any((T &)t);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
31
tjp/core/containers/SafeIteration.h
Executable file
31
tjp/core/containers/SafeIteration.h
Executable file
@@ -0,0 +1,31 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector.h"
|
||||
#include "FilledArray.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
struct SafeIterationException;
|
||||
|
||||
template<class container, class iterator_type, class reference_type, class microsoftfix>
|
||||
class SafeIterator;
|
||||
|
||||
template<typename T>
|
||||
using SafeIteratorMutable =
|
||||
SafeIterator<T, typename T::iterator, typename T::reference, char>;
|
||||
|
||||
template<typename T>
|
||||
using SafeIteratorConst =
|
||||
SafeIterator<T, typename T::const_iterator, typename T::const_reference, int>;
|
||||
|
||||
|
||||
template<typename T, typename CM=FilledArray<SafeIteratorMutable<T> *, 1>>
|
||||
class SafeIteration;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
7
tjp/core/containers/SafeIteration.hpp
Executable file
7
tjp/core/containers/SafeIteration.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SafeIteration_v_all_mutable.hpp"
|
||||
369
tjp/core/containers/SafeIteration_v_all_mutable.hpp
Executable file
369
tjp/core/containers/SafeIteration_v_all_mutable.hpp
Executable file
@@ -0,0 +1,369 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SafeIteration.h"
|
||||
|
||||
#include "FilledArrayThreadSafe.hpp"
|
||||
#include "../exception/Exception.hpp"
|
||||
#include "../assert/debug_assert.h"
|
||||
#include "../algorithm/vector_erase_if_value.hpp"
|
||||
|
||||
#include "../threads/Lock.hpp"
|
||||
#include "../threads/TestMutex.hpp"
|
||||
|
||||
#ifdef SAFE_ITERATION_LOG
|
||||
#include "../log/Log.h"
|
||||
#include "../log/LogOf.h"
|
||||
#define xLogDebugSafeIteration(x) xLogDebug(x)
|
||||
#else
|
||||
#define xLogDebugSafeIteration(x)
|
||||
#endif
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
* the only exception the safe iteration templates throw
|
||||
*/
|
||||
|
||||
DECLARE_EXCEPTION (SafeIterationException);
|
||||
|
||||
/**
|
||||
* provides an iterator template which is tightly bound to a safe iteration class
|
||||
*/
|
||||
template<class container, class iterator_type, class reference_type, class microsoftfix>
|
||||
class SafeIterator : public iterator_type
|
||||
{
|
||||
friend class SafeIteration<container>;
|
||||
|
||||
protected:
|
||||
const SafeIteration<container> *parent;
|
||||
|
||||
bool valid;
|
||||
|
||||
protected:
|
||||
void invalidate ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = false;
|
||||
iterator_type::operator ++();
|
||||
}
|
||||
|
||||
void invalidate (iterator_type i)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
iterator_type::operator =(i);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
public:
|
||||
SafeIterator () :
|
||||
parent (nullptr)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = false;
|
||||
}
|
||||
|
||||
SafeIterator (const SafeIteration<container> *parent_, const iterator_type &i) :
|
||||
iterator_type(i),
|
||||
parent (parent_)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = true;
|
||||
parent->addSafeIterator (this);
|
||||
}
|
||||
|
||||
SafeIterator(const SafeIterator &rhs) :
|
||||
iterator_type(rhs)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = rhs.valid;
|
||||
|
||||
parent = rhs.parent;
|
||||
parent->addSafeIterator (this);
|
||||
}
|
||||
|
||||
SafeIterator &operator=(const SafeIterator &rhs)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
if (parent)
|
||||
parent->removeSafeIterator(this);
|
||||
|
||||
iterator_type::operator=(rhs);
|
||||
parent = rhs.parent;
|
||||
valid = rhs.valid;
|
||||
|
||||
if (parent)
|
||||
parent->addSafeIterator(this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SafeIterator ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
if (parent)
|
||||
parent->removeSafeIterator (this);
|
||||
}
|
||||
|
||||
reference_type operator *() const
|
||||
{
|
||||
validate ();
|
||||
return (reference_type)iterator_type::operator *();
|
||||
}
|
||||
|
||||
SafeIterator<container, iterator_type, reference_type, microsoftfix> &operator ++()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
if (valid)
|
||||
{
|
||||
iterator_type::operator ++();
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = true;
|
||||
};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SafeIterator<container, iterator_type, reference_type, microsoftfix> &operator --()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
iterator_type::operator --();
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
valid = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isValid () const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
void validate () const
|
||||
{
|
||||
if (!valid)
|
||||
throw SafeIterationException ("invalid iterator dereferenced");
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
void safe_iterator_insert(Vector<T *> &v, T *t)
|
||||
{
|
||||
v.push_back(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void safe_iterator_erase(Vector<T *> &v, T *t)
|
||||
{
|
||||
v.erase(
|
||||
std::remove(
|
||||
v.begin(), v.end(),
|
||||
t
|
||||
),
|
||||
v.end()
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T, int N>
|
||||
void safe_iterator_insert(FilledArray<T *, N> &v, T *t)
|
||||
{
|
||||
v.insert(t);
|
||||
}
|
||||
|
||||
template<typename T, int N>
|
||||
void safe_iterator_erase(FilledArray<T *, N> &v, T *t)
|
||||
{
|
||||
v.erase(t);
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename CM>
|
||||
class SafeIteration : public T
|
||||
{
|
||||
public:
|
||||
// static constexpr int FilledArrayInitialSize = 4;
|
||||
|
||||
public:
|
||||
using container_type = T;
|
||||
|
||||
using T_iterator = typename T::iterator;
|
||||
using T_const_iterator = T_iterator ;
|
||||
|
||||
using T_reference = typename T::reference;
|
||||
using T_const_reference = T_reference ;
|
||||
|
||||
using safe_iterator = SafeIteratorMutable<T>;
|
||||
using safe_const_iterator = safe_iterator;
|
||||
|
||||
using iterator = safe_iterator;
|
||||
using const_iterator = safe_const_iterator;
|
||||
|
||||
using iterators_container = CM;
|
||||
//FilledArray<safe_iterator *, FilledArrayInitialSize>;
|
||||
|
||||
protected:
|
||||
mutable iterators_container iterators;
|
||||
|
||||
void ensureAllIterators (T_const_reference k)
|
||||
{
|
||||
ensureAllIterators (this->find(k));
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void ensureIteratorSet (const T_iterator &I, Z &set)
|
||||
{
|
||||
for (typename Z::iterator i=set.begin(); i!=set.end(); ++i)
|
||||
{
|
||||
if ( (*(*i))!=T::end() )
|
||||
{
|
||||
if ( (*(*i)) == I )
|
||||
{
|
||||
(*i)->invalidate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ensureAllIterators (const T_iterator &I)
|
||||
{
|
||||
ensureIteratorSet (I, iterators);
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void clearIteratorSet (Z &set)
|
||||
{
|
||||
for (typename Z::iterator i=set.begin(); i!=set.end(); ++i)
|
||||
{
|
||||
if ( (*(*i))!= T::end() )
|
||||
{
|
||||
(*i)->invalidate (T::end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clearAllIterators ()
|
||||
{
|
||||
clearIteratorSet (iterators);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename ... Args>
|
||||
SafeIteration (Args && ...args) :
|
||||
T(std::forward<Args>(args)...)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
}
|
||||
|
||||
SafeIteration (const SafeIteration ©)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
T::operator =(copy);
|
||||
}
|
||||
|
||||
~SafeIteration ()
|
||||
{
|
||||
debug_assert(iterators.empty());
|
||||
}
|
||||
|
||||
SafeIteration &operator =(const SafeIteration ©)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
T::operator =(copy);
|
||||
clearAllIterators();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void erase (const T_const_reference &k)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
ensureAllIterators(k);
|
||||
T::erase(k);
|
||||
}
|
||||
|
||||
inline void erase (const T_iterator &i)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
T_iterator I(i);
|
||||
ensureAllIterators(i);
|
||||
T::erase(I);
|
||||
}
|
||||
|
||||
inline void clear ()
|
||||
{
|
||||
T::clear();
|
||||
clearAllIterators();
|
||||
}
|
||||
|
||||
auto begin ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
return safe_iterator(this, T::begin());
|
||||
}
|
||||
|
||||
auto begin () const
|
||||
{
|
||||
auto this_ = remove_const_of_var(this);
|
||||
return this_->begin();
|
||||
}
|
||||
|
||||
auto end ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
return safe_iterator(this, T::end());
|
||||
}
|
||||
|
||||
auto end () const
|
||||
{
|
||||
auto this_ = remove_const_of_var(this);
|
||||
return this_->end();
|
||||
}
|
||||
|
||||
template<typename ...U>
|
||||
void remove(U &&... u)
|
||||
{
|
||||
// use erase not remove
|
||||
debug_assert(false);
|
||||
}
|
||||
|
||||
public:
|
||||
inline void addSafeIterator (safe_iterator *i) const
|
||||
{
|
||||
safe_iterator_insert(iterators, i);
|
||||
}
|
||||
|
||||
inline void removeSafeIterator (safe_iterator *i) const
|
||||
{
|
||||
safe_iterator_erase(iterators, i);
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
364
tjp/core/containers/SafeIteration_v_consts.hpp
Executable file
364
tjp/core/containers/SafeIteration_v_consts.hpp
Executable file
@@ -0,0 +1,364 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SafeIteration.h"
|
||||
|
||||
#include "FilledArrayThreadSafe.hpp"
|
||||
#include "../exception/Exception.hpp"
|
||||
#include "../assert/debug_assert.h"
|
||||
|
||||
#include "../threads/Lock.hpp"
|
||||
#include "../threads/TestMutex.hpp"
|
||||
|
||||
#ifdef SAFE_ITERATION_LOG
|
||||
#include "../log/Log.h"
|
||||
#include "../log/LogOf.h"
|
||||
#define xLogDebugSafeIteration(x) xLogDebug(x)
|
||||
#else
|
||||
#define xLogDebugSafeIteration(x)
|
||||
#endif
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
* the only exception the safe iteration templates throw
|
||||
*/
|
||||
|
||||
DECLARE_EXCEPTION (SafeIterationException);
|
||||
|
||||
template<class T> class SafeIteration;
|
||||
|
||||
/**
|
||||
* provides an iterator template which is tightly bound to a safe iteration class
|
||||
*/
|
||||
template<class container, class iterator_type, class reference_type, class microsoftfix>
|
||||
class SafeIterator : public iterator_type
|
||||
{
|
||||
friend class SafeIteration<container>;
|
||||
|
||||
protected:
|
||||
const SafeIteration<container> *parent;
|
||||
|
||||
bool valid;
|
||||
|
||||
protected:
|
||||
void invalidate ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = false;
|
||||
iterator_type::operator ++();
|
||||
}
|
||||
|
||||
void invalidate (iterator_type i)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
iterator_type::operator =(i);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
public:
|
||||
SafeIterator () :
|
||||
parent (nullptr)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = false;
|
||||
}
|
||||
|
||||
SafeIterator (const SafeIteration<container> *parent_, const iterator_type &i) :
|
||||
iterator_type(i),
|
||||
parent (parent_)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = true;
|
||||
parent->addSafeIterator (this);
|
||||
}
|
||||
|
||||
SafeIterator(const SafeIterator &rhs) :
|
||||
iterator_type(rhs)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
valid = rhs.valid;
|
||||
|
||||
parent = rhs.parent;
|
||||
parent->addSafeIterator (this);
|
||||
}
|
||||
|
||||
SafeIterator &operator=(const SafeIterator &rhs)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
if (parent)
|
||||
parent->removeSafeIterator(this);
|
||||
|
||||
iterator_type::operator=(rhs);
|
||||
parent = rhs.parent;
|
||||
valid = rhs.valid;
|
||||
|
||||
if (parent)
|
||||
parent->addSafeIterator(this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SafeIterator ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
if (parent)
|
||||
parent->removeSafeIterator (this);
|
||||
}
|
||||
|
||||
reference_type operator *() const
|
||||
{
|
||||
validate ();
|
||||
return (reference_type)iterator_type::operator *();
|
||||
}
|
||||
|
||||
SafeIterator<container, iterator_type, reference_type, microsoftfix> &operator ++()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
if (valid)
|
||||
{
|
||||
iterator_type::operator ++();
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = true;
|
||||
};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SafeIterator<container, iterator_type, reference_type, microsoftfix> &operator --()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
iterator_type::operator --();
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
valid = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isValid () const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
void validate () const
|
||||
{
|
||||
if (!valid)
|
||||
throw SafeIterationException ("invalid iterator dereferenced");
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
class SafeIteration : public T
|
||||
{
|
||||
public:
|
||||
static constexpr int FilledArrayInitialSize = 4;
|
||||
|
||||
public:
|
||||
typedef T container_type;
|
||||
|
||||
typedef typename T::iterator T_iterator;
|
||||
typedef typename T::const_iterator T_const_iterator;
|
||||
|
||||
typedef typename T::reference T_reference;
|
||||
typedef typename T::const_reference T_const_reference;
|
||||
|
||||
typedef SafeIterator<T, T_iterator, T_reference, char> safe_iterator;
|
||||
typedef SafeIterator<T, T_const_iterator, T_const_reference, int> safe_const_iterator;
|
||||
|
||||
typedef safe_iterator iterator;
|
||||
typedef safe_const_iterator const_iterator;
|
||||
|
||||
using iterators_container = FilledArray<safe_iterator *, FilledArrayInitialSize>;
|
||||
using const_iterators_container = FilledArray<safe_const_iterator *, FilledArrayInitialSize>;
|
||||
|
||||
protected:
|
||||
mutable iterators_container iterators;
|
||||
mutable const_iterators_container const_iterators;
|
||||
|
||||
void ensureAllIterators (T_const_reference k)
|
||||
{
|
||||
ensureAllIterators (this->find(k));
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void ensureIteratorSet (const T_iterator &I, Z &set)
|
||||
{
|
||||
for (typename Z::iterator i=set.begin(); i!=set.end(); ++i)
|
||||
{
|
||||
if ( (*(*i))!=T::end() )
|
||||
{
|
||||
if ( (*(*i)) == I )
|
||||
{
|
||||
(*i)->invalidate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ensureAllIterators (const T_iterator &I)
|
||||
{
|
||||
ensureIteratorSet (I, iterators);
|
||||
ensureIteratorSet (I, const_iterators);
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void clearIteratorSet (Z &set)
|
||||
{
|
||||
for (typename Z::iterator i=set.begin(); i!=set.end(); ++i)
|
||||
{
|
||||
if ( (*(*i))!= T::end() )
|
||||
{
|
||||
(*i)->invalidate (T::end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clearAllIterators ()
|
||||
{
|
||||
clearIteratorSet (iterators);
|
||||
clearIteratorSet (const_iterators);
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename ... Args>
|
||||
SafeIteration (Args && ...args) :
|
||||
T(std::forward<Args>(args)...)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
}
|
||||
|
||||
SafeIteration (const SafeIteration ©)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
T::operator =(copy);
|
||||
}
|
||||
|
||||
~SafeIteration ()
|
||||
{
|
||||
debug_assert(iterators.empty() && const_iterators.empty());
|
||||
}
|
||||
|
||||
SafeIteration &operator =(const SafeIteration ©)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
T::operator =(copy);
|
||||
clearAllIterators();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// SafeIteration &operator =(SafeIteration &©)
|
||||
// {
|
||||
// xLogDebugSafeIteration(logOfThis(this));
|
||||
//
|
||||
// T::operator =(copy);
|
||||
// clearAllIterators();
|
||||
//
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
inline void erase (const T_const_reference &k)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
ensureAllIterators(k);
|
||||
T::erase(k);
|
||||
}
|
||||
|
||||
inline void erase (const T_iterator &i)
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
T_iterator I(i);
|
||||
ensureAllIterators(i);
|
||||
T::erase(I);
|
||||
}
|
||||
|
||||
inline void clear ()
|
||||
{
|
||||
T::clear();
|
||||
clearAllIterators();
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
return safe_iterator(this, T::begin());
|
||||
}
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
return const_iterator(this, T::begin());
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
return safe_iterator(this, T::end());
|
||||
}
|
||||
|
||||
const_iterator end () const
|
||||
{
|
||||
xLogDebugSafeIteration(logOfThis(this));
|
||||
|
||||
return const_iterator(this, T::end());
|
||||
}
|
||||
|
||||
template<typename ...U>
|
||||
void remove(U &&... u)
|
||||
{
|
||||
// use erase not remove
|
||||
debug_assert(false);
|
||||
}
|
||||
|
||||
public:
|
||||
inline void addSafeIterator (safe_iterator *i) const
|
||||
{
|
||||
iterators.insert (i);
|
||||
}
|
||||
|
||||
inline void addSafeIterator (safe_const_iterator *i) const
|
||||
{
|
||||
const_iterators.insert (i);
|
||||
}
|
||||
|
||||
inline void removeSafeIterator (safe_iterator *i) const
|
||||
{
|
||||
iterators.erase (i);
|
||||
}
|
||||
|
||||
inline void removeSafeIterator (safe_const_iterator *i) const
|
||||
{
|
||||
const_iterators.erase (i);
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace
|
||||
17
tjp/core/containers/Set.h
Executable file
17
tjp/core/containers/Set.h
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename V>
|
||||
using Set = std::set<V>;
|
||||
|
||||
template<typename V, typename S>
|
||||
using SetSortBy = std::set<V, S>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Set.hpp
Executable file
7
tjp/core/containers/Set.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Set.h"
|
||||
13
tjp/core/containers/StackArray+IO.hpp
Executable file
13
tjp/core/containers/StackArray+IO.hpp
Executable file
@@ -0,0 +1,13 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray_v2+IO.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
using namespace stackarray_v2;
|
||||
|
||||
} // namespace
|
||||
34
tjp/core/containers/StackArray+hash.hpp
Executable file
34
tjp/core/containers/StackArray+hash.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray.hpp"
|
||||
#include "StackArray_v2+hash.hpp"
|
||||
|
||||
namespace std {
|
||||
template<typename T, size_t N>
|
||||
struct hash<tjp::core::stackarray_v2::StackArray<T, N>> {
|
||||
|
||||
using A = tjp::core::stackarray_v2::StackArray<T, N>;
|
||||
|
||||
size_t operator()(const A &a) const {
|
||||
size_t value = 0;
|
||||
|
||||
hash<typename A::value_type> hasher;
|
||||
for (auto &v: a)
|
||||
{
|
||||
constexpr auto bitsToShift = 8;
|
||||
// this is dumb, but we want to protect against x,x always going to zero
|
||||
value = (
|
||||
(value << bitsToShift) |
|
||||
(value >> ((sizeof(value) * 8) - bitsToShift))
|
||||
);
|
||||
value = value ^ hasher(v);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
14
tjp/core/containers/StackArray.h
Executable file
14
tjp/core/containers/StackArray.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray_v2.h"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
using namespace stackarray_v2;
|
||||
|
||||
} // namespace
|
||||
|
||||
13
tjp/core/containers/StackArray.hpp
Executable file
13
tjp/core/containers/StackArray.hpp
Executable file
@@ -0,0 +1,13 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray_v2.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
using namespace stackarray_v2;
|
||||
|
||||
} // namespace
|
||||
51
tjp/core/containers/StackArray_v2+IO.hpp
Executable file
51
tjp/core/containers/StackArray_v2+IO.hpp
Executable file
@@ -0,0 +1,51 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray_v2.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#include "../iterators/is_first.hpp"
|
||||
#include "../string/trim.h"
|
||||
#include "../string/split.hpp"
|
||||
|
||||
#include "../string/from_string.inl"
|
||||
|
||||
namespace tjp::core::stackarray_v2 {
|
||||
|
||||
template<typename T, size_t N>
|
||||
std::ostream &operator<<(std::ostream &out, const StackArray<T, N> &a)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "{";
|
||||
core::is_first first;
|
||||
for (auto &id : a)
|
||||
{
|
||||
if (!first.check())
|
||||
s << ",";
|
||||
s << id;
|
||||
}
|
||||
s << "}";
|
||||
|
||||
out << s.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
std::istream &operator>>(std::istream &in, StackArray<T, N> &a)
|
||||
{
|
||||
std::string s;
|
||||
in >> s;
|
||||
s = core::trim_copy(s, " {}");
|
||||
auto parts = core::split(s, ',');
|
||||
|
||||
a.clear();
|
||||
for (auto &part : parts)
|
||||
a.push_back(core::from_string<T>(part));
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
12
tjp/core/containers/StackArray_v2+hash.hpp
Executable file
12
tjp/core/containers/StackArray_v2+hash.hpp
Executable file
@@ -0,0 +1,12 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray_v2.hpp"
|
||||
|
||||
namespace tjp::core::stackarray_v2 {
|
||||
|
||||
|
||||
} // namespace
|
||||
18
tjp/core/containers/StackArray_v2.h
Executable file
18
tjp/core/containers/StackArray_v2.h
Executable file
@@ -0,0 +1,18 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../types/Types.h"
|
||||
|
||||
namespace tjp::core::stackarray_v2 {
|
||||
|
||||
/**
|
||||
* std list and vector and set are too slow for some reason, need fast allocation, with
|
||||
*/
|
||||
template<typename T, size_t N=32>
|
||||
class StackArray;
|
||||
|
||||
} // namespace
|
||||
|
||||
120
tjp/core/containers/StackArray_v2.hpp
Executable file
120
tjp/core/containers/StackArray_v2.hpp
Executable file
@@ -0,0 +1,120 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StackArray_v2.h"
|
||||
#include "InPlaceArray.hpp"
|
||||
#include "Vector.h"
|
||||
#include "../debug/Debug.h"
|
||||
#include "../algorithm/cmp.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <variant>
|
||||
|
||||
namespace tjp::core::stackarray_v2 {
|
||||
|
||||
// this makes random accesses faster, but at a memory pointer
|
||||
//#define STACK_ARRAY_USE_PTR
|
||||
|
||||
template<typename T, size_t N>
|
||||
class StackArray
|
||||
{
|
||||
public:
|
||||
using Self = StackArray<T, N>;
|
||||
static constexpr size_t Reserved = N;
|
||||
|
||||
using Fixed = InPlaceArray<T, N>;
|
||||
using Variable = Vector<T>;
|
||||
using Ptr = T *;
|
||||
|
||||
private:
|
||||
std::variant<Fixed, Variable> v = Fixed();
|
||||
|
||||
Fixed &fixed();
|
||||
const Fixed &fixed() const;
|
||||
|
||||
Variable &variable();
|
||||
const Variable &variable() const;
|
||||
|
||||
#ifdef STACK_ARRAY_USE_PTR
|
||||
Ptr array;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
inline T *data();
|
||||
inline const T *data() const;
|
||||
|
||||
inline iterator begin();
|
||||
inline const_iterator begin() const;
|
||||
|
||||
inline iterator end ();
|
||||
inline const_iterator end () const;
|
||||
|
||||
inline reverse_iterator rbegin() { return std::make_reverse_iterator(end()); }
|
||||
inline const_reverse_iterator rbegin() const { return std::make_reverse_iterator(end()); }
|
||||
|
||||
inline reverse_iterator rend () { return std::make_reverse_iterator(begin()); }
|
||||
inline const_reverse_iterator rend () const { return std::make_reverse_iterator(begin()); }
|
||||
|
||||
inline T &front () { return *begin(); }
|
||||
inline T &back () { return *(end() - 1); }
|
||||
inline const T &front () const { return *begin(); }
|
||||
inline const T &back () const { return *(end() - 1); }
|
||||
|
||||
void size_to(size_t newSize);
|
||||
void changed();
|
||||
|
||||
public:
|
||||
StackArray ();
|
||||
StackArray (size_t _allocsize);
|
||||
|
||||
StackArray(const std::initializer_list<T> &rhs);
|
||||
StackArray(const T *begin, const T *end);
|
||||
|
||||
template<size_t N2>
|
||||
StackArray(const StackArray<T,N2> &rhs);
|
||||
|
||||
template<size_t N2>
|
||||
StackArray &operator =(const StackArray<T,N2> &rhs);
|
||||
|
||||
~StackArray ();
|
||||
|
||||
void append(const T *begin, const T *end);
|
||||
void emplace(const T *begin, const T *end);
|
||||
void resize(size_t length_, T t=T());
|
||||
|
||||
void push_back (const T &element);
|
||||
void push_back (T &&element);
|
||||
void pop_back ();
|
||||
|
||||
template<typename ... Args>
|
||||
T &emplace_back (Args&& ...element);
|
||||
|
||||
iterator find (const T &element);
|
||||
|
||||
const T &at(size_t i) const;
|
||||
T &at(size_t i);
|
||||
|
||||
const T &operator[] (size_t i) const;
|
||||
T &operator[] (size_t i);
|
||||
|
||||
size_t size () const;
|
||||
void clear ();
|
||||
|
||||
bool empty () const;
|
||||
bool on_stack () const;
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "StackArray_v2.inl"
|
||||
411
tjp/core/containers/StackArray_v2.inl
Executable file
411
tjp/core/containers/StackArray_v2.inl
Executable file
@@ -0,0 +1,411 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include "../assert/debug_assert.h"
|
||||
#include "../algorithm/cmp.hpp"
|
||||
|
||||
#include "../log/Log.h"
|
||||
#include "../log/LogOf.h"
|
||||
|
||||
namespace tjp::core::stackarray_v2 {
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::Fixed &StackArray<T, N>::fixed ()
|
||||
{
|
||||
return std::get<Fixed>(v);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::Variable &StackArray<T, N>::variable ()
|
||||
{
|
||||
return std::get<Variable>(v);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const typename StackArray<T, N>::Fixed &StackArray<T, N>::fixed () const
|
||||
{
|
||||
return std::get<Fixed>(v);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const typename StackArray<T, N>::Variable &StackArray<T, N>::variable () const
|
||||
{
|
||||
return std::get<Variable>(v);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
StackArray<T, N>::StackArray ()
|
||||
#ifdef STACK_ARRAY_USE_PTR
|
||||
: array(fixed().data())
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
template<size_t N2>
|
||||
StackArray<T, N>::StackArray(const StackArray<T, N2> &rhs) :
|
||||
Self()
|
||||
{
|
||||
append(rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
StackArray<T, N>::StackArray(const T *begin_, const T *end_) :
|
||||
Self()
|
||||
{
|
||||
append(begin_, end_);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
template<size_t N2>
|
||||
StackArray<T,N> &StackArray<T, N>::operator =(const StackArray<T,N2> &rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
append(rhs.begin(), rhs.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
StackArray<T, N>::StackArray(const std::initializer_list<T> &rhs) :
|
||||
Self()
|
||||
{
|
||||
for (auto &element: rhs)
|
||||
push_back(element);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
StackArray<T, N>::StackArray (size_t size) :
|
||||
Self()
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
StackArray<T, N>::~StackArray ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
T * StackArray<T, N>::data()
|
||||
{
|
||||
#ifdef STACK_ARRAY_USE_PTR
|
||||
return array;
|
||||
#else
|
||||
return
|
||||
on_stack() ?
|
||||
fixed().data() :
|
||||
variable().data();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const T * StackArray<T, N>::data() const
|
||||
{
|
||||
#ifdef STACK_ARRAY_USE_PTR
|
||||
return array;
|
||||
#else
|
||||
return
|
||||
on_stack() ?
|
||||
fixed().data() :
|
||||
variable().data();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::iterator StackArray<T, N>::begin()
|
||||
{
|
||||
return data();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::const_iterator StackArray<T, N>::begin() const
|
||||
{
|
||||
return data();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::iterator StackArray<T, N>::end ()
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::const_iterator StackArray<T, N>::end () const
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::append(const T *begin, const T *end)
|
||||
{
|
||||
size_to(size() + (end - begin));
|
||||
|
||||
if (on_stack())
|
||||
fixed().append(begin, end);
|
||||
else
|
||||
variable().insert(variable().end(), begin, end);
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::emplace(const T *begin, const T *end)
|
||||
{
|
||||
size_to(size() + (end - begin));
|
||||
|
||||
if (on_stack())
|
||||
fixed().emplace(begin, end);
|
||||
else
|
||||
variable().emplace(variable().end(), begin, end);
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::resize(size_t length_, T t)
|
||||
{
|
||||
size_to(length_);
|
||||
|
||||
if (on_stack())
|
||||
fixed().resize(length_, t);
|
||||
else
|
||||
variable().resize(length_, t);
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::size_to(size_t newSize)
|
||||
{
|
||||
if (!on_stack())
|
||||
return;
|
||||
|
||||
// why not reserve before each push_back:
|
||||
|
||||
/**
|
||||
https://en.cppreference.com/w/cpp/container/vector/reserve
|
||||
|
||||
Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing the capacity to grow linearly rather than exponentially) and result in increased computational complexity and decreased performance. For example, a function that receives an arbitrary vector by reference and appends elements to it should usually not call reserve() on the vector, since it does not know of the vector's usage characteristics.
|
||||
|
||||
**/
|
||||
|
||||
if (newSize > N)
|
||||
{
|
||||
sLogDebug("core::StackArray::transfer", logVar(newSize) << logVar(N));
|
||||
|
||||
Variable variable_;
|
||||
variable_.reserve(newSize);
|
||||
|
||||
auto &fixed_ = fixed();
|
||||
for (auto &i: fixed_)
|
||||
variable_.emplace_back(std::move(i));
|
||||
|
||||
v = std::move(variable_);
|
||||
|
||||
#ifdef STACK_ARRAY_USE_PTR
|
||||
array = variable().data();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::changed()
|
||||
{
|
||||
#ifdef STACK_ARRAY_USE_PTR
|
||||
if (!on_stack())
|
||||
array = variable().data();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::push_back (const T &element)
|
||||
{
|
||||
size_to(size()+1);
|
||||
|
||||
if (on_stack())
|
||||
fixed().push_back(element);
|
||||
else
|
||||
variable().push_back(element);
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::push_back (T &&element)
|
||||
{
|
||||
size_to(size()+1);
|
||||
|
||||
if (on_stack())
|
||||
fixed().push_back(std::move(element));
|
||||
else
|
||||
variable().push_back(std::move(element));
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
template<typename ... Args>
|
||||
T &StackArray<T, N>::emplace_back (Args&& ...element)
|
||||
{
|
||||
size_to(size()+1);
|
||||
|
||||
T *r = nullptr;
|
||||
if (on_stack())
|
||||
{
|
||||
auto &i = fixed().emplace_back(std::forward<Args>(element)...);
|
||||
r = &i;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &i = variable().emplace_back(std::forward<Args>(element)...);
|
||||
r = &i;
|
||||
}
|
||||
|
||||
changed();
|
||||
|
||||
return *r;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::pop_back ()
|
||||
{
|
||||
if (on_stack())
|
||||
fixed().pop_back();
|
||||
else
|
||||
variable().pop_back();
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
typename StackArray<T, N>::iterator StackArray<T, N>::find (const T &element)
|
||||
{
|
||||
// now iterator all except for what used to be the end element
|
||||
for (iterator i=begin(); i!=end(); ++i)
|
||||
{
|
||||
if (*i == element)
|
||||
{
|
||||
// the end element was the last element
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const T &StackArray<T, N>::at(size_t i) const
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
T &StackArray<T, N>::at(size_t i)
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
const T &StackArray<T, N>::operator[] (size_t i) const
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
T &StackArray<T, N>::operator[] (size_t i)
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
size_t StackArray<T, N>::size () const
|
||||
{
|
||||
return
|
||||
on_stack() ?
|
||||
fixed().size() :
|
||||
variable().size();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void StackArray<T, N>::clear ()
|
||||
{
|
||||
resize(0);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool StackArray<T, N>::empty () const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool StackArray<T, N>::on_stack () const
|
||||
{
|
||||
return v.index() == 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
int cmp(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
auto lhs_size = lhs.size();
|
||||
auto rhs_size = rhs.size();
|
||||
auto max = std::min(lhs_size, rhs_size);
|
||||
|
||||
auto *l = lhs.data();
|
||||
auto *r = rhs.data();
|
||||
for (auto i=0; i<max; ++i, ++l, ++r)
|
||||
{
|
||||
auto v = core::cmp(*l, *r);
|
||||
if (v != 0)
|
||||
return v;
|
||||
}
|
||||
|
||||
return core::cmp(lhs_size, rhs_size);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator <(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
return cmp(lhs, rhs) < 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator <=(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
return cmp(lhs, rhs) <= 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator >(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
return cmp(lhs, rhs) > 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator >=(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
return cmp(lhs, rhs) >= 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator ==(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
return cmp(lhs, rhs) == 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool operator !=(const StackArray<T, N> &lhs, const StackArray<T, N> &rhs)
|
||||
{
|
||||
return cmp(lhs, rhs) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
20
tjp/core/containers/TransparentLess.hpp
Executable file
20
tjp/core/containers/TransparentLess.hpp
Executable file
@@ -0,0 +1,20 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
struct TransparentLess {
|
||||
using is_transparent = void;
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr bool operator()(const T& lhs, const U& rhs) const {
|
||||
return lhs < rhs;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
14
tjp/core/containers/Tuple.h
Executable file
14
tjp/core/containers/Tuple.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename ... T>
|
||||
using Tuple = std::tuple<T...>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Tuple.hpp
Executable file
7
tjp/core/containers/Tuple.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tuple.h"
|
||||
14
tjp/core/containers/UnorderedMap.h
Executable file
14
tjp/core/containers/UnorderedMap.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename K, typename V>
|
||||
using UnorderedMap = std::unordered_map<K, V>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/UnorderedMap.hpp
Executable file
7
tjp/core/containers/UnorderedMap.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UnorderedMap.h"
|
||||
14
tjp/core/containers/UnorderedSet.h
Executable file
14
tjp/core/containers/UnorderedSet.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename V, typename H>
|
||||
using UnorderedSet = std::unordered_set<V, H>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/UnorderedSet.hpp
Executable file
7
tjp/core/containers/UnorderedSet.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UnorderedSet.h"
|
||||
14
tjp/core/containers/Vector.h
Executable file
14
tjp/core/containers/Vector.h
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename V>
|
||||
using Vector = std::vector<V>;
|
||||
|
||||
} // namespace
|
||||
7
tjp/core/containers/Vector.hpp
Executable file
7
tjp/core/containers/Vector.hpp
Executable file
@@ -0,0 +1,7 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector.h"
|
||||
187
tjp/core/containers/_tests/InPlaceArray.cpp
Executable file
187
tjp/core/containers/_tests/InPlaceArray.cpp
Executable file
@@ -0,0 +1,187 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/containers/InPlaceArray.hpp>
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/iterators/range.hpp>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <tjp/core/containers/List.hpp>
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
|
||||
namespace tjp::core::containers {
|
||||
namespace {
|
||||
|
||||
struct E {
|
||||
int i;
|
||||
} ;
|
||||
|
||||
struct Constructable {
|
||||
static int constructed;
|
||||
static int copy_constructed;
|
||||
static int move_constructed;
|
||||
static int destructed;
|
||||
|
||||
static void clear() {
|
||||
constructed =
|
||||
copy_constructed =
|
||||
move_constructed =
|
||||
destructed = 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
Constructable(const Constructable &c)
|
||||
{
|
||||
i = c.i+1;
|
||||
copy_constructed++;
|
||||
}
|
||||
|
||||
Constructable(Constructable &&c)
|
||||
{
|
||||
std::swap(i, c.i);
|
||||
move_constructed++;
|
||||
}
|
||||
|
||||
Constructable ()
|
||||
{
|
||||
i = 0;
|
||||
constructed++;
|
||||
}
|
||||
|
||||
~Constructable()
|
||||
{
|
||||
destructed++;
|
||||
}
|
||||
} ;
|
||||
|
||||
int Constructable::constructed = 0;
|
||||
int Constructable::copy_constructed = 0;
|
||||
int Constructable::move_constructed = 0;
|
||||
int Constructable::destructed = 0;
|
||||
|
||||
SCENARIO("core::containers::InPlace" )
|
||||
{
|
||||
GIVEN("sizes")
|
||||
{
|
||||
using IPA = InPlaceArray<char, 32>;
|
||||
|
||||
sLogTest("debug",
|
||||
logVar(sizeof(IPA))
|
||||
);
|
||||
}
|
||||
|
||||
GIVEN("a list with X elements")
|
||||
{
|
||||
InPlaceArray<E, 20> a;
|
||||
|
||||
WHEN("add less than N itesm")
|
||||
{
|
||||
for (auto i : range(0, 10))
|
||||
a.push_back(E{i});
|
||||
|
||||
REQUIRE(a.size() == 10);
|
||||
|
||||
THEN("arrays elements match")
|
||||
{
|
||||
int i=0;
|
||||
for (auto &v : a)
|
||||
{
|
||||
REQUIRE(v.i == i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("remove some itesm")
|
||||
{
|
||||
for (auto _ : range(0, 5))
|
||||
{
|
||||
unused(_);
|
||||
a.pop_back();
|
||||
}
|
||||
|
||||
REQUIRE(a.size() == 5);
|
||||
|
||||
THEN("arrays elements match")
|
||||
{
|
||||
int i=0;
|
||||
for (auto &v : a)
|
||||
{
|
||||
REQUIRE(v.i == i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("things are copied")
|
||||
{
|
||||
THEN("arrays a elements match")
|
||||
{
|
||||
int i=0;
|
||||
for (auto &v : a)
|
||||
{
|
||||
REQUIRE(v.i == i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
auto b = a;
|
||||
|
||||
REQUIRE(b.size() == 5);
|
||||
|
||||
|
||||
THEN("arrays elements match")
|
||||
{
|
||||
int i=0;
|
||||
for (auto &v : b)
|
||||
{
|
||||
REQUIRE(v.i == i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("a list with X unconstructed constructables")
|
||||
{
|
||||
{
|
||||
Constructable::clear();
|
||||
|
||||
InPlaceArray<Constructable, 20> a;
|
||||
|
||||
REQUIRE(Constructable::constructed == 0);
|
||||
REQUIRE(Constructable::destructed == 0);
|
||||
|
||||
Constructable c;
|
||||
a.push_back(std::move(c));
|
||||
}
|
||||
|
||||
REQUIRE(Constructable::constructed == 1);
|
||||
REQUIRE(Constructable::move_constructed == 1);
|
||||
REQUIRE(Constructable::destructed == 2);
|
||||
|
||||
{
|
||||
Constructable::clear();
|
||||
|
||||
InPlaceArray<Constructable, 20> a;
|
||||
|
||||
REQUIRE(Constructable::constructed == 0);
|
||||
REQUIRE(Constructable::destructed == 0);
|
||||
|
||||
Constructable c;
|
||||
a.push_back(c);
|
||||
}
|
||||
|
||||
REQUIRE(Constructable::constructed == 1);
|
||||
REQUIRE(Constructable::copy_constructed == 1);
|
||||
REQUIRE(Constructable::destructed == 2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
108
tjp/core/containers/_tests/MultiContainer.cpp
Executable file
108
tjp/core/containers/_tests/MultiContainer.cpp
Executable file
@@ -0,0 +1,108 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/containers/MultiContainer.hpp>
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <tjp/core/containers/Vector.hpp>
|
||||
|
||||
namespace tjp::core::containers {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::containers::MultiContainer")
|
||||
{
|
||||
GIVEN("a multicontainer")
|
||||
{
|
||||
using V = Vector<int>;
|
||||
MultiContainer<V> c;
|
||||
|
||||
V v1, v2, v3;
|
||||
c.add(&v1);
|
||||
c.add(&v2);
|
||||
c.add(&v3);
|
||||
|
||||
REQUIRE(c.size() == 0);
|
||||
|
||||
auto m = 0;
|
||||
for (auto &_: c)
|
||||
{
|
||||
unused(_);
|
||||
m++;
|
||||
}
|
||||
|
||||
REQUIRE(m == 0);
|
||||
|
||||
auto v1s = 1;
|
||||
auto v2s = 7;
|
||||
auto v3s = 15;
|
||||
|
||||
v1.resize(v1s);
|
||||
v2.resize(v2s);
|
||||
v3.resize(v3s);
|
||||
|
||||
auto s = v1s + v2s + v3s;
|
||||
REQUIRE(c.size() == s);
|
||||
|
||||
m = 0;
|
||||
for (auto &_: c)
|
||||
{
|
||||
unused(_);
|
||||
m++;
|
||||
}
|
||||
|
||||
REQUIRE(m == s);
|
||||
}
|
||||
|
||||
GIVEN("a multicontainer of multicontainer")
|
||||
{
|
||||
using V = Vector<int>;
|
||||
using M = MultiContainer<V>;
|
||||
using MM = MultiContainer<M>;
|
||||
M cx0, cx1;
|
||||
|
||||
V v1, v2, v3;
|
||||
cx0.add(&v1);
|
||||
cx0.add(&v2);
|
||||
|
||||
cx1.add(&v3);
|
||||
|
||||
MM c(&cx0, &cx1);
|
||||
|
||||
auto size = c.size();
|
||||
REQUIRE(size == 0);
|
||||
|
||||
auto m = 0;
|
||||
for (auto &_: c)
|
||||
{
|
||||
unused(_);
|
||||
m++;
|
||||
}
|
||||
|
||||
REQUIRE(m == 0);
|
||||
|
||||
auto v1s = 1;
|
||||
auto v2s = 7;
|
||||
auto v3s = 15;
|
||||
|
||||
v1.resize(v1s);
|
||||
v2.resize(v2s);
|
||||
v3.resize(v3s);
|
||||
|
||||
auto s = v1s + v2s + v3s;
|
||||
REQUIRE(c.size() == s);
|
||||
|
||||
m = 0;
|
||||
for (auto &_: c)
|
||||
{
|
||||
unused(_);
|
||||
m++;
|
||||
}
|
||||
|
||||
REQUIRE(m == s);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
114
tjp/core/containers/_tests/SafeIteration.cpp
Executable file
114
tjp/core/containers/_tests/SafeIteration.cpp
Executable file
@@ -0,0 +1,114 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/containers/SafeIteration.hpp>
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
#include <tjp/core/containers/List.h>
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
|
||||
namespace tjp::core::containers {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::containers::SafeIteration")
|
||||
{
|
||||
GIVEN("sizes")
|
||||
{
|
||||
using LI = List<int>;
|
||||
using SLI = SafeIteration<List<int>>;
|
||||
|
||||
using FA = FilledArray<void *, 4>;
|
||||
|
||||
sLogTest("debug",
|
||||
logVar(sizeof(SLI))
|
||||
<< logVar(sizeof(SLI::container_type))
|
||||
<< logVar(sizeof(SLI::iterators_container))
|
||||
);
|
||||
}
|
||||
GIVEN("a list with X elements")
|
||||
{
|
||||
SafeIteration<List<int>> l;
|
||||
l.push_back(0);
|
||||
l.push_back(1);
|
||||
l.push_back(2);
|
||||
l.push_back(3);
|
||||
l.push_back(4);
|
||||
l.push_back(5);
|
||||
|
||||
WHEN("iterate but my item+1")
|
||||
{
|
||||
List<int> r;
|
||||
|
||||
for (auto i : l)
|
||||
{
|
||||
r.push_back(i);
|
||||
|
||||
if (i == 3)
|
||||
{
|
||||
l.erase(std::find(l.begin(), l.end(), i+1));
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(r == List<int> { 0, 1, 2, 3, 5 });
|
||||
}
|
||||
|
||||
WHEN("iterate but my item")
|
||||
{
|
||||
List<int> r;
|
||||
|
||||
for (auto i : l)
|
||||
{
|
||||
r.push_back(i);
|
||||
|
||||
if (i == 3)
|
||||
{
|
||||
l.erase(std::find(l.begin(), l.end(), i));
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(r == List<int> { 0, 1, 2, 3, 4, 5 });
|
||||
}
|
||||
|
||||
WHEN("iterate but remove from front to back")
|
||||
{
|
||||
List<int> r;
|
||||
|
||||
for (auto i : l)
|
||||
{
|
||||
r.push_back(i);
|
||||
|
||||
if (i == 3)
|
||||
{
|
||||
while (!l.empty())
|
||||
l.erase(std::find(l.begin(), l.end(), l.front()));
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(r == List<int> { 0, 1, 2, 3 });
|
||||
}
|
||||
|
||||
WHEN("iterate but remove from back to front")
|
||||
{
|
||||
List<int> r;
|
||||
for (auto i : l)
|
||||
{
|
||||
r.push_back(i);
|
||||
if (i == 3)
|
||||
{
|
||||
while (!l.empty())
|
||||
l.erase(std::find(l.begin(), l.end(), l.back()));
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(r == List<int> { 0, 1, 2, 3 });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
91
tjp/core/containers/_tests/StackArray_v2.cpp
Executable file
91
tjp/core/containers/_tests/StackArray_v2.cpp
Executable file
@@ -0,0 +1,91 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/containers/StackArray_v2.hpp>
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/iterators/range.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
|
||||
namespace tjp::core::stackarray_v2 {
|
||||
namespace {
|
||||
|
||||
struct E {
|
||||
int i;
|
||||
} ;
|
||||
|
||||
SCENARIO("core::containers::stackarray_v2" )
|
||||
{
|
||||
GIVEN("sizes")
|
||||
{
|
||||
using SA32 = StackArray<char,32>;
|
||||
sLogTest("debug",
|
||||
logVar(sizeof(SA32))
|
||||
<< logVar(sizeof(SA32::Fixed))
|
||||
<< logVar(sizeof(SA32::Variable))
|
||||
<< logVar(sizeof(SA32::Ptr))
|
||||
);
|
||||
}
|
||||
GIVEN("a list with X elements")
|
||||
{
|
||||
StackArray<E> a;
|
||||
|
||||
WHEN("add less than N items")
|
||||
{
|
||||
for (auto i : range(0, 10))
|
||||
a.push_back(E{i});
|
||||
|
||||
THEN("array is static")
|
||||
{
|
||||
REQUIRE(a.on_stack());
|
||||
}
|
||||
|
||||
THEN("arrays elements match")
|
||||
{
|
||||
int i=0;
|
||||
for (auto &v : a)
|
||||
{
|
||||
REQUIRE(v.i == i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("add more than N items")
|
||||
{
|
||||
for (auto i : range(0, 32))
|
||||
a.push_back(E{i});
|
||||
|
||||
for (auto i : range(32, 128))
|
||||
a.push_back(E{i});
|
||||
|
||||
THEN("array is not static")
|
||||
{
|
||||
REQUIRE(!a.on_stack());
|
||||
}
|
||||
|
||||
THEN("arrays elements match")
|
||||
{
|
||||
int i=0;
|
||||
for (auto &v : a)
|
||||
{
|
||||
REQUIRE(v.i == i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
THEN("item is popped")
|
||||
{
|
||||
a.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user