- Documentation of containers and adjusting page hierarchy

This commit is contained in:
2025-08-18 14:13:35 -04:00
parent 27754a56d7
commit 55a8c54119
28 changed files with 934 additions and 313 deletions

View File

@@ -40,24 +40,62 @@ namespace fennec
///
///
/// \brief wrapper for fixed size arrays
/// \brief Data Structure that defines a compile-time allocated array
///
/// \details
/// | Property | Value |
/// |:--------:|:-----------------------:|
/// | stable | \emoji heavy_check_mark |
/// | access | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | |
/// | homogenous | |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(N)\f$ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
///
/// \tparam ValueT value type
/// \tparam ElemV number of elements
template<typename ValueT, size_t ElemV>
struct array
{
// Public Members ======================================================================================================
/// \name Public Members
/// @{
///
/// \brief backing c-style array handle
ValueT elements[ElemV];
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
///
/// \brief returns the number of elements in the array
/// \returns the number of elements in the array
[[nodiscard]] constexpr size_t size() const { return ElemV; }
///
/// \brief returns **true** when the array is empty
/// \return \f$ElemV == 0\f$
[[nodiscard]] constexpr bool_t empty() const { return ElemV == 0; }
/// @}
// Access ==============================================================================================================
/// \name Element Access
/// @{
@@ -84,32 +122,11 @@ struct array
return elements[i];
}
constexpr ValueT* begin() { return elements; }
constexpr ValueT* end() { return elements + ElemV; }
constexpr const ValueT* begin() const { return elements; }
constexpr const ValueT* end() const { return elements + ElemV; }
/// @}
/// \name Capacity
/// @{
///
/// \brief returns the number of elements in the array
/// \returns the number of elements in the array
[[nodiscard]] constexpr size_t size() const { return ElemV; }
///
/// \brief returns **true** when the array is empty
/// \return \f$ElemV == 0\f$
[[nodiscard]] constexpr bool_t empty() const { return ElemV == 0; }
/// @}
// Comparison ==========================================================================================================
/// \name Comparison Operators
/// @{
@@ -126,6 +143,32 @@ struct array
/// @}
// Iteration ===========================================================================================================
/// \name Iteration
/// @{
///
/// \returns A pointer to the first element of the array
constexpr ValueT* begin() { return elements; }
///
/// \returns A pointer to one after the end of the array
constexpr ValueT* end() { return elements + ElemV; }
///
/// \returns A const-qualified pointer to the first element of the array
constexpr const ValueT* begin() const { return elements; }
///
/// \returns A const-qualified pointer to one after the end of the array
constexpr const ValueT* end() const { return elements + ElemV; }
/// @}
private:
template<size_t...i>
static bool _compare(const array& lhs, const array& rhs, const_index_sequence<i...>) {

View File

@@ -0,0 +1,94 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file containers.h
/// \brief fennec containers library main header
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_CONTAINERS_CONTAINERS_H
#define FENNEC_CONTAINERS_CONTAINERS_H
///
/// \page fennec_containers Containers Library
///
/// \brief The fennec Containers Library.
/// Includes various data structures, those specified in the C++ Standard Library, and custom data structures
/// that fennec uses.
///
/// \code #include <fennec/containers/containers.h> \endcode
///
/// \section fennec_containers_cppstdlib C++ Standard Template Library
///
/// | Symbol | Implemented | Passed |
/// |:----------------------------------------------------------------------------|:-----------:|:------:|
/// | \ref fennec::any "fennec::any" | ⛔ | ⛔ |
/// | \ref fennec::array "fennec::array" | ✅ | ✅ |
/// | \ref fennec::bitset "fennec::bitset" | ⛔ | ⛔ |
/// | \ref fennec::deque "fennec::deque" | ⛔ | ⛔ |
/// | \ref fennec::dynarray "fennec::dynarray" `std::vector` | 🚧 | 🚧 |
/// | \ref fennec::list "fennec::list" | ✅ | ✅ |
/// | \ref fennec::map "fennec::map" `std::unordered_map` | ✅ | ✅ |
/// | \ref fennec::map_sequence "fennec::map_sequence" `std::map` | ⛔ | ⛔ |
/// | \ref fennec::multiset "fennec::multiset" `std::unordered_multiset` | ⛔ | ⛔ |
/// | \ref fennec::multisequence "fennec::multisequence" `std::multiset` | ⛔ | ⛔ |
/// | \ref fennec::multimap "fennec::multimap" `std::unordered_multimap` | ⛔ | ⛔ |
/// | \ref fennec::multimap_sequence "fennec::multimap_sequence" `std::multimap` | ⛔ | ⛔ |
/// | \ref fennec::optional "fennec::optional" | ✅ | ✅ |
/// | \ref fennec::pair "fennec::pair" | ✅ | ✅ |
/// | \ref fennec::sequence "fennec::sequence" `std::set` | ⛔ | ⛔ |
/// | \ref fennec::set "fennec::set" `std::unordered_set` | ✅ | ✅ |
/// | \ref fennec::tuple "fennec::tuple" | 🚧 | 🚧 |
/// | \ref fennec::variant "fennec::variant" | ⛔ | ⛔ |
///
///
/// \section fennec_containers_fennec fennec
///
/// | Symbol | Implemented | Passed |
/// |:-------------------------|:-----------:|:------:|
/// | \ref fennec::graph | 🚧 | 🚧 |
/// | \ref fennec::object_pool | 🚧 | 🚧 |
/// | \ref fennec::rdtree | ✅ | ✅ |
///
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
#include <fennec/containers/traversal.h>
#include <fennec/containers/array.h>
#include <fennec/containers/deque.h>
#include <fennec/containers/dynarray.h>
#include <fennec/containers/graph.h>
#include <fennec/containers/list.h>
#include <fennec/containers/map.h>
#include <fennec/containers/object_pool.h>
#include <fennec/containers/optional.h>
#include <fennec/containers/pair.h>
#include <fennec/containers/rdtree.h>
#include <fennec/containers/set.h>
#include <fennec/containers/tuple.h>
#endif // FENNEC_CONTAINERS_CONTAINERS_H

View File

@@ -26,15 +26,40 @@
namespace fennec
{
///
///
/// \brief Data structure defining a double-ended queue.
///
/// \details
/// This behaves the similar to fennec::list, however it does not allow arbitrary access, insertion, or deletion.
/// It is one of the few data structures in this library that is stable, i.e. pointers to elements do not change.
///
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | ✅ |
/// | homogenous | ✅ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ⛔ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam TypeT value type
template<typename TypeT, typename AllocT = allocator<TypeT>>
struct deque {
// Definitions =========================================================================================================
public:
using elem_t = TypeT;
using value_t = TypeT;
class iterator;
private:
struct node {
elem_t value;
value_t value;
node *prev, *next;
template<typename...ArgsT>
@@ -46,11 +71,18 @@ public:
~node() = default;
};
public:
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
using elem_t = node*;
// Constructors ========================================================================================================
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes an empty deque
deque()
: _alloc()
, _first(nullptr)
@@ -58,6 +90,24 @@ public:
, _size(0) {
}
///
/// \brief Copy Constructor
/// \param deque the deque to copy
deque(const deque& deque)
: _alloc(deque._alloc)
, _first(nullptr)
, _last(nullptr)
, _size(0) {
const elem_t node = deque._first;
while (node) {
this->push_back(node->value);
node = node->next;
}
}
///
/// \brief Deque Move Constructor
/// \param deque the deque to move
deque(deque&& deque) noexcept
: _alloc(deque._alloc)
, _first(deque._first)
@@ -67,69 +117,128 @@ public:
deque._last = nullptr;
}
///
/// \brief Destructor, calls deque::clear
~deque() {
clear();
}
/// @}
// Properties ==========================================================================================================
bool empty() const {
/// \name Properties
/// @{
///
/// \returns `true` when the deque is empty, `false` otherwise
constexpr bool empty() const {
return _size == 0;
}
size_t size() const {
///
/// \returns the number of elements in size()
constexpr size_t size() const {
return _size;
}
/// @}
// Access ==============================================================================================================
elem_t& front() {
/// \name Access
/// @{
///
/// \returns a reference to the first element in the deque
value_t& front() {
assert(not empty(), "Attempted to access an empty deque.");
return _first->value;
}
elem_t& back() {
///
/// \returns a const-qualified reference to the first element in the deque
const value_t& front() const {
assert(not empty(), "Attempted to access an empty deque.");
return _first->value;
}
///
/// \returns a reference to the last element in the deque
value_t& back() {
assert(not empty(), "Attempted to access an empty deque.");
return _last->value;
}
///
/// \returns a const-qualified reference to the last element in the deque
const value_t& back() const {
assert(not empty(), "Attempted to access an empty deque.");
return _last->value;
}
// Insertion ===========================================================================================================
/// @}
void push_front(elem_t&& elem) {
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
///
/// \brief Push Front Move, moves a value to the front of the deque
/// \param elem the value to move
void push_front(value_t&& elem) {
this->_push_front(elem);
}
void push_front(const elem_t& elem) {
///
/// \brief Push Front Copy, copies a value to the front of the deque
/// \param elem the value to copy
void push_front(const value_t& elem) {
this->_push_front(elem);
}
///
/// \brief Emplace Front, constructs a new value at the front of the deque
/// \tparam ArgsT Argument types
/// \param args Arguments used to construct the value
template<typename...ArgsT>
void emplace_front(ArgsT&&...args) {
this->_push_front(fennec::forward<ArgsT>(args)...);
}
void push_back(elem_t&& elem) {
///
/// \brief Push Back Move, moves a value to the back of the deque
/// \param elem the value to move
void push_back(value_t&& elem) {
this->_push_back(elem);
}
void push_back(const elem_t& elem) {
///
/// \brief Push Back Copy, copies a value to the back of the deque
/// \param elem the value to copy
void push_back(const value_t& elem) {
this->_push_back(elem);
}
///
/// \brief Emplace Back, constructs a new value at the back of the deque
/// \tparam ArgsT Argument types
/// \param args Arguments used to construct the value
template<typename...ArgsT>
void emplace_back(ArgsT&&...args) {
this->_push_back(fennec::forward<ArgsT>(args)...);
}
// Deletion ============================================================================================================
///
/// \brief Clears the contents of the deque
void clear() {
node* it = _first;
elem_t it = _first;
while (it) {
node* next = it->next;
elem_t next = it->next;
fennec::destruct(it);
_alloc.deallocate(it);
it = next;
@@ -139,11 +248,13 @@ public:
_size = 0;
}
///
/// \brief Erase the First Element
void pop_front() {
if (_first == nullptr) {
return;
}
node* next = _first->next;
elem_t next = _first->next;
fennec::destruct(_first);
_alloc.deallocate(_first);
_first = next;
@@ -151,11 +262,13 @@ public:
--_size;
}
///
/// \brief Erase the Last Element
void pop_back() {
if (_last == nullptr) {
return;
}
node* prev = _last->prev;
elem_t prev = _last->prev;
fennec::destruct(_last);
_alloc.deallocate(_last);
_last = prev;
@@ -163,6 +276,15 @@ public:
--_size;
}
/// @}
// Iteration ===========================================================================================================
/*
* TODO: Decide whether you should be able to iterate over a deque
*/
private:
alloc_t _alloc;
node *_first, *_last;
@@ -170,7 +292,7 @@ private:
template<typename...ArgsT>
void _push_front(ArgsT&&...args) {
node* next = _first;
elem_t next = _first;
_first = _alloc.allocate(1);
fennec::construct(_first, nullptr, next, fennec::forward<ArgsT>(args)...);
if (next) {
@@ -183,7 +305,7 @@ private:
template<typename...ArgsT>
void _push_back(ArgsT&&...args) {
node* prev = _last;
elem_t prev = _last;
_last = _alloc.allocate(1);
fennec::construct(_last, prev, nullptr, fennec::forward<ArgsT>(args)...);
if (prev) {

View File

@@ -40,15 +40,21 @@ namespace fennec
///
///
/// \brief wrapper for dynamically sized arrays
/// \brief Wrapper for dynamically sized arrays
/// \details
/// | Property | Value |
/// |-----------|:----------:|
/// | stable | \emoji x |
/// | access | \f$O(1)\f$ |
/// | insertion | \f$O(N)\f$ |
/// | deletion | \f$O(N)\f$ |
/// | space | \f$O(N)\f$ |
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | |
/// | dynamic | ✅ |
/// | homogenous | ✅ |
/// | distinct | |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(N)\f$ |
/// | deletion | \f$O(N)\f$ |
///
/// \tparam TypeT value type
template<class TypeT, class Alloc = allocator<TypeT>>
@@ -63,13 +69,20 @@ public:
// Constructors ========================================================================================================
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes an empty allocation.
constexpr dynarray() : _alloc(8), _size(0) {}
constexpr dynarray()
: _alloc(8)
, _size(0) {
}
///
/// \brief Alloc Constructor, initialize empty allocation with allocator instance.
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
/// data.
constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc)
, _size(0) {
@@ -77,14 +90,16 @@ public:
///
/// \brief Alloc Move Constructor, initialize empty allocation with allocator instance.
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
/// data.
constexpr dynarray(alloc_t&& alloc) noexcept
: _alloc(8, alloc)
, _size(0) {
}
///
/// \brief Sized Allocation, create an allocation of size `n` elements, initialized with the default constructor.
/// \brief Sized Allocation, create an allocation of size `n` elements,
/// initialized with the default constructor.
constexpr dynarray(size_t n)
: _alloc(n)
, _size(n)
@@ -96,7 +111,8 @@ public:
}
///
/// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator `alloc` and `n` elements using the default constructor.
/// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator `alloc` and `n` elements
/// using the default constructor.
/// \param n The number of elements
/// \param alloc The allocator object to copy
constexpr dynarray(size_t n, const alloc_t& alloc)
@@ -109,7 +125,8 @@ public:
}
///
/// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator `alloc` and `n` elements using the default constructor.
/// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator `alloc` and `n` elements
/// using the default constructor.
/// \param n The number of elements
/// \param alloc The allocator object to copy
constexpr dynarray(size_t n, alloc_t&& alloc)
@@ -122,8 +139,9 @@ public:
}
///
/// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element constructed using the copy constructor
/// \brief n the number of elements
/// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element
/// constructed using the copy constructor
/// \param n the number of elements
constexpr dynarray(size_t n, const TypeT& val)
: _alloc(n)
, _size(n) {
@@ -143,13 +161,33 @@ public:
/// \param n The number of objects to create
/// \param args The arguments to create each object with
template<typename...ArgsT>
constexpr dynarray(size_t n, ArgsT&&...args) {
element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) {
fennec::construct(addr, fennec::forward<ArgsT>(args)...);
constexpr dynarray(size_t n, ArgsT&&...args)
: _alloc(n)
, _size(n) {
for(; n > 0; --n) {
fennec::construct(&_alloc[n], fennec::forward<ArgsT>(args)...);
}
}
///
/// \brief Copy Constructor, uses the copy constructor to copy each element
/// \param arr the dynarray to copy
constexpr dynarray(const dynarray& arr)
: _alloc(arr._size)
, _size(arr._size) {
for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], arr[i]);
}
}
///
/// \brief Move Constructor, takes ownership of the allocation
/// \param arr the dynarray to move
constexpr dynarray(dynarray&& arr)
: _alloc(fennec::move(arr._alloc))
, _size(arr._size) {
}
///
/// \brief Default Destructor, destructs all elements and frees the underlying allocation
constexpr ~dynarray() {
@@ -160,9 +198,14 @@ public:
}
}
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
///
/// \returns The size of the dynarray in elements
constexpr size_t size() const {
@@ -181,9 +224,14 @@ public:
return _size == 0;
}
/// @}
// Element Access ======================================================================================================
/// \name Access
/// @{
///
/// \brief Array Access Operator
/// \param i The index to access
@@ -226,28 +274,13 @@ public:
return this->operator[](size() - 1);
}
///
/// \brief "Iterator" Begin Function
/// \returns A pointer to the first element in the dynarray
constexpr TypeT* begin() { return _alloc.data(); }
///
/// \brief "Iterator" End Function
/// \return A pointer to the address after the last element in the dynarray
constexpr TypeT* end() { return begin() + _size; }
///
/// \brief Const "Iterator" Begin Function
/// \returns A const qualified pointer to the first element in the dynarray
constexpr const TypeT* begin() const { return _alloc; }
///
/// \brief Const "Iterator" End Function
/// \return A const qualified pointer to the address after the last element in the dynarray
constexpr const TypeT* end() const { return begin() + _size; }
/// @}
// Insertion & Deletion ================================================================================================
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
///
/// \brief Move Insertion
@@ -364,6 +397,36 @@ public:
}
}
/// @}
// Iteration ===========================================================================================================
/// \name Iteration
/// @{
///
/// \brief "Iterator" Begin Function
/// \returns A pointer to the first element in the dynarray
constexpr TypeT* begin() { return _alloc.data(); }
///
/// \brief "Iterator" End Function
/// \return A pointer to the address after the last element in the dynarray
constexpr TypeT* end() { return begin() + _size; }
///
/// \brief Const "Iterator" Begin Function
/// \returns A const qualified pointer to the first element in the dynarray
constexpr const TypeT* begin() const { return _alloc; }
///
/// \brief Const "Iterator" End Function
/// \return A const qualified pointer to the address after the last element in the dynarray
constexpr const TypeT* end() const { return begin() + _size; }
/// @}
private:
constexpr void _grow() {
_alloc.creallocate(_alloc.capacity() * 2);

View File

@@ -39,26 +39,54 @@
namespace fennec
{
template<typename NodeT, typename ConnectionT = nullptr_t>
///
/// \brief Graph Data Structure, describes sets of arbitrarily connected nodes
/// \tparam NodeT The type associated with each node
/// \tparam WeightT The type associated with each connection
template<typename NodeT, typename WeightT = nullptr_t>
struct graph {
public:
using weight_t = ConnectionT;
// Definitions =========================================================================================================
/// \name Definitions
/// @{
using weight_t = WeightT;
using node_t = NodeT;
using conn_map_t = dynarray<map<size_t, size_t>>;
using node_pool_t = object_pool<node_t>;
using conn_pool_t = object_pool<weight_t>;
static constexpr size_t npos = -1;
/// @}
// Constructors ========================================================================================================
/// \name Constructors
/// @{
///
/// \brief Default Constructor, initializes empty graph
constexpr graph() = default;
///
/// \brief Destructor
constexpr ~graph() = default;
/// @}
/// \name Assignment Operators
/// @{
constexpr graph& operator=(const graph& g) = default;
constexpr graph& operator=(graph&& g) = default;
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
constexpr size_t num_nodes() const {
return _node_pool.size();
}
@@ -74,6 +102,7 @@ public:
constexpr bool empty() const {
return num_nodes() == 0;
}
/// @}
// Nodes ===============================================================================================================
@@ -106,18 +135,24 @@ public:
// Connections =========================================================================================================
list<size_t> connections(size_t n) {
list<size_t> conns;
if (_conn_map.empty()) return conns;
for (auto it : _conn_map[n]) {
conns.push_back(it.first);
list<pair<size_t, size_t>> connections(size_t n) {
list<pair<size_t, size_t>> conns;
for (size_t i = 0; i < _conn_map.size(); ++i) {
for (auto it : _conn_map[i]) {
if (i == n || it.first == n) {
conns.emplace_back(i, n);
}
}
}
return conns;
}
template<typename...ArgsT>
constexpr void connect(size_t a, size_t b, ArgsT&&...args) {
if (a == b) {
return;
}
if (_conn_map.size() < _node_pool.capacity()) {
_conn_map.resize(_node_pool.capacity());
}
@@ -132,25 +167,29 @@ public:
}
_conn_map[a].emplace(b, conn);
_conn_map[b].emplace(a, conn);
}
constexpr void disconnect(size_t a, size_t b) {
size_t c = *_conn_map[a][b];
const auto* it = _conn_map[a][b];
if (not it) {
return;
}
size_t c = *it;
_conn_pool.erase(c);
_conn_map[a].erase(b);
_conn_map[b].erase(a);
}
void disconnect(size_t n) {
list<size_t> conns = connections(n);
for (size_t conn : conns) {
disconnect(n, conn);
const auto conns = connections(n);
for (const auto& conn : conns) {
disconnect(conn.first, conn.second);
}
}
constexpr weight_t& operator[](size_t a, size_t b) {
return _conn_pool[_conn_map[a][b]];
weight_t* it = _conn_map[a][b];
assertd(it, "Element not Found!");
return _conn_pool[*it];
}
constexpr const weight_t& operator[](size_t a, size_t b) const {

View File

@@ -43,18 +43,24 @@ namespace fennec
///
///
/// \brief wrapper for lists of elements
/// \brief Data Structure defining lists of elements
/// \details
/// This data-structure behaves like a linked list, but does not use pointers. Instead, it is in-array. This creates the
/// following properties:
///
/// | Property | Value |
/// |:----------|:-------------------------------------:|
/// | stable | \emoji x |
/// | access | \f$O(N)\f$ or \f$O(1)\f$ (front/back) |
/// | insertion | \f$O(N)\f$ or \f$O(1)\f$ (iterator) |
/// | deletion | \f$O(N)\f$ or \f$O(1)\f$ (iterator) |
/// | space | \f$O(N)\f$ |
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogenous | ✅ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(N)\f$ |
/// | deletion | \f$O(N)\f$ |
///
/// \tparam TypeT value type
template<class TypeT, class Alloc = allocator<TypeT>>
@@ -75,7 +81,10 @@ public:
class const_iterator;
// Constructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes an empty list.
@@ -91,9 +100,13 @@ public:
}
}
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
///
/// \returns The size of the list in elements.
constexpr size_t size() const { return _size; }
@@ -106,9 +119,14 @@ public:
/// \returns `true` when the list is empty, `false` otherwise.
constexpr bool empty() const { return _root == npos; }
/// @}
// Access ==============================================================================================================
/// \name Access
/// @{
///
/// \brief Array Access Operator
/// \param i Index to access
@@ -163,8 +181,13 @@ public:
return *_table[_last].value;
}
/// @}
// Insertions & Deletions ==============================================================================================
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
///
/// \brief Copy Insertion
@@ -301,6 +324,8 @@ public:
_erase(_last);
}
/// @}
// ITERATOR ============================================================================================================
///
@@ -403,6 +428,9 @@ public:
}
};
/// \name Iteration
/// @{
///
/// \returns An iterator for the first element in the list
constexpr iterator begin() {
@@ -427,6 +455,8 @@ public:
return const_iterator(this, npos);
}
/// @}
private:
allocation<elem_t, alloc_t> _table;
dynarray<size_t> _freed;

View File

@@ -44,7 +44,22 @@ namespace fennec
*/
///
/// \brief Map for Pairing Values to Keys
/// \brief Data Structure defining a mapping of `key` \f$KeyT\f$ to `value` \f$ValueT\f$
/// \details
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogenous | ✅ |
/// | distinct | ✅ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam KeyT The Key Type
/// \tparam ValueT The Value Type
/// \tparam Hash The Hash to Use
@@ -79,7 +94,10 @@ public:
};
// Constructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes empty map
@@ -89,9 +107,40 @@ public:
/// \brief Destructor, Destructs all elements and releases the allocation
constexpr ~map() = default;
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
///
/// \returns The size of the set
constexpr size_t size() const {
return _set.size();
}
///
/// \returns `true` when there are no elements in the set, `false` otherwise
constexpr size_t empty() const {
return _set.size();
}
///
/// \returns The capacity of the underlying allocation
constexpr size_t capacity() const {
return _set.capacity();
}
/// @}
// Access ==============================================================================================================
/// \name Access
/// @{
///
/// \brief Key Access Operator
/// \param key Key value to access
@@ -132,8 +181,13 @@ public:
return it ? &it->second : nullptr;
}
/// @}
// Insertion & Deletion ================================================================================================
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
///
/// \brief Key-Value Insertion
@@ -181,9 +235,14 @@ public:
_set.erase(this->_find(fennec::forward<ArgsT>(args)...));
}
/// @}
// Iteration ===========================================================================================================
/// \name Iteration
/// @{
constexpr iterator begin() {
return _set.begin();
}
@@ -192,6 +251,8 @@ public:
return _set.end();
}
/// @}
private:
set_t _set;

View File

@@ -33,17 +33,21 @@ namespace fennec
///
///
/// \brief wrapper for multisets of elements
/// \brief A Data Structure that defines a set of elements that may repeat
/// \details
/// This data-structure behaves like a multiset, but does not use pointers, instead storing the table in-array
///
/// | Property | Value |
/// |:----------|:----------:|
/// | stable | \emoji x |
/// | access | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogenous | ✅ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam TypeT The type to contain
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
@@ -73,6 +77,9 @@ private:
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes empty multiset
constexpr multiset()
@@ -193,24 +200,40 @@ public:
}
}
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
///
/// \returns Size of the multiset in elements
constexpr size_t size() const {
return _size;
}
///
/// \returns `true` when the set is empty, `false` otherwise
constexpr bool empty() const {
return _size == 0;
}
///
/// \returns Capacity of the multiset in elements
constexpr size_t capacity() const {
return _alloc.capacity();
}
/// @}
// Access ==============================================================================================================
/// \name Access
/// @{
///
/// \brief Find an Element
/// \param val Value to find
@@ -295,7 +318,12 @@ public:
return &*_alloc[it._i].value;
}
// Insertion & Deletion ================================================================================================
/// @}
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
///
/// \brief Move Insertion
@@ -352,6 +380,8 @@ public:
this->erase(this->find(val));
}
/// @}
// ITERATOR ============================================================================================================
@@ -462,6 +492,9 @@ public:
}
};
/// \name Iteration
/// @{
constexpr iterator begin() const {
iterator it(this, 0);
if (not _alloc[it._i].value) {
@@ -474,6 +507,8 @@ public:
return iterator(this, npos);
}
/// @}
// PRIVATE =============================================================================================================

View File

@@ -18,6 +18,7 @@
#ifndef FENNEC_CONTAINERS_OBJECT_POOL_H
#define FENNEC_CONTAINERS_OBJECT_POOL_H
#include <fennec/containers/dynarray.h>
#include <fennec/containers/list.h>
#include <fennec/containers/optional.h>

View File

@@ -38,13 +38,19 @@ namespace fennec
/// \details
/// This data-structure behaves like a set, but does not use pointers, instead storing the table in-array
///
/// | Property | Value |
/// |:----------|:----------:|
/// | stable | \emoji x |
/// | access | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | |
/// | dynamic | ✅ |
/// | homogenous | ✅ |
/// | distinct | |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam TypeT The type to contain
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
@@ -73,6 +79,9 @@ private:
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes empty set
constexpr set()
@@ -193,24 +202,40 @@ public:
}
}
/// @}
// Properties ==========================================================================================================
/// \name Properties
/// @{
///
/// \returns Size of the set in elements
constexpr size_t size() const {
return _size;
}
///
/// \returns `true` when the set is empty, `false` otherwise
constexpr bool empty() const {
return _size == 0;
}
///
/// \returns Capacity of the set in elements
constexpr size_t capacity() const {
return _alloc.capacity();
}
/// @}
// Access ==============================================================================================================
/// \name Access
/// @{
///
/// \brief Find an Element
/// \param val Value to find
@@ -291,7 +316,12 @@ public:
return &*_alloc[it._i].value;
}
// Insertion & Deletion ================================================================================================
/// @}
// Modifiers ===========================================================================================================
/// \name Properties
/// @{
///
/// \brief Move Insertion
@@ -348,6 +378,8 @@ public:
this->erase(this->find(val));
}
/// @}
// ITERATOR ============================================================================================================
@@ -406,6 +438,9 @@ public:
friend set;
};
/// \name Iteration
/// @{
constexpr iterator begin() const {
iterator it(this, 0);
if (not _alloc[it._i].value) {
@@ -418,6 +453,8 @@ public:
return iterator(this, npos);
}
/// @}
// PRIVATE =============================================================================================================

View File

@@ -29,6 +29,21 @@ namespace fennec
///
/// \brief Tuple, holds a collection of values of different types
/// \details
/// | Property | Value |
/// |:----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogenous | ⛔ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(1)\f$ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
///
/// \tparam TypesT The types to store
template<typename...TypesT> struct tuple;

View File

@@ -29,32 +29,19 @@
///
///
/// \page documentation Documentation
/// \page libraries Libraries
///
/// | Library | Brief |
/// |:---------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
/// | \subpage fennec_lang | Implementation for functions and classes related to the C++ Language, including base types, common utility functions, and metaprogramming templates |
/// | \subpage fennec_math | Implementation of math functions according to the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). Additional extensions are provided for other common math functions. |
/// | \subpage fennec_memory | Implementation of functions related to memory management. |
/// | \subpage fennec_containers | Implementation of common data structures, those that are specified in the C++ STD Library, and custom data structures that fennec uses. |
///
/// 1. \ref introduction "Introduction"
/// 1. \ref coding-standards "Coding Standards"
/// 2. \ref building-from-source "Building from Source"
/// 1. \ref building-from-terminal "Building from Terminal"
/// 2. \ref building-on-windows "Building on Windows"
/// 3. \ref running-the-test-suite "Running the Test Suite"
/// 4. \ref usage "Usage"
/// 5. \ref contribution "Contribution"
/// 6. \subpage libraries
/// 1. \ref fennec_lang "C++ Language Library"
/// 2. \ref fennec_math "Math Library"
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
/// \page libraries Libraries
///
/// | Library | Brief |
/// | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
/// | \subpage fennec_lang | Implementation for functions and classes related to the C++ Language, including base types, common utility functions, and metaprogramming templates |
/// | \subpage fennec_math | Implementation of math functions according to the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). Additional extensions are provided for other common math functions. |
/// | \subpage fennec_memory | Implementation of functions related to memory management. |
#ifndef FENNEC_CORE_ENGINE_H
#define FENNEC_CORE_ENGINE_H

View File

@@ -276,6 +276,16 @@ public:
size_t write(const void* data, size_t size, size_t n);
template<size_t n>
size_t write(const char (&data)[n]) {
return write(data, sizeof(char), n - 1);
}
template<size_t n>
size_t write(const wchar_t (&data)[n]) {
return write(data, sizeof(wchar_t), n - 1);
}
template<typename T>
size_t write(const T* data, size_t n) {
return write(static_cast<const void*>(data), sizeof(T), n);