- A few Vulkan wrapper structs

- Framework for Vulkan context
 - Fixed a bug with dynarray where if `resize()` shrinks the array, destructors are not called.
 - Fixed grammar issues with the containers library and added property tables to existing data structures.
This commit is contained in:
2026-01-02 15:38:03 -05:00
parent c1be5385d3
commit 7c2f89b331
53 changed files with 825 additions and 415 deletions

View File

@@ -104,8 +104,7 @@ fennec_add_sources(
include/fennec/renderers/interface/forward.h include/fennec/renderers/interface/forward.h
include/fennec/renderers/interface/gfxcontext.h include/fennec/renderers/interface/gfxcontext.h
include/fennec/renderers/interface/gfxsubpass.h include/fennec/renderers/interface/gfxsurface.h
include/fennec/renderers/interface/gfxresourcepool.h
# CONTAINERS =========================================================================================================== # CONTAINERS ===========================================================================================================

View File

@@ -30,6 +30,9 @@ if( TARGET Vulkan::Headers AND TARGET Vulkan::volk # Base Headers and Meta-Loade
fennec_add_definitions(FENNEC_GRAPHICS_VULKAN=1) fennec_add_definitions(FENNEC_GRAPHICS_VULKAN=1)
fennec_add_sources( fennec_add_sources(
include/fennec/renderers/vulkan/lib/app_info.h
include/fennec/renderers/vulkan/lib/instance.h
include/fennec/renderers/vulkan/vkcontext.h include/fennec/renderers/vulkan/vkcontext.cpp include/fennec/renderers/vulkan/vkcontext.h include/fennec/renderers/vulkan/vkcontext.cpp
) )
else() else()

View File

@@ -45,10 +45,10 @@ namespace fennec
/// ///
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:----------:|:-----------:| /// |:-----------:|:-----------:|
/// | stable | ✅ | /// | stable | ✅ |
/// | dynamic | ⛔ | /// | dynamic | ⛔ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
@@ -65,9 +65,18 @@ struct array {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public: public:
/// \name Definitions
/// @{
using value_t = ValueT; ///< Alias for \f$ValueT\f$ using value_t = ValueT; ///< Alias for \f$ValueT\f$
/// @}
// Public Members ====================================================================================================== // Public Members ======================================================================================================
public:
/// \name Public Members /// \name Public Members
/// @{ /// @{
@@ -81,6 +90,7 @@ public:
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// \name Properties /// \name Properties
/// @{ /// @{
@@ -93,13 +103,14 @@ public:
/// ///
/// \brief returns **true** when the array is empty /// \brief returns **true** when the array is empty
/// \return \f$ElemV == 0\f$ /// \return \f$ElemV == 0\f$
[[nodiscard]] constexpr bool_t empty() const { return ElemV == 0; } [[nodiscard]] constexpr bool_t is_empty() const { return ElemV == 0; }
/// @} /// @}
// Access ============================================================================================================== // Access ==============================================================================================================
public:
/// \name Element Access /// \name Element Access
/// @{ /// @{
@@ -168,6 +179,7 @@ public:
// Comparison ========================================================================================================== // Comparison ==========================================================================================================
public:
/// \name Comparison Operators /// \name Comparison Operators
/// @{ /// @{
@@ -188,6 +200,7 @@ public:
// Iteration =========================================================================================================== // Iteration ===========================================================================================================
public:
/// \name Iteration /// \name Iteration
/// @{ /// @{
@@ -224,6 +237,8 @@ public:
/// @} /// @}
// Helpers =============================================================================================================
private: private:
template<size_t...i> template<size_t...i>
static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) { static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) {

View File

@@ -42,6 +42,22 @@ namespace fennec
/// ///
/// \brief Structure defining a binary tree /// \brief Structure defining a binary tree
///
/// \details
/// | Property | Value |
/// |:-----------:|:-----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ✅ |
/// | 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 The data type /// \tparam TypeT The data type
/// \tparam AllocT An allocator class /// \tparam AllocT An allocator class
template<typename TypeT, class AllocT = allocator<TypeT>> template<typename TypeT, class AllocT = allocator<TypeT>>
@@ -52,10 +68,15 @@ private:
struct node; struct node;
public: public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< The element type using value_t = TypeT; //!< The element type
using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The allocator type using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The allocator type
static constexpr size_t npos = -1; //!< null position constant static constexpr size_t npos = -1; //!< null position constant
/// @}
friend class iterator; friend class iterator;
friend class const_iterator; friend class const_iterator;
@@ -145,7 +166,7 @@ public:
/// ///
/// \returns \f$true\f$ when there are no elements in the tree, \f$false\f$ otherwise. /// \returns \f$true\f$ when there are no elements in the tree, \f$false\f$ otherwise.
constexpr bool empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -159,7 +180,7 @@ public:
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$. /// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
constexpr size_t next_id() const { constexpr size_t next_id() const {
size_t i = _size; size_t i = _size;
if (not _freed.empty()) { if (not _freed.is_empty()) {
i = _freed.front(); i = _freed.front();
} }
return i; return i;
@@ -455,7 +476,7 @@ public:
queue.push_back(_root); queue.push_back(_root);
} }
while (not queue.empty()) { while (not queue.is_empty()) {
size_t i = queue.front(); size_t i = queue.front();
queue.pop_front(); queue.pop_front();
@@ -540,7 +561,7 @@ public:
visit.push_back(chd); visit.push_back(chd);
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -591,7 +612,7 @@ public:
visit.push_front(chd); visit.push_front(chd);
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -642,7 +663,7 @@ public:
visit.push_front(next); visit.push_front(next);
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -692,7 +713,7 @@ public:
visit.push_front(this->_successor(tree, pright)); visit.push_front(this->_successor(tree, pright));
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -926,7 +947,7 @@ private:
constexpr size_t _next_free() { constexpr size_t _next_free() {
size_t i = _size; size_t i = _size;
if (not _freed.empty()) { if (not _freed.is_empty()) {
i = _freed.front(); i = _freed.front();
_freed.pop_front(); _freed.pop_front();
} }

View File

@@ -40,6 +40,22 @@ namespace fennec
/// ///
/// \brief Bitfield Container with basic Bit Ops /// \brief Bitfield Container with basic Bit Ops
///
/// \details
/// | Property | Value |
/// |:-----------:|:------------------------------:|
/// | stable | Elements cannot be referenced. |
/// | dynamic | ⛔ |
/// | homogeneous | ✅ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | \f$O(N)\f$ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
///
/// \tparam N The number of bits in the bitfield /// \tparam N The number of bits in the bitfield
template<size_t N> template<size_t N>
struct bitfield { struct bitfield {

View File

@@ -40,6 +40,23 @@
/// ///
/// \code #include <fennec/containers/containers.h> \endcode /// \code #include <fennec/containers/containers.h> \endcode
/// ///
/// \section Data Structure Properties
///
/// | Property | Meaning |
/// |:-----------:|:----------------------------------------------------------------------------------------------:|
/// | stable | Any pointer reference to an element remains constant for the lifetime of the data structure. |
/// | dynamic | Memory for this data structure is allocated on the heap. |
/// | homogeneous | The types of all elements are either identical, or inherit the same base type. |
/// | distinct | Elements are guaranteed to be unique in their value. |
/// | ordered | Elements are guaranteed to be in order, such that for any index \f$i\f$, \f$E_i < E_{i + 1}\f$ |
/// | space | The amount of memory allocated with respect to the number of elements, in big-O notation. |
/// | linear | Each element is sequential in terms of access. |
/// | access | The runtime of the access operators and functions, in big-O notation. |
/// | find | The runtime of finding an element in the data structure, in big-O notation. |
/// | insertion | The runtime of inserting an element in the data structure, in big-O notation. |
/// | deletion | The runtime of erasing an element in the data structure, in big-O notation. |
///
///
/// \section fennec_containers_cppstdlib C++ Standard Template Library /// \section fennec_containers_cppstdlib C++ Standard Template Library
/// ///
/// | Symbol | Implemented | Passed | /// | Symbol | Implemented | Passed |

View File

@@ -47,10 +47,10 @@ namespace fennec
/// It is one of the few data structures in this library that is stable, i.e. pointers to elements do not change. /// It is one of the few data structures in this library that is stable, i.e. pointers to elements do not change.
/// ///
/// | Property | Value | /// | Property | Value |
/// |:----------:|:----------:| /// |:-----------:|:----------:|
/// | stable | ✅ | /// | stable | ✅ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
@@ -154,7 +154,7 @@ public:
/// ///
/// \returns \f$true\f$ when the deque is empty, \f$false\f$ otherwise /// \returns \f$true\f$ when the deque is empty, \f$false\f$ otherwise
constexpr bool empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -175,28 +175,28 @@ public:
/// ///
/// \returns a reference to the first element in the deque /// \returns a reference to the first element in the deque
value_t& front() { value_t& front() {
assert(not empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _first->value; return _first->value;
} }
/// ///
/// \returns a const-qualified reference to the first element in the deque /// \returns a const-qualified reference to the first element in the deque
const value_t& front() const { const value_t& front() const {
assert(not empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _first->value; return _first->value;
} }
/// ///
/// \returns a reference to the last element in the deque /// \returns a reference to the last element in the deque
value_t& back() { value_t& back() {
assert(not empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _last->value; return _last->value;
} }
/// ///
/// \returns a const-qualified reference to the last element in the deque /// \returns a const-qualified reference to the last element in the deque
const value_t& back() const { const value_t& back() const {
assert(not empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _last->value; return _last->value;
} }

View File

@@ -44,10 +44,10 @@ namespace fennec
/// \brief Wrapper for dynamically sized and allocated arrays /// \brief Wrapper for dynamically sized and allocated arrays
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:----------:|:----------:| /// |:-----------:|:----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
@@ -62,15 +62,15 @@ namespace fennec
/// \tparam TypeT value type /// \tparam TypeT value type
template<class TypeT, class Alloc = allocator<TypeT>> template<class TypeT, class Alloc = allocator<TypeT>>
struct dynarray { struct dynarray {
public:
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public:
using value_t = TypeT; ///< Alias for the value type using value_t = TypeT; ///< Alias for the value type
using alloc_t = Alloc; ///< Alias for the allocator type using alloc_t = Alloc; ///< Alias for the allocator type
// Constructors ======================================================================================================== // Constructors ========================================================================================================
public:
/// \name Constructors & Destructor /// \name Constructors & Destructor
/// @{ /// @{
@@ -260,6 +260,7 @@ public:
/// @} /// @}
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public:
/// \name Properties /// \name Properties
/// @{ /// @{
@@ -322,6 +323,7 @@ public:
/// @} /// @}
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// \name Properties /// \name Properties
/// @{ /// @{
@@ -340,7 +342,7 @@ public:
/// ///
/// \returns True when there are no elements active, otherwise false /// \returns True when there are no elements active, otherwise false
constexpr bool empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -348,6 +350,7 @@ public:
// Element Access ====================================================================================================== // Element Access ======================================================================================================
public:
/// \name Access /// \name Access
/// @{ /// @{
@@ -358,7 +361,7 @@ public:
/// \returns A reference to the element at index \f$i\f$ /// \returns A reference to the element at index \f$i\f$
constexpr TypeT& operator[](size_t i) { constexpr TypeT& operator[](size_t i) {
assertd(i < _size, "Array Out of Bounds"); assertd(i < _size, "Array Out of Bounds");
return _alloc.data()[i]; return _alloc[i];
} }
/// ///
@@ -367,7 +370,7 @@ public:
/// \returns A const qualified reference to the element at index \f$i\f$ /// \returns A const qualified reference to the element at index \f$i\f$
constexpr const TypeT& operator[](size_t i) const { constexpr const TypeT& operator[](size_t i) const {
assertd(i < _size, "Array Out of Bounds"); assertd(i < _size, "Array Out of Bounds");
return _alloc.data()[i]; return _alloc[i];
} }
/// ///
@@ -394,10 +397,23 @@ public:
return this->operator[](size() - 1); return this->operator[](size() - 1);
} }
///
/// \returns A pointer to the underlying allocation
constexpr TypeT* data() {
return _alloc.data();
}
///
/// \returns A pointer to the underlying allocation
constexpr const TypeT* data() const {
return _alloc.data();
}
/// @} /// @}
// Modifiers =========================================================================================================== // Modifiers ===========================================================================================================
public:
/// \name Modifiers /// \name Modifiers
/// @{ /// @{
@@ -510,31 +526,47 @@ public:
/// \brief Resize the dynarray, invoking the default constructor for all new elements /// \brief Resize the dynarray, invoking the default constructor for all new elements
/// \param n The new size in elements /// \param n The new size in elements
constexpr void resize(size_t n) { constexpr void resize(size_t n) {
_reduce(n);
_alloc.creallocate(n); _alloc.creallocate(n);
while (_size < n) { for (size_t i = _size; i < n; ++i) {
emplace_back(); fennec::construct(&_alloc[i]);
} }
_size = n;
} }
/// ///
/// \brief Resize the dynarray, invoking the copy constructor for all new elements /// \brief Resize the dynarray, invoking the copy constructor for all new elements
/// \param n The new size in elements /// \param n The new size in elements
/// \param val The value to fill with /// \param val The value to fill with
///
/// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
constexpr void resize(size_t n, const TypeT& val) { constexpr void resize(size_t n, const TypeT& val) {
_reduce(n);
_alloc.creallocate(n); _alloc.creallocate(n);
while (_size < n) { for (size_t i = _size; i < n; ++i) {
emplace_back(val); fennec::construct(&_alloc[i], val);
} }
_size = n;
}
///
/// \brief Reserve the array, allocating new space without initialization
/// \param n The new capacity in elements
///
/// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
constexpr void reserve(size_t n) {
_reduce(n);
_alloc.creallocate(n);
} }
/// ///
/// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation. /// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation.
constexpr void clear() { constexpr void clear() {
while (_size > 0) { _reduce(0);
fennec::destruct(&_alloc[--_size]);
}
_alloc.deallocate(); _alloc.deallocate();
} }
@@ -542,6 +574,7 @@ public:
// Iteration =========================================================================================================== // Iteration ===========================================================================================================
public:
/// \name Iteration /// \name Iteration
/// @{ /// @{
@@ -567,13 +600,26 @@ public:
/// @} /// @}
// Private Members =====================================================================================================
private: private:
allocation<value_t, alloc_t> _alloc;
size_t _size;
// Private Helpers =====================================================================================================
private:
// helper to double the capacity of the allocation
constexpr void _grow() { constexpr void _grow() {
_alloc.creallocate(_alloc.capacity() * 2); _alloc.creallocate(_alloc.capacity() * 2);
} }
allocation<value_t, alloc_t> _alloc; // helper to destruct elements past n
size_t _size; constexpr void _reduce(size_t n) {
while (_size > n) {
fennec::destruct(&_alloc[--_size]);
}
}
}; };
} }

View File

@@ -39,6 +39,20 @@ namespace fennec
/// ///
/// \brief A struct capable of holding a single object of any type /// \brief A struct capable of holding a single object of any type
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | ⛔ |
/// | homogeneous | ⛔ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(1)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
struct generic { struct generic {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
@@ -114,6 +128,7 @@ public:
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// ///
/// \brief runtime type acquisition /// \brief runtime type acquisition
@@ -130,6 +145,7 @@ public:
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public:
/// ///
/// \brief copy assignment /// \brief copy assignment
@@ -169,7 +185,8 @@ public:
} }
// Utility ============================================================================================================= // Insertion & Deletion ================================================================================================
public:
/// ///
/// \brief emplace value /// \brief emplace value
@@ -195,6 +212,10 @@ public:
} }
} }
// Utility =============================================================================================================
public:
/// ///
/// \brief C++ 11 Swap Specification /// \brief C++ 11 Swap Specification
/// \param gen the generic to swap with /// \param gen the generic to swap with
@@ -223,10 +244,15 @@ public:
return static_cast<T>(*static_cast<U*>(_handle)); return static_cast<T>(*static_cast<U*>(_handle));
} }
// Members =============================================================================================================
private: private:
void* _handle; void* _handle;
manager_t _manage; manager_t _manage;
// Helpers =============================================================================================================
private:
template<typename T> template<typename T>
static void* _manage_impl(uint8_t op, void* hnd) { static void* _manage_impl(uint8_t op, void* hnd) {
static fennec::type t = type::get<T>(); static fennec::type t = type::get<T>();

View File

@@ -56,10 +56,10 @@ namespace fennec
/// ///
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:----------:|:----------:| /// |:-----------:|:----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
@@ -67,7 +67,7 @@ namespace fennec
/// | access | \f$O(1)\f$ | /// | access | \f$O(1)\f$ |
/// | find | \f$O(1)\f$ | /// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(N)\f$ | /// | deletion | \f$O(M)\f$ |
/// ///
/// Graphs contain vertices and edges. Graphs are either directed /// Graphs contain vertices and edges. Graphs are either directed
/// or undirected. This structure allows the creation of both directed and undirected edges. As /// or undirected. This structure allows the creation of both directed and undirected edges. As
@@ -160,7 +160,7 @@ public:
/// ///
/// \returns \f$true\f$ when there are no vertices in the graph, \f$false\f$ otherwise /// \returns \f$true\f$ when there are no vertices in the graph, \f$false\f$ otherwise
constexpr bool empty() const { constexpr bool is_empty() const {
return num_vertices() == 0; return num_vertices() == 0;
} }
@@ -229,7 +229,7 @@ public:
/// \param b The id of the second vertex /// \param b The id of the second vertex
/// \returns A pointer to the value stored in the edge, \f$nullptr\f$ if not found /// \returns A pointer to the value stored in the edge, \f$nullptr\f$ if not found
constexpr edge_t* operator[](size_t a, size_t b) { constexpr edge_t* operator[](size_t a, size_t b) {
if (empty()) { if (is_empty()) {
return nullptr; return nullptr;
} }
edge_t* it = _edge_map[a][b]; edge_t* it = _edge_map[a][b];
@@ -245,7 +245,7 @@ public:
/// \param b The id of the second vertex /// \param b The id of the second vertex
/// \returns A const-qualified pointer to the value stored in the edge, \f$nullptr\f$ if not found /// \returns A const-qualified pointer to the value stored in the edge, \f$nullptr\f$ if not found
constexpr const edge_t* operator[](size_t a, size_t b) const { constexpr const edge_t* operator[](size_t a, size_t b) const {
if (empty()) { if (is_empty()) {
return nullptr; return nullptr;
} }
const edge_t* it = _edge_map[a][b]; const edge_t* it = _edge_map[a][b];
@@ -261,7 +261,7 @@ public:
/// \returns A list containing all vertices \f$x\f$ with edges from \f$vertex\f$ to `x...` /// \returns A list containing all vertices \f$x\f$ with edges from \f$vertex\f$ to `x...`
list<size_t> outgoing(size_t vertex) { list<size_t> outgoing(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (const auto& it : _edge_map[vertex]) { for (const auto& it : _edge_map[vertex]) {
@@ -276,7 +276,7 @@ public:
/// \returns A list containing all vertices \f$x\f$ with edges from `x...` to \f$vertex\f$ /// \returns A list containing all vertices \f$x\f$ with edges from `x...` to \f$vertex\f$
list<size_t> incoming(size_t vertex) { list<size_t> incoming(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (size_t n = 0; n < _edge_map.size(); ++n) { for (size_t n = 0; n < _edge_map.size(); ++n) {
@@ -293,7 +293,7 @@ public:
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$ /// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
list<size_t> symmetric(size_t vertex) { list<size_t> symmetric(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (const auto& it : _edge_map[vertex]) { for (const auto& it : _edge_map[vertex]) {
@@ -314,7 +314,7 @@ public:
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$ /// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
list<size_t> undirected(size_t vertex) { list<size_t> undirected(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (const auto& it : _edge_map[vertex]) { for (const auto& it : _edge_map[vertex]) {
@@ -332,7 +332,7 @@ public:
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \returns A pointer to a map containing edges mapped from this vertex /// \returns A pointer to a map containing edges mapped from this vertex
const auto* edges(size_t vertex) { const auto* edges(size_t vertex) {
if (empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
return nullptr; return nullptr;
} }
return &_edge_map[vertex]; return &_edge_map[vertex];

View File

@@ -49,19 +49,22 @@ namespace fennec
/// following properties: /// following properties:
/// ///
/// | Property | Value | /// | Property | Value |
/// |:----------:|:----------:| /// |:-----------:|:----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
/// | linear | ✅ | /// | linear | ✅ |
/// | access | \f$O(1)\f$ | /// | access | \f$O(N)\f$ |
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | \f$O(N)\f$ | /// | insertion | \f$O(N)\f$ |
/// | deletion | \f$O(N)\f$ | /// | deletion | \f$O(N)\f$ |
/// ///
/// \note Access, Insertion, and Deletion are \f$O(N)\f$ using the index pattern,
/// using the iterator pattern yields \f$O(1)\f$ runtime.
///
/// \tparam TypeT value type /// \tparam TypeT value type
template<class TypeT, class Alloc = allocator<TypeT>> template<class TypeT, class Alloc = allocator<TypeT>>
struct list { struct list {
@@ -82,8 +85,13 @@ public:
class iterator; ///< Iterator type for forward iteration over the list class iterator; ///< Iterator type for forward iteration over the list
class const_iterator; ///< Iterator type for forward iteration over a constant list class const_iterator; ///< Iterator type for forward iteration over a constant list
private:
using table_t = dynarray<node, alloc_t>;
using freed_t = dynarray<size_t>;
// Constructors & Destructor =========================================================================================== // Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor /// \name Constructors & Destructor
/// @{ /// @{
@@ -127,6 +135,7 @@ public:
/// @} /// @}
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public:
/// \name Assignment /// \name Assignment
/// @{ /// @{
@@ -160,6 +169,7 @@ public:
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// \name Properties /// \name Properties
/// @{ /// @{
@@ -173,12 +183,12 @@ public:
/// ///
/// \returns The capacity of the list in elements. /// \returns The capacity of the list in elements.
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _table.capacity(); return _table.size();
} }
/// ///
/// \returns \f$true\f$ when the list is empty, \f$false\f$ otherwise. /// \returns \f$true\f$ when the list is empty, \f$false\f$ otherwise.
constexpr bool empty() const { constexpr bool is_empty() const {
return _root == npos; return _root == npos;
} }
@@ -186,6 +196,7 @@ public:
// Access ============================================================================================================== // Access ==============================================================================================================
public:
/// \name Access /// \name Access
/// @{ /// @{
@@ -248,6 +259,7 @@ public:
// Modifiers =========================================================================================================== // Modifiers ===========================================================================================================
public:
/// \name Modifiers /// \name Modifiers
/// @{ /// @{
@@ -259,7 +271,7 @@ public:
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(1)\f$ /// \details \f$O(1)\f$
constexpr size_t insert(const iterator& it, const value_t& x) { constexpr iterator insert(const iterator& it, const value_t& x) {
return this->_insert(it._n, x); return this->_insert(it._n, x);
} }
@@ -270,7 +282,7 @@ public:
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(1)\f$ /// \details \f$O(1)\f$
constexpr size_t insert(const iterator& it, value_t&& x) { constexpr iterator insert(const iterator& it, value_t&& x) {
return this->_insert(it._n, fennec::forward<value_t>(x)); return this->_insert(it._n, fennec::forward<value_t>(x));
} }
@@ -281,7 +293,7 @@ public:
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(N)\f$ /// \details \f$O(N)\f$
constexpr size_t insert(size_t i, const value_t& x) { constexpr iterator insert(size_t i, const value_t& x) {
assert(i <= size(), "Index out of Bounds"); assert(i <= size(), "Index out of Bounds");
size_t n = _walk(min(i, size_t(size() - 1))); size_t n = _walk(min(i, size_t(size() - 1)));
@@ -295,7 +307,7 @@ public:
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(N)\f$ /// \details \f$O(N)\f$
constexpr size_t insert(size_t i, value_t&& x) { constexpr iterator insert(size_t i, value_t&& x) {
assert(i <= size(), "Index out of Bounds"); assert(i <= size(), "Index out of Bounds");
size_t n = _walk(min(i, size_t(size() - 1))); size_t n = _walk(min(i, size_t(size() - 1)));
@@ -311,18 +323,31 @@ public:
/// ///
/// \details \f$O(N)\f$ /// \details \f$O(N)\f$
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace(size_t i, ArgsT&&...args) { constexpr iterator emplace(size_t i, ArgsT&&...args) {
assert(i <= size(), "Index out of Bounds"); assert(i <= size(), "Index out of Bounds");
size_t n = _walk(min(i, size_t(size() - 1))); size_t n = _walk(min(i, size_t(size() - 1)));
return this->_insert(n, fennec::forward<ArgsT>(args)...); return this->_insert(n, fennec::forward<ArgsT>(args)...);
} }
///
/// \brief Emplace Insertion
/// \tparam ArgsT Argument types
/// \param it Location to insert at
/// \param args Arguments to construct with
/// \returns The id of the inserted node
///
/// \details \f$O(N)\f$
template<typename...ArgsT>
constexpr iterator emplace(const iterator& it, ArgsT&&...args) {
return this->_insert(it._n, fennec::forward<ArgsT>(args)...);
}
/// ///
/// \brief Push Front Copy /// \brief Push Front Copy
/// \param x Value to copy /// \param x Value to copy
/// \returns The id of the inserted node /// \returns The id of the inserted node
constexpr size_t push_front(const value_t& x) { constexpr iterator push_front(const value_t& x) {
return this->_insert(_root, x); return this->_insert(_root, x);
} }
@@ -330,7 +355,7 @@ public:
/// \brief Push Front Move /// \brief Push Front Move
/// \param x Value to move /// \param x Value to move
/// \returns The id of the inserted node /// \returns The id of the inserted node
constexpr size_t push_front(value_t&& x) { constexpr iterator push_front(value_t&& x) {
return this->_insert(_root, fennec::forward<value_t>(x)); return this->_insert(_root, fennec::forward<value_t>(x));
} }
@@ -340,7 +365,7 @@ public:
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \returns The id of the inserted node /// \returns The id of the inserted node
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace_front(ArgsT&&...args) { constexpr iterator emplace_front(ArgsT&&...args) {
return this->_insert(_root, fennec::forward<ArgsT>(args)...); return this->_insert(_root, fennec::forward<ArgsT>(args)...);
} }
@@ -348,7 +373,7 @@ public:
/// \brief Push Back Copy /// \brief Push Back Copy
/// \param x Value to copy /// \param x Value to copy
/// \returns The id of the inserted node /// \returns The id of the inserted node
constexpr size_t push_back(const value_t& x) { constexpr iterator push_back(const value_t& x) {
return this->_insert(npos, x); return this->_insert(npos, x);
} }
@@ -356,7 +381,7 @@ public:
/// \brief Push Back Move /// \brief Push Back Move
/// \param x Value to move /// \param x Value to move
/// \returns The id of the inserted node /// \returns The id of the inserted node
constexpr size_t push_back(value_t&& x) { constexpr iterator push_back(value_t&& x) {
return this->_insert(npos, fennec::forward<value_t>(x)); return this->_insert(npos, fennec::forward<value_t>(x));
} }
@@ -366,7 +391,7 @@ public:
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \returns The id of the inserted node /// \returns The id of the inserted node
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace_back(ArgsT&&...args) { constexpr iterator emplace_back(ArgsT&&...args) {
return this->_insert(npos, fennec::forward<ArgsT>(args)...); return this->_insert(npos, fennec::forward<ArgsT>(args)...);
} }
@@ -383,7 +408,7 @@ public:
/// \brief Erase Element /// \brief Erase Element
/// \param it Location to Erase /// \param it Location to Erase
constexpr void erase(const iterator& it) { constexpr void erase(const iterator& it) {
_erase(it._n); this->_erase(it._n);
} }
/// ///
@@ -403,15 +428,16 @@ public:
constexpr void clear() { constexpr void clear() {
size_t i = _root; size_t i = _root;
while (i != npos) { while (i != npos) {
fennec::destruct(&_table[i]); _table[i].value = nullopt;
i = this->_next(i); i = this->_next(i);
} }
_table.deallocate(); _table.clear();
} }
/// @} /// @}
// ITERATOR ============================================================================================================ // Iterator ============================================================================================================
public:
/// \name Iteration /// \name Iteration
/// @{ /// @{
@@ -587,15 +613,19 @@ public:
} }
}; };
// Members =============================================================================================================
private: private:
allocation<node, alloc_t> _table; table_t _table;
dynarray<size_t> _freed; freed_t _freed;
size_t _root, _last, _size; size_t _root, _last, _size;
friend class iterator; friend class iterator;
// Helpers =============================================================================================================
private:
constexpr void _expand() { constexpr void _expand() {
_table.creallocate(fennec::max(_table.capacity(), size_t(1)) * 2); _table.resize(fennec::max(_table.size(), size_t(4)) * 2);
} }
struct node { struct node {
@@ -608,18 +638,6 @@ private:
, next(npos) { , next(npos) {
} }
constexpr node(size_t p, size_t n)
: value()
, prev(p)
, next(n) {
}
constexpr node(size_t p, size_t n, value_t&& val)
: value(fennec::forward<value_t>(val))
, prev(p)
, next(n) {
}
constexpr ~node() = default; constexpr ~node() = default;
constexpr void clear() { constexpr void clear() {
@@ -647,7 +665,7 @@ private:
} }
constexpr size_t _next_free() { constexpr size_t _next_free() {
if (not _freed.empty()) { if (not _freed.is_empty()) {
size_t n = _freed.back(); size_t n = _freed.back();
_freed.pop_back(); _freed.pop_back();
return n; return n;
@@ -656,20 +674,20 @@ private:
} }
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t _insert(size_t n, ArgsT&&...args) { constexpr iterator _insert(size_t n, ArgsT&&...args) {
if (size() == capacity()) { if (size() == capacity()) {
_expand(); _expand();
} }
size_t i = _next_free(); size_t i = _next_free();
++_size; ++_size;
fennec::construct(&_table[i].value, fennec::forward<ArgsT>(args)...); _table[i].value.emplace(fennec::forward<ArgsT>(args)...);
if (_root == npos) { if (_root == npos) {
_table[i].prev = npos; _table[i].prev = npos;
_table[i].next = npos; _table[i].next = npos;
_root = _last = i; _root = _last = i;
return i; return iterator(this, i);
} }
if (n == npos) { if (n == npos) {
@@ -677,20 +695,20 @@ private:
_table[i].prev = _last; _table[i].prev = _last;
_table[i].next = npos; _table[i].next = npos;
_last = i; _last = i;
return i; return iterator(this, i);
} }
_table[i].prev = _prev(n); _table[i].prev = _prev(n);
_table[i].next = n; _table[i].next = n;
_table[n].prev = i; _table[n].prev = i;
_root = n == _root ? i : _root; _root = n == _root ? i : _root;
return i; return iterator(this, i);
} }
constexpr void _erase(size_t n) { constexpr void _erase(size_t n) {
if (n == npos) return; if (n == npos) return;
fennec::destruct(&_table[n].value); _table[n].value = nullopt;
_freed.push_back(n); _freed.push_back(n);
--_size; --_size;

View File

@@ -59,19 +59,21 @@ namespace fennec
/// \brief Data Structure defining a mapping of \f$key\f$ \f$KeyT\f$ to \f$value\f$ \f$ValueT\f$ /// \brief Data Structure defining a mapping of \f$key\f$ \f$KeyT\f$ to \f$value\f$ \f$ValueT\f$
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:----------:|:----------:| /// |:-----------:|:----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ✅ | /// | distinct | ✅ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
/// | linear | | /// | linear | |
/// | access | \f$O(1)\f$ | /// | access | \f$O(1)\f$ |
/// | find | \f$O(1)\f$ | /// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// ///
/// \note These runtimes are amortized, in theory the worst case is \f$O(N)\f$, but that is highly improbable.
///
/// \tparam KeyT The Key Type /// \tparam KeyT The Key Type
/// \tparam ValueT The Value Type /// \tparam ValueT The Value Type
/// \tparam Hash The Hash to Use /// \tparam Hash The Hash to Use
@@ -146,7 +148,7 @@ public:
/// ///
/// \returns \f$true\f$ when there are no elements in the set, \f$false\f$ otherwise /// \returns \f$true\f$ when there are no elements in the set, \f$false\f$ otherwise
constexpr size_t empty() const { constexpr size_t is_empty() const {
return _set.size(); return _set.size();
} }

View File

@@ -40,6 +40,21 @@ namespace fennec
/// ///
/// \brief Struct which holds a pool of objects associated with ids /// \brief Struct which holds a pool of objects associated with ids
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ✅ |
/// | 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 The value type /// \tparam TypeT The value type
/// \tparam AllocT The allocator type /// \tparam AllocT The allocator type
template<typename TypeT, typename AllocT = allocator<TypeT>> template<typename TypeT, typename AllocT = allocator<TypeT>>
@@ -93,7 +108,7 @@ public:
/// ///
/// \returns \f$true\f$ when there are no objects in the pool, \f$false\f$ otherwise /// \returns \f$true\f$ when there are no objects in the pool, \f$false\f$ otherwise
constexpr bool empty() const { constexpr bool is_empty() const {
return size() == 0; return size() == 0;
} }
@@ -104,7 +119,7 @@ public:
/// \returns The id of the next inserted node /// \returns The id of the next inserted node
constexpr size_t next_id() const { constexpr size_t next_id() const {
size_t next = _size; size_t next = _size;
if (not _freed.empty()) { if (not _freed.is_empty()) {
next = _freed.front(); next = _freed.front();
} }
return next; return next;
@@ -429,7 +444,7 @@ private:
size_t _next_free() { size_t _next_free() {
size_t next = _size; size_t next = _size;
if (not _freed.empty()) { if (not _freed.is_empty()) {
next = _freed.front(); next = _freed.front();
_freed.pop_front(); _freed.pop_front();
} }

View File

@@ -52,6 +52,21 @@ constexpr nullopt_t nullopt_v = {};
/// ///
/// \brief Structure to hold an optional value. /// \brief Structure to hold an optional value.
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | ⛔ |
/// | homogeneous | ✅ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ⛔ |
/// | access | \f$O(1)\f$ |
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam T /// \tparam T
template<typename T> template<typename T>
struct optional { struct optional {
@@ -160,7 +175,7 @@ public:
/// ///
/// \returns \f$true\f$ when there is no held value, \f$false\f$ otherwise. /// \returns \f$true\f$ when there is no held value, \f$false\f$ otherwise.
constexpr bool empty() const { constexpr bool is_empty() const {
return not _set; return not _set;
} }

View File

@@ -42,6 +42,21 @@ namespace fennec
/// ///
/// \brief Struct for holding a pair of values /// \brief Struct for holding a pair of values
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | ⛔ |
/// | homogeneous | ⛔ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | ⛔ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
///
/// \tparam TypeT0 The type of the first value /// \tparam TypeT0 The type of the first value
/// \tparam TypeT1 The type of the second value /// \tparam TypeT1 The type of the second value
template<typename TypeT0, typename TypeT1> template<typename TypeT0, typename TypeT1>

View File

@@ -55,6 +55,21 @@ namespace fennec
/// ///
/// \brief a priority queue data structure implemented using a binary heap /// \brief a priority queue data structure implemented using a binary heap
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ✅ |
/// | distinct | ⛔ |
/// | ordered | ✅ |
/// | space | \f$O(N)\f$ |
/// | linear | ✅ |
/// | access | \f$O(1)\f$ |
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam ValueT The value type /// \tparam ValueT The value type
/// \tparam CompareT The compare type, defaults to `fennec::less` /// \tparam CompareT The compare type, defaults to `fennec::less`
/// \tparam AllocT The allocator type, defaults to `fennec::allocator` /// \tparam AllocT The allocator type, defaults to `fennec::allocator`
@@ -87,6 +102,7 @@ private:
// Constructors & Destructor =========================================================================================== // Constructors & Destructor ===========================================================================================
public: public:
/// ///
/// \brief default constructor /// \brief default constructor
/// \details initializes an empty queue /// \details initializes an empty queue
@@ -105,6 +121,7 @@ public:
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// ///
/// \returns the size of the queue /// \returns the size of the queue
@@ -120,12 +137,13 @@ public:
/// ///
/// \returns \f$true\f$ if the queue holds no elements /// \returns \f$true\f$ if the queue holds no elements
constexpr bool empty() const { constexpr bool is_empty() const {
return size() == 0; return size() == 0;
} }
// Access ============================================================================================================== // Access ==============================================================================================================
public:
/// ///
/// \returns the value at the front of the queue /// \returns the value at the front of the queue
@@ -135,6 +153,7 @@ public:
// Modifiers =========================================================================================================== // Modifiers ===========================================================================================================
public:
/// ///
/// \brief push a new key into the queue /// \brief push a new key into the queue
@@ -173,7 +192,9 @@ private:
alloc_t _table; alloc_t _table;
size_t _size; size_t _size;
// Helpers ============================================================================================================= // Helpers =============================================================================================================
private:
template<typename...ArgsT> template<typename...ArgsT>
constexpr void _insert(ArgsT&&...args) { constexpr void _insert(ArgsT&&...args) {

View File

@@ -43,6 +43,21 @@ namespace fennec
/// ///
/// \brief Rooted-Directed Tree /// \brief Rooted-Directed Tree
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ✅ |
/// | 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 Data type /// \tparam TypeT Data type
/// \tparam AllocT Allocator Type /// \tparam AllocT Allocator Type
template<typename TypeT, typename AllocT = allocator<TypeT>> template<typename TypeT, typename AllocT = allocator<TypeT>>
@@ -177,7 +192,7 @@ public:
/// ///
/// \returns \f$true\f$ when there are no nodes in the tree, \f$false\f$ otherwise /// \returns \f$true\f$ when there are no nodes in the tree, \f$false\f$ otherwise
constexpr bool empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -311,7 +326,7 @@ public:
/// \returns The next node id were \f$insert\f$ or \f$emplace\f$ to be called /// \returns The next node id were \f$insert\f$ or \f$emplace\f$ to be called
constexpr size_t next_id() const { constexpr size_t next_id() const {
size_t i = _size; size_t i = _size;
if (not _freed.empty()) { if (not _freed.is_empty()) {
i = _freed.front(); i = _freed.front();
} }
return i; return i;
@@ -365,7 +380,7 @@ public:
visit.push_front({ root, parent }); visit.push_front({ root, parent });
size_t res = npos; size_t res = npos;
while (not visit.empty()) { while (not visit.is_empty()) {
auto node = visit.front(); auto node = visit.front();
visit.pop_front(); visit.pop_front();
@@ -490,7 +505,7 @@ public:
visit.push_back(chd); visit.push_back(chd);
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -540,7 +555,7 @@ public:
visit.push_front(chd); visit.push_front(chd);
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -592,7 +607,7 @@ public:
} }
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -642,7 +657,7 @@ public:
} }
} }
if (not visit.empty()) { if (not visit.is_empty()) {
node = visit.front(); node = visit.front();
visit.pop_front(); visit.pop_front();
} else { } else {
@@ -669,7 +684,7 @@ private:
size_t _next_free() { size_t _next_free() {
size_t next = _size; size_t next = _size;
if (not _freed.empty()) { if (not _freed.is_empty()) {
next = _freed.front(); next = _freed.front();
_freed.pop_front(); _freed.pop_front();
} }
@@ -723,7 +738,7 @@ private:
constexpr void _erase(size_t i) { constexpr void _erase(size_t i) {
list<size_t> queue; list<size_t> queue;
queue.push_back(child(i)); queue.push_back(child(i));
while (not queue.empty()) { while (not queue.is_empty()) {
size_t n = queue.front(); queue.pop_front(); size_t n = queue.front(); queue.pop_front();
if (n == npos) continue; if (n == npos) continue;
queue.push_back(next(n)); queue.push_back(next(n));

View File

@@ -57,10 +57,10 @@ namespace fennec
/// This data-structure behaves like an ordered-set, but does not use pointers, instead storing the table in-array /// This data-structure behaves like an ordered-set, but does not use pointers, instead storing the table in-array
/// ///
/// | Property | Value | /// | Property | Value |
/// |:----------:|:---------------:| /// |:-----------:|:---------------:|
/// | stable | ✅ | /// | stable | ✅ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ✅ | /// | distinct | ✅ |
/// | ordered | ✅ | /// | ordered | ✅ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
@@ -282,7 +282,7 @@ public:
/// ///
/// \returns \f$true\f$ when there are no elements in the sequence, \f$false\f$ otherwise. /// \returns \f$true\f$ when there are no elements in the sequence, \f$false\f$ otherwise.
constexpr bool empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -414,7 +414,7 @@ public:
it._visit.push_front(next); it._visit.push_front(next);
} }
if (not it._visit.empty()) { if (not it._visit.is_empty()) {
it._node = it._visit.front(); it._node = it._visit.front();
it._visit.pop_front(); it._visit.pop_front();
} else { } else {
@@ -513,7 +513,7 @@ public:
it._visit.push_front(next); it._visit.push_front(next);
} }
if (not it._visit.empty()) { if (not it._visit.is_empty()) {
it._node = it._visit.front(); it._node = it._visit.front();
it._visit.pop_front(); it._visit.pop_front();
} else { } else {

View File

@@ -50,10 +50,10 @@ namespace fennec
/// This data-structure behaves like a set, but does not use pointers, instead storing the table in-array /// This data-structure behaves like a set, but does not use pointers, instead storing the table in-array
/// ///
/// | Property | Value | /// | Property | Value |
/// |:----------:|:----------:| /// |:-----------:|:----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ✅ | /// | distinct | ✅ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |
@@ -184,7 +184,7 @@ public:
/// ///
/// \returns \f$true\f$ when the set is empty, \f$false\f$ otherwise /// \returns \f$true\f$ when the set is empty, \f$false\f$ otherwise
constexpr bool empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }

View File

@@ -43,10 +43,10 @@ namespace fennec
/// \brief Tuple, holds a collection of values of different types /// \brief Tuple, holds a collection of values of different types
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:----------:|:-----------:| /// |:-----------:|:-----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogenous | ⛔ | /// | homogeneous | ⛔ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
/// | ordered | ⛔ | /// | ordered | ⛔ |
/// | space | \f$O(N)\f$ | /// | space | \f$O(N)\f$ |

View File

@@ -41,6 +41,21 @@ namespace fennec
/// ///
/// \brief A structure that represents a union between `TypesT...` /// \brief A structure that represents a union between `TypesT...`
/// \details
/// | Property | Value |
/// |:-----------:|:-----------:|
/// | stable | ✅ |
/// | dynamic | ⛔ |
/// | homogeneous | ⛔ |
/// | distinct | ⛔ |
/// | ordered | ⛔ |
/// | space | \f$O(N)\f$ |
/// | linear | ⛔ |
/// | access | \f$O(1)\f$ |
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
///
/// \tparam TypesT The types to hold in the variant /// \tparam TypesT The types to hold in the variant
template<typename...TypesT> template<typename...TypesT>
struct variant { struct variant {

View File

@@ -41,10 +41,18 @@ namespace fennec
/// ///
/// \brief simple version struct for drivers and systems /// \brief simple version struct for drivers and systems
struct version { struct version {
uint32_t major; //!< the major version uint32_t major = { 1 }; //!< the major version
uint32_t minor; //!< the minor version uint32_t minor = { 0 }; //!< the minor version
uint32_t patch; //!< the patch uint32_t patch = { 0 }; //!< the patch
string str; //!< string representation of the version string str = { string("") }; //!< string representation of the version
friend bool operator==(const version& lhs, const version& rhs) {
return lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch and lhs.str == rhs.str;
}
friend bool operator!=(const version& lhs, const version& rhs) {
return lhs.major != rhs.major or lhs.minor != rhs.minor or lhs.patch != rhs.patch or lhs.str != rhs.str;
}
}; };
} }

View File

@@ -191,7 +191,7 @@ public:
/// ///
/// \returns \f$true\f$ if the path is empty or points to root /// \returns \f$true\f$ if the path is empty or points to root
bool empty() { bool is_empty() {
size_t size = _str.size(); size_t size = _str.size();
if (size == 0) return true; if (size == 0) return true;
#if FENNEC_PLATFORM_WINDOWS #if FENNEC_PLATFORM_WINDOWS
@@ -221,7 +221,7 @@ public:
} }
return _str.substring(0, start); return _str.substring(0, start);
#else #else
size_t start = _str.size() - 1; size_t start = _str.size();
start = _str[start] == '/' ? start - 1 : start; start = _str[start] == '/' ? start - 1 : start;
return path(_str.substring(0, _str.rfind('/', start))); return path(_str.substring(0, _str.rfind('/', start)));
#endif #endif
@@ -243,9 +243,9 @@ public:
working = current(); working = current();
} }
while (not parse.empty()) { while (not parse.is_empty()) {
// Handle dots // Handle dots
while (not parse.empty() && parse._str[0] == '.') { while (not parse.is_empty() && parse._str[0] == '.') {
// Check for ".." // Check for ".."
if (parse._str[1] == '.') { if (parse._str[1] == '.') {
// ".." // ".."
@@ -265,7 +265,7 @@ public:
} }
} }
if (parse.empty()) break; if (parse.is_empty()) break;
// Push the path // Push the path
const size_t loc = parse._str.find('/'); const size_t loc = parse._str.find('/');

View File

@@ -188,7 +188,7 @@ public:
/// ///
/// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise /// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise
bool empty() { bool is_empty() {
return _handle == nullptr; return _handle == nullptr;
} }

View File

@@ -40,7 +40,6 @@
#include <fennec/rtti/enable.h> #include <fennec/rtti/enable.h>
#include <fennec/renderers/interface/forward.h> #include <fennec/renderers/interface/forward.h>
#include <fennec/renderers/interface/gfxresourcepool.h>
namespace fennec namespace fennec
{ {
@@ -49,8 +48,6 @@ class gfxcontext {
public: public:
using handle_t = uint32_t; using handle_t = uint32_t;
gfxresourcepool resources;
gfxcontext(display_server* display) gfxcontext(display_server* display)
: display(display) : display(display)
, version(0, 0, 0, string("")) { , version(0, 0, 0, string("")) {
@@ -65,7 +62,6 @@ public:
virtual gfxsurface* create_surface(window* window) = 0; virtual gfxsurface* create_surface(window* window) = 0;
virtual gfxpass* create_pass() = 0;
virtual const version& get_version() const { return version; }; virtual const version& get_version() const { return version; };
protected: protected:

View File

@@ -1,60 +0,0 @@
// =====================================================================================================================
// 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 gfxcontext.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
#define FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
#include <fennec/lang/types.h>
#include <fennec/string/string.h>
#include <fennec/renderers/interface/forward.h>
namespace fennec
{
///
/// \brief Defines an interface that holds a series of passes with one coherent objective
/// \details This represents the overarching renderer, and not any platform specific behaviour.
/// I.E. This acts as a proxy for creating API objects, but the behaviour of those objects
/// is defined elsewhere.
class gfxpass {
public:
gfxsubpass* add_subpass();
private:
};
class gfxsubpass {
};
}
#endif // FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H

View File

@@ -1,43 +0,0 @@
// =====================================================================================================================
// 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 gfxresourcepool.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_INTERFACE_GFXRESOURCEPOOL_H
#define FENNEC_RENDERERS_INTERFACE_GFXRESOURCEPOOL_H
namespace fennec
{
class gfxresourcepool {
};
}
#endif // FENNEC_RENDERERS_INTERFACE_GFXRESOURCEPOOL_H

View File

@@ -1,41 +0,0 @@
// =====================================================================================================================
// 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 gfxsubpass.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_INTERFACE_GFXSUBPASS_H
#define FENNEC_RENDERERS_INTERFACE_GFXSUBPASS_H
namespace fennec
{
}
#endif // FENNEC_RENDERERS_INTERFACE_GFXSUBPASS_H

View File

@@ -45,9 +45,6 @@ public:
: gfxcontext(display) { : gfxcontext(display) {
} }
/// \brief create a render pass
/// \returns a new render pass
gfxpass* create_pass() override;
private: private:
#ifndef FENNEC_DOXYGEN #ifndef FENNEC_DOXYGEN

View File

@@ -0,0 +1,210 @@
// =====================================================================================================================
// 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 instance.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_VULKAN_LIB_APP_INFO_H
#define FENNEC_RENDERERS_VULKAN_LIB_APP_INFO_H
#include <volk.h>
#include <fennec/core/version.h>
#include <fennec/string/cstring.h>
namespace fennec::vk
{
struct app_info : private VkApplicationInfo {
// Constructors & Destructor ===========================================================================================
public:
///
/// \brief Create a Vulkan application information structure
/// \param app_name the name of the application, this cstring must exist for the lifetime of this object
/// until a structure of type fennec::vk::instance is constructed
/// \param app_version the internal version of the application
/// \param engine_name the name of the engine, this cstring must exist for the lifetime of this object
/// until a structure of type fennec::vk::instance is constructed
/// \param engine_version the internal version of the engine
/// \param api_version the Vulkan API version to use, version::patch and version::str are ignored
/// \param ext a pointer to an extension structure, the object next points to must exist for the lifetime of this
/// object until a structure of type fennec::vk::instance is constructed
/// TODO: DEFINE EXTENSION STRUCTURE WRAPPERS
app_info(
const cstring& app_name = {}, const version& app_version = {},
const cstring& engine_name = {}, const version& engine_version = {},
const version& api_version = {},
void* ext = nullptr
) noexcept : VkApplicationInfo {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = ext,
.pApplicationName = app_name,
.applicationVersion = VK_MAKE_VERSION(app_version.major, app_version.minor, app_version.patch),
.pEngineName = engine_name,
.engineVersion = VK_MAKE_VERSION(engine_version.major, engine_version.minor, engine_version.patch),
.apiVersion = VK_MAKE_API_VERSION(0, api_version.major, api_version.minor, 0),
} {
}
///
/// \brief Copy Constructor
app_info(const app_info&) noexcept = default;
///
/// \brief Move Constructor
app_info(app_info&&) noexcept = default;
///
/// \brief Destructor
~app_info() noexcept = default;
// Assignment Operators ================================================================================================
public:
///
/// \brief Copy Assignment
app_info& operator=(const app_info&) noexcept = default;
///
/// \brief Move Assignment
app_info& operator=(app_info&&) noexcept = default;
// Implicit Conversions ================================================================================================
public:
///
operator VkApplicationInfo*() noexcept {
return this;
}
///
/// \brief Implicit Pointer Conversion
operator const VkApplicationInfo*() const noexcept {
return this;
}
// Properties ==========================================================================================================
public:
///
/// \returns A cstring containing the application name
cstring get_app_name() const {
return cstring(pApplicationName, strlen(pApplicationName));
}
///
/// \brief Set the application name
/// \param str A cstring containing the new name
void set_app_name(const cstring& str) {
pApplicationName = str;
}
///
/// \returns A version struct containing the application version
version get_app_version() const {
return version {
.major = VK_VERSION_MAJOR(applicationVersion),
.minor = VK_VERSION_MINOR(applicationVersion),
.patch = VK_VERSION_PATCH(applicationVersion)
};
}
///
/// \brief Set the engine version
/// \param ver A version struct containing the new version
void set_engine_version(const version& ver) {
engineVersion = VK_MAKE_VERSION(ver.major, ver.minor, ver.patch);
}
///
/// \returns A cstring containing the engine name
cstring get_engine_name() const { return cstring(pEngineName, strlen(pEngineName)); }
///
/// \brief Set the engine name
/// \param str A cstring containing the new name
void set_engine_name(const cstring& str) { pEngineName = str; }
///
/// \returns A version struct containing the engine version
version get_engine_version() const {
return version {
.major = VK_VERSION_MAJOR(engineVersion),
.minor = VK_VERSION_MINOR(engineVersion),
.patch = VK_VERSION_PATCH(engineVersion)
};
}
///
/// \brief Set the engine version
/// \param ver A version struct containing the new version
void set_engine_version(const version& ver) {
engineVersion = VK_MAKE_VERSION(ver.major, ver.minor, ver.patch);
}
///
/// \returns A version struct containing the Vulkan API version
version get_api_version() const {
return version {
.major = VK_API_VERSION_MAJOR(apiVersion),
.minor = VK_API_VERSION_MINOR(apiVersion)
};
}
///
/// \brief Set the Vulkan API version
/// \param ver A version struct containing the new version
void set_api_version(const version& ver) {
apiVersion = VK_MAKE_API_VERSION(0, ver.major, ver.minor, 0);
}
///
/// \brief Set the extension structure
/// \param ext A pointer to the new extension object
void set_extension(void* ext) {
pNext = ext;
}
///
/// \brief Clear the extension structure with \f$nullptr\f$
void set_extension(nullptr_t) {
pNext = nullptr;
}
// Private Members =====================================================================================================
private:
};
}
#endif // FENNEC_RENDERERS_VULKAN_LIB_APP_INFO_H

View File

@@ -0,0 +1,89 @@
// =====================================================================================================================
// 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 instance.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_VULKAN_LIB_INSTANCE_H
#define FENNEC_RENDERERS_VULKAN_LIB_INSTANCE_H
#include <volk.h>
#include <fennec/containers/dynarray.h>
#include <fennec/renderers/vulkan/lib/app_info.h>
namespace fennec::vk
{
struct instance {
public:
using create_flags = VkInstanceCreateFlags;
struct create_info : private VkInstanceCreateInfo {
public:
template<size_t LayersN, size_t ExtensionsN>
create_info(
create_flags flags, const app_info& info,
const cstring (&layers)[LayersN], const cstring (&extensions)[ExtensionsN],
void* ext
) : VkInstanceCreateInfo {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = ext,
.flags = flags,
.pApplicationInfo = info,
.enabledLayerCount = LayersN,
.ppEnabledLayerNames = nullptr,
.enabledExtensionCount = ExtensionsN,
.ppEnabledExtensionNames = nullptr,
} {
_layers.reserve(LayersN);
for (const auto& layer : layers) { _layers.push_back(layer); }
_extensions.reserve(ExtensionsN);
for (const auto& extension : extensions) { _extensions.push_back(extension); }
ppEnabledLayerNames = _layers.data();
ppEnabledExtensionNames = _extensions.data();
}
private:
dynarray<const char*> _layers;
dynarray<const char*> _extensions;
};
instance();
private:
VkInstance _handle;
};
}
#endif // FENNEC_RENDERERS_VULKAN_LIB_INSTANCE_H

View File

@@ -23,7 +23,6 @@ namespace fennec {
vkcontext::vkcontext(display_server* display) vkcontext::vkcontext(display_server* display)
: gfxcontext(display) { : gfxcontext(display) {
} }
vkcontext::~vkcontext() { vkcontext::~vkcontext() {

View File

@@ -40,15 +40,14 @@
namespace fennec namespace fennec
{ {
class vkcontext : gfxcontext { class vkcontext : public gfxcontext {
public: public:
vkcontext(display_server* display); vkcontext(display_server* display);
~vkcontext(); ~vkcontext();
bool is_valid() override; bool is_valid() override;
private: protected:
}; };
} // fennec } // fennec

View File

@@ -116,7 +116,7 @@ public:
typelist.resize(uuid * 2); typelist.resize(uuid * 2);
} }
if (typelist[uuid].empty()) { if (typelist[uuid].is_empty()) {
typelist[uuid] = fennec::forward<unique_ptr<type_data>>(_make_data<T>()); typelist[uuid] = fennec::forward<unique_ptr<type_data>>(_make_data<T>());
} }

View File

@@ -87,10 +87,10 @@ public:
/// \note If used with `::strlen`, the result should be incremented by 1 to include the null terminator /// \note If used with `::strlen`, the result should be incremented by 1 to include the null terminator
constexpr cstring(char* str, size_t n) constexpr cstring(char* str, size_t n)
: _str(str) : _str(str)
, _size(n - 1) , _size(n)
, _const(false) { , _const(false) {
if constexpr(not is_constant_evaluated()) { if constexpr(not is_constant_evaluated()) {
assert(_str[n - 1] == '\0', "Invalid NTBS."); assert(_str[n] == '\0', "Invalid NTBS.");
} }
} }
@@ -114,10 +114,10 @@ public:
/// \note If used with `::strlen`, the result should be incremented by 1 to include the null terminator /// \note If used with `::strlen`, the result should be incremented by 1 to include the null terminator
constexpr cstring(const char* str, size_t n) constexpr cstring(const char* str, size_t n)
: _cstr(str) : _cstr(str)
, _size(n - 1) , _size(n)
, _const(true) { , _const(true) {
if constexpr(not is_constant_evaluated()) { if constexpr(not is_constant_evaluated()) {
assert(_str[n - 1] == '\0', "Invalid NTBS."); assert(_str[n] == '\0', "Invalid NTBS.");
} }
} }
@@ -195,7 +195,7 @@ public:
return _size + 1; return _size + 1;
} }
constexpr bool empty() const { constexpr bool is_empty() const {
return _cstr == nullptr || _size == 0; return _cstr == nullptr || _size == 0;
} }

View File

@@ -188,7 +188,7 @@ public:
/// ///
/// \returns \f$true\f$ if the string contains no characters, \f$false\f$ otherwise. /// \returns \f$true\f$ if the string contains no characters, \f$false\f$ otherwise.
constexpr bool empty() const { constexpr bool is_empty() const {
return size() == 0; return size() == 0;
} }

View File

@@ -178,7 +178,7 @@ public:
/// \returns the size of the string including its null terminator, i.e. `(*str)[capacity() - 1] == '\0'` /// \returns the size of the string including its null terminator, i.e. `(*str)[capacity() - 1] == '\0'`
constexpr size_t capacity() const { return _size + 1; } constexpr size_t capacity() const { return _size + 1; }
constexpr bool empty() const { constexpr bool is_empty() const {
return _cstr == nullptr || _size == 0; return _cstr == nullptr || _size == 0;
} }

View File

@@ -181,7 +181,7 @@ public:
/// ///
/// \returns \f$true\f$ if the string contains no characters, \f$false\f$ otherwise. /// \returns \f$true\f$ if the string contains no characters, \f$false\f$ otherwise.
constexpr bool empty() const { constexpr bool is_empty() const {
return size() == 0; return size() == 0;
} }

View File

@@ -87,7 +87,7 @@ public:
return _data.capacity(); return _data.capacity();
} }
bool empty() const { bool is_empty() const {
return size() == 0; return size() == 0;
} }

View File

@@ -42,7 +42,7 @@ path path::current() {
if (getcwd(cstr, sizeof(cstr)) == nullptr) { if (getcwd(cstr, sizeof(cstr)) == nullptr) {
return path(""); return path("");
} }
return path(cstring(cstr, strlen(cstr) + 1)); return path(cstring(cstr, strlen(cstr)));
} }
path path::current(const path& path) { path path::current(const path& path) {

View File

@@ -30,7 +30,7 @@ void _assert_impl(const char* expr, size_t expr_l,
fennec::cstring(expr, expr_l), fennec::cstring(expr, expr_l),
fennec::cstring(file, file_l), line, fennec::cstring(file, file_l), line,
fennec::cstring(func, func_l), fennec::cstring(func, func_l),
fennec::cstring(desc, ::strlen(desc) + 1) fennec::cstring(desc, ::strlen(desc))
); );
if (halt) { if (halt) {

View File

@@ -112,7 +112,7 @@ void wayland_server::connect() {
#endif #endif
auto contexts = ctx_registry::get_type_list(); auto contexts = ctx_registry::get_type_list();
while (not contexts.empty()) { while (not contexts.is_empty()) {
const auto& ctx = contexts.front(); const auto& ctx = contexts.front();
gfx_context = unique_ptr(ctx.ctor(this)); gfx_context = unique_ptr(ctx.ctor(this));
@@ -125,7 +125,7 @@ void wayland_server::connect() {
} }
} }
assertf(not gfx_context.empty(), "Failed to create graphics context."); assertf(not gfx_context.is_empty(), "Failed to create graphics context.");
} }
void wayland_server::disconnect() { void wayland_server::disconnect() {
@@ -191,7 +191,7 @@ void wayland_server::_wl_registry_listen_global(void* data, wl_registry* reg, ui
}; };
wayland_server* server = static_cast<wayland_server*>(data); wayland_server* server = static_cast<wayland_server*>(data);
const cstring interface = cstring(name, strlen(name) + 1); const cstring interface = cstring(name, strlen(name));
if (interface == "wl_compositor") { if (interface == "wl_compositor") {
server->compositor = static_cast<wl_compositor*>(wl_registry_bind(reg, id, &wl_compositor_interface, version)); server->compositor = static_cast<wl_compositor*>(wl_registry_bind(reg, id, &wl_compositor_interface, version));

View File

@@ -44,7 +44,7 @@ void window_manager::initialize() {
display_server::entrylist_t display_servers = display_server::get_type_list(); display_server::entrylist_t display_servers = display_server::get_type_list();
// Find first valid server // Find first valid server
while (not display_servers.empty()) { while (not display_servers.is_empty()) {
display_server::entry it = display_servers.front(); display_server::entry it = display_servers.front();
display_servers.pop(); display_servers.pop();

View File

@@ -21,8 +21,5 @@
namespace fennec namespace fennec
{ {
gfxpass* glcontext::create_pass() {
return nullptr;
}
} }

View File

@@ -37,7 +37,7 @@ namespace fennec
scene_node* scene::operator[](const cstring& name) const { scene_node* scene::operator[](const cstring& name) const {
list<size_t> parse; list<size_t> parse;
parse.push_back(table_t::root); parse.push_back(table_t::root);
while (not parse.empty()) { while (not parse.is_empty()) {
size_t n = parse.front(); size_t n = parse.front();
if (_table[n]->name == name) { if (_table[n]->name == name) {
return _table[n].get(); return _table[n].get();
@@ -54,7 +54,7 @@ scene_node* scene::operator[](const cstring& name) const {
scene_node* scene::operator[](const string& name) const { scene_node* scene::operator[](const string& name) const {
list<size_t> parse; list<size_t> parse;
parse.push_back(table_t::root); parse.push_back(table_t::root);
while (not parse.empty()) { while (not parse.is_empty()) {
size_t n = parse.front(); size_t n = parse.front();
if (_table[n]->name == name) { if (_table[n]->name == name) {
return _table[n].get(); return _table[n].get();

View File

@@ -51,7 +51,7 @@ inline void fennec_test_containers_bintree() {
test.clear(); test.clear();
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
fennec_test_spacer(1); fennec_test_spacer(1);
@@ -98,7 +98,7 @@ inline void fennec_test_containers_bintree() {
test.clear(); test.clear();
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }

View File

@@ -42,7 +42,7 @@ inline void fennec_test_containers_deque() {
test.pop_back(); test.pop_back();
} }
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }
} }

View File

@@ -42,7 +42,7 @@ inline void fennec_test_containers_graph() {
test.erase(i); test.erase(i);
} }
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }

View File

@@ -39,11 +39,11 @@ inline void fennec_test_containers_list() {
assertf(test.insert(p, i) == i, "List Construct Test Failed."); assertf(test.insert(p, i) == i, "List Construct Test Failed.");
} }
while (test.empty() == false) { while (test.is_empty() == false) {
test.pop_back(); test.pop_back();
} }
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }

View File

@@ -42,7 +42,7 @@ inline void fennec_test_containers_object_pool() {
test.erase(i); test.erase(i);
} }
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }

View File

@@ -61,7 +61,7 @@ inline void fennec_test_containers_rdtree() {
test.erase(0); test.erase(0);
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
fennec_test_spacer(1); fennec_test_spacer(1);
@@ -108,7 +108,7 @@ inline void fennec_test_containers_rdtree() {
test.erase(0); test.erase(0);
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }

View File

@@ -66,7 +66,7 @@ inline void fennec_test_containers_sequence() {
test.erase(v); test.erase(v);
} }
fennec_test_run(test.empty(), true); fennec_test_run(test.is_empty(), true);
} }
} }

View File

@@ -91,7 +91,7 @@ inline void fennec_test_threading_test_mpscq_producer(mpscq<size_t>* queue, size
} }
inline void fennec_test_threading_test_mpscq_consumer(mpscq<size_t>* queue, atomic<size_t>* res, atomic<bool>* done) { inline void fennec_test_threading_test_mpscq_consumer(mpscq<size_t>* queue, atomic<size_t>* res, atomic<bool>* done) {
while (not done->load() or not queue->empty()) { while (not done->load() or not queue->is_empty()) {
unique_ptr<size_t> ptr = queue->pop(); unique_ptr<size_t> ptr = queue->pop();
if (ptr) { if (ptr) {
*res += *ptr; *res += *ptr;