Compare commits

..

2 Commits

Author SHA1 Message Date
ed381c4178 - More Documentation 2026-01-12 00:36:39 -05:00
450f725cab - More Documentation
- Updated Copyright
2026-01-06 19:48:28 -05:00
277 changed files with 6554 additions and 2641 deletions

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -91,6 +91,7 @@ fennec_add_sources(
include/fennec/core/system.h include/fennec/core/system.h
# SCENE ================================================================================================================ # SCENE ================================================================================================================
include/fennec/scene/scene.h source/scene/scene.cpp include/fennec/scene/scene.h source/scene/scene.cpp
include/fennec/scene/component.h include/fennec/scene/component.h
@@ -100,6 +101,7 @@ fennec_add_sources(
# RENDERERS ============================================================================================================ # RENDERERS ============================================================================================================
include/fennec/renderers/interface/forward.h include/fennec/renderers/interface/forward.h
@@ -107,6 +109,7 @@ fennec_add_sources(
include/fennec/renderers/interface/gfxsurface.h include/fennec/renderers/interface/gfxsurface.h
# CONTAINERS =========================================================================================================== # CONTAINERS ===========================================================================================================
include/fennec/containers/containers.h include/fennec/containers/containers.h
@@ -135,6 +138,7 @@ fennec_add_sources(
include/fennec/containers/detail/_tuple.h include/fennec/containers/detail/_tuple.h
# lang ================================================================================================================= # lang =================================================================================================================
include/fennec/lang/lang.h include/fennec/lang/lang.h
include/fennec/lang/metaprogramming.h include/fennec/lang/metaprogramming.h
@@ -191,6 +195,7 @@ fennec_add_sources(
include/fennec/rtti/detail/_type_name.h include/fennec/rtti/detail/_type_name.h
# MEMORY =============================================================================================================== # MEMORY ===============================================================================================================
include/fennec/memory/new.h source/memory/new.cpp include/fennec/memory/new.h source/memory/new.cpp
@@ -203,10 +208,13 @@ fennec_add_sources(
include/fennec/memory/detail/_ptr_traits.h include/fennec/memory/detail/_ptr_traits.h
# DEBUG ================================================================================================================ # DEBUG ================================================================================================================
source/debug/assert_impl.cpp source/debug/assert_impl.cpp
# MATH ================================================================================================================= # MATH =================================================================================================================
include/fennec/math/math.h include/fennec/math/math.h
@@ -236,7 +244,7 @@ fennec_add_sources(
include/fennec/math/ext/transform.h include/fennec/math/ext/transform.h
include/fennec/math/detail/_fwd.h include/fennec/math/detail/_forward.h
include/fennec/math/detail/_math.h include/fennec/math/detail/_math.h
include/fennec/math/detail/_matrix.h include/fennec/math/detail/_matrix.h
include/fennec/math/detail/_types.h include/fennec/math/detail/_types.h
@@ -287,14 +295,16 @@ fennec_add_sources(
include/fennec/interpret/tokenizer.h include/fennec/interpret/tokenizer.h
# PLATFORM =============================================================================================================
include/fennec/platform/interface/fwd.h # PLATFORM =============================================================================================================
include/fennec/platform/interface/forward.h
include/fennec/platform/interface/display_server.h include/fennec/platform/interface/display_server.h
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
include/fennec/platform/interface/window.h source/platform/interface/window.cpp include/fennec/platform/interface/window.h source/platform/interface/window.cpp
include/fennec/platform/window_manager.h source/platform/window_manager.cpp include/fennec/platform/window_manager.h source/platform/window_manager.cpp
# GRAPHICS ============================================================================================================= # GRAPHICS =============================================================================================================
) )
@@ -304,7 +314,7 @@ add_subdirectory(test)
add_library(fennec STATIC add_library(fennec STATIC
${FENNEC_SOURCES} ${FENNEC_SOURCES}
include/fennec/rtti/this_t.h
) )
add_dependencies(fennec metaprogramming fennec-dependencies) add_dependencies(fennec metaprogramming fennec-dependencies)
@@ -353,7 +363,7 @@ if(DOXYGEN_FOUND)
# Target for building docs # Target for building docs
add_custom_target(fennecdocs ALL add_custom_target(fennecdocs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT} COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT}
WORKING_DIRECTORY ${FENNEC_SOURCE_DIR} WORKING_DIRECTORY ${FENNEC_SOURCE_DIR}/include/
COMMAND ${CMAKE_COMMAND} -E copy ${FENNEC_SOURCE_DIR}/logo/raster.png COMMAND ${CMAKE_COMMAND} -E copy ${FENNEC_SOURCE_DIR}/logo/raster.png
${DOXY_OUTPUT_DIR}/logo/raster.png ${DOXY_OUTPUT_DIR}/logo/raster.png
COMMENT "Generating Doxygen Documentation" COMMENT "Generating Doxygen Documentation"

View File

@@ -78,6 +78,24 @@ fennec Standards:
* Most behaviours should be type independent. Specifically interactions with the core systems of the engine. * Most behaviours should be type independent. Specifically interactions with the core systems of the engine.
- Classes should have banners between each distinct group of definitions, with the access specifier on the following
line. E.G.
```c++
class foo {
// Definitions ============================
public:
using bar = int;
// Constructors & Destructor ==============
public:
foo();
~foo();
};
```
This helps significantly with readability, and it also serves to reduce bugs related to mistakes involving access
specifiers. E.G. in the example above, bar is changed to private, the constructors are still labeled public in the
case the person forgets to update the succeeding access specifiers.
<br><br> <br><br>
<a id="f1"></a> <a id="f1"></a>
@@ -134,18 +152,18 @@ is also a viable IDE but involves some extra setup.
### Dependencies ### Dependencies
| Dependency | Notes | | Dependency | Notes |
|-----------------------------------|----------------------------------------------------------------------------------------------------------| |------------------------------|----------------------------------------------------------------------------------------------------------|
| C/C++ Compiler | GCC/G++ is the compiler that fennec is designed around, however, Clang, MSVC, and MinGW may also be used | | C/C++ Compiler | GCC/G++ is the compiler that fennec is designed around, however, Clang, MSVC, and MinGW may also be used |
| CMake | The build manager used by the engine | | CMake | The build manager used by the engine |
| Volk <sup>[__*__](#opt)</sup> | The Vulkan loader Volk, includes necessary headers for Vulkan. | | Volk<sup>[*](#opt)</sup> | The Vulkan loader Volk, includes necessary headers for Vulkan. |
| A build system | Any build system will work, however, `build.sh` uses Ninja by default. | | A build system | Any build system will work, however, `build.sh` uses Ninja by default. |
| A memory debugger | Any memory debugger will work, however, `test.sh` uses Valgrind by default. | | A memory debugger | Any memory debugger will work, however, `test.sh` uses Valgrind by default. |
| Doxygen <sup>[__*__](#opt)</sup> | Doxygen is required for building the documentation for fennec. | | Doxygen<sup>[*](#opt)</sup> | Doxygen is required for building the documentation for fennec. |
| Graphviz <sup>[__*__](#opt)</sup> | Graphviz is a required dependency for Doxygen | | Graphviz<sup>[*](#opt)</sup> | Graphviz is a required dependency for Doxygen |
<a id="opt"></a> <a id="opt"></a>
<sup>[__*__](#opt)</sup> Optional Dependency <sup>[*](#opt)</sup> Optional Dependency
<br> <br>
@@ -162,6 +180,7 @@ build scripts to use another build manager, see the [CMake documentation for ava
using specific toolchains for specific platforms that necessitate this. The primary examples would be Android and iOS. using specific toolchains for specific platforms that necessitate this. The primary examples would be Android and iOS.
If you wish to build for Windows *and* Linux, your options are WSL or Dual Boot. I recommend Dual Boot over WSL. If you wish to build for Windows *and* Linux, your options are WSL or Dual Boot. I recommend Dual Boot over WSL.
<a id="git"></a>
#### Git #### Git
Install git dependencies with the following command: Install git dependencies with the following command:

View File

@@ -1,6 +1,6 @@
## ===================================================================================================================== ## =====================================================================================================================
## fennec, a free and open source game engine ## fennec, a free and open source game engine
## Copyright © 2025 Medusa Slockbower ## Copyright © 2025 - 2026 Medusa Slockbower
## ##
## This program is free software: you can redistribute it and/or modify ## 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 ## it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -20,6 +20,10 @@
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
fennec_add_definitions(
FENNEC_LONG_COMPILER_NAME="${CMAKE_CXX_COMPILER_ID} ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}"
)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set(FENNEC_COMPILER "GCC") set(FENNEC_COMPILER "GCC")
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake") include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -943,7 +943,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = "@PROJECT_SOURCE_DIR@/include" \ INPUT = "@PROJECT_SOURCE_DIR@/include/" \
"@PROJECT_SOURCE_DIR@/README.md" "@PROJECT_SOURCE_DIR@/README.md"
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
@@ -1050,7 +1050,8 @@ RECURSIVE = YES
EXCLUDE = "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/lib" \ EXCLUDE = "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/lib" \
"@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/libdecor" \ "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/libdecor" \
"@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/xkb/lib" "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/xkb/lib" \
"@PROJECT_SOURCE_DIR@/include/fennec/platform/opengl/glad"
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded # directories that are symbolic links (a Unix file system feature) are excluded
@@ -2403,7 +2404,7 @@ MACRO_EXPANSION = YES
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = YES EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES, the include files in the # If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found. # INCLUDE_PATH will be searched if a #include is found.
@@ -2418,7 +2419,7 @@ SEARCH_INCLUDES = YES
# RECURSIVE has no effect here. # RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES. # This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = INCLUDE_PATH = "@PROJECT_SOURCE_DIR@/include"
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the # patterns (like *.h and *.hpp) to filter out the header-files in the

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
# ====================================================================================================================== # ======================================================================================================================
# fennec, a free and open source game engine # fennec, a free and open source game engine
# Copyright © 2025 Medusa Slockbower # Copyright © 2025 - 2026 Medusa Slockbower
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file array.h /// \file fennec/containers/array.h
/// \brief A header containing the definition for a static/stack allocated array /// \brief A header containing the definition for a static/stack allocated array
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -45,7 +45,7 @@ namespace fennec
/// ///
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:-----------:|:-----------:| /// |:-----------:|:----------:|
/// | stable | ✅ | /// | stable | ✅ |
/// | dynamic | ⛔ | /// | dynamic | ⛔ |
/// | homogeneous | ✅ | /// | homogeneous | ✅ |
@@ -57,10 +57,11 @@ namespace fennec
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | ⛔ | /// | insertion | ⛔ |
/// | deletion | ⛔ | /// | deletion | ⛔ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam ValueT value type /// \tparam ValueT value type
/// \tparam ElemV number of elements /// \tparam N number of elements
template<typename ValueT, size_t ElemV> template<typename ValueT, size_t N>
struct array { struct array {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
@@ -69,21 +70,19 @@ public:
/// \name Definitions /// \name Definitions
/// @{ /// @{
using value_t = ValueT; ///< Alias for \f$ValueT\f$ using value_t = ValueT; //!< Alias for \f$ValueT\f$
/// @} /// @}
// Public Members ====================================================================================================== // Public Member Variables =============================================================================================
public: public:
/// \name Public Members /// \name Member Variables
/// @{ /// @{
/// value_t data[N]; //!< Backing c-style array handle
/// \brief backing c-style array handle
value_t data[ElemV];
/// @} /// @}
@@ -96,14 +95,22 @@ public:
/// @{ /// @{
/// ///
/// \brief returns the number of elements in the array /// \brief Returns the number of elements in the array.
/// \returns the number of elements in the array /// \returns \f$N\f$
[[nodiscard]] constexpr size_t size() const { return ElemV; } ///
/// \par Complexity
/// \f$O(1)\f$
///
[[nodiscard]] constexpr size_t size() const { return N; }
/// ///
/// \brief returns **true** when the array is empty /// \brief Returns \f$true\f$ when the array is empty
/// \return \f$ElemV == 0\f$ /// \returns \f$ElemV == 0\f$
[[nodiscard]] constexpr bool_t is_empty() const { return ElemV == 0; } ///
/// \par Complexity
/// \f$O(1)\f$
///
[[nodiscard]] constexpr bool_t is_empty() const { return N == 0; }
/// @} /// @}
@@ -120,58 +127,68 @@ public:
/// \param i index of the element to return /// \param i index of the element to return
/// \return reference to the requested element /// \return reference to the requested element
/// ///
/// \par Time-Complexity /// \par Complexity
/// Constant /// \f$O(1)\f$
/// ///
/// \par Space-Complexity
/// Constant
constexpr value_t& operator[](size_t i) { constexpr value_t& operator[](size_t i) {
assertd(i < ElemV, "Array Out of Bounds"); assertd(i < N, "Array Out of Bounds");
return data[i]; return data[i];
} }
/// ///
/// \brief access specified element /// \brief Indexed access
/// \details Returns a reference to the element at \c i /// \details Returns a reference to the element at \c i
/// \param i index of the element to return /// \param i index of the element to return
/// \return reference to the requested element /// \return reference to the requested element
/// ///
/// \par Time-Complexity /// \par Complexity
/// Constant /// \f$O(1)\f$
/// ///
/// \par Space-Complexity
/// Constant
constexpr const value_t& operator[](size_t i) const { constexpr const value_t& operator[](size_t i) const {
assertd(i < ElemV, "Array Out of Bounds"); assertd(i < N, "Array Out of Bounds");
return data[i]; return data[i];
} }
/// ///
/// \brief Access the first element /// \returns A reference to \f$data[0]\f$
/// \returns A reference to the element at `elements[0]` ///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& front() { constexpr value_t& front() {
return data[0]; return data[0];
} }
/// ///
/// \brief Const Access the first element /// \brief Access the first element
/// \returns A const-qualified reference to the element at `elements[0]` /// \returns A const-qualified reference to \f$data[0]\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& front() const { constexpr const value_t& front() const {
return data[0]; return data[0];
} }
/// ///
/// \brief Access the first element /// \returns A reference to \f$data[N - 1]\f$
/// \returns A reference to the element at `elements[ElemV - 1]` ///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& back() { constexpr value_t& back() {
return data[ElemV - 1]; return data[N - 1];
} }
/// ///
/// \brief Const Access the first element /// \brief Access the last element
/// \returns A const-qualified reference to the element at `elements[ElemV - 1]` /// \returns A const-qualified reference to \f$data[N - 1]\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& back() const { constexpr const value_t& back() const {
return data[ElemV - 1]; return data[N - 1];
} }
/// @} /// @}
@@ -186,14 +203,22 @@ public:
/// ///
/// \brief Checks if all elements in the arrays are equal /// \brief Checks if all elements in the arrays are equal
///
/// \par Complexity
/// \f$O(N)\f$
///
friend constexpr bool_t operator==(const array& lhs, const array& rhs) { friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
return array::_compare(lhs, rhs, make_index_metasequence<ElemV>{}); return array::_compare(lhs, rhs, make_index_metasequence<N>{});
} }
/// ///
/// \brief Checks if any element in the arrays is not equal /// \brief Checks if any element in the arrays is not equal
///
/// \par Complexity
/// \f$O(N)\f$
///
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) { friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
return not array::_compare(lhs, rhs, make_index_metasequence<ElemV>{}); return not array::_compare(lhs, rhs, make_index_metasequence<N>{});
} }
/// @} /// @}
@@ -206,39 +231,51 @@ public:
/// @{ /// @{
/// ///
/// \brief C++ Iterator Specification `begin()`
/// \returns A pointer to the first element of the array /// \returns A pointer to the first element of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t* begin() { constexpr value_t* begin() {
return data; return data;
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A pointer to one after the end of the array
constexpr value_t* end() {
return data + ElemV;
}
///
/// \brief Const C++ Iterator Specification `begin()`
/// \returns A const-qualified pointer to the first element of the array /// \returns A const-qualified pointer to the first element of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t* begin() const { constexpr const value_t* begin() const {
return data; return data;
} }
/// ///
/// \brief Const C++ Iterator Specification `end()` /// \returns A pointer to one after the end of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t* end() {
return data + N;
}
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns A const-qualified pointer to one after the end of the array /// \returns A const-qualified pointer to one after the end of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t* end() const { constexpr const value_t* end() const {
return data + ElemV; return data + N;
} }
/// @} /// @}
// Helpers ============================================================================================================= // Private 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

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,23 +17,24 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file bintree.h /// \file fennec/containers/bintree.h
/// \brief /// \brief A header containing the definition for an in-array binary tree.
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
#ifndef FENNEC_CONTAINERS_BINTREE_H #ifndef FENNEC_CONTAINERS_BINTREE_H
#define FENNEC_CONTAINERS_BINTREE_H #define FENNEC_CONTAINERS_BINTREE_H
#include <fennec/containers/dynarray.h> #include <fennec/containers/deque.h>
#include <fennec/containers/list.h> #include <fennec/containers/list.h>
#include <fennec/containers/optional.h> #include <fennec/containers/optional.h>
#include <fennec/containers/pair.h>
#include <fennec/containers/traversal.h> #include <fennec/containers/traversal.h>
#include <fennec/memory/allocator.h> #include <fennec/memory/allocator.h>
@@ -45,7 +46,7 @@ namespace fennec
/// ///
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:-----------:|:-----------:| /// |:-----------:|:----------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogeneous | ✅ | /// | homogeneous | ✅ |
@@ -57,6 +58,7 @@ namespace fennec
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypeT The data type /// \tparam TypeT The data type
/// \tparam AllocT An allocator class /// \tparam AllocT An allocator class
@@ -68,6 +70,7 @@ private:
struct node; struct node;
public: public:
/// \name Definitions /// \name Definitions
/// @{ /// @{
@@ -75,39 +78,20 @@ public:
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
///
/// \brief Enum representing node side relative to parent
enum side_ : bool {
side_left = false, //!< Left Side
side_right = true //!< Right Side
};
/// @} /// @}
friend class iterator; friend class iterator;
friend class const_iterator; friend class const_iterator;
private: private:
struct node {
value_t value;
size_t parent;
size_t child[2];
constexpr node()
: value()
, parent(npos), child{ npos, npos } {
}
template<typename...ArgsT>
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, parent(p), child{ l, r } {
}
constexpr ~node() {
parent = npos;
child[0] = npos;
child[1] = npos;
}
size_t& operator[](bool d) {
return child[d];
}
};
using table_t = allocation<node, alloc_t>; using table_t = allocation<node, alloc_t>;
using freed_t = list<size_t, alloc_t>; using freed_t = list<size_t, alloc_t>;
@@ -119,6 +103,12 @@ public:
/// ///
/// \brief Default Constructor, initializes an empty tree /// \brief Default Constructor, initializes an empty tree
///
/// \details The underlying allocation is not initialized.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bintree() constexpr bintree()
: _table() : _table()
, _freed() , _freed()
@@ -129,6 +119,12 @@ public:
/// ///
/// \brief Move Constructor, takes ownership of a tree /// \brief Move Constructor, takes ownership of a tree
/// \param tree The tree to take ownership of /// \param tree The tree to take ownership of
///
/// \details Takes ownership of the underlying allocation of \f$tree\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bintree(bintree&& tree) noexcept constexpr bintree(bintree&& tree) noexcept
: _table(fennec::move(tree._table)) : _table(fennec::move(tree._table))
, _freed(fennec::move(tree._freed)) , _freed(fennec::move(tree._freed))
@@ -139,15 +135,49 @@ public:
/// ///
/// \brief Copy Constructor, copies a tree /// \brief Copy Constructor, copies a tree
/// \param tree The tree to copy /// \param tree The tree to copy
///
/// \details Copies the contents of \f$tree\f$ into a new tree. Invokes copy constructor.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr bintree(const bintree& tree) constexpr bintree(const bintree& tree)
: _table(tree._table) : _table(tree._table.capacity())
, _freed(tree._freed) , _freed()
, _root(tree._root) , _root(nullid)
, _size(tree._size) { , _size(0) {
// Visitor for copying
struct {
bintree& self;
const bintree& target;
deque<pair<size_t, size_t>> stack;
uint8_t operator()(const value_t& x, size_t n) {
while (stack.back().second != target.parent(n)) {
stack.pop_back();
}
stack.emplace_back(self.insert(stack.back().first, target.side(n), x), n);
return traversal_control_continue;
}
} visitor = {
.self = *this,
.target = tree
};
tree.template traverse<pre_order>(
visitor, tree._root
);
} }
/// ///
/// \brief Destructor, clears the tree /// \brief Destructor, clears the tree
///
/// \details Clears the contents of \f$tree\f$. Invokes destructor.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~bintree() { constexpr ~bintree() {
clear(); clear();
} }
@@ -158,26 +188,45 @@ public:
// Properties ========================================================================================================== // Properties ==========================================================================================================
public: public:
/// \name Properties
/// @{
/// ///
/// \returns The number of elements in the tree /// \returns The number of elements in the tree
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \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.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
/// ///
/// \returns The capacity of the underlying allocation /// \returns The capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _table.capacity(); return _table.capacity();
} }
/// ///
/// \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$.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next_id() const { constexpr size_t next_id() const {
size_t i = _size; size_t i = _size;
if (not _freed.is_empty()) { if (not _freed.is_empty()) {
@@ -188,10 +237,16 @@ 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$.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t root() const { constexpr size_t root() const {
return _root; return _root;
} }
/// @}
// Navigation ========================================================================================================== // Navigation ==========================================================================================================
@@ -201,58 +256,79 @@ public:
/// @{ /// @{
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \returns The parent of node \f$i\f$ /// \returns The parent of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t parent(size_t i) const { constexpr size_t parent(size_t i) const {
return i == npos ? npos : _table[i].parent; return i == npos ? npos : _table[i].parent;
} }
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \returns The grandparent of node \f$i\f$ /// \returns The grandparent of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t grandparent(size_t i) const { constexpr size_t grandparent(size_t i) const {
return parent(parent(i)); return parent(parent(i));
} }
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \returns The left child of node \f$i\f$ /// \returns The left child of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t left(size_t i) const { constexpr size_t left(size_t i) const {
return i == npos ? npos : _table[i].child[false]; return i == npos ? npos : _table[i].child[false];
} }
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \returns The right child of node \f$i\f$ /// \returns The right child of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t right(size_t i) const { constexpr size_t right(size_t i) const {
return i == npos ? npos : _table[i].child[true]; return i == npos ? npos : _table[i].child[true];
} }
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \param dir The direction to go \f$true\f$ for right, \f$false\f$ for left /// \param dir The direction to go \f$true\f$ for right, \f$false\f$ for left
/// \returns The child in the direction specified by \f$dir\f$ /// \returns The child in the direction specified by \f$dir\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t child(size_t i, bool dir) const { constexpr size_t child(size_t i, bool dir) const {
return i == npos ? npos : _table[i].child[dir]; return i == npos ? npos : _table[i].child[dir];
} }
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \returns \f$true\f$ if \f$i\f$ is the right node of `parent(i)`, \f$false\f$ otherwise /// \returns \f$true\f$ if \f$i\f$ is the right node of \f$parent(i)\f$, \f$false\f$ otherwise
constexpr bool direction(size_t i) const { ///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool side(size_t i) const {
return i == npos ? false : i == right(_parent(i)); return i == npos ? false : i == right(_parent(i));
} }
/// ///
/// \brief \f$O(1)\f$
/// \param i The id of the node /// \param i The id of the node
/// \returns The id of the sibling of \f$i\f$ /// \returns The id of the sibling of \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t sibling(size_t i) const { constexpr size_t sibling(size_t i) const {
if (i == npos) { if (i == npos) {
return npos; return npos;
@@ -266,9 +342,12 @@ public:
} }
/// ///
/// \details \f$O(\log n)\f$
/// \param i The node id /// \param i The node id
/// \returns The depth of node \f$i\f$ /// \returns The depth of node \f$i\f$
///
/// \par Complexity
/// \f$O(\log n)\f$
///
constexpr size_t depth(size_t i) const { constexpr size_t depth(size_t i) const {
size_t d = 0; size_t d = 0;
while (i != npos) { while (i != npos) {
@@ -279,9 +358,12 @@ public:
} }
/// ///
/// \brief \f$O(\log n)\f$
/// \param i The node id /// \param i The node id
/// \returns The id of the left-most node of \f$i\f$ /// \returns The id of the left-most node of \f$i\f$
///
/// \par Complexity
/// \f$O(\log n)\f$
///
constexpr size_t left_most(size_t i) const { constexpr size_t left_most(size_t i) const {
if (i >= _table.size()) { if (i >= _table.size()) {
return npos; return npos;
@@ -293,9 +375,12 @@ public:
} }
/// ///
/// \brief \f$O(\log n)\f$
/// \param i The node id /// \param i The node id
/// \returns The id of the right-most node of \f$i\f$ /// \returns The id of the right-most node of \f$i\f$
///
/// \par Complexity
/// \f$O(\log n)\f$
///
constexpr size_t right_most(size_t i) const { constexpr size_t right_most(size_t i) const {
if (i >= _table.size()) { if (i >= _table.size()) {
return npos; return npos;
@@ -316,18 +401,25 @@ public:
/// @{ /// @{
/// ///
/// \details \f$O(1)\f$
/// \param i The node id /// \param i The node id
/// \returns \f$nullptr\f$ if node \f$i\f$ does not exist, otherwise, a pointer to the value of node \f$i\f$ /// \returns a reference to the value of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& operator[](size_t i) { constexpr value_t& operator[](size_t i) {
assertd(i < _table.size(), "Index out of bounds."); assertd(i < _table.size(), "Index out of bounds.");
return _table[i].value; return _table[i].value;
} }
/// ///
/// \details Const Access, \f$O(1)\f$ /// \details Node access
/// \param i The node id /// \param i The node id
/// \returns \f$nullptr\f$ if node \f$i\f$ does not exist, otherwise, a pointer to the value of node \f$i\f$ /// \returns a reference to the value of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& operator[](size_t i) const { constexpr const value_t& operator[](size_t i) const {
assertd(i < _table.size(), "Index out of bounds."); assertd(i < _table.size(), "Index out of bounds.");
return _table[i].value; return _table[i].value;
@@ -335,68 +427,90 @@ public:
/// @} /// @}
// Modifiers =========================================================================================================== // Modifiers ===========================================================================================================
public:
/// \name Modifiers /// \name Modifiers
/// @{ /// @{
/// ///
/// \brief Move Left Insertion, constructs a new node as the left child of \f$p\f$
/// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead /// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead
/// \param p The parent node /// \param p The parent node
/// \param val The object to move into the new node /// \param val The object to move into the new node
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_left(size_t p, value_t&& val) { constexpr size_t insert_left(size_t p, value_t&& val) {
return this->_insert_left(p, fennec::forward<value_t>(val)); return this->_insert_left(p, fennec::forward<value_t>(val));
} }
/// ///
/// \brief Copy Left Insertion, constructs a new node as the left child of \f$p\f$
/// \details If the left node of \f$p\f$ already exists, the copy assignment operator is used instead /// \details If the left node of \f$p\f$ already exists, the copy assignment operator is used instead
/// \param p The parent node /// \param p The parent node
/// \param val The object to copy to the new node /// \param val The object to copy to the new node
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_left(size_t p, const value_t& val) { constexpr size_t insert_left(size_t p, const value_t& val) {
return this->_insert_left(p, val); return this->_insert_left(p, val);
} }
/// ///
/// \brief Emplace Left Insertion, constructs a new node as the left child of \f$p\f$ /// \brief Left Insertion, constructs a new node as the left child of \f$p\f$
/// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead /// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead
/// \param p The parent node /// \param p The parent node
/// \param args The arguments to construct the new node with /// \param args The arguments to construct the new node with
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace_left(size_t p, ArgsT&&...args) { constexpr size_t emplace_left(size_t p, ArgsT&&...args) {
return this->_insert_left(p, fennec::forward<ArgsT>(args)...); return this->_insert_left(p, fennec::forward<ArgsT>(args)...);
} }
/// ///
/// \brief Move Right Insertion, constructs a new node as the right child of \f$p\f$
/// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead /// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead
/// \param p The parent node /// \param p The parent node
/// \param val The object to move into the new node /// \param val The object to move into the new node
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_right(size_t p, value_t&& val) { constexpr size_t insert_right(size_t p, value_t&& val) {
return this->_insert_right(p, fennec::forward<value_t>(val)); return this->_insert_right(p, fennec::forward<value_t>(val));
} }
/// ///
/// \brief Copy Right Insertion, constructs a new node as the right child of \f$p\f$
/// \details If the right node of \f$p\f$ already exists, the copy assignment operator is used instead /// \details If the right node of \f$p\f$ already exists, the copy assignment operator is used instead
/// \param p The parent node /// \param p The parent node
/// \param val The object to copy to the new node /// \param val The object to copy to the new node
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_right(size_t p, const value_t& val) { constexpr size_t insert_right(size_t p, const value_t& val) {
return this->_insert_right(p, val); return this->_insert_right(p, val);
} }
/// ///
/// \brief Emplace Right Insertion, constructs a new node as the right child of \f$p\f$ /// \brief Right Insertion, constructs a new node as the right child of \f$p\f$
/// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead /// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead
/// \param p The parent node /// \param p The parent node
/// \param args The arguments to construct the new node with /// \param args The arguments to construct the new node with
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace_right(size_t p, ArgsT&&...args) { constexpr size_t emplace_right(size_t p, ArgsT&&...args) {
return this->_insert_right(p, fennec::forward<ArgsT>(args)...); return this->_insert_right(p, fennec::forward<ArgsT>(args)...);
@@ -408,7 +522,11 @@ public:
/// \brief Perform a Tree Rotation at \f$i\f$ in the specified direction /// \brief Perform a Tree Rotation at \f$i\f$ in the specified direction
/// \param sub The root node for the rotation /// \param sub The root node for the rotation
/// \param dir The direction to rotate, \f$true\f$ for right, \f$false\f$ for left /// \param dir The direction to rotate, \f$true\f$ for right, \f$false\f$ for left
/// \returns the new root /// \returns the new root node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t rotate(size_t sub, bool dir) { constexpr size_t rotate(size_t sub, bool dir) {
if (sub == npos) { if (sub == npos) {
return npos; return npos;
@@ -434,41 +552,55 @@ public:
} }
/// ///
/// \brief Move Insertion, bool d, constructs a new node as the child of \f$p\f$
/// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead /// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead
/// \param p The parent node /// \param parent The parent node
/// \param d The direction to insert /// \param side The side to insert on
/// \param val The object to move into the new node /// \param val The object to move into the new node
/// \returns The id of the new node /// \returns The id of the new node
constexpr size_t insert(size_t p, bool d, value_t&& val) { ///
return this->_insert(p, d, fennec::forward<value_t>(val)); /// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, bool side, value_t&& val) {
return this->_insert(parent, side, fennec::forward<value_t>(val));
} }
/// ///
/// \brief Copy Insertion, bool d, constructs a new node as the child of \f$p\f$
/// \details If the child of \f$p\f$ already exists, the copy assignment operator is used instead /// \details If the child of \f$p\f$ already exists, the copy assignment operator is used instead
/// \param p The parent node /// \param parent The parent node
/// \param d The direction to insert /// \param side The side to insert on
/// \param val The object to copy to the new node /// \param val The object to copy to the new node
/// \returns The id of the new node /// \returns The id of the new node
constexpr size_t insert(size_t p, bool d, const value_t& val) { ///
return this->_insert(p, d, val); /// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, bool side, const value_t& val) {
return this->_insert(parent, side, val);
} }
/// ///
/// \brief Emplace Insertion, constructs a new node as the child of \f$p\f$ /// \brief Insertion, constructs a new node as the child of \f$p\f$
/// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead /// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead
/// \param p The parent node /// \param parent The parent node
/// \param d The direction to insert /// \param side The side to insert on
/// \param args The arguments to construct the new node with /// \param args The arguments to construct the new node with
/// \returns The id of the new node /// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace(size_t p, bool d, ArgsT&&...args) { constexpr size_t emplace(size_t parent, bool side, ArgsT&&...args) {
return this->_insert(p, d, fennec::forward<ArgsT>(args)...); return this->_insert(parent, side, fennec::forward<ArgsT>(args)...);
} }
/// ///
/// \brief Clears the tree, destroying all elements /// \brief Clears the tree, destroying all elements
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() { constexpr void clear() {
list<size_t> queue; list<size_t> queue;
@@ -499,19 +631,55 @@ public:
// Traversal =========================================================================================================== // Traversal ===========================================================================================================
/// \name Traversal
/// @{
///
/// \details
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a \f$size_t\f$ which contains the node's id.
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
///
/// \tparam OrderT The order with which to traverse the tree.
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object
/// \param i The node to start at
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i) {
OrderT order;
i = order(*this, i);
while (i != npos) {
uint8_t mode = traversal_control_continue;
if (_table[i].value) {
mode = visit(_table[i].value, i);
}
if (mode == traversal_control_break) {
break;
}
i = order[*this, i, mode];
}
}
/// ///
/// \brief Traverse the tree using a specified order and visiting functor /// \brief Traverse the tree using a specified order and visiting functor
/// ///
/// \details /// \details
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a `size_t` which contains the node's id. /// The visitor should accept a reference to a value of type \f$TypeT\f$ and a \f$size_t\f$ which contains the node's id.
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum /// The visitor should return one of the following values in the `fennec::traversal_control_` enum
/// ///
/// \tparam OrderT The order with which to traverse the tree. /// \tparam OrderT The order with which to traverse the tree.
/// \tparam VisitorT The visitor, should fulfill the signature `uint8_t visit(TypeT&, size_t)` /// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object /// \param visit The visiting object
/// \param i The node to start at /// \param i The node to start at
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename OrderT, typename VisitorT> template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i) { constexpr void traverse(VisitorT&& visit, size_t i) const {
OrderT order; OrderT order;
i = order(*this, i); i = order(*this, i);
while (i != npos) { while (i != npos) {
@@ -743,11 +911,15 @@ public:
} }
}; };
/// @}
// Iterator ============================================================================================================ // Iterator ============================================================================================================
/// \name Iteration
/// @{
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
/// \details Performs pre-order traversal /// \details Performs pre-order traversal
class iterator { class iterator {
@@ -837,7 +1009,7 @@ public:
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
/// \details Performs pre-order traversal /// \details Performs pre-order traversal
class const_iterator { class const_iterator {
@@ -913,38 +1085,58 @@ public:
/// ///
/// \returns an iterator at the first element in pre-order traversal /// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(\log N)\f$
///
iterator begin() { iterator begin() {
return iterator(this, _root); return iterator(this, _root);
} }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the first element in pre-order traversal /// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(\log N)\f$
///
const_iterator begin() const { const_iterator begin() const {
return iterator(this, _root); return iterator(this, _root);
} }
/// ///
/// \returns an iterator at the first element in pre-order traversal /// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(1)\f$
///
iterator end() { iterator end() {
return iterator(this, _root, nullid); return iterator(this, _root, nullid);
} }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator at the first element in pre-order traversal /// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(1)\f$
///
const_iterator end() const { const_iterator end() const {
return iterator(this, _root, nullid); return iterator(this, _root, nullid);
} }
// Fields ============================================================================================================== /// @}
// Private Member Variables ============================================================================================
private: private:
table_t _table; table_t _table;
freed_t _freed; freed_t _freed;
size_t _root, _size; size_t _root, _size;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
constexpr size_t _next_free() { constexpr size_t _next_free() {
size_t i = _size; size_t i = _size;
if (not _freed.is_empty()) { if (not _freed.is_empty()) {
@@ -952,7 +1144,7 @@ private:
_freed.pop_front(); _freed.pop_front();
} }
if (i >= _table.capacity()) { if (i >= _table.capacity()) {
_table.creallocate(2 * fennec::max(_table.capacity(), size_t(4))); _table.reallocate(2 * fennec::max(_table.capacity(), size_t(4)));
} }
++_size; ++_size;
return i; return i;
@@ -1040,6 +1232,35 @@ private:
bool d = i == _right(p); bool d = i == _right(p);
return _child(p, !d); return _child(p, !d);
} }
// Private Definitions =================================================================================================
private:
struct node {
value_t value;
size_t parent;
size_t child[2];
constexpr node()
: value()
, parent(npos), child{ npos, npos } {
}
template<typename...ArgsT>
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, parent(p), child{ l, r } {
}
constexpr ~node() {
parent = npos;
child[0] = npos;
child[1] = npos;
}
size_t& operator[](bool d) {
return child[d];
}
};
}; };
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file bitfield.h /// \file fennec/containers/bitfield.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -43,8 +43,8 @@ namespace fennec
/// ///
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:-----------:|:------------------------------:| /// |:-----------:|:----------:|
/// | stable | Elements cannot be referenced. | /// | stable | |
/// | dynamic | ⛔ | /// | dynamic | ⛔ |
/// | homogeneous | ✅ | /// | homogeneous | ✅ |
/// | distinct | ⛔ | /// | distinct | ⛔ |
@@ -55,6 +55,7 @@ namespace fennec
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | ⛔ | /// | insertion | ⛔ |
/// | deletion | ⛔ | /// | deletion | ⛔ |
/// | space | \f$O(N)\f$ |
/// ///
/// \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>
@@ -62,21 +63,41 @@ struct bitfield {
// Constants =========================================================================================================== // Constants ===========================================================================================================
public: public:
/// \name Constants
/// @{
static constexpr size_t bits = N; //!< The number of bits in the bitfield static constexpr size_t bits = N; //!< The number of bits in the bitfield
static constexpr size_t bytes = (N + 7) / 8; //!< The number of bytes that hold the bitfield static constexpr size_t bytes = (N + 7) / 8; //!< The number of bytes that hold the bitfield
/// @}
// Constructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
public: public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default constructor.
/// \details Initializes all bits with \f$0\f$.
///
/// \par Complexity
/// \f$O(N)\f$
/// ///
/// \brief default constructor, initializes with \f$0\f$
constexpr bitfield() constexpr bitfield()
: _bytes() { : _bytes() {
} }
/// ///
/// \brief boolean array constructor /// \brief Boolean array constructor.
/// \param arr An array of boolean values resembling each bit. /// \param arr An array of boolean values resembling each bit.
/// \details Initializes each bit with the respective boolean value in \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
explicit constexpr bitfield(const bool (&arr)[N]) explicit constexpr bitfield(const bool (&arr)[N])
: _bytes() { : _bytes() {
for (size_t i = 0; i < arr; ++i) { for (size_t i = 0; i < arr; ++i) {
@@ -85,8 +106,13 @@ public:
} }
/// ///
/// \brief index array constructor /// \brief Index array constructor.
/// \param arr An array of indices values resembling which bits to set. /// \param arr An array of indices.
/// \details Sets the bits of each index provided in \f$arr\f$.
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t I> template<size_t I>
explicit constexpr bitfield(const size_t (&arr)[I]) explicit constexpr bitfield(const size_t (&arr)[I])
: _bytes() { : _bytes() {
@@ -96,8 +122,13 @@ public:
} }
/// ///
/// \brief variadic array constructor /// \param args A set of indices.
/// \param args A set of indices values resembling which bits to set. /// \details This substitution assumes \f$ArgsT\ldots\f$ can be taken as an array of indices. <br>
/// Sets the bits of each index provided in \f$args\ldots\f$.
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr bitfield(ArgsT&&...args) constexpr bitfield(ArgsT&&...args)
: _bytes() { : _bytes() {
@@ -105,7 +136,15 @@ public:
} }
/// ///
/// \param args A set of boolean values resembling each bit. /// \brief Variadic array constructor
/// \param args A set of boolean values.
/// \details This substitution assumes \f$ArgsT\ldots\f$ can be taken as an array of booleans. <br>
/// Initializes each bit with the respective boolean in \f$args\ldots\f$. <br>
/// Does not necessitate the number of arguments be equal to the number of bits.
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...) template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
constexpr bitfield(ArgsT&&...args) constexpr bitfield(ArgsT&&...args)
: _bytes() { : _bytes() {
@@ -116,6 +155,10 @@ public:
/// ///
/// \brief copy constructor /// \brief copy constructor
/// \param bf bitfield to copy /// \param bf bitfield to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
bitfield(const bitfield& bf) bitfield(const bitfield& bf)
: _bytes(bf._bytes) { : _bytes(bf._bytes) {
} }
@@ -123,6 +166,10 @@ public:
/// ///
/// \brief move constructor /// \brief move constructor
/// \param bf bitfield to move /// \param bf bitfield to move
///
/// \par Complexity
/// \f$O(1)\f$
///
bitfield(bitfield&& bf) noexcept bitfield(bitfield&& bf) noexcept
: _bytes(bf._bytes) { : _bytes(bf._bytes) {
} }
@@ -131,22 +178,52 @@ public:
/// \brief destructor /// \brief destructor
constexpr ~bitfield() = default; constexpr ~bitfield() = default;
/// @}
// Assignment ==========================================================================================================
public:
/// \name Assignment Operators
/// @{
/// ///
/// \brief copy assignment /// \brief copy assignment
/// \param bf bitfield to copy /// \param bf bitfield to copy
/// \returns a reference to self /// \returns a reference to self
///
/// \par Complexity
/// \f$O(N)\f$
///
bitfield& operator=(const bitfield& bf) = default; bitfield& operator=(const bitfield& bf) = default;
/// ///
/// \brief move assignment /// \brief move assignment
/// \param bf bitfield to move /// \param bf bitfield to move
/// \returns a reference to self /// \returns a reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
bitfield& operator=(bitfield&& bf) noexcept = default; bitfield& operator=(bitfield&& bf) noexcept = default;
/// @}
// Access & Modifiers ==================================================================================================
public:
/// \name Access & Modifiers
/// @{
/// ///
/// \brief test a bit /// \brief test a bit
/// \param i the index of the bit /// \param i the index of the bit
/// \returns the value stored in the bit as a boolean /// \returns the value stored in the bit as a boolean
///
/// \par Complexity
/// \f$O(1)\f$
///
bool test(size_t i) const { bool test(size_t i) const {
assertd(i < bits, "Index out of Bounds!"); assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8; size_t b = i / 8;
@@ -157,6 +234,10 @@ public:
/// ///
/// \brief set a bit /// \brief set a bit
/// \param i the index of the bit /// \param i the index of the bit
///
/// \par Complexity
/// \f$O(1)\f$
///
void set(size_t i) { void set(size_t i) {
assertd(i < bits, "Index out of Bounds!"); assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8; size_t b = i / 8;
@@ -167,6 +248,10 @@ public:
/// ///
/// \brief clear a bit /// \brief clear a bit
/// \param i the index of the bit /// \param i the index of the bit
///
/// \par Complexity
/// \f$O(1)\f$
///
void clear(size_t i) { void clear(size_t i) {
assertd(i < bits, "Index out of Bounds!"); assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8; size_t b = i / 8;
@@ -177,6 +262,10 @@ public:
/// ///
/// \brief toggle a bit /// \brief toggle a bit
/// \param i the index of the bit /// \param i the index of the bit
///
/// \par Complexity
/// \f$O(1)\f$
///
void toggle(size_t i) { void toggle(size_t i) {
assertd(i < bits, "Index out of Bounds!"); assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8; size_t b = i / 8;
@@ -186,8 +275,12 @@ public:
/// ///
/// \brief store \f$v\f$ in bit \f$i\f$ /// \brief store \f$v\f$ in bit \f$i\f$
/// \param i /// \param i the index of the bit
/// \param v /// \param v the value to store
///
/// \par Complexity
/// \f$O(1)\f$
///
void store(size_t i, bool v) { void store(size_t i, bool v) {
assertd(i < bits, "Index out of Bounds!"); assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8; size_t b = i / 8;
@@ -198,15 +291,26 @@ public:
/// ///
/// \brief not operator /// \brief not operator
/// \returns a bitfield containing the bit-wise inverse /// \returns a bitfield containing the bit-wise inverse
///
/// \par Complexity
/// \f$O(N)\f$
///
bitfield operator~() const { bitfield operator~() const {
bitfield res = *this; bitfield res = *this;
res._inv_helper(make_index_metasequence_t<bytes>{}); res._inv_helper(make_index_metasequence_t<bytes>{});
return res; return res;
} }
/// @}
// Private Member Variables ============================================================================================
private: private:
array<uint8_t, bytes> _bytes; array<uint8_t, bytes> _bytes;
// Private Helpers =====================================================================================================
private:
template<size_t...I> template<size_t...I>
void _inv_helper(index_metasequence<I...>) { void _inv_helper(index_metasequence<I...>) {
((_bytes[I] = ~_bytes[I]), ...); ((_bytes[I] = ~_bytes[I]), ...);

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file containers.h /// \file fennec/containers/containers.h
/// \brief fennec containers library main header /// \brief fennec containers library main header
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -40,24 +40,25 @@
/// ///
/// \code #include <fennec/containers/containers.h> \endcode /// \code #include <fennec/containers/containers.h> \endcode
/// ///
/// \section Data Structure Properties /// \section fennec_containers_container_section_properties Container Properties
/// ///
/// | Property | Meaning | /// | Property | Meaning |
/// |:-----------:|:----------------------------------------------------------------------------------------------:| /// |:----------------|:-----------------------------------------------------------------------------------------------|
/// | stable | Any pointer reference to an element remains constant for the lifetime of the data structure. | /// | **stable** | Any pointer reference to an element remains constant for the lifetime of the container. |
/// | dynamic | Memory for this data structure is allocated on the heap. | /// | **dynamic** | Memory for this container is allocated on the heap. |
/// | homogeneous | The types of all elements are either identical, or inherit the same base type. | /// | **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. | /// | **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$ | /// | **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. | /// | **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. | /// | **linear** | Each element is sequential in terms of access. |
/// | access | The runtime of the access operators and functions, in big-O notation. | /// | **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. | /// | **find** | The runtime of finding an element in the container, in big-O notation. |
/// | insertion | The runtime of inserting an element in the data structure, in big-O notation. | /// | **insertion** | The runtime of inserting an element in the container, in big-O notation. |
/// | deletion | The runtime of erasing an element in the data structure, in big-O notation. | /// | **deletion** | The runtime of erasing an element in the container, in big-O notation. |
/// | **space** | The space complexity of the container. |
/// ///
/// ///
/// \section fennec_containers_cppstdlib C++ Standard Template Library /// \section fennec_containers_section_cppstdlib C++ Standard Template Library
/// ///
/// | Symbol | Implemented | Passed | /// | Symbol | Implemented | Passed |
/// |:----------------------------------------------------------------------------|:-----------:|:------:| /// |:----------------------------------------------------------------------------|:-----------:|:------:|
@@ -81,7 +82,7 @@
/// | \ref fennec::variant "fennec::variant" | 🚧 | 🚧 | /// | \ref fennec::variant "fennec::variant" | 🚧 | 🚧 |
/// ///
/// ///
/// \section fennec_containers_fennec fennec /// \section fennec_containers_section_fennec fennec
/// ///
/// | Symbol | Implemented | Passed | /// | Symbol | Implemented | Passed |
/// |:-------------------------|:-----------:|:------:| /// |:-------------------------|:-----------:|:------:|
@@ -90,7 +91,7 @@
/// | \ref fennec::rdtree | ✅ | ✅ | /// | \ref fennec::rdtree | ✅ | ✅ |
/// ///
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
#include <fennec/containers/traversal.h> #include <fennec/containers/traversal.h>

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file deque.h /// \file fennec/containers/deque.h
/// \brief A header containing the definition for a double-ended queue /// \brief A header containing the definition for a double-ended queue
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -59,34 +59,30 @@ namespace fennec
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypeT value type /// \tparam TypeT value type
template<typename TypeT, typename AllocT = allocator<TypeT>> template<typename TypeT, typename AllocT = allocator<TypeT>>
struct deque { struct deque {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public:
using value_t = TypeT; ///< Alias for the value type
class iterator;
private: private:
struct node { struct node;
value_t value;
node *prev, *next;
template<typename...ArgsT>
node(node* prev, node* next, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, prev(prev), next(next) {
}
~node() = default;
};
public: public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< Alias for the value type
using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The underlying allocator type using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The underlying allocator type
using elem_t = node*; //!< The underlying element type using elem_t = node*; //!< The underlying element type
/// @}
class iterator;
// Constructors ======================================================================================================== // Constructors ========================================================================================================
@@ -95,6 +91,10 @@ public:
/// ///
/// \brief Default Constructor, initializes an empty deque /// \brief Default Constructor, initializes an empty deque
///
/// \par Complexity
/// \f$O(1)\f$
///
deque() deque()
: _alloc() : _alloc()
, _first(nullptr) , _first(nullptr)
@@ -105,6 +105,10 @@ public:
/// ///
/// \brief Alloc Constructor, initializes an empty deque with the specified allocator /// \brief Alloc Constructor, initializes an empty deque with the specified allocator
/// \param alloc the allocator to copy /// \param alloc the allocator to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
deque(const alloc_t& alloc) deque(const alloc_t& alloc)
: _alloc(alloc) : _alloc(alloc)
, _first(nullptr) , _first(nullptr)
@@ -115,6 +119,10 @@ public:
/// ///
/// \brief Copy Constructor /// \brief Copy Constructor
/// \param deque the deque to copy /// \param deque the deque to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
deque(const deque& deque) deque(const deque& deque)
: _alloc(deque._alloc) : _alloc(deque._alloc)
, _first(nullptr) , _first(nullptr)
@@ -130,6 +138,10 @@ public:
/// ///
/// \brief Deque Move Constructor /// \brief Deque Move Constructor
/// \param deque the deque to move /// \param deque the deque to move
///
/// \par Complexity
/// \f$O(1)\f$
///
deque(deque&& deque) noexcept deque(deque&& deque) noexcept
: _alloc(deque._alloc) : _alloc(deque._alloc)
, _first(deque._first) , _first(deque._first)
@@ -141,6 +153,10 @@ public:
/// ///
/// \brief Destructor, calls deque::clear /// \brief Destructor, calls deque::clear
///
/// \par Complexity
/// \f$O(N)\f$
///
~deque() { ~deque() {
clear(); clear();
} }
@@ -154,12 +170,20 @@ 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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
/// ///
/// \returns the number of elements in size() /// \returns the number of elements in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
@@ -174,6 +198,10 @@ public:
/// ///
/// \returns a reference to the first element in the deque /// \returns a reference to the first element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
value_t& front() { value_t& front() {
assert(not is_empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _first->value; return _first->value;
@@ -181,6 +209,10 @@ public:
/// ///
/// \returns a const-qualified reference to the first element in the deque /// \returns a const-qualified reference to the first element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
const value_t& front() const { const value_t& front() const {
assert(not is_empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _first->value; return _first->value;
@@ -188,6 +220,10 @@ public:
/// ///
/// \returns a reference to the last element in the deque /// \returns a reference to the last element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
value_t& back() { value_t& back() {
assert(not is_empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _last->value; return _last->value;
@@ -195,6 +231,10 @@ public:
/// ///
/// \returns a const-qualified reference to the last element in the deque /// \returns a const-qualified reference to the last element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
const value_t& back() const { const value_t& back() const {
assert(not is_empty(), "Attempted to access an empty deque."); assert(not is_empty(), "Attempted to access an empty deque.");
return _last->value; return _last->value;
@@ -211,6 +251,10 @@ public:
/// ///
/// \brief Push Front Move, moves a value to the front of the deque /// \brief Push Front Move, moves a value to the front of the deque
/// \param elem the value to move /// \param elem the value to move
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_front(value_t&& elem) { void push_front(value_t&& elem) {
this->_push_front(elem); this->_push_front(elem);
} }
@@ -218,6 +262,10 @@ public:
/// ///
/// \brief Push Front Copy, copies a value to the front of the deque /// \brief Push Front Copy, copies a value to the front of the deque
/// \param elem the value to copy /// \param elem the value to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_front(const value_t& elem) { void push_front(const value_t& elem) {
this->_push_front(elem); this->_push_front(elem);
} }
@@ -226,6 +274,10 @@ public:
/// \brief Emplace Front, constructs a new value at the front of the deque /// \brief Emplace Front, constructs a new value at the front of the deque
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \param args Arguments used to construct the value /// \param args Arguments used to construct the value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
void emplace_front(ArgsT&&...args) { void emplace_front(ArgsT&&...args) {
this->_push_front(fennec::forward<ArgsT>(args)...); this->_push_front(fennec::forward<ArgsT>(args)...);
@@ -235,6 +287,10 @@ public:
/// ///
/// \brief Push Back Move, moves a value to the back of the deque /// \brief Push Back Move, moves a value to the back of the deque
/// \param elem the value to move /// \param elem the value to move
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_back(value_t&& elem) { void push_back(value_t&& elem) {
this->_push_back(elem); this->_push_back(elem);
} }
@@ -242,6 +298,10 @@ public:
/// ///
/// \brief Push Back Copy, copies a value to the back of the deque /// \brief Push Back Copy, copies a value to the back of the deque
/// \param elem the value to copy /// \param elem the value to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_back(const value_t& elem) { void push_back(const value_t& elem) {
this->_push_back(elem); this->_push_back(elem);
} }
@@ -250,6 +310,10 @@ public:
/// \brief Emplace Back, constructs a new value at the back of the deque /// \brief Emplace Back, constructs a new value at the back of the deque
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \param args Arguments used to construct the value /// \param args Arguments used to construct the value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
void emplace_back(ArgsT&&...args) { void emplace_back(ArgsT&&...args) {
this->_push_back(fennec::forward<ArgsT>(args)...); this->_push_back(fennec::forward<ArgsT>(args)...);
@@ -257,6 +321,10 @@ public:
/// ///
/// \brief Clears the contents of the deque /// \brief Clears the contents of the deque
///
/// \par Complexity
/// \f$O(N)\f$
///
void clear() { void clear() {
elem_t it = _first; elem_t it = _first;
while (it) { while (it) {
@@ -272,6 +340,10 @@ public:
/// ///
/// \brief Erase the First Element /// \brief Erase the First Element
///
/// \par Complexity
/// \f$O(1)\f$
///
void pop_front() { void pop_front() {
if (_first == nullptr) { if (_first == nullptr) {
return; return;
@@ -286,6 +358,10 @@ public:
/// ///
/// \brief Erase the Last Element /// \brief Erase the Last Element
///
/// \par Complexity
/// \f$O(1)\f$
///
void pop_back() { void pop_back() {
if (_last == nullptr) { if (_last == nullptr) {
return; return;
@@ -307,11 +383,16 @@ public:
* TODO: Decide whether you should be able to iterate over a deque * TODO: Decide whether you should be able to iterate over a deque
*/ */
// Private Member Variables ============================================================================================
private: private:
alloc_t _alloc; alloc_t _alloc;
node *_first, *_last; node *_first, *_last;
size_t _size; size_t _size;
// Private Helpers =====================================================================================================
private:
template<typename...ArgsT> template<typename...ArgsT>
void _push_front(ArgsT&&...args) { void _push_front(ArgsT&&...args) {
elem_t next = _first; elem_t next = _first;
@@ -337,6 +418,22 @@ private:
} }
++_size; ++_size;
} }
// Private Definitions =================================================================================================
private:
struct node {
value_t value;
node *prev, *next;
template<typename...ArgsT>
node(node* prev, node* next, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, prev(prev), next(next) {
}
~node() = default;
};
}; };

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file dynarray.h /// \file fennec/containers/dynarray.h
/// \brief A header containing the definition for a dynamically allocated array /// \brief A header containing the definition for a dynamically allocated array
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -56,6 +56,7 @@ namespace fennec
/// | 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$ |
/// | space | \f$O(N)\f$ |
/// ///
/// This structure prefers shallow moves and deep copies. /// This structure prefers shallow moves and deep copies.
/// ///
@@ -65,8 +66,14 @@ struct dynarray {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public: public:
using value_t = TypeT; ///< Alias for the value type
using alloc_t = Alloc; ///< Alias for the allocator type /// \name Definitions
/// @{
using value_t = TypeT; //!< Alias for the value type
using alloc_t = Alloc; //!< Alias for the allocator type
/// @}
// Constructors ======================================================================================================== // Constructors ========================================================================================================
@@ -77,6 +84,10 @@ public:
/// ///
/// \brief Default Constructor, initializes an empty allocation. /// \brief Default Constructor, initializes an empty allocation.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr dynarray() constexpr dynarray()
: _alloc(8) : _alloc(8)
, _size(0) { , _size(0) {
@@ -86,16 +97,11 @@ public:
/// \brief Alloc Constructor, initialize empty allocation with allocator instance. /// \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 /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
/// data. /// data.
explicit constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc)
, _size(0) {
}
/// ///
/// \brief Alloc Move Constructor, initialize empty allocation with allocator instance. /// \par Complexity
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some /// \f$O(1)\f$
/// data. ///
explicit constexpr dynarray(alloc_t&& alloc) noexcept explicit constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc) : _alloc(8, alloc)
, _size(0) { , _size(0) {
} }
@@ -103,6 +109,10 @@ public:
/// ///
/// \brief Sized Allocation, initializes a dynarray with \f$n\f$ elements using the default constructor. /// \brief Sized Allocation, initializes a dynarray with \f$n\f$ elements using the default constructor.
/// \param n The number of elements. /// \param n The number of elements.
///
/// \par Complexity
/// \f$O(N)\f$
///
explicit constexpr dynarray(size_t n) explicit constexpr dynarray(size_t n)
: _alloc(n) : _alloc(n)
, _size(n) , _size(n)
@@ -118,21 +128,11 @@ public:
/// using the default constructor. /// using the default constructor.
/// \param n The number of elements /// \param n The number of elements
/// \param alloc The allocator object to copy /// \param alloc The allocator object to copy
constexpr dynarray(size_t n, const alloc_t& alloc)
: _alloc(n, alloc)
, _size(n) {
value_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) {
fennec::construct(addr);
}
}
/// ///
/// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator \f$alloc\f$ and \f$n\f$ elements /// \par Complexity
/// using the default constructor. /// \f$O(N)\f$
/// \param n The number of elements ///
/// \param alloc The allocator object to copy constexpr dynarray(size_t n, const alloc_t& alloc)
constexpr dynarray(size_t n, alloc_t&& alloc)
: _alloc(n, alloc) : _alloc(n, alloc)
, _size(n) { , _size(n) {
value_t* addr = _alloc.data(); value_t* addr = _alloc.data();
@@ -146,6 +146,10 @@ public:
/// constructed using the copy constructor /// constructed using the copy constructor
/// \param n the number of elements /// \param n the number of elements
/// \param val the value to copy /// \param val the value to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(size_t n, const TypeT& val) constexpr dynarray(size_t n, const TypeT& val)
: _alloc(n) : _alloc(n)
, _size(n) { , _size(n) {
@@ -155,15 +159,15 @@ public:
} }
} }
// This constructor should not be invokable since moving is a single object operation and will cause undefined
// behaviour when moving to multiple elements
constexpr dynarray(size_t n, TypeT&& val) = delete;
/// ///
/// \brief Emplace Constructor /// \brief Emplace Constructor
/// \tparam ArgsT A sequence of argument types /// \tparam ArgsT A sequence of argument types
/// \param n The number of objects to create /// \param n The number of objects to create
/// \param args The arguments to create each object with /// \param args The arguments to create each object with
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr explicit dynarray(size_t n, ArgsT&&...args) constexpr explicit dynarray(size_t n, ArgsT&&...args)
: _alloc(n) : _alloc(n)
@@ -177,6 +181,10 @@ public:
/// \brief Array Copy Constructor /// \brief Array Copy Constructor
/// \tparam N The length of the array, automatically deduced /// \tparam N The length of the array, automatically deduced
/// \param arr The array to copy /// \param arr The array to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N> template<size_t N>
constexpr dynarray(const TypeT (&arr)[N]) constexpr dynarray(const TypeT (&arr)[N])
: _alloc(N) : _alloc(N)
@@ -190,6 +198,10 @@ public:
/// \brief Array Move Constructor /// \brief Array Move Constructor
/// \tparam N The length of the array, automatically deduced /// \tparam N The length of the array, automatically deduced
/// \param arr The array to move /// \param arr The array to move
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N> template<size_t N>
constexpr dynarray(TypeT (&&arr)[N]) constexpr dynarray(TypeT (&&arr)[N])
: _alloc(N) : _alloc(N)
@@ -200,10 +212,14 @@ public:
} }
/// ///
/// \brief Conversion Constructor, copies elements of conv as this `value_t` /// \brief Conversion Constructor, copies elements of conv as this \f$value_t\f$
/// \tparam OTypeT The other value type /// \tparam OTypeT The other value type
/// \tparam OAlloc The other allocator type /// \tparam OAlloc The other allocator type
/// \param conv The dynarray to convert /// \param conv The dynarray to convert
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename OTypeT, class OAlloc> template<typename OTypeT, class OAlloc>
constexpr dynarray(const dynarray<OTypeT, OAlloc>& conv) constexpr dynarray(const dynarray<OTypeT, OAlloc>& conv)
: _alloc(conv.size()) : _alloc(conv.size())
@@ -218,6 +234,10 @@ public:
/// \brief Initializer List Constructor /// \brief Initializer List Constructor
/// \param l List of elements to initialize with /// \param l List of elements to initialize with
/// \param alloc An allocator object to copy /// \param alloc An allocator object to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(initializer_list<value_t> l, const alloc_t& alloc = alloc_t()) constexpr dynarray(initializer_list<value_t> l, const alloc_t& alloc = alloc_t())
: _alloc(l.size(), alloc) : _alloc(l.size(), alloc)
, _size(l.size()) { , _size(l.size()) {
@@ -230,6 +250,10 @@ public:
/// ///
/// \brief Copy Constructor, uses the copy constructor to copy each element /// \brief Copy Constructor, uses the copy constructor to copy each element
/// \param arr the dynarray to copy /// \param arr the dynarray to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(const dynarray& arr) constexpr dynarray(const dynarray& arr)
: _alloc(arr._size) : _alloc(arr._size)
, _size(arr._size) { , _size(arr._size) {
@@ -241,6 +265,10 @@ public:
/// ///
/// \brief Move Constructor, takes ownership of the allocation /// \brief Move Constructor, takes ownership of the allocation
/// \param arr the dynarray to move /// \param arr the dynarray to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr dynarray(dynarray&& arr) noexcept constexpr dynarray(dynarray&& arr) noexcept
: _alloc(fennec::move(arr._alloc)) : _alloc(fennec::move(arr._alloc))
, _size(arr._size) { , _size(arr._size) {
@@ -249,6 +277,10 @@ public:
/// ///
/// \brief Default Destructor, destructs all elements and frees the underlying allocation /// \brief Default Destructor, destructs all elements and frees the underlying allocation
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~dynarray() { constexpr ~dynarray() {
value_t* addr = _alloc.data(); value_t* addr = _alloc.data();
if (addr == nullptr) return; if (addr == nullptr) return;
@@ -259,6 +291,13 @@ public:
/// @} /// @}
private:
// This constructor should not be invokable since moving is a single object operation and will cause undefined
// behaviour when moving to multiple elements
constexpr dynarray(size_t n, TypeT&& val) = delete;
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public: public:
@@ -269,9 +308,13 @@ public:
/// \brief Copy Assignment Operator /// \brief Copy Assignment Operator
/// \param arr the array to copy /// \param arr the array to copy
/// \returns A dynarray after having copied each element of \f$arr\f$ /// \returns A dynarray after having copied each element of \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray& operator=(const dynarray& arr) { constexpr dynarray& operator=(const dynarray& arr) {
this->clear(); this->clear();
_alloc.creallocate(_size = arr._size); _alloc.reallocate(_size = arr._size);
for (size_t i = 0; i < _size; ++i) { for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], fennec::copy(arr[i])); fennec::construct(&_alloc[i], fennec::copy(arr[i]));
} }
@@ -282,6 +325,10 @@ public:
/// \brief Move Assignment Operator /// \brief Move Assignment Operator
/// \param arr the array to move /// \param arr the array to move
/// \returns A dynarray after having taken ownership of the contents of \f$arr\f$ /// \returns A dynarray after having taken ownership of the contents of \f$arr\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr dynarray& operator=(dynarray&& arr) noexcept { constexpr dynarray& operator=(dynarray&& arr) noexcept {
this->clear(); this->clear();
_alloc = fennec::move(arr._alloc); _alloc = fennec::move(arr._alloc);
@@ -295,10 +342,14 @@ public:
/// \tparam N the length of the array /// \tparam N the length of the array
/// \param arr the array to copy /// \param arr the array to copy
/// \returns A dynarray after having copied each element of \f$arr\f$ /// \returns A dynarray after having copied each element of \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N> template<size_t N>
constexpr dynarray& operator=(const TypeT (&arr)[N]) { constexpr dynarray& operator=(const TypeT (&arr)[N]) {
this->clear(); this->clear();
_alloc.creallocate(_size = N); _alloc.reallocate(_size = N);
for (size_t i = 0; i < _size; ++i) { for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], fennec::copy(arr[i])); fennec::construct(&_alloc[i], fennec::copy(arr[i]));
} }
@@ -310,10 +361,14 @@ public:
/// \tparam N the length of the array /// \tparam N the length of the array
/// \param arr the array to copy /// \param arr the array to copy
/// \returns A dynarray after having moved each element of \f$arr\f$ /// \returns A dynarray after having moved each element of \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N> template<size_t N>
constexpr dynarray& operator=(TypeT (&&arr)[N]) { constexpr dynarray& operator=(TypeT (&&arr)[N]) {
this->clear(); this->clear();
_alloc.creallocate(_size = N); _alloc.reallocate(_size = N);
for (size_t i = 0; i < _size; ++i) { for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], fennec::move(arr[i])); fennec::construct(&_alloc[i], fennec::move(arr[i]));
} }
@@ -330,18 +385,30 @@ public:
/// ///
/// \returns The size of the dynarray in elements /// \returns The size of the dynarray in elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \returns The current capacity, in elements, of the underlying allocation /// \returns The current capacity, in elements, of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _alloc.capacity(); return _alloc.capacity();
} }
/// ///
/// \returns True when there are no elements active, otherwise false /// \returns True when there are no elements active, otherwise false
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -359,6 +426,10 @@ public:
/// \brief Array Access Operator /// \brief Array Access Operator
/// \param i The index to access /// \param i The index to access
/// \returns A reference to the element at index \f$i\f$ /// \returns A reference to the element at index \f$i\f$
///
/// \par Complexity
/// \f$O(1)\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[i]; return _alloc[i];
@@ -368,6 +439,10 @@ public:
/// \brief Array Access Operator (const) /// \brief Array Access Operator (const)
/// \param i The index to access /// \param i The index to access
/// \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$
///
/// \par Complexity
/// \f$O(1)\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[i]; return _alloc[i];
@@ -375,36 +450,60 @@ public:
/// ///
/// \returns Reference to the first element in the dynarray /// \returns Reference to the first element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT& front() { constexpr TypeT& front() {
return this->operator[](0); return this->operator[](0);
} }
/// ///
/// \returns A const-qualified reference to the first element in the dynarray /// \returns A const-qualified reference to the first element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT& front() const { constexpr const TypeT& front() const {
return this->operator[](0); return this->operator[](0);
} }
/// ///
/// \returns A reference to the last element in the dynarray /// \returns A reference to the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT& back() { constexpr TypeT& back() {
return this->operator[](size() - 1); return this->operator[](size() - 1);
} }
/// ///
/// \returns A const-qualified reference to the last element in the dynarray /// \returns A const-qualified reference to the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT& back() const { constexpr const TypeT& back() const {
return this->operator[](size() - 1); return this->operator[](size() - 1);
} }
/// ///
/// \returns A pointer to the underlying allocation /// \returns A pointer to the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT* data() { constexpr TypeT* data() {
return _alloc.data(); return _alloc.data();
} }
/// ///
/// \returns A pointer to the underlying allocation /// \returns A pointer to the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT* data() const { constexpr const TypeT* data() const {
return _alloc.data(); return _alloc.data();
} }
@@ -422,6 +521,10 @@ public:
/// \brief Move Insertion /// \brief Move Insertion
/// \param i index to insert at /// \param i index to insert at
/// \param val the value to initialize with /// \param val the value to initialize with
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void insert(size_t i, TypeT&& val) { constexpr void insert(size_t i, TypeT&& val) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
@@ -446,6 +549,10 @@ public:
/// \brief Copy Insertion /// \brief Copy Insertion
/// \param i index to insert at /// \param i index to insert at
/// \param val the value to initialize with /// \param val the value to initialize with
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void insert(size_t i, const TypeT& val) { constexpr void insert(size_t i, const TypeT& val) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
@@ -472,6 +579,10 @@ public:
/// \param i index to insert at /// \param i index to insert at
/// \param args Arguments to construct with /// \param args Arguments to construct with
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void emplace(size_t i, ArgsT&&...args) { constexpr void emplace(size_t i, ArgsT&&...args) {
@@ -496,6 +607,10 @@ public:
/// ///
/// \brief Push Back Copy /// \brief Push Back Copy
/// \param val Value to initialize with /// \param val Value to initialize with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void push_back(const TypeT& val) { constexpr void push_back(const TypeT& val) {
dynarray::insert(_size, val); dynarray::insert(_size, val);
} }
@@ -503,6 +618,10 @@ public:
/// ///
/// \brief Push Back Move /// \brief Push Back Move
/// \param val Value to initialize with /// \param val Value to initialize with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void push_back(TypeT&& val) { constexpr void push_back(TypeT&& val) {
dynarray::insert(_size, fennec::forward<TypeT>(val)); dynarray::insert(_size, fennec::forward<TypeT>(val));
} }
@@ -511,6 +630,10 @@ public:
/// \brief Emplace Back /// \brief Emplace Back
/// \tparam ArgsT Argument Types /// \tparam ArgsT Argument Types
/// \param args Arguments to construct with /// \param args Arguments to construct with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void emplace_back(ArgsT...args) { constexpr void emplace_back(ArgsT...args) {
dynarray::emplace(_size, fennec::forward<ArgsT>(args)...); dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
@@ -518,6 +641,10 @@ public:
/// ///
/// \brief Erase last element /// \brief Erase last element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void pop_back() { constexpr void pop_back() {
fennec::destruct(&_alloc[--_size]); fennec::destruct(&_alloc[--_size]);
} }
@@ -525,9 +652,15 @@ 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
///
/// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void resize(size_t n) { constexpr void resize(size_t n) {
_reduce(n); _reduce(n);
_alloc.creallocate(n); _alloc.reallocate(n);
for (size_t i = _size; i < n; ++i) { for (size_t i = _size; i < n; ++i) {
fennec::construct(&_alloc[i]); fennec::construct(&_alloc[i]);
@@ -542,9 +675,13 @@ public:
/// \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 /// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void resize(size_t n, const TypeT& val) { constexpr void resize(size_t n, const TypeT& val) {
_reduce(n); _reduce(n);
_alloc.creallocate(n); _alloc.reallocate(n);
for (size_t i = _size; i < n; ++i) { for (size_t i = _size; i < n; ++i) {
fennec::construct(&_alloc[i], val); fennec::construct(&_alloc[i], val);
@@ -558,13 +695,21 @@ public:
/// \param n The new capacity in elements /// \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 /// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void reserve(size_t n) { constexpr void reserve(size_t n) {
_reduce(n); _reduce(n);
_alloc.creallocate(n); _alloc.reallocate(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.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() { constexpr void clear() {
_reduce(0); _reduce(0);
_alloc.deallocate(); _alloc.deallocate();
@@ -581,26 +726,42 @@ public:
/// ///
/// \returns A pointer to the first element in the dynarray /// \returns A pointer to the first element in the dynarray
constexpr TypeT* begin() { return _alloc.data(); } ///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT* begin() { return _alloc; }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A const qualified pointer to the first element in the dynarray /// \returns A const qualified pointer to the first element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT* begin() const { return _alloc; } constexpr const TypeT* begin() const { return _alloc; }
/// ///
/// \return A pointer to the address after the last element in the dynarray /// \return A pointer to the address after the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT* end() { return begin() + _size; } constexpr TypeT* end() { return begin() + _size; }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \return A const qualified pointer to the address after the last element in the dynarray /// \return A const qualified pointer to the address after the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT* end() const { return begin() + _size; } constexpr const TypeT* end() const { return begin() + _size; }
/// @} /// @}
// Private Members ===================================================================================================== // Public Member Variables =============================================================================================
private: private:
allocation<value_t, alloc_t> _alloc; allocation<value_t, alloc_t> _alloc;
size_t _size; size_t _size;
@@ -611,7 +772,7 @@ private:
// helper to double the capacity of the allocation // helper to double the capacity of the allocation
constexpr void _grow() { constexpr void _grow() {
_alloc.creallocate(_alloc.capacity() * 2); _alloc.reallocate(_alloc.capacity() * 2);
} }
// helper to destruct elements past n // helper to destruct elements past n

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file generic.h /// \file fennec/containers/generic.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -53,6 +53,7 @@ namespace fennec
/// | find | ⛔ | /// | find | ⛔ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
struct generic { struct generic {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
@@ -68,11 +69,18 @@ private:
using manager_t = void* (*)(uint8_t, void*); using manager_t = void* (*)(uint8_t, void*);
// Constructors ======================================================================================================== // Constructors & Destructor ===========================================================================================
public: public:
/// \name Constructors & Destructor
/// @{
/// ///
/// \brief Default Constructor /// \brief Default Constructor
///
/// \par Complexity
/// \f$O(1)\f$
///
generic() generic()
: _handle(nullptr) : _handle(nullptr)
, _manage(nullptr) { , _manage(nullptr) {
@@ -81,6 +89,10 @@ public:
/// ///
/// \brief Copy Constructor /// \brief Copy Constructor
/// \param gen The generic object to copy /// \param gen The generic object to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
generic(const generic& gen) generic(const generic& gen)
: _handle(nullptr) : _handle(nullptr)
, _manage(gen._manage) { , _manage(gen._manage) {
@@ -92,6 +104,10 @@ public:
/// ///
/// \brief Move Constructor /// \brief Move Constructor
/// \param gen The generic object to move /// \param gen The generic object to move
///
/// \par Complexity
/// \f$O(1)\f$
///
generic(generic&& gen) generic(generic&& gen)
: _handle(gen._handle) : _handle(gen._handle)
, _manage(gen._manage) { , _manage(gen._manage) {
@@ -103,6 +119,10 @@ public:
/// \brief Value Constructor /// \brief Value Constructor
/// \tparam T The type of the value /// \tparam T The type of the value
/// \param x The value /// \param x The value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> template<typename T>
generic(T&& x) generic(T&& x)
: _handle(new T(fennec::forward<T>(x))) : _handle(new T(fennec::forward<T>(x)))
@@ -114,6 +134,10 @@ public:
/// \tparam T The type to construct /// \tparam T The type to construct
/// \tparam ArgsT The argument types /// \tparam ArgsT The argument types
/// \param args The argument values /// \param args The argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT> template<typename T, typename...ArgsT>
generic(type_identity<T>, ArgsT&&...args) generic(type_identity<T>, ArgsT&&...args)
: _handle(new T(fennec::forward<ArgsT>(args)...)) : _handle(new T(fennec::forward<ArgsT>(args)...))
@@ -126,31 +150,53 @@ public:
reset(); reset();
} }
/// @}
// Properties ========================================================================================================== // Properties ==========================================================================================================
public: public:
/// \name Properties
/// @{
/// ///
/// \brief runtime type acquisition /// \brief runtime type acquisition
/// \returns a runtime type struct referencing the held type /// \returns a runtime type struct referencing the held type
///
/// \par Complexity
/// \f$O(1)\f$
///
type type() const { type type() const {
return *static_cast<fennec::type*>(_manage(op_type, nullptr)); return *static_cast<fennec::type*>(_manage(op_type, nullptr));
} }
/// ///
/// \returns \f$true\f$ if there is a held value, \f$false\f$ otherwise /// \returns \f$true\f$ if there is a held value, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
bool has_value() const { bool has_value() const {
return _handle != nullptr; return _handle != nullptr;
} }
/// @}
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public: public:
/// \name Assignment Operators
/// @{
/// ///
/// \brief copy assignment /// \brief copy assignment
/// \param gen the generic to copy /// \param gen the generic to copy
/// \returns a reference to self after copying the contents of \f$gen\f$ /// \returns a reference to self after copying the contents of \f$gen\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
generic& operator=(const generic& gen) { generic& operator=(const generic& gen) {
if (this == &gen) { // self-assignment case if (this == &gen) { // self-assignment case
return *this; return *this;
@@ -166,6 +212,10 @@ public:
/// \brief move assignment /// \brief move assignment
/// \param gen the generic to move /// \param gen the generic to move
/// \returns a reference to self after swapping contents with \f$gen\f$ /// \returns a reference to self after swapping contents with \f$gen\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
generic& operator=(generic&& gen) noexcept { generic& operator=(generic&& gen) noexcept {
swap(gen); swap(gen);
return *this; return *this;
@@ -176,6 +226,10 @@ public:
/// \tparam T the type of the value /// \tparam T the type of the value
/// \param x the value to assign /// \param x the value to assign
/// \returns a reference to self after having assigned \f$x\f$ /// \returns a reference to self after having assigned \f$x\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> template<typename T>
generic& operator=(T&& x) { generic& operator=(T&& x) {
reset(); reset();
@@ -184,17 +238,26 @@ public:
return *this; return *this;
} }
/// @}
// Insertion & Deletion ================================================================================================
// Modifiers ===========================================================================================================
public: public:
/// \name Modifiers
/// @{
/// ///
/// \brief emplace value /// \brief emplace value
/// ///
/// \details constructs a new value of type \f$T\f$ using \f$args...\f$ /// \details constructs a new value of type \f$T\f$ using \f$args\ldots\f$
/// \tparam T the type to construct /// \tparam T the type to construct
/// \tparam ArgsT the argument types /// \tparam ArgsT the argument types
/// \param args the argument values /// \param args the argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT> template<typename T, typename...ArgsT>
void emplace(ArgsT&&...args) { void emplace(ArgsT&&...args) {
reset(); reset();
@@ -205,6 +268,10 @@ public:
/// ///
/// \brief reset value /// \brief reset value
/// \details clears the held value using the appropriate destructor /// \details clears the held value using the appropriate destructor
///
/// \par Complexity
/// \f$O(1)\f$
///
void reset() { void reset() {
if (_manage) { if (_manage) {
_handle = _manage(op_destroy, _handle); _handle = _manage(op_destroy, _handle);
@@ -212,46 +279,65 @@ 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
///
/// \par Complexity
/// \f$O(1)\f$
///
void swap(generic& gen) noexcept { void swap(generic& gen) noexcept {
fennec::swap(_handle, gen._handle); fennec::swap(_handle, gen._handle);
fennec::swap(_manage, gen._manage); fennec::swap(_manage, gen._manage);
} }
/// @}
// Casting =============================================================================================================
public:
/// \name Casting
/// @{
/// ///
/// \brief cast value /// \brief cast value
/// ///
/// \details equivalent to `reinterpret_cast` /// \details equivalent to \f$reinterpret_cast\f$
/// \tparam T The type to cast to /// \tparam T The type to cast to
/// \returns The contents of generic after having cast to \f$T\f$ /// \returns The contents of generic after having cast to \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename U = remove_cvref_t<T>> template<typename T, typename U = remove_cvref_t<T>>
T cast() { T cast() {
return static_cast<T>(*static_cast<U*>(_handle)); return static_cast<T>(*static_cast<U*>(_handle));
} }
/// ///
/// \details equivalent to `reinterpret_cast` /// \details equivalent to \f$reinterpret_cast\f$
/// \tparam T The type to cast to /// \tparam T The type to cast to
/// \returns The contents of generic after having cast to \f$T\f$ /// \returns The contents of generic after having cast to \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename U = remove_cvref_t<T>> template<typename T, typename U = remove_cvref_t<T>>
T cast() const { T cast() const {
return static_cast<T>(*static_cast<U*>(_handle)); return static_cast<T>(*static_cast<U*>(_handle));
} }
/// @}
// Members =============================================================================================================
// Private Member Variables ============================================================================================
private: private:
void* _handle; void* _handle;
manager_t _manage; manager_t _manage;
// Helpers ============================================================================================================= // Private Helpers =====================================================================================================
private: 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) {

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file graph.h /// \file fennec/containers/graph.h
/// \brief A header containing the definition for a graph of vertices connected by edges /// \brief A header containing the definition for a graph of vertices connected by edges
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -56,7 +56,7 @@ namespace fennec
/// ///
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:-----------:|:----------:| /// |:-----------:|:--------------:|
/// | stable | ⛔ | /// | stable | ⛔ |
/// | dynamic | ✅ | /// | dynamic | ✅ |
/// | homogeneous | ✅ | /// | homogeneous | ✅ |
@@ -68,6 +68,7 @@ namespace fennec
/// | find | \f$O(1)\f$ | /// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(M)\f$ | /// | deletion | \f$O(M)\f$ |
/// | space | \f$O(N + 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
@@ -80,10 +81,10 @@ namespace fennec
/// produce a connected graph. We will call this "disjointed" /// produce a connected graph. We will call this "disjointed"
/// ///
/// A directed graph is semi-connected if there is a directed path p for \f$u\f$ &rarr; \f$v\f$ *or* \f$v\f$ &rarr; \f$u\f$ for every /// A directed graph is semi-connected if there is a directed path p for \f$u\f$ &rarr; \f$v\f$ *or* \f$v\f$ &rarr; \f$u\f$ for every
/// pair of vertices `u, v`. We will call this "unilateral" /// pair of vertices \f$[u, v]\f$. We will call this "unilateral"
/// ///
/// A directed graph is strongly-connected if there is a directed path p for \f$u\f$ &rarr; \f$v\f$ *and* \f$v\f$ &rarr; \f$u\f$ for every pair /// A directed graph is strongly-connected if there is a directed path p for \f$u\f$ &rarr; \f$v\f$ *and* \f$v\f$ &rarr; \f$u\f$ for every pair
/// of vertices `u, v`. We will call this "connected" /// of vertices \f$[u, v]\f$. We will call this "connected"
/// ///
/// \tparam VertexT The type associated with each vertex /// \tparam VertexT The type associated with each vertex
/// \tparam EdgeT The type associated with each edge /// \tparam EdgeT The type associated with each edge
@@ -92,13 +93,24 @@ struct graph {
public: public:
// Definitions ========================================================================================================= // Definitions =========================================================================================================
using edge_t = EdgeT; ///< Alias for the edge type /// \name Definitions
using vertex_t = VertexT; ///< Alias for the vertex type /// @{
using vertex_pool_t = object_pool<vertex_t>; ///< Alias for a pool of vertices
using edge_map_t = dynarray<map<size_t, size_t>>; ///< Alias for edge mapping
using edge_pool_t = object_pool<edge_t>; ///< Alias for a pool of edges
static constexpr size_t npos = -1; ///< Constant for a non-existent vertex using edge_t = EdgeT; //!< Alias for the edge type
using vertex_t = VertexT; //!< Alias for the vertex type
using vertex_pool_t = object_pool<vertex_t>; //!< Alias for a pool of vertices
using edge_map_t = dynarray<map<size_t, size_t>>; //!< Alias for edge mapping
using edge_pool_t = object_pool<edge_t>; //!< Alias for a pool of edges
/// @}
/// \name Constants
/// @{
static constexpr size_t npos = -1; //!< Constant for a non-existent vertex
/// @}
// Constructors ======================================================================================================== // Constructors ========================================================================================================
@@ -108,10 +120,18 @@ public:
/// ///
/// \brief Default Constructor, initializes empty graph /// \brief Default Constructor, initializes empty graph
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr graph() = default; constexpr graph() = default;
/// ///
/// \brief Destructor /// \brief Destructor
///
/// \par Complexity
/// \f$O(N + M)\f$
///
constexpr ~graph() = default; constexpr ~graph() = default;
/// @} /// @}
@@ -124,12 +144,20 @@ public:
/// \brief Copy Assignment Operator /// \brief Copy Assignment Operator
/// \param g The graph to copy /// \param g The graph to copy
/// \returns A reference to this after assigning g /// \returns A reference to this after assigning g
///
/// \par Complexity
/// \f$O(N + M)\f$
///
constexpr graph& operator=(const graph& g) = default; constexpr graph& operator=(const graph& g) = default;
/// ///
/// \brief Move Assignment Operator /// \brief Move Assignment Operator
/// \param g The graph to copy /// \param g The graph to copy
/// \returns A reference to this after assigning g /// \returns A reference to this after assigning g
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr graph& operator=(graph&& g) = default; constexpr graph& operator=(graph&& g) = default;
/// @} /// @}
@@ -142,24 +170,40 @@ public:
/// ///
/// \returns The number of vertices in the graph /// \returns The number of vertices in the graph
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t num_vertices() const { constexpr size_t num_vertices() const {
return _vertex_pool.size(); return _vertex_pool.size();
} }
/// ///
/// \returns The number of edges in the graph /// \returns The number of edges in the graph
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t num_edges() const { constexpr size_t num_edges() const {
return _edge_pool.size(); return _edge_pool.size();
} }
/// ///
/// \returns The capacity of the vertex pool /// \returns The capacity of the vertex pool
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _vertex_pool.capacity(); return _vertex_pool.capacity();
} }
/// ///
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return num_vertices() == 0; return num_vertices() == 0;
} }
@@ -169,6 +213,10 @@ public:
/// \param a The first vertex /// \param a The first vertex
/// \param b The second vertex /// \param b The second vertex
/// \returns \f$true\f$ if the edge exists, \f$false\f$ otherwise /// \returns \f$true\f$ if the edge exists, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool exists(size_t a, size_t b) const { constexpr bool exists(size_t a, size_t b) const {
return _edge_map[a][b] != nullptr; return _edge_map[a][b] != nullptr;
} }
@@ -179,6 +227,10 @@ public:
/// \param a The first vertex /// \param a The first vertex
/// \param b The second vertex /// \param b The second vertex
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise /// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_symmetric(size_t a, size_t b) const { constexpr bool is_symmetric(size_t a, size_t b) const {
return exists(a, b) and exists(b, a); return exists(a, b) and exists(b, a);
} }
@@ -188,6 +240,10 @@ public:
/// \param a The first vertex /// \param a The first vertex
/// \param b The second vertex /// \param b The second vertex
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise /// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_undirected(size_t a, size_t b) const { constexpr bool is_undirected(size_t a, size_t b) const {
const auto* e0 = _edge_map[a][b]; const auto* e0 = _edge_map[a][b];
const auto* e1 = _edge_map[b][a]; const auto* e1 = _edge_map[b][a];
@@ -211,6 +267,10 @@ public:
/// \brief vertex Access Operator /// \brief vertex Access Operator
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \returns A reference to the value stored in the vertex /// \returns A reference to the value stored in the vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr vertex_t& operator[](size_t vertex) { constexpr vertex_t& operator[](size_t vertex) {
return _vertex_pool[vertex]; return _vertex_pool[vertex];
} }
@@ -219,6 +279,10 @@ public:
/// \brief vertex Const Access Operator /// \brief vertex Const Access Operator
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \returns A reference to the value stored in the vertex /// \returns A reference to the value stored in the vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const vertex_t& operator[](size_t vertex) const { constexpr const vertex_t& operator[](size_t vertex) const {
return _vertex_pool[vertex]; return _vertex_pool[vertex];
} }
@@ -228,6 +292,10 @@ public:
/// \param a The id of the first vertex /// \param a The id of the first vertex
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr edge_t* operator[](size_t a, size_t b) { constexpr edge_t* operator[](size_t a, size_t b) {
if (is_empty()) { if (is_empty()) {
return nullptr; return nullptr;
@@ -244,6 +312,10 @@ public:
/// \param a The id of the first vertex /// \param a The id of the first vertex
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
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 (is_empty()) { if (is_empty()) {
return nullptr; return nullptr;
@@ -256,9 +328,13 @@ public:
} }
/// ///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to `x...` /// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to \f$x\ldots\f$
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \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 \f$x\ldots\f$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> outgoing(size_t vertex) { list<size_t> outgoing(size_t vertex) {
list<size_t> res; list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
@@ -271,9 +347,13 @@ public:
} }
/// ///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge from `x...` /// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge from \f$x\ldots\f$
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \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 \f$x\ldots\f$ to \f$vertex\f$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> incoming(size_t vertex) { list<size_t> incoming(size_t vertex) {
list<size_t> res; list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
@@ -288,9 +368,13 @@ public:
} }
/// ///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from `x...` /// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x\ldots\f$
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \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$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> symmetric(size_t vertex) { list<size_t> symmetric(size_t vertex) {
list<size_t> res; list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
@@ -305,13 +389,17 @@ public:
} }
/// ///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from `x...` and share the same value /// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x\ldots\f$ and share the same value
/// \details /// \details
/// "Joined" edges may also be referred to as "undirected." A joined, or undirected, edge may be /// "Joined" edges may also be referred to as "undirected." A joined, or undirected, edge may be
/// turned into a directed edge by changing the weight object associated with the edge, or by /// turned into a directed edge by changing the weight object associated with the edge, or by
/// removing one of the sub-edges. /// removing one of the sub-edges.
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \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$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> undirected(size_t vertex) { list<size_t> undirected(size_t vertex) {
list<size_t> res; list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
@@ -331,6 +419,10 @@ public:
/// Use this when you want to iterate over edges that start from this vertex. /// Use this when you want to iterate over edges that start from this vertex.
/// \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
///
/// \par Complexity
/// \f$O(M)\f$
///
const auto* edges(size_t vertex) { const auto* edges(size_t vertex) {
if (is_empty() || vertex >= _edge_map.size()) { if (is_empty() || vertex >= _edge_map.size()) {
return nullptr; return nullptr;
@@ -350,6 +442,10 @@ public:
/// \brief Move a new vertex into the graph /// \brief Move a new vertex into the graph
/// \param vertex The vertex to move into the graph /// \param vertex The vertex to move into the graph
/// \returns The id of the new vertex /// \returns The id of the new vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(vertex_t&& vertex) { constexpr size_t insert(vertex_t&& vertex) {
return this->_insert(fennec::forward<vertex_t>(vertex)); return this->_insert(fennec::forward<vertex_t>(vertex));
} }
@@ -358,6 +454,10 @@ public:
/// \brief Copy a new vertex into the graph /// \brief Copy a new vertex into the graph
/// \param vertex The vertex to copy into the graph /// \param vertex The vertex to copy into the graph
/// \returns The id of the new vertex /// \returns The id of the new vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(const vertex_t& vertex) { constexpr size_t insert(const vertex_t& vertex) {
return this->_insert(vertex); return this->_insert(vertex);
} }
@@ -367,6 +467,10 @@ public:
/// \tparam ArgsT The types of the arguments /// \tparam ArgsT The types of the arguments
/// \param args The arguments to construct the vertex with /// \param args The arguments to construct the vertex with
/// \returns The id of the new vertex /// \returns The id of the new vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace(ArgsT&&...args) { constexpr size_t emplace(ArgsT&&...args) {
return this->_insert(fennec::forward<ArgsT>(args)...); return this->_insert(fennec::forward<ArgsT>(args)...);
@@ -375,6 +479,10 @@ public:
/// ///
/// \brief Erase a vertex from the graph /// \brief Erase a vertex from the graph
/// \param vertex The id of the vertex to erase /// \param vertex The id of the vertex to erase
///
/// \par Complexity
/// \f$O(M)\f$
///
constexpr void erase(size_t vertex) { constexpr void erase(size_t vertex) {
cut(vertex); cut(vertex);
_vertex_pool.erase(vertex); _vertex_pool.erase(vertex);
@@ -386,6 +494,10 @@ public:
/// \param a The first vertex id /// \param a The first vertex id
/// \param b The second vertex id /// \param b The second vertex id
/// \param args The arguments to construct the edge with /// \param args The arguments to construct the edge with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void make_edge(size_t a, size_t b, ArgsT&&...args) { constexpr void make_edge(size_t a, size_t b, ArgsT&&...args) {
if (a == b) { if (a == b) {
@@ -413,6 +525,10 @@ public:
/// \param a The first vertex id /// \param a The first vertex id
/// \param b The second vertex id /// \param b The second vertex id
/// \param args The arguments to construct the edge with /// \param args The arguments to construct the edge with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void make_edge2(size_t a, size_t b, ArgsT&&...args) { constexpr void make_edge2(size_t a, size_t b, ArgsT&&...args) {
if (a == b) { if (a == b) {
@@ -440,6 +556,10 @@ public:
/// \brief Disconnect an edge from vertex \f$a\f$ to vertex \f$b\f$ /// \brief Disconnect an edge from vertex \f$a\f$ to vertex \f$b\f$
/// \param a The first vertex id /// \param a The first vertex id
/// \param b The second vertex id /// \param b The second vertex id
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void cut_edge(size_t a, size_t b) { constexpr void cut_edge(size_t a, size_t b) {
// Find the edge object // Find the edge object
@@ -463,6 +583,10 @@ public:
/// \brief Disconnect both directed edges between vertices \f$a\f$ and \f$b\f$ /// \brief Disconnect both directed edges between vertices \f$a\f$ and \f$b\f$
/// \param a The first vertex id /// \param a The first vertex id
/// \param b The second vertex id /// \param b The second vertex id
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void cut_edge2(size_t a, size_t b) { constexpr void cut_edge2(size_t a, size_t b) {
const auto* ita = _edge_map[a][b]; const auto* ita = _edge_map[a][b];
const auto* itb = _edge_map[a][b]; const auto* itb = _edge_map[a][b];
@@ -476,8 +600,12 @@ public:
} }
/// ///
/// \brief Break *all* edges to and from \f$n\f$ /// \brief Break *all* edges connected to \f$n\f$
/// \param n The vertex id /// \param n The vertex id
///
/// \par Complexity
/// \f$O(M)\f$
///
void cut(size_t n) { void cut(size_t n) {
for (const auto it : outgoing(n)) { for (const auto it : outgoing(n)) {
cut_edge(n, it); cut_edge(n, it);
@@ -489,6 +617,10 @@ public:
/// ///
/// \brief Clear the graph, destructing all vertices and edges. /// \brief Clear the graph, destructing all vertices and edges.
///
/// \par Complexity
/// \f$O(N + M)\f$
///
void clear() { void clear() {
_vertex_pool.clear(); _vertex_pool.clear();
_edge_pool.clear(); _edge_pool.clear();

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file initializer_list.h /// \file fennec/containers/initializer_list.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file list.h /// \file fennec/containers/list.h
/// \brief A header containing the definition for a linked list of values /// \brief A header containing the definition for a linked list of values
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -61,6 +61,7 @@ namespace fennec
/// | 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$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \note Access, Insertion, and Deletion are \f$O(N)\f$ using the index pattern, /// \note Access, Insertion, and Deletion are \f$O(N)\f$ using the index pattern,
/// using the iterator pattern yields \f$O(1)\f$ runtime. /// using the iterator pattern yields \f$O(1)\f$ runtime.
@@ -70,20 +71,25 @@ template<class TypeT, class Alloc = allocator<TypeT>>
struct list { struct list {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
private: private:
struct node; struct node;
public: public:
/// \name Definitions
/// @{
/// \brief Alias for the allocator type, rebound to list nodes /// \brief Alias for the allocator type, rebound to list nodes
using alloc_t = typename allocator_traits<Alloc>::template rebind<node>; using alloc_t = typename allocator_traits<Alloc>::template rebind<node>;
using value_t = TypeT; ///< Alias for the value type using value_t = TypeT; //!< Alias for the value type
static constexpr size_t npos = -1; ///< Constant representing a non-existant position static constexpr size_t npos = -1; //!< Constant representing a non-existant position
class iterator; ///< Iterator type for forward iteration over the list /// @}
class const_iterator; ///< Iterator type for forward iteration over a constant list
class iterator;
class const_iterator;
private: private:
using table_t = dynarray<node, alloc_t>; using table_t = dynarray<node, alloc_t>;
@@ -98,6 +104,10 @@ public:
/// ///
/// \brief Default Constructor, initializes an empty list. /// \brief Default Constructor, initializes an empty list.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr list() constexpr list()
: _table(), _freed(), _root(npos), _last(npos), _size(0) { : _table(), _freed(), _root(npos), _last(npos), _size(0) {
} }
@@ -105,6 +115,10 @@ public:
/// ///
/// \brief Copy Constructor, copies all elements in \f$l\f$ with optimized layout /// \brief Copy Constructor, copies all elements in \f$l\f$ with optimized layout
/// \param l The list to copy /// \param l The list to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr list(const list& l) constexpr list(const list& l)
: list() { : list() {
for (const value_t& it : l) { for (const value_t& it : l) {
@@ -116,6 +130,10 @@ public:
/// ///
/// \brief Move Constructor, takes ownership of the list /// \brief Move Constructor, takes ownership of the list
/// \param l The list to move /// \param l The list to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr list(list&& l) noexcept constexpr list(list&& l) noexcept
: _table(fennec::move(l._table)) : _table(fennec::move(l._table))
, _freed(fennec::move(l._freed)) , _freed(fennec::move(l._freed))
@@ -126,10 +144,12 @@ public:
/// ///
/// \brief Destructor, destructs all elements then releases the allocation. /// \brief Destructor, destructs all elements then releases the allocation.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~list() { constexpr ~list() {
for (size_t i = 0; i < capacity(); ++i) { clear();
_table[i].value = nullopt;
}
} }
/// @} /// @}
@@ -137,13 +157,17 @@ public:
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public: public:
/// \name Assignment /// \name Assignment Operators
/// @{ /// @{
/// ///
/// \brief Copy Assignment Operator /// \brief Copy Assignment Operator
/// \param l the list to copy /// \param l the list to copy
/// \returns \f$this\f$ after having copied all elements of \f$l\f$ /// \returns \f$this\f$ after having copied all elements of \f$l\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr list& operator=(const list& l) { constexpr list& operator=(const list& l) {
this->clear(); this->clear();
for (const value_t& it : l) { for (const value_t& it : l) {
@@ -156,6 +180,10 @@ public:
/// \brief Move Assignment Operator /// \brief Move Assignment Operator
/// \param l the list to copy /// \param l the list to copy
/// \returns \f$this\f$ after having taken ownership over the contents of \f$l\f$ /// \returns \f$this\f$ after having taken ownership over the contents of \f$l\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr list& operator=(list&& l) noexcept { constexpr list& operator=(list&& l) noexcept {
this->clear(); this->clear();
_table = fennec::move(l._table); _table = fennec::move(l._table);
@@ -176,18 +204,30 @@ public:
/// ///
/// \returns The size of the list in elements. /// \returns The size of the list in elements.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \returns The capacity of the list in elements. /// \returns The capacity of the list in elements.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _table.size(); 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.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _root == npos; return _root == npos;
} }
@@ -206,7 +246,9 @@ public:
/// \param i Index to access /// \param i Index to access
/// \returns A reference to the element at \f$i\f$ /// \returns A reference to the element at \f$i\f$
/// ///
/// \details \f$O(N)\f$ /// \par Complexity
/// \f$O(N)\f$
///
constexpr value_t& operator[](int i) { constexpr value_t& operator[](int i) {
assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds"); assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds");
size_t n = _walk(i); size_t n = _walk(i);
@@ -219,7 +261,9 @@ public:
/// \param i Index to access /// \param i Index to access
/// \returns A const-qualified reference to the element at \f$i\f$ /// \returns A const-qualified reference to the element at \f$i\f$
/// ///
/// \details \f$O(N)\f$ /// \par Complexity
/// \f$O(N)\f$
///
constexpr const value_t& operator[](int i) const { constexpr const value_t& operator[](int i) const {
assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds"); assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds");
size_t n = _walk(i); size_t n = _walk(i);
@@ -230,6 +274,10 @@ public:
/// ///
/// \brief Access Front Element /// \brief Access Front Element
/// \returns A reference to the first element in the list /// \returns A reference to the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& front() { constexpr value_t& front() {
return *_table[_root].value; return *_table[_root].value;
} }
@@ -237,6 +285,10 @@ public:
/// ///
/// \brief Const Access Front Element /// \brief Const Access Front Element
/// \returns A const-qualified reference to the first element in the list /// \returns A const-qualified reference to the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& front() const { constexpr const value_t& front() const {
return *_table[_root].value; return *_table[_root].value;
} }
@@ -244,6 +296,10 @@ public:
/// ///
/// \brief Access Back Element /// \brief Access Back Element
/// \returns A reference to the last element in the list /// \returns A reference to the last element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& back() { constexpr value_t& back() {
return *_table[_last].value; return *_table[_last].value;
} }
@@ -251,6 +307,10 @@ public:
/// ///
/// \brief Const Access Back Element /// \brief Const Access Back Element
/// \returns A const-qualified reference to the last element in the list /// \returns A const-qualified reference to the last element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& back() const { constexpr const value_t& back() const {
return *_table[_last].value; return *_table[_last].value;
} }
@@ -270,7 +330,9 @@ public:
/// \param x value to copy /// \param x value to copy
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(1)\f$ /// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator 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);
} }
@@ -281,7 +343,9 @@ public:
/// \param x value to move /// \param x value to move
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(1)\f$ /// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator 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));
} }
@@ -292,7 +356,9 @@ public:
/// \param x value to copy /// \param x value to copy
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(N)\f$ /// \par Complexity
/// \f$O(N)\f$
///
constexpr iterator 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");
@@ -306,7 +372,9 @@ public:
/// \param x value to move /// \param x value to move
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(N)\f$ /// \par Complexity
/// \f$O(N)\f$
///
constexpr iterator 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");
@@ -321,7 +389,9 @@ public:
/// \param args Arguments to construct with /// \param args Arguments to construct with
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(N)\f$ /// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr iterator 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");
@@ -337,7 +407,9 @@ public:
/// \param args Arguments to construct with /// \param args Arguments to construct with
/// \returns The id of the inserted node /// \returns The id of the inserted node
/// ///
/// \details \f$O(N)\f$ /// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr iterator emplace(const iterator& it, ArgsT&&...args) { constexpr iterator emplace(const iterator& it, ArgsT&&...args) {
return this->_insert(it._n, fennec::forward<ArgsT>(args)...); return this->_insert(it._n, fennec::forward<ArgsT>(args)...);
@@ -347,6 +419,10 @@ public:
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator push_front(const value_t& x) { constexpr iterator push_front(const value_t& x) {
return this->_insert(_root, x); return this->_insert(_root, x);
} }
@@ -355,6 +431,10 @@ 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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator 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));
} }
@@ -364,6 +444,10 @@ public:
/// \param args Arguments to construct with /// \param args Arguments to construct with
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \returns The id of the inserted node /// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr iterator 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)...);
@@ -373,6 +457,10 @@ 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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator push_back(const value_t& x) { constexpr iterator push_back(const value_t& x) {
return this->_insert(npos, x); return this->_insert(npos, x);
} }
@@ -381,6 +469,10 @@ 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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator 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));
} }
@@ -390,6 +482,10 @@ public:
/// \param args Arguments to construct with /// \param args Arguments to construct with
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \returns The id of the inserted node /// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr iterator 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)...);
@@ -398,6 +494,10 @@ public:
/// ///
/// \brief Erase Element /// \brief Erase Element
/// \param i Index to erase /// \param i Index to erase
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void erase(size_t i) { constexpr void erase(size_t i) {
assert(i < size(), "Index out of Bounds!"); assert(i < size(), "Index out of Bounds!");
size_t n = _walk(i); size_t n = _walk(i);
@@ -407,24 +507,40 @@ public:
/// ///
/// \brief Erase Element /// \brief Erase Element
/// \param it Location to Erase /// \param it Location to Erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(const iterator& it) { constexpr void erase(const iterator& it) {
this->_erase(it._n); this->_erase(it._n);
} }
/// ///
/// \brief Pop Front, erases first element /// \brief Pop Front, erases first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void pop_front() { constexpr void pop_front() {
_erase(_root); _erase(_root);
} }
/// ///
/// \brief Pop Back, erases first element /// \brief Pop Back, erases first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void pop_back() { constexpr void pop_back() {
_erase(_last); _erase(_last);
} }
/// ///
/// \brief Clears the list, destructing all elements in order /// \brief Clears the list, destructing all elements in order
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() { constexpr void clear() {
size_t i = _root; size_t i = _root;
while (i != npos) { while (i != npos) {
@@ -432,6 +548,8 @@ public:
i = this->_next(i); i = this->_next(i);
} }
_table.clear(); _table.clear();
_root = npos;
_size = 0;
} }
/// @} /// @}
@@ -444,34 +562,48 @@ public:
/// ///
/// \returns An iterator for the first element in the list /// \returns An iterator for the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator begin() { constexpr iterator begin() {
return iterator(this, _root); return iterator(this, _root);
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A const iterator for the first element in the list /// \returns A const iterator for the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_iterator begin() const { constexpr const_iterator begin() const {
return const_iterator(this, _root); return const_iterator(this, _root);
} }
/// ///
/// \returns An iterator for the end of the list /// \returns An iterator for the end of the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() { constexpr iterator end() {
return iterator(this, npos); return iterator(this, npos);
} }
/// ///
/// \brief Const C++ Iterator Specification `end()` /// \brief Const C++ Iterator Specification \f$end()\f$
/// \returns A const iterator for the end of the list /// \returns A const iterator for the end of the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_iterator end() const { constexpr const_iterator end() const {
return const_iterator(this, npos); return const_iterator(this, npos);
} }
/// @}
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
class iterator { class iterator {
public: public:
/// ///
@@ -613,7 +745,9 @@ public:
} }
}; };
// Members ============================================================================================================= /// @}
// Private Member Variables ============================================================================================
private: private:
table_t _table; table_t _table;
freed_t _freed; freed_t _freed;
@@ -622,7 +756,7 @@ private:
friend class iterator; friend class iterator;
// Helpers ============================================================================================================= // Private Helpers =====================================================================================================
private: private:
constexpr void _expand() { constexpr void _expand() {
_table.resize(fennec::max(_table.size(), size_t(4)) * 2); _table.resize(fennec::max(_table.size(), size_t(4)) * 2);

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file map.h /// \file fennec/containers/map.h
/// \brief A header containing the definition for a mapping of keys to values /// \brief A header containing the definition for a mapping of keys to values
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -71,6 +71,7 @@ namespace fennec
/// | 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$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \note These runtimes are amortized, in theory the worst case is \f$O(N)\f$, but that is highly improbable. /// \note These runtimes are amortized, in theory the worst case is \f$O(N)\f$, but that is highly improbable.
/// ///
@@ -83,21 +84,25 @@ struct map {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public: public:
struct key_hash; ///< Hash for node keys
struct key_equals; ///< Comparison for node keys /// \name Definitions
using key_t = KeyT; ///< The key type /// @{
using value_t = ValueT; ///< The value type
using elem_t = pair<KeyT, ValueT>; ///< then node type struct key_hash; //!< Hash for node keys
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; ///< Rebinds the allocator type to nodes struct key_equals; //!< Comparison for node keys
using hash_t = Hash; ///< The hash type using key_t = KeyT; //!< The key type
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; ///< The underlying set using value_t = ValueT; //!< The value type
using iterator = set_t::iterator; ///< Iterator type using elem_t = pair<KeyT, ValueT>; //!< then node type
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; //!< Rebinds the allocator type to nodes
using hash_t = Hash; //!< The hash type
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; //!< The underlying set
using iterator = set_t::iterator; //!< Iterator type
/// ///
/// \brief key hash helper /// \brief key hash helper
struct key_hash : hash_t { struct key_hash : hash_t {
/// ///
/// \brief C++ 11 Hash Specification `operator()` /// \brief C++ 11 Hash Specification \f$operator()\f$
/// \param p the pair to hash /// \param p the pair to hash
/// \returns the hash of the key /// \returns the hash of the key
constexpr size_t operator()(const elem_t& p) const { constexpr size_t operator()(const elem_t& p) const {
@@ -109,7 +114,7 @@ public:
/// \brief key comparison helper /// \brief key comparison helper
struct key_equals : equality<KeyT> { struct key_equals : equality<KeyT> {
/// ///
/// \brief C++ 11 Compare Specification `operator()` /// \brief C++ 11 Compare Specification \f$operator()\f$
/// \param a the first pair /// \param a the first pair
/// \param b the second pair /// \param b the second pair
/// \returns \f$true\f$ if the keys are equal, \f$false\f$ otherwise /// \returns \f$true\f$ if the keys are equal, \f$false\f$ otherwise
@@ -118,8 +123,11 @@ public:
} }
}; };
/// @}
// Constructors & Destructor =========================================================================================== // Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor /// \name Constructors & Destructor
/// @{ /// @{
@@ -136,6 +144,7 @@ public:
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// \name Properties /// \name Properties
/// @{ /// @{
@@ -162,6 +171,7 @@ public:
// Access ============================================================================================================== // Access ==============================================================================================================
public:
/// \name Access /// \name Access
/// @{ /// @{
@@ -170,6 +180,10 @@ public:
/// \brief Key Access Operator /// \brief Key Access Operator
/// \param key Key value to access /// \param key Key value to access
/// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present. /// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t* operator[](const KeyT& key) { constexpr value_t* operator[](const KeyT& key) {
auto it = _set.at(this->_find(key)); auto it = _set.at(this->_find(key));
return it ? &it->second : nullptr; return it ? &it->second : nullptr;
@@ -179,6 +193,10 @@ public:
/// \brief Key Const Access Operator /// \brief Key Const Access Operator
/// \param key Key value to access /// \param key Key value to access
/// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present. /// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t* operator[](const KeyT& key) const { constexpr const value_t* operator[](const KeyT& key) const {
auto it = _set.at(this->_find(key)); auto it = _set.at(this->_find(key));
return it ? &it->second : nullptr; return it ? &it->second : nullptr;
@@ -189,6 +207,10 @@ public:
/// \tparam ArgsT Argument Types /// \tparam ArgsT Argument Types
/// \param args Arguments to construct the key with /// \param args Arguments to construct the key with
/// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present. /// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr value_t* operator[](ArgsT&&...args) { constexpr value_t* operator[](ArgsT&&...args) {
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...)); auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
@@ -200,6 +222,10 @@ public:
/// \tparam ArgsT Argument Type /// \tparam ArgsT Argument Type
/// \param args Argument to construct the key with /// \param args Argument to construct the key with
/// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present. /// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr const value_t* operator[](ArgsT&&...args) const { constexpr const value_t* operator[](ArgsT&&...args) const {
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...)); auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
@@ -210,6 +236,7 @@ public:
// Modifiers =========================================================================================================== // Modifiers ===========================================================================================================
public:
/// \name Modifiers /// \name Modifiers
/// @{ /// @{
@@ -217,6 +244,10 @@ public:
/// ///
/// \brief Key-Value Insertion /// \brief Key-Value Insertion
/// \param pair a pair containing the key and its value /// \param pair a pair containing the key and its value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void insert(elem_t&& pair) { constexpr void insert(elem_t&& pair) {
this->_insert(fennec::forward<elem_t>(pair)); this->_insert(fennec::forward<elem_t>(pair));
} }
@@ -225,6 +256,10 @@ public:
/// \brief Key-Value Insertion /// \brief Key-Value Insertion
/// \param key key to insert /// \param key key to insert
/// \param args Arguments for constructing the key-value pair /// \param args Arguments for constructing the key-value pair
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void emplace(const KeyT& key, ArgsT&&...args) { constexpr void emplace(const KeyT& key, ArgsT&&...args) {
this->_insert(key, fennec::forward<ArgsT>(args)...); this->_insert(key, fennec::forward<ArgsT>(args)...);
@@ -233,6 +268,10 @@ public:
/// ///
/// \brief Key-Value Insertion /// \brief Key-Value Insertion
/// \param args Arguments for constructing the key-value pair /// \param args Arguments for constructing the key-value pair
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) { constexpr void emplace(ArgsT&&...args) {
this->_insert(fennec::forward<ArgsT>(args)...); this->_insert(fennec::forward<ArgsT>(args)...);
@@ -241,6 +280,10 @@ public:
/// ///
/// \brief Erase a key /// \brief Erase a key
/// \param key key to erase /// \param key key to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(KeyT&& key) { constexpr void erase(KeyT&& key) {
_set.erase(this->_find(fennec::forward<KeyT>(key))); _set.erase(this->_find(fennec::forward<KeyT>(key)));
} }
@@ -248,6 +291,10 @@ public:
/// ///
/// \brief Erase a key /// \brief Erase a key
/// \param key key to erase /// \param key key to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(const KeyT& key) { constexpr void erase(const KeyT& key) {
_set.erase(this->_find(key)); _set.erase(this->_find(key));
} }
@@ -256,6 +303,10 @@ public:
/// \brief Argument Erase /// \brief Argument Erase
/// \tparam ArgsT Argument Types /// \tparam ArgsT Argument Types
/// \param args Arguments to construct a key to erase /// \param args Arguments to construct a key to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void erase(ArgsT&&...args) { constexpr void erase(ArgsT&&...args) {
_set.erase(this->_find(fennec::forward<ArgsT>(args)...)); _set.erase(this->_find(fennec::forward<ArgsT>(args)...));
@@ -263,6 +314,10 @@ public:
/// ///
/// \brief Clears the map destructing all elements /// \brief Clears the map destructing all elements
///
/// \par Complexity
/// \f$O(1)\f$
///
void clear() { void clear() {
_set.clear(); _set.clear();
} }
@@ -271,21 +326,30 @@ public:
// Iteration =========================================================================================================== // Iteration ===========================================================================================================
public:
/// \name Iteration /// \name Iteration
/// @{ /// @{
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the start of the map /// \returns an iterator at the start of the map
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator begin() { constexpr iterator begin() {
return _set.begin(); return _set.begin();
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator at the end of the map /// \returns an iterator at the end of the map
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() { constexpr iterator end() {
return _set.end(); return _set.end();
} }
@@ -293,9 +357,13 @@ public:
/// @} /// @}
// Private Member Variables ============================================================================================
private: private:
set_t _set; set_t _set;
// Private Helpers =====================================================================================================
private:
template<typename...ArgsT> template<typename...ArgsT>
set_t::iterator _find(ArgsT&&...args) const { set_t::iterator _find(ArgsT&&...args) const {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file object_pool.h /// \file fennec/containers/object_pool.h
/// \brief A header containing the definition for a pool of objects associated by ids /// \brief A header containing the definition for a pool of objects associated by ids
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -54,6 +54,7 @@ namespace fennec
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypeT The value type /// \tparam TypeT The value type
/// \tparam AllocT The allocator type /// \tparam AllocT The allocator type
@@ -62,28 +63,43 @@ struct object_pool {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public: public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< The held object type using value_t = TypeT; //!< The held object type
using elem_t = optional<value_t>; //!< The element type using elem_t = optional<value_t>; //!< The element type
using table_t = dynarray<elem_t, AllocT>; //!< The underlying table type using table_t = dynarray<elem_t, AllocT>; //!< The underlying table type
using freed_t = list<size_t, AllocT>; //!< The underlying free queue using freed_t = list<size_t, AllocT>; //!< The underlying free queue
/// @}
class iterator; class iterator;
class const_iterator; class const_iterator;
// Constructors & Destructor =========================================================================================== // Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor /// \name Constructors & Destructor
/// @{ /// @{
/// ///
/// \brief Default Constructor, initializes an empty object pool /// \brief Default Constructor, initializes an empty object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr object_pool() constexpr object_pool()
: _size(0) { : _size(0) {
} }
/// ///
/// \brief Default Destructor, destructs objects then releases the allocation. /// \brief Default Destructor, destructs objects then releases the allocation.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~object_pool() = default; constexpr ~object_pool() = default;
/// @} /// @}
@@ -96,18 +112,30 @@ public:
/// ///
/// \returns The number of active objects in the pool /// \returns The number of active objects in the pool
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \returns The capacity of the underlying allocation /// \returns The capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _table.capacity(); return _table.capacity();
} }
/// ///
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return size() == 0; return size() == 0;
} }
@@ -117,6 +145,10 @@ public:
/// ///
/// \details This can be useful if there are constant members that need to be assigned at construction. /// \details This can be useful if there are constant members that need to be assigned at construction.
/// \returns The id of the next inserted node /// \returns The id of the next inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next_id() const { constexpr size_t next_id() const {
size_t next = _size; size_t next = _size;
if (not _freed.is_empty()) { if (not _freed.is_empty()) {
@@ -136,6 +168,10 @@ public:
/// \brief Array Access Operator /// \brief Array Access Operator
/// \param i id of the object /// \param i id of the object
/// \returns a reference to the object with id \f$i\f$ /// \returns a reference to the object with id \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& operator[](size_t i) { constexpr value_t& operator[](size_t i) {
assert(i < capacity(), "Index out of Bounds!"); assert(i < capacity(), "Index out of Bounds!");
assert(_table[i], "Attempted to access null object.") assert(_table[i], "Attempted to access null object.")
@@ -146,6 +182,10 @@ public:
/// \brief Array Const Access Operator /// \brief Array Const Access Operator
/// \param i id of the object /// \param i id of the object
/// \returns a const-qualified reference to the object with id \f$i\f$ /// \returns a const-qualified reference to the object with id \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& operator[](size_t i) const { constexpr const value_t& operator[](size_t i) const {
assert(i < capacity(), "Index out of Bounds!"); assert(i < capacity(), "Index out of Bounds!");
assert(_table[i], "Attempted to access null object.") assert(_table[i], "Attempted to access null object.")
@@ -169,6 +209,10 @@ public:
/// \brief Move Insertion, inserts \f$x\f$ into the pool /// \brief Move Insertion, inserts \f$x\f$ into the pool
/// \param x the object to move /// \param x the object to move
/// \returns An integer corresponding to the id of the node /// \returns An integer corresponding to the id of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(value_t&& x) { constexpr size_t insert(value_t&& x) {
return this->_insert(fennec::forward<value_t>(x)); return this->_insert(fennec::forward<value_t>(x));
} }
@@ -177,15 +221,23 @@ public:
/// \brief Move Insertion, inserts a copy of \f$x\f$ into the pool /// \brief Move Insertion, inserts a copy of \f$x\f$ into the pool
/// \param x the object to copy /// \param x the object to copy
/// \returns An integer corresponding to the id of the node /// \returns An integer corresponding to the id of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(const value_t& x) { constexpr size_t insert(const value_t& x) {
return this->_insert(x); return this->_insert(x);
} }
/// ///
/// \brief Emplacement, constructs a new object using `args...` /// \brief Emplacement, constructs a new object using \f$args\ldots\f$
/// \param args The arguments to construct the new object with /// \param args The arguments to construct the new object with
/// \returns An integer corresponding to the id of the node /// \returns An integer corresponding to the id of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace(ArgsT&&...args) { constexpr size_t emplace(ArgsT&&...args) {
return this->_insert(fennec::forward<ArgsT>(args)...); return this->_insert(fennec::forward<ArgsT>(args)...);
@@ -194,6 +246,10 @@ public:
/// ///
/// \brief Erase an object from the pool /// \brief Erase an object from the pool
/// \param i The id of the object /// \param i The id of the object
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(size_t i) { constexpr void erase(size_t i) {
_table[i] = nullopt; _table[i] = nullopt;
_freed.push_back(i); _freed.push_back(i);
@@ -202,12 +258,14 @@ public:
/// ///
/// \brief Clear the object pool /// \brief Clear the object pool
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() { constexpr void clear() {
for (auto& it : _table) { _table.clear();
it = nullopt;
}
_size = 0;
_freed.clear(); _freed.clear();
_size = 0;
} }
/// @} /// @}
@@ -217,32 +275,48 @@ public:
/// ///
/// \returns an iterator at the start of the object pool /// \returns an iterator at the start of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
iterator begin() { iterator begin() {
return iterator(this, 0); return iterator(this, 0);
} }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the start of the object pool /// \returns an iterator at the start of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
const_iterator begin() const { const_iterator begin() const {
return const_iterator(this, 0); return const_iterator(this, 0);
} }
/// ///
/// \returns an iterator at the start of the end of the object pool /// \returns an iterator at the start of the end of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
iterator end() { iterator end() {
return iterator(this, _size); return iterator(this, _size);
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator at the start of the end of the object pool /// \returns an iterator at the start of the end of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
const_iterator end() const { const_iterator end() const {
return const_iterator(this, _size); return const_iterator(this, _size);
} }
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
class iterator { class iterator {
public: public:
/// ///
@@ -340,7 +414,7 @@ public:
}; };
/// ///
/// \brief C++ Iterator Specification `const_iterator` /// \brief C++ Iterator Specification \f$const_iterator\f$
class const_iterator { class const_iterator {
public: public:
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file optional.h /// \file fennec/containers/optional.h
/// \brief A header containing the definition for a container with an optionally present variable /// \brief A header containing the definition for a container with an optionally present variable
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -39,15 +39,15 @@
namespace fennec namespace fennec
{ {
/// ///
/// \brief struct to represent a \f$null\f$ `optional` /// \brief struct to represent a \f$null\f$ `fennec::optional`
struct nullopt_t {}; struct nullopt_t {};
/// ///
/// \brief value representing a \f$null\f$ `optional` /// \brief value representing a \f$null\f$ `fennec::optional`
constexpr nullopt_t nullopt_v = {}; constexpr nullopt_t nullopt_v = {};
/// ///
/// \brief alias for representing a \f$null\f$ `optional` /// \brief alias for representing a \f$null\f$ `fennec::optional`
#define nullopt nullopt_v #define nullopt nullopt_v
/// ///
@@ -66,6 +66,7 @@ constexpr nullopt_t nullopt_v = {};
/// | find | ⛔ | /// | find | ⛔ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
/// ///
/// \tparam T /// \tparam T
template<typename T> template<typename T>
@@ -73,11 +74,17 @@ struct optional {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public: public:
/// \name Definitions
/// @{
using reference_t = T&; //!< reference type using reference_t = T&; //!< reference type
using pointer_t = T*; //!< pointer type using pointer_t = T*; //!< pointer type
using const_reference_t = T&; //!< const reference type using const_reference_t = T&; //!< const reference type
using const_pointer_t = const T*; //!< const pointer type using const_pointer_t = const T*; //!< const pointer type
/// @}
// Constructors ======================================================================================================== // Constructors ========================================================================================================
@@ -86,6 +93,10 @@ public:
/// ///
/// \brief Default Constructor /// \brief Default Constructor
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional() constexpr optional()
: _root(0) : _root(0)
, _set(false) { , _set(false) {
@@ -93,6 +104,10 @@ public:
/// ///
/// \brief Default Constructor /// \brief Default Constructor
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(nullopt_t) constexpr optional(nullopt_t)
: _root(0) : _root(0)
, _set(false) { , _set(false) {
@@ -101,6 +116,10 @@ public:
/// ///
/// \brief Type Copy Constructor /// \brief Type Copy Constructor
/// \param val the value to initialize the underlying object with /// \param val the value to initialize the underlying object with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(const T& val) constexpr optional(const T& val)
: _val(val) : _val(val)
, _set(true) { , _set(true) {
@@ -109,6 +128,10 @@ public:
/// ///
/// \brief Type Move Constructor /// \brief Type Move Constructor
/// \param val the value to initialize the underlying object with /// \param val the value to initialize the underlying object with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(T&& val) constexpr optional(T&& val)
: _val(fennec::forward<T>(val)) : _val(fennec::forward<T>(val))
, _set(true) { , _set(true) {
@@ -117,6 +140,10 @@ public:
/// ///
/// \brief Copy Constructor /// \brief Copy Constructor
/// \param opt the optional to copy /// \param opt the optional to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(const optional& opt) requires is_copy_assignable_v<T> constexpr optional(const optional& opt) requires is_copy_assignable_v<T>
: optional() { : optional() {
_set = opt._set; _set = opt._set;
@@ -128,6 +155,10 @@ public:
/// ///
/// \brief Move Constructor /// \brief Move Constructor
/// \param opt the optional to move /// \param opt the optional to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(optional&& opt) noexcept requires is_move_assignable_v<T> constexpr optional(optional&& opt) noexcept requires is_move_assignable_v<T>
: optional() { : optional() {
_set = opt._set; _set = opt._set;
@@ -141,6 +172,10 @@ public:
/// \brief Emplace Constructor /// \brief Emplace Constructor
/// \tparam ArgsT The argument types /// \tparam ArgsT The argument types
/// \param args The argument values /// \param args The argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr optional(ArgsT&&...args) constexpr optional(ArgsT&&...args)
: _val(fennec::forward<ArgsT>(args)...) : _val(fennec::forward<ArgsT>(args)...)
@@ -149,6 +184,10 @@ public:
/// ///
/// \brief destructor /// \brief destructor
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr ~optional() { constexpr ~optional() {
if constexpr(is_fundamental_v<T>) { if constexpr(is_fundamental_v<T>) {
return; return;
@@ -169,12 +208,20 @@ public:
/// ///
/// \brief Implicit Boolean Check /// \brief Implicit Boolean Check
/// \returns \f$true\f$ when there is a value contained /// \returns \f$true\f$ when there is a value contained
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr operator bool() const { constexpr operator bool() const {
return _set; return _set;
} }
/// ///
/// \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.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return not _set; return not _set;
} }
@@ -184,12 +231,16 @@ public:
// Assignment Operators ================================================================================================ // Assignment Operators ================================================================================================
/// \name Assignment /// \name Assignment Operators
/// @{ /// @{
/// ///
/// \brief Null Assignment /// \brief Null Assignment
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(nullopt_t) { constexpr optional& operator=(nullopt_t) {
if constexpr(not is_fundamental_v<T>) { if constexpr(not is_fundamental_v<T>) {
if (_set) { if (_set) {
@@ -205,6 +256,10 @@ public:
/// \brief Type Copy Assignment /// \brief Type Copy Assignment
/// \param val The value to set with /// \param val The value to set with
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(const T& val) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> { constexpr optional& operator=(const T& val) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set) { if (_set) {
_val = val; _val = val;
@@ -219,6 +274,10 @@ public:
/// \brief Type Move Assignment /// \brief Type Move Assignment
/// \param val The value to set with /// \param val The value to set with
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(T&& val) requires is_move_constructible_v<T> and is_move_assignable_v<T> { constexpr optional& operator=(T&& val) requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set) { if (_set) {
_val = fennec::forward<T>(val); _val = fennec::forward<T>(val);
@@ -233,6 +292,10 @@ public:
/// \brief Copy Assignment /// \brief Copy Assignment
/// \param opt The optional to copy /// \param opt The optional to copy
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> { constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set != opt._set) { if (_set != opt._set) {
_set = opt._set; _set = opt._set;
@@ -252,6 +315,10 @@ public:
/// \brief Move Assignment /// \brief Move Assignment
/// \param opt The optional to move /// \param opt The optional to move
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v<T> and is_move_assignable_v<T> { constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set != opt._set) { if (_set != opt._set) {
_set = opt._set; _set = opt._set;
@@ -277,12 +344,20 @@ public:
/// ///
/// \returns A pointer to the value, \f$nullptr\f$ if there is no value /// \returns A pointer to the value, \f$nullptr\f$ if there is no value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pointer_t operator->() noexcept { constexpr pointer_t operator->() noexcept {
return _set ? &_val : nullptr; return _set ? &_val : nullptr;
} }
/// ///
/// \returns A const-qualified pointer to the value, \f$nullptr\f$ if there is no value /// \returns A const-qualified pointer to the value, \f$nullptr\f$ if there is no value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_pointer_t operator->() const noexcept { constexpr const_pointer_t operator->() const noexcept {
return _set ? &_val : nullptr; return _set ? &_val : nullptr;
} }
@@ -290,6 +365,10 @@ public:
/// ///
/// \brief Dereference Operator /// \brief Dereference Operator
/// \returns A reference to the value /// \returns A reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T& operator*() & noexcept { constexpr T& operator*() & noexcept {
assertd(_set, "Attempted to reference the value of an unset optional"); assertd(_set, "Attempted to reference the value of an unset optional");
return _val; return _val;
@@ -298,6 +377,10 @@ public:
/// ///
/// \brief Const Dereference Operator /// \brief Const Dereference Operator
/// \returns A const-qualified reference to the value /// \returns A const-qualified reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const T& operator*() const& noexcept { constexpr const T& operator*() const& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional"); assertd(_set, "Attempted to reference the value of an unset optional");
return _val; return _val;
@@ -306,6 +389,10 @@ public:
/// ///
/// \brief Dereference Operator /// \brief Dereference Operator
/// \returns A reference to the value /// \returns A reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T&& operator*() && noexcept { constexpr T&& operator*() && noexcept {
assertd(_set, "Attempted to reference the value of an unset optional"); assertd(_set, "Attempted to reference the value of an unset optional");
return _val; return _val;
@@ -314,6 +401,10 @@ public:
/// ///
/// \brief Const Dereference Operator /// \brief Const Dereference Operator
/// \returns A const-qualified reference to the value /// \returns A const-qualified reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const T&& operator*() const&& noexcept { constexpr const T&& operator*() const&& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional"); assertd(_set, "Attempted to reference the value of an unset optional");
return _val; return _val;
@@ -330,6 +421,10 @@ public:
/// \brief Emplace Assignment, Move overload /// \brief Emplace Assignment, Move overload
/// \param val The object to take ownership of /// \param val The object to take ownership of
/// \returns A reference to the held value /// \returns A reference to the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T& emplace(T&& val) { constexpr T& emplace(T&& val) {
if (_set) { if (_set) {
_val = fennec::forward<T>(val); _val = fennec::forward<T>(val);
@@ -344,6 +439,10 @@ public:
/// \brief Emplace Assignment, Copy overload /// \brief Emplace Assignment, Copy overload
/// \param val The object to copy /// \param val The object to copy
/// \returns A reference to the held value /// \returns A reference to the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T& emplace(const T& val) { constexpr T& emplace(const T& val) {
if (_set) { if (_set) {
_val = val; _val = val;
@@ -358,6 +457,10 @@ public:
/// \brief Emplace Assignment /// \brief Emplace Assignment
/// \param args The arguments to construct with /// \param args The arguments to construct with
/// \returns A reference to the held value /// \returns A reference to the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr T& emplace(ArgsT&&...args) { constexpr T& emplace(ArgsT&&...args) {
if (_set) { if (_set) {
@@ -371,6 +474,10 @@ public:
/// ///
/// \brief Reset the Optional /// \brief Reset the Optional
///
/// \par Complexity
/// \f$O(1)\f$
///
void reset() { void reset() {
this->operator=(nullopt); this->operator=(nullopt);
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file pair.h /// \file fennec/containers/pair.h
/// \brief A header containing the definition for a container holding a pair of values /// \brief A header containing the definition for a container holding a pair of values
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -56,34 +56,55 @@ namespace fennec
/// | find | ⛔ | /// | find | ⛔ |
/// | insertion | ⛔ | /// | insertion | ⛔ |
/// | deletion | ⛔ | /// | deletion | ⛔ |
/// | space | \f$O(1)\f$ |
/// ///
/// \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>
struct pair { struct pair {
// Members ============================================================================================================= // Public Member Variables =============================================================================================
public:
/// \name Member Variables
/// @{
TypeT0 first; //!< The first value in the pair
TypeT1 second; //!< The second value in the pair
/// @}
TypeT0 first; ///< The first value in the pair
TypeT1 second; ///< The second value in the pair
// Constructors ======================================================================================================== // Constructors ========================================================================================================
public:
/// \name Constructors & Destructor /// \name Constructors & Destructor
/// @{ /// @{
/// ///
/// \brief Default Constructor, invokes default constructor for both elements /// \brief Default Constructor, invokes default constructor for both elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair() = default; constexpr pair() = default;
/// ///
/// \brief Destructor, invokes destructor for both elements /// \brief Destructor, invokes destructor for both elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr ~pair() = default; constexpr ~pair() = default;
/// ///
/// \brief Pair Copy Constructor /// \brief Pair Copy Constructor
/// \param x Value to copy for the first element /// \param x Value to copy for the first element
/// \param y Value to copy for the first element /// \param y Value to copy for the first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(const TypeT0& x, const TypeT1& y) constexpr pair(const TypeT0& x, const TypeT1& y)
: first(x) : first(x)
, second(y) { , second(y) {
@@ -93,6 +114,10 @@ struct pair {
/// \brief Pair Move Constructor /// \brief Pair Move Constructor
/// \param x Value to move for the first element /// \param x Value to move for the first element
/// \param y Value to move for the first element /// \param y Value to move for the first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(TypeT0&& x, TypeT1&& y) noexcept constexpr pair(TypeT0&& x, TypeT1&& y) noexcept
: first(fennec::forward<TypeT0>(x)) : first(fennec::forward<TypeT0>(x))
, second(fennec::forward<TypeT1>(y)) { , second(fennec::forward<TypeT1>(y)) {
@@ -102,6 +127,10 @@ struct pair {
/// \brief Pair Implicit Constructor /// \brief Pair Implicit Constructor
/// \param arg1 Value to initialize the first element /// \param arg1 Value to initialize the first element
/// \param arg2 Value to initialize the first element /// \param arg2 Value to initialize the first element
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename Arg1T, typename Arg2T> template<typename Arg1T, typename Arg2T>
constexpr pair(Arg1T&& arg1, Arg2T&& arg2) constexpr pair(Arg1T&& arg1, Arg2T&& arg2)
: first(fennec::forward<Arg1T>(arg1)) : first(fennec::forward<Arg1T>(arg1))
@@ -111,6 +140,10 @@ struct pair {
/// ///
/// \brief Copy Constructor, copies both elements /// \brief Copy Constructor, copies both elements
/// \param pair The pair to copy /// \param pair The pair to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(const pair& pair) constexpr pair(const pair& pair)
: first(fennec::copy(pair.first)) : first(fennec::copy(pair.first))
, second(fennec::copy(pair.second)) { , second(fennec::copy(pair.second)) {
@@ -119,6 +152,10 @@ struct pair {
/// ///
/// \brief Move Constructor, moves both elements /// \brief Move Constructor, moves both elements
/// \param pair The pair to move /// \param pair The pair to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(pair&& pair) noexcept constexpr pair(pair&& pair) noexcept
: first(fennec::move(pair.first)) : first(fennec::move(pair.first))
, second(fennec::move(pair.second)) { , second(fennec::move(pair.second)) {
@@ -128,6 +165,10 @@ struct pair {
/// \brief Copy Assignment, copies both elements /// \brief Copy Assignment, copies both elements
/// \param pair The pair to copy /// \param pair The pair to copy
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair& operator=(const pair& pair) { constexpr pair& operator=(const pair& pair) {
first = fennec::copy(pair.first); first = fennec::copy(pair.first);
second = fennec::copy(pair.second); second = fennec::copy(pair.second);
@@ -138,6 +179,10 @@ struct pair {
/// \brief Move Assignment, moves both elements /// \brief Move Assignment, moves both elements
/// \param pair The pair to move /// \param pair The pair to move
/// \returns A reference to self /// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair& operator=(pair&& pair) { constexpr pair& operator=(pair&& pair) {
first = fennec::move(pair.first); first = fennec::move(pair.first);
second = fennec::move(pair.second); second = fennec::move(pair.second);
@@ -148,6 +193,7 @@ struct pair {
// Comparison ========================================================================================================== // Comparison ==========================================================================================================
public:
/// \name Comparison /// \name Comparison
/// @{ /// @{
@@ -156,6 +202,10 @@ struct pair {
/// \brief Equality Operator /// \brief Equality Operator
/// \param p Pair to compare with /// \param p Pair to compare with
/// \returns \f$true\f$ when both elements of each pair are equal /// \returns \f$true\f$ when both elements of each pair are equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator==(const pair& p) const { constexpr bool operator==(const pair& p) const {
return first == p.first and second == p.second; return first == p.first and second == p.second;
} }
@@ -164,6 +214,10 @@ struct pair {
/// \brief Inequality Operator /// \brief Inequality Operator
/// \param p Pair to compare with /// \param p Pair to compare with
/// \returns \f$true\f$ when either element of each pair are equal /// \returns \f$true\f$ when either element of each pair are equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator!=(const pair& p) const { constexpr bool operator!=(const pair& p) const {
return first != p.first or second != p.second; return first != p.first or second != p.second;
} }
@@ -173,6 +227,10 @@ struct pair {
/// \param p Pair to compare with /// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are /// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are
/// equal and the second element is less /// equal and the second element is less
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator<(const pair& p) const { constexpr bool operator<(const pair& p) const {
return first < p.first or (first == p.first and second < p.second); return first < p.first or (first == p.first and second < p.second);
} }
@@ -182,6 +240,10 @@ struct pair {
/// \param p Pair to compare with /// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are /// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are
/// equal and the second element is less or equal /// equal and the second element is less or equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator<=(const pair& p) const { constexpr bool operator<=(const pair& p) const {
return first < p.first or (first == p.first and second <= p.second); return first < p.first or (first == p.first and second <= p.second);
} }
@@ -191,6 +253,10 @@ struct pair {
/// \param p Pair to compare with /// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are /// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are
/// equal and the second element is greater /// equal and the second element is greater
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator>(const pair& p) const { constexpr bool operator>(const pair& p) const {
return first > p.first or (first == p.first and second > p.second); return first > p.first or (first == p.first and second > p.second);
} }
@@ -200,6 +266,10 @@ struct pair {
/// \param p Pair to compare with /// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are /// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are
/// equal and the second element is greater or equal /// equal and the second element is greater or equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator>=(const pair& p) const { constexpr bool operator>=(const pair& p) const {
return first > p.first or (first == p.first and second >= p.second); return first > p.first or (first == p.first and second >= p.second);
} }
@@ -208,13 +278,13 @@ struct pair {
}; };
/// ///
/// \brief C++ 11 Hash Specification for `pair<TypeT0, TypeT1>` /// \brief C++ 11 Hash Specification for `fennec::pair<TypeT0, TypeT1>`
/// \tparam TypeT0 The first type of the pair /// \tparam TypeT0 The first type of the pair
/// \tparam TypeT1 The second type of the pair /// \tparam TypeT1 The second type of the pair
template<typename TypeT0, typename TypeT1> template<typename TypeT0, typename TypeT1>
struct hash<pair<TypeT0, TypeT1>> : hash<TypeT0>, hash<TypeT1> { struct hash<pair<TypeT0, TypeT1>> : hash<TypeT0>, hash<TypeT1> {
/// ///
/// \brief C++ 11 Hash Specification `operator()` /// \brief C++ 11 Hash Specification \f$operator()\f$
/// \param p The pair to hash /// \param p The pair to hash
/// \returns a pairing of the hashes of both elements of \f$p\f$ using `fennec::pair_hash` /// \returns a pairing of the hashes of both elements of \f$p\f$ using `fennec::pair_hash`
constexpr size_t operator()(const pair<TypeT0, TypeT1>& p) const { constexpr size_t operator()(const pair<TypeT0, TypeT1>& p) const {

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file priority_queue.h /// \file fennec/containers/priority_queue.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -69,6 +69,7 @@ namespace fennec
/// | find | ⛔ | /// | find | ⛔ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\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`
@@ -78,10 +79,16 @@ struct priority_queue {
// Definitions & Constants ============================================================================================= // Definitions & Constants =============================================================================================
public: public:
/// \name Definitions
/// @{
using value_t = ValueT; //!< Alias for the value type using value_t = ValueT; //!< Alias for the value type
using compare_t = CompareT; //!< Alias for the compare type using compare_t = CompareT; //!< Alias for the compare type
using alloc_t = allocation<value_t, AllocT>; //!< The underlying allocation type using alloc_t = allocation<value_t, AllocT>; //!< The underlying allocation type
/// @}
static constexpr size_t npos = -1; //!< value representing a null node static constexpr size_t npos = -1; //!< value representing a null node
private: private:
@@ -106,12 +113,20 @@ public:
/// ///
/// \brief default constructor /// \brief default constructor
/// \details initializes an empty queue /// \details initializes an empty queue
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr priority_queue() constexpr priority_queue()
: _size(0) { : _size(0) {
} }
/// ///
/// \brief destructor /// \brief destructor
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~priority_queue() { constexpr ~priority_queue() {
while (_size > 0) { while (_size > 0) {
--_size; --_size;
@@ -125,18 +140,30 @@ public:
/// ///
/// \returns the size of the queue /// \returns the size of the queue
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \returns the capacity of the underlying allocation /// \returns the capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _table.capacity(); return _table.capacity();
} }
/// ///
/// \returns \f$true\f$ if the queue holds no elements /// \returns \f$true\f$ if the queue holds no elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return size() == 0; return size() == 0;
} }
@@ -147,6 +174,10 @@ public:
/// ///
/// \returns the value at the front of the queue /// \returns the value at the front of the queue
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& front() const { constexpr const value_t& front() const {
return _table[0]; return _table[0];
} }
@@ -158,12 +189,20 @@ public:
/// ///
/// \brief push a new key into the queue /// \brief push a new key into the queue
/// \param key the key to insert /// \param key the key to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void push(const value_t& key) { constexpr void push(const value_t& key) {
this->_insert(key); this->_insert(key);
} }
/// ///
/// \param key the key to insert /// \param key the key to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void push(value_t&& key) { constexpr void push(value_t&& key) {
this->_insert(fennec::forward<value_t>(key)); this->_insert(fennec::forward<value_t>(key));
} }
@@ -172,6 +211,10 @@ public:
/// \brief emplace a new key into the queue /// \brief emplace a new key into the queue
/// \tparam ArgsT the argument types /// \tparam ArgsT the argument types
/// \param args the argument values /// \param args the argument values
///
/// \par Complexity
/// \f$O(\log N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) { constexpr void emplace(ArgsT&&...args) {
this->_insert(fennec::forward<ArgsT>(args)...); this->_insert(fennec::forward<ArgsT>(args)...);
@@ -179,6 +222,10 @@ public:
/// ///
/// \brief pop the element at the front of the queue /// \brief pop the element at the front of the queue
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void pop() { constexpr void pop() {
fennec::swap(_table[0], _table[--_size]); fennec::swap(_table[0], _table[--_size]);
fennec::destruct(&_table[_size]); fennec::destruct(&_table[_size]);
@@ -186,14 +233,14 @@ public:
} }
// Members ============================================================================================================= // Private Member Variables ============================================================================================
private: private:
compare_t _compare; compare_t _compare;
alloc_t _table; alloc_t _table;
size_t _size; size_t _size;
// Helpers ============================================================================================================= // Private Helpers =====================================================================================================
private: private:
template<typename...ArgsT> template<typename...ArgsT>

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file rdtree.h /// \file fennec/containers/rdtree.h
/// \brief A header containing the definition for a tree with a root and directed edges /// \brief A header containing the definition for a tree with a root and directed edges
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -57,6 +57,7 @@ namespace fennec
/// | find | \f$O(N)\f$ | /// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypeT Data type /// \tparam TypeT Data type
/// \tparam AllocT Allocator Type /// \tparam AllocT Allocator Type
@@ -68,11 +69,24 @@ private:
struct node; struct node;
public: public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< the held value type using value_t = TypeT; //!< the held value type
using alloc_t = typename allocator_traits<AllocT>::template rebind<node>; //!< the underlying allocator type using alloc_t = typename allocator_traits<AllocT>::template rebind<node>; //!< the underlying allocator type
/// @}
/// \name Constants
/// @{
static constexpr size_t root = 0; //!< the id of the root node static constexpr size_t root = 0; //!< the id of the root node
static constexpr size_t npos = -1; //!< the id of a null node static constexpr size_t npos = -1; //!< the id of a null node
/// @}
private: private:
struct node { struct node {
value_t value; value_t value;
@@ -80,7 +94,7 @@ private:
size_t depth, num_children; size_t depth, num_children;
constexpr node() constexpr node()
: value(nullopt) : value()
, parent(npos), child(npos) , parent(npos), child(npos)
, prev(npos), next(npos) , prev(npos), next(npos)
, depth(0), num_children(0) { , depth(0), num_children(0) {
@@ -103,6 +117,9 @@ private:
} }
}; };
using table_t = allocation<node, alloc_t>;
using freed_t = list<size_t>;
public: public:
// Constructors ======================================================================================================== // Constructors ========================================================================================================
@@ -114,23 +131,36 @@ public:
/// \brief Root Constructor, constructs the root node of the tree /// \brief Root Constructor, constructs the root node of the tree
/// \tparam ArgsT The argument types /// \tparam ArgsT The argument types
/// \param args The arguments to construct the root with /// \param args The arguments to construct the root with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
explicit constexpr rdtree(ArgsT&&...args) explicit constexpr rdtree(ArgsT&&...args)
: _table(), _freed(), _size(1) { : _table(), _freed(), _size(1) {
_table.creallocate(8); _table.reallocate(8);
fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...); fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...);
} }
/// ///
/// \brief Copy Constructor, copies the contents of \f$tree\f$ /// \brief Copy Constructor, copies the contents of \f$tree\f$
/// \param tree the rdtree to copy /// \param tree the rdtree to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr rdtree(const rdtree& tree) constexpr rdtree(const rdtree& tree)
: _table(tree._table), _freed(tree._freed), _size(tree._size) { : _table(tree._table), _freed(tree._freed), _size(tree._size) {
// TODO: properly invoke copy constructor for all elements
} }
/// ///
/// \brief Move Constructor, takes ownership over the contents of \f$tree\f$ /// \brief Move Constructor, takes ownership over the contents of \f$tree\f$
/// \param tree the rdtree to move /// \param tree the rdtree to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr rdtree(rdtree&& tree) noexcept constexpr rdtree(rdtree&& tree) noexcept
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) { : _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
} }
@@ -140,14 +170,19 @@ public:
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
/// \name Assignment /// \name Assignment Operators
/// @{ /// @{
/// ///
/// \brief Copy Assignment Operator /// \brief Copy Assignment Operator
/// \param rhs the rdtree to copy /// \param rhs the rdtree to copy
/// \returns \f$this\f$ after copying the contents of \f$rhs\f$ /// \returns \f$this\f$ after copying the contents of \f$rhs\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr rdtree& operator=(const rdtree& rhs) { constexpr rdtree& operator=(const rdtree& rhs) {
// TODO: properly invoke copy constructor for all elements
for (value_t* it : this->_table) { for (value_t* it : this->_table) {
fennec::destruct(it); fennec::destruct(it);
} }
@@ -161,6 +196,10 @@ public:
/// \brief Move Assignment Operator /// \brief Move Assignment Operator
/// \param rhs the rdtree to move /// \param rhs the rdtree to move
/// \returns \f$this\f$ after taking ownership over the contents of \f$rhs\f$ /// \returns \f$this\f$ after taking ownership over the contents of \f$rhs\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr rdtree& operator=(rdtree&& rhs) noexcept { constexpr rdtree& operator=(rdtree&& rhs) noexcept {
for (value_t* it : _table) { for (value_t* it : _table) {
fennec::destruct(it); fennec::destruct(it);
@@ -180,28 +219,49 @@ public:
/// ///
/// \returns The number of nodes in the tree /// \returns The number of nodes in the tree
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \returns The capacity of the underlying allocation /// \returns The capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _table.capacity(); return _table.capacity();
} }
/// ///
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
/// @}
// Access ============================================================================================================== // Access ==============================================================================================================
/// \name Access
/// @{
/// ///
/// \param i The id of the node to check /// \param i The id of the node to check
/// \returns The id of the parent node /// \returns The id of the parent node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t parent(size_t i) const { constexpr size_t parent(size_t i) const {
if (i >= _table.capacity()) return npos; if (i >= _table.capacity()) return npos;
return i == npos ? npos : _table[i].parent; return i == npos ? npos : _table[i].parent;
@@ -211,6 +271,10 @@ public:
/// \param i The id of the node to check /// \param i The id of the node to check
/// \param n The index of the child relative to the parent /// \param n The index of the child relative to the parent
/// \returns The id of the child node /// \returns The id of the child node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t child(size_t i, size_t n = 0) const { constexpr size_t child(size_t i, size_t n = 0) const {
if (i >= _table.capacity() && n != npos) return npos; if (i >= _table.capacity() && n != npos) return npos;
size_t c = i == npos ? npos : _table[i].child; size_t c = i == npos ? npos : _table[i].child;
@@ -223,6 +287,10 @@ public:
/// \param i The id of the node to check /// \param i The id of the node to check
/// \param n The index of the child relative to the parent /// \param n The index of the child relative to the parent
/// \returns The id of the next node /// \returns The id of the next node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next(size_t i, size_t n = 0) const { constexpr size_t next(size_t i, size_t n = 0) const {
if (i >= _table.capacity() && n != npos) return npos; if (i >= _table.capacity() && n != npos) return npos;
if (i == npos) { if (i == npos) {
@@ -248,6 +316,10 @@ public:
/// \param i The id of the node to check /// \param i The id of the node to check
/// \param n The index of the child relative to the parent /// \param n The index of the child relative to the parent
/// \returns The id of the previous node /// \returns The id of the previous node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t prev(size_t i, size_t n = 0) const { constexpr size_t prev(size_t i, size_t n = 0) const {
if (i >= _table.capacity()) return npos; if (i >= _table.capacity()) return npos;
if (i == npos) { if (i == npos) {
@@ -272,6 +344,10 @@ public:
/// ///
/// \param i the node to start at /// \param i the node to start at
/// \returns the left-most child of node \f$i\f$ /// \returns the left-most child of node \f$i\f$
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr size_t left_most(size_t i) const { constexpr size_t left_most(size_t i) const {
if (i >= _table.capacity()) return npos; if (i >= _table.capacity()) return npos;
size_t n = i; size_t n = i;
@@ -289,6 +365,10 @@ public:
/// ///
/// \param i the node to start at /// \param i the node to start at
/// \returns the right-most child of node \f$i\f$ /// \returns the right-most child of node \f$i\f$
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr size_t right_most(size_t i) const { constexpr size_t right_most(size_t i) const {
if (i >= _table.capacity()) return npos; if (i >= _table.capacity()) return npos;
if ((i = child(i)) == npos) { if ((i = child(i)) == npos) {
@@ -309,6 +389,10 @@ public:
/// ///
/// \param i The id of the node to check /// \param i The id of the node to check
/// \returns The depth of the node /// \returns The depth of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t depth(size_t i) const { constexpr size_t depth(size_t i) const {
if (i >= _table.capacity()) return npos; if (i >= _table.capacity()) return npos;
return i == npos ? npos : _table[i].depth; return i == npos ? npos : _table[i].depth;
@@ -317,6 +401,10 @@ public:
/// ///
/// \param i The id of the node to check /// \param i The id of the node to check
/// \returns The number of children the node has /// \returns The number of children the node has
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t num_children(size_t i) const { constexpr size_t num_children(size_t i) const {
if (i >= _table.capacity()) return 0; if (i >= _table.capacity()) return 0;
return i == npos ? 0 : _table[i].num_children; return i == npos ? 0 : _table[i].num_children;
@@ -324,6 +412,10 @@ 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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next_id() const { constexpr size_t next_id() const {
size_t i = _size; size_t i = _size;
if (not _freed.is_empty()) { if (not _freed.is_empty()) {
@@ -335,6 +427,10 @@ public:
/// ///
/// \param i The id of the node to access /// \param i The id of the node to access
/// \returns A reference to the value of the node wrapped in an optional /// \returns A reference to the value of the node wrapped in an optional
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& operator[](size_t i) { constexpr value_t& operator[](size_t i) {
return _table[i].value; return _table[i].value;
} }
@@ -342,12 +438,21 @@ public:
/// ///
/// \param i The id of the node to access /// \param i The id of the node to access
/// \returns A const-qualified reference to the value of the node wrapped in an optional /// \returns A const-qualified reference to the value of the node wrapped in an optional
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& operator[](size_t i) const { constexpr const value_t& operator[](size_t i) const {
return _table[i].value; return _table[i].value;
} }
/// @}
// Insertion & Deletion ================================================================================================
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
/// ///
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$ /// \brief Insertion, creates a node in the tree with parent \f$parent\f$
@@ -355,6 +460,10 @@ public:
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next /// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
/// \param val the value to insert /// \param val the value to insert
/// \returns the index of the created node /// \returns the index of the created node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, size_t next, const value_t& val) { constexpr size_t insert(size_t parent, size_t next, const value_t& val) {
return this->_insert(parent, next, val); return this->_insert(parent, next, val);
} }
@@ -365,6 +474,10 @@ public:
/// \param next the next node, as an index relative to the parent /// \param next the next node, as an index relative to the parent
/// \param val the value to insert /// \param val the value to insert
/// \returns the index of the created node /// \returns the index of the created node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, size_t next, value_t&& val) { constexpr size_t insert(size_t parent, size_t next, value_t&& val) {
return this->_insert(parent, next, fennec::forward<value_t>(val)); return this->_insert(parent, next, fennec::forward<value_t>(val));
} }
@@ -375,6 +488,10 @@ public:
/// \param next the next node, as an index relative to the parent /// \param next the next node, as an index relative to the parent
/// \param tree the tree to insert /// \param tree the tree to insert
/// \returns the index of the inserted root /// \returns the index of the inserted root
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) { constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) {
list<pair<size_t, size_t>> visit; list<pair<size_t, size_t>> visit;
visit.push_front({ root, parent }); visit.push_front({ root, parent });
@@ -404,6 +521,10 @@ public:
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next /// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
/// \param args the args to construct the value to insert /// \param args the args to construct the value to insert
/// \returns the index of the created node /// \returns the index of the created node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr size_t emplace(size_t parent, size_t next, ArgsT&&...args) { constexpr size_t emplace(size_t parent, size_t next, ArgsT&&...args) {
return this->_insert(parent, next, fennec::forward<ArgsT>(args)...); return this->_insert(parent, next, fennec::forward<ArgsT>(args)...);
@@ -413,6 +534,10 @@ public:
/// \brief Swap two nodes /// \brief Swap two nodes
/// \param i0 The id of the first node /// \param i0 The id of the first node
/// \param i1 The id of the second node /// \param i1 The id of the second node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void swap(size_t i0, size_t i1) { constexpr void swap(size_t i0, size_t i1) {
assertf(i0 != root and i1 != root, "Cannot Swap With Root"); assertf(i0 != root and i1 != root, "Cannot Swap With Root");
@@ -438,22 +563,29 @@ public:
_erase(i); _erase(i);
} }
/// @}
// Traversal =========================================================================================================== // Traversal ===========================================================================================================
/// \name Traversal
/// @{
/// ///
/// \brief Traverse the tree using a specified order and visiting functor /// \brief Traverse the tree using a specified order and visiting functor
/// ///
/// \details /// \details
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a `size_t` which contains the node's id. /// The visitor should accept a reference to a value of type \f$TypeT\f$ and a \f$size_t\f$ which contains the node's id.
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum /// The visitor should return one of the following values in the `fennec::traversal_control_` enum
/// ///
/// \tparam OrderT The order with which to traverse the tree. /// \tparam OrderT The order with which to traverse the tree.
/// \tparam VisitorT The visitor, should fulfill the signature `uint8_t visit(TypeT&, size_t)` /// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object /// \param visit The visiting object
/// \param i The node to start at /// \param i The node to start at
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename OrderT, typename VisitorT> template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i = root) { constexpr void traverse(VisitorT&& visit, size_t i = root) {
OrderT order; OrderT order;
@@ -470,6 +602,37 @@ public:
} }
} }
///
/// \brief Traverse the tree using a specified order and visiting functor
///
/// \details
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a \f$size_t\f$ which contains the node's id.
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
///
/// \tparam OrderT The order with which to traverse the tree.
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object
/// \param i The node to start at
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i = root) const {
OrderT order;
i = order(*this, i);
while (i != npos) {
uint8_t mode = traversal_control_continue;
if (_table[i].value) {
mode = visit(_table[i].value, i);
}
if (mode == traversal_control_break) {
break;
}
i = order[*this, i, mode];
}
}
/// ///
/// \brief Traverser pattern for breadth-first traversal /// \brief Traverser pattern for breadth-first traversal
struct breadth_first { struct breadth_first {
@@ -672,14 +835,21 @@ public:
size_t head; size_t head;
}; };
/// @}
// Private Member Variables ============================================================================================
private: private:
allocation<node, alloc_t> _table; table_t _table;
list<size_t> _freed; freed_t _freed;
size_t _size; size_t _size;
// Private Helpers =====================================================================================================
private:
void _expand() { void _expand() {
_table.creallocate(_table.capacity() * 2); _table.reallocate(_table.capacity() * 2);
} }
size_t _next_free() { size_t _next_free() {

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file sequence.h /// \file fennec/containers/sequence.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -69,6 +69,7 @@ namespace fennec
/// | find | \f$O(\log N)\f$ | /// | find | \f$O(\log N)\f$ |
/// | insertion | \f$O(\log N)\f$ | /// | insertion | \f$O(\log N)\f$ |
/// | deletion | \f$O(\log N)\f$ | /// | deletion | \f$O(\log N)\f$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypeT The type to contain /// \tparam TypeT The type to contain
/// \tparam CompareT Function for comparing two values /// \tparam CompareT Function for comparing two values
@@ -91,11 +92,17 @@ private:
}; };
public: public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< the value type using value_t = TypeT; //!< the value type
using node_t = pair<TypeT, bool>; //!< the node type using node_t = pair<TypeT, bool>; //!< the node type
using alloc_t = allocator_traits<AllocT>::template rebind<_node>; //!< underlying alloc type using alloc_t = allocator_traits<AllocT>::template rebind<_node>; //!< underlying alloc type
using compare_t = CompareT; //!< comparison type using compare_t = CompareT; //!< comparison type
/// @}
class iterator; class iterator;
class const_iterator; class const_iterator;
@@ -215,20 +222,33 @@ public:
/// ///
/// \brief Default Constructor, initializes an empty sequence /// \brief Default Constructor, initializes an empty sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr sequence() constexpr sequence()
: _root(nullptr), _size(0) { : _root(nullptr), _size(0) {
} }
/// ///
/// \brief Move Constructor, takes ownership of a sequence /// \brief Move Constructor, takes ownership of a sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr sequence(sequence&&) noexcept = default; constexpr sequence(sequence&&) noexcept = default;
/// ///
/// \brief Copy Constructor, copies a sequence /// \brief Copy Constructor, copies a sequence
constexpr sequence(const sequence&) = default; constexpr sequence(const sequence&) = default;
// TODO: properly implement
/// ///
/// \brief Default Destructor, destructs elements *in-order* /// \brief Default Destructor, destructs elements *in-order*
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~sequence() { constexpr ~sequence() {
this->clear(); this->clear();
} }
@@ -241,9 +261,13 @@ public:
/// @{ /// @{
/// ///
/// \brief Value Find Function, finds the iterator position for \f$val\f$, otherwise returns `end()` /// \brief Value Find Function, finds the iterator position for \f$val\f$, otherwise returns \f$end()\f$
/// \param val The value to find /// \param val The value to find
/// \returns An iterator at the value /// \returns An iterator at the value
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr iterator find(const value_t& val) { constexpr iterator find(const value_t& val) {
node node = _root; node node = _root;
while (node) { while (node) {
@@ -276,12 +300,20 @@ public:
/// ///
/// \returns The number of elements in the sequence /// \returns The number of elements in the sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \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.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
@@ -296,6 +328,10 @@ public:
/// ///
/// \brief Move Insertion, moves \f$val\f$ into the sequence /// \brief Move Insertion, moves \f$val\f$ into the sequence
/// \param val The value to insert /// \param val The value to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void insert(value_t&& val) { constexpr void insert(value_t&& val) {
node i = _insert_bst(fennec::forward<value_t>(val)); node i = _insert_bst(fennec::forward<value_t>(val));
_fix_insert(i); _fix_insert(i);
@@ -304,6 +340,10 @@ public:
/// ///
/// \brief Copy Insertion, inserts a copy of \f$val\f$ into the sequence /// \brief Copy Insertion, inserts a copy of \f$val\f$ into the sequence
/// \param val The value to insert /// \param val The value to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void insert(const value_t& val) { constexpr void insert(const value_t& val) {
node i = _insert_bst(val); node i = _insert_bst(val);
_fix_insert(i); _fix_insert(i);
@@ -313,6 +353,10 @@ public:
/// \brief Emplacement, constructs and adds a value into the sequence /// \brief Emplacement, constructs and adds a value into the sequence
/// \tparam ArgsT The argument types /// \tparam ArgsT The argument types
/// \param args The arguments to construct with /// \param args The arguments to construct with
///
/// \par Complexity
/// \f$O(\log N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) { constexpr void emplace(ArgsT&&...args) {
node i = _insert_bst(fennec::forward<ArgsT>(args)...); node i = _insert_bst(fennec::forward<ArgsT>(args)...);
@@ -322,12 +366,20 @@ public:
/// ///
/// \brief Erase the specified value from the sequence /// \brief Erase the specified value from the sequence
/// \param val the value to erase /// \param val the value to erase
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void erase(const value_t& val) { constexpr void erase(const value_t& val) {
_erase(find(val)._node); _erase(find(val)._node);
} }
/// ///
/// \brief Destructs all elements, *in-order*, contained in the sequence /// \brief Destructs all elements, *in-order*, contained in the sequence
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() { constexpr void clear() {
list<node> visit; list<node> visit;
for (iterator it = begin(); it != end(); ++it) { for (iterator it = begin(); it != end(); ++it) {
@@ -346,51 +398,49 @@ public:
/// ///
/// \returns An iterator at the smallest element in the sequence /// \returns An iterator at the smallest element in the sequence
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr iterator begin() { constexpr iterator begin() {
return sequence::iterator(this, _root); return sequence::iterator(this, _root);
} }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns An iterator at the smallest element in the sequence /// \returns An iterator at the smallest element in the sequence
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr const_iterator begin() const { constexpr const_iterator begin() const {
return sequence::const_iterator(this, _root); return sequence::const_iterator(this, _root);
} }
/// ///
/// \returns An iterator after the largest element in the sequence /// \returns An iterator after the largest element in the sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() { constexpr iterator end() {
return sequence::iterator(this, _root, nullptr); return sequence::iterator(this, _root, nullptr);
} }
/// ///
/// \brief Const C++ Iterator Specification `end()` /// \brief Const C++ Iterator Specification \f$end()\f$
/// \returns An iterator after the largest element in the sequence /// \returns An iterator after the largest element in the sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_iterator end() const { constexpr const_iterator end() const {
return sequence::const_iterator(this, _root, nullptr); return sequence::const_iterator(this, _root, nullptr);
} }
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
class iterator { class iterator {
private:
sequence* _seq;
node _head;
node _node;
list<node> _visit;
constexpr iterator(sequence* seq, node start)
: _seq(seq)
, _head(start)
, _node(seq->leftmost(start)) {
}
constexpr iterator(sequence* seq, node root, node start)
: _seq(seq)
, _head(root)
, _node(start) {
}
public: public:
/// ///
@@ -466,30 +516,30 @@ public:
return lhs._seq != rhs._seq or lhs._node != rhs._node; return lhs._seq != rhs._seq or lhs._node != rhs._node;
} }
friend struct sequence;
};
///
/// \brief C++ Iterator Specification `iterator`
class const_iterator {
private: private:
const sequence* _seq; sequence* _seq;
node _head; node _head;
node _node; node _node;
list<node> _visit; list<node> _visit;
constexpr const_iterator(const sequence* seq, node start) constexpr iterator(sequence* seq, node start)
: _seq(seq) : _seq(seq)
, _head(start) , _head(start)
, _node(seq->leftmost(start)) { , _node(seq->leftmost(start)) {
} }
constexpr const_iterator(const sequence* seq, node root, node start) constexpr iterator(sequence* seq, node root, node start)
: _seq(seq) : _seq(seq)
, _head(root) , _head(root)
, _node(start) { , _node(start) {
} }
friend struct sequence;
};
///
/// \brief C++ Iterator Specification \f$iterator\f$
class const_iterator {
public: public:
/// ///
@@ -565,18 +615,37 @@ public:
return lhs._seq != rhs._seq or lhs._node != rhs._node; return lhs._seq != rhs._seq or lhs._node != rhs._node;
} }
private:
const sequence* _seq;
node _head;
node _node;
list<node> _visit;
constexpr const_iterator(const sequence* seq, node start)
: _seq(seq)
, _head(start)
, _node(seq->leftmost(start)) {
}
constexpr const_iterator(const sequence* seq, node root, node start)
: _seq(seq)
, _head(root)
, _node(start) {
}
friend struct sequence; friend struct sequence;
}; };
// Fields ============================================================================================================== // Private Member Variables ============================================================================================
private: private:
alloc_t _alloc; alloc_t _alloc;
node _root; node _root;
compare_t _compare; compare_t _compare;
size_t _size; size_t _size;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private: private:
template<typename...ArgsT> template<typename...ArgsT>

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file set.h /// \file fennec/containers/set.h
/// \brief A header containing the definition for a set of unique values /// \brief A header containing the definition for a set of unique values
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -62,32 +62,46 @@ namespace fennec
/// | 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$ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypeT The type to contain /// \tparam TypeT The type to contain
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>> template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
struct set { struct set {
// Definitions ========================================================================================================= // Definitions =========================================================================================================
private:
struct node;
public: public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>; //!< the allocator type
/// \name Definitions
/// @{
using alloc_t = typename allocator_traits<Alloc>::template rebind<node>; //!< the allocator type
using hash_t = Hash; //!< the hash type using hash_t = Hash; //!< the hash type
using equal_t = Equals; //!< the equality type using equal_t = Equals; //!< the equality type
using elem_t = TypeT; //!< the element type using elem_t = TypeT; //!< the element type
/// @}
/// \name Constants
/// @{
static constexpr double default_load = 0.8; //!< the default load factor for reallocation static constexpr double default_load = 0.8; //!< the default load factor for reallocation
/// @}
class iterator; class iterator;
private: private:
struct node {
optional<elem_t> value;
int psl;
constexpr node() = default;
constexpr ~node() = default;
};
static constexpr size_t npos = -1; static constexpr size_t npos = -1;
using table_t = dynarray<node, alloc_t>;
// Constructors ======================================================================================================== // Constructors ========================================================================================================
public: public:
@@ -96,8 +110,12 @@ public:
/// ///
/// \brief Default Constructor, initializes empty set /// \brief Default Constructor, initializes empty set
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set() constexpr set()
: _alloc() : _table()
, _hash() , _hash()
, _size(0) , _size(0)
, _sumpsl(0) , _sumpsl(0)
@@ -107,8 +125,12 @@ public:
/// ///
/// \brief Hash Copy Constructor, initializes empty set with a hash /// \brief Hash Copy Constructor, initializes empty set with a hash
/// \param hash the hash object /// \param hash the hash object
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(const hash_t& hash) constexpr set(const hash_t& hash)
: _alloc() : _table()
, _hash(hash) , _hash(hash)
, _size(0) , _size(0)
, _sumpsl(0) , _sumpsl(0)
@@ -118,8 +140,12 @@ public:
/// ///
/// \brief Alloc Copy Constructor, initializes empty set with an allocator /// \brief Alloc Copy Constructor, initializes empty set with an allocator
/// \param alloc the allocator object /// \param alloc the allocator object
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr set(const alloc_t& alloc) constexpr set(const alloc_t& alloc)
: _alloc(alloc) : _table(alloc)
, _hash() , _hash()
, _size(0) , _size(0)
, _sumpsl(0) , _sumpsl(0)
@@ -130,8 +156,12 @@ public:
/// \brief Hash Alloc Copy Constructor, initializes empty set with a hash and allocator /// \brief Hash Alloc Copy Constructor, initializes empty set with a hash and allocator
/// \param hash the hash object /// \param hash the hash object
/// \param alloc the allocator object /// \param alloc the allocator object
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(const hash_t& hash, const alloc_t& alloc) constexpr set(const hash_t& hash, const alloc_t& alloc)
: _alloc(alloc) : _table(alloc)
, _hash(hash) , _hash(hash)
, _size(0) , _size(0)
, _sumpsl(0) , _sumpsl(0)
@@ -141,8 +171,12 @@ public:
/// ///
/// \brief Set Copy Constructor /// \brief Set Copy Constructor
/// \param set Set to copy /// \param set Set to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(const set& set) constexpr set(const set& set)
: _alloc(set._alloc) : _table(set._table)
, _hash(set._hash) , _hash(set._hash)
, _size(set._size) , _size(set._size)
, _sumpsl(set._sumpsl) , _sumpsl(set._sumpsl)
@@ -152,8 +186,12 @@ public:
/// ///
/// \brief Set Move Constructor /// \brief Set Move Constructor
/// \param set Set to move /// \param set Set to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(set&& set) noexcept constexpr set(set&& set) noexcept
: _alloc(fennec::move(set._alloc)) : _table(fennec::move(set._table))
, _hash(fennec::move(set._hash)) , _hash(fennec::move(set._hash))
, _size(fennec::move(set._size)) , _size(fennec::move(set._size))
, _sumpsl(set._sumpsl) , _sumpsl(set._sumpsl)
@@ -162,9 +200,13 @@ public:
/// ///
/// \brief Destructor, destructs all elements and releases the allocation /// \brief Destructor, destructs all elements and releases the allocation
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~set() { constexpr ~set() {
for (size_t i = 0; i < capacity(); ++i) { for (size_t i = 0; i < capacity(); ++i) {
_alloc[i].value = nullopt; _table[i].value = nullopt;
} }
} }
@@ -178,20 +220,32 @@ public:
/// ///
/// \returns Size of the set in elements /// \returns Size of the set in elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
/// ///
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const { constexpr bool is_empty() const {
return _size == 0; return _size == 0;
} }
/// ///
/// \returns Capacity of the set in elements /// \returns Capacity of the set in elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const { constexpr size_t capacity() const {
return _alloc.size(); return _table.size();
} }
/// @} /// @}
@@ -206,6 +260,10 @@ public:
/// \brief Find an Element /// \brief Find an Element
/// \param val Value to find /// \param val Value to find
/// \returns An iterator at the location of the value /// \returns An iterator at the location of the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator find(const elem_t& val) const { constexpr iterator find(const elem_t& val) const {
if (capacity() == 0) { if (capacity() == 0) {
return end(); return end();
@@ -216,8 +274,8 @@ public:
size_t n = 0; size_t n = 0;
// Check the first element; // Check the first element;
if (_alloc[i].psl >= psl && _alloc[i].value) { if (_table[i].psl >= psl && _table[i].value) {
if (_equal(*_alloc[i].value, val)) { if (_equal(*_table[i].value, val)) {
return iterator(this, i); return iterator(this, i);
} }
} }
@@ -228,16 +286,16 @@ public:
size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow
size_t i1 = (i + n) % capacity(); size_t i1 = (i + n) % capacity();
int p0 = psl - n, p1 = psl + n; int p0 = psl - n, p1 = psl + n;
bool c0 = p0 >= 0 && _alloc[i0].psl >= p0, c1 = _alloc[i1].psl >= p1; // Check that we are in range bool c0 = p0 >= 0 && _table[i0].psl >= p0, c1 = _table[i1].psl >= p1; // Check that we are in range
if (c0 && _alloc[i0].value) { if (c0 && _table[i0].value) {
if (_equal(*_alloc[i0].value, val)) { if (_equal(*_table[i0].value, val)) {
return iterator(this, i0); return iterator(this, i0);
} }
} }
if (c1 && _alloc[i1].value) { if (c1 && _table[i1].value) {
if (_equal(*_alloc[i1].value, val)) { if (_equal(*_table[i1].value, val)) {
return iterator(this, i1); return iterator(this, i1);
} }
} }
@@ -254,6 +312,10 @@ public:
/// \brief Check if a set contains a value /// \brief Check if a set contains a value
/// \param val Value to check /// \param val Value to check
/// \returns \f$true\f$ if \f$val\f$ can be found, \f$false\f$ otherwise /// \returns \f$true\f$ if \f$val\f$ can be found, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool contains(const elem_t& val) const { constexpr bool contains(const elem_t& val) const {
return this->find(val) != end(); return this->find(val) != end();
} }
@@ -263,23 +325,31 @@ public:
/// \param it Location to access /// \param it Location to access
/// \returns A pointer to the element, \f$nullptr\f$ if not found. /// \returns A pointer to the element, \f$nullptr\f$ if not found.
/// The value should not be changed in a manner that will change the hash of the element. /// The value should not be changed in a manner that will change the hash of the element.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr elem_t* at(const iterator& it) { constexpr elem_t* at(const iterator& it) {
if (it == end()) { if (it == end()) {
return nullptr; return nullptr;
} }
if (not _alloc[it._i].value) { if (not _table[it._i].value) {
return nullptr; return nullptr;
} }
return &*_alloc[it._i].value; return &*_table[it._i].value;
} }
/// ///
/// \brief Iterator Const Access /// \brief Iterator Const Access
/// \param it Location to access /// \param it Location to access
/// \returns A const-qualified pointer to the element, \f$nullptr\f$ if not found. /// \returns A const-qualified pointer to the element, \f$nullptr\f$ if not found.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const elem_t* at(const iterator& it) const { constexpr const elem_t* at(const iterator& it) const {
if (not _alloc[it._i].value) return nullptr; if (not _table[it._i].value) return nullptr;
return &*_alloc[it._i].value; return &*_table[it._i].value;
} }
/// @} /// @}
@@ -293,6 +363,10 @@ public:
/// \brief Move Insertion /// \brief Move Insertion
/// \param val Value to insert /// \param val Value to insert
/// \returns An iterator at the held value /// \returns An iterator at the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator insert(elem_t&& val) { constexpr iterator insert(elem_t&& val) {
return this->_insert(fennec::forward<elem_t>(val)); return this->_insert(fennec::forward<elem_t>(val));
} }
@@ -301,6 +375,10 @@ public:
/// \brief Copy Insertion /// \brief Copy Insertion
/// \param val Value to insert /// \param val Value to insert
/// \returns An iterator at the held value /// \returns An iterator at the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator insert(const elem_t& val) { constexpr iterator insert(const elem_t& val) {
return this->_insert(val); return this->_insert(val);
} }
@@ -310,6 +388,10 @@ public:
/// \tparam ArgsT Argument types /// \tparam ArgsT Argument types
/// \param args Arguments to construct with /// \param args Arguments to construct with
/// \returns An iterator at the held value /// \returns An iterator at the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
constexpr iterator emplace(ArgsT&&...args) { constexpr iterator emplace(ArgsT&&...args) {
return this->_insert(fennec::forward<ArgsT>(args)...); return this->_insert(fennec::forward<ArgsT>(args)...);
@@ -318,24 +400,28 @@ public:
/// ///
/// \brief Element Erase /// \brief Element Erase
/// \param it Location to erase /// \param it Location to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(iterator it) { constexpr void erase(iterator it) {
size_t i = it._i; size_t i = it._i;
if (i >= capacity()) { if (i >= capacity()) {
return; return;
} // These are separated due to compilers being inconsistent } // These are separated due to compilers being inconsistent
if (not _alloc[i].value) { if (not _table[i].value) {
return; return;
} }
_alloc[i].value = nullopt; _table[i].value = nullopt;
_sumpsl -= _alloc[i].psl; _sumpsl -= _table[i].psl;
--_size; --_size;
size_t p = i; size_t p = i;
while (_alloc[i = (i + 1) % capacity()].value) { while (_table[i = (i + 1) % capacity()].value) {
if (_alloc[i].psl == 0) break; if (_table[i].psl == 0) break;
fennec::swap(_alloc[p].value, _alloc[i].value); fennec::swap(_table[p].value, _table[i].value);
--_alloc[p].psl, --_sumpsl; --_table[p].psl, --_sumpsl;
p = i; p = i;
} }
} }
@@ -343,14 +429,22 @@ public:
/// ///
/// \brief Element Erase /// \brief Element Erase
/// \param val Value to erase /// \param val Value to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(const elem_t& val) { constexpr void erase(const elem_t& val) {
this->erase(this->find(val)); this->erase(this->find(val));
} }
/// ///
/// \brief Clear all elements from the set, destructing them /// \brief Clear all elements from the set, destructing them
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() { constexpr void clear() {
_alloc.clear(); _table.clear();
} }
/// @} /// @}
@@ -362,19 +456,27 @@ public:
/// @{ /// @{
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns An iterator for all elements of the set in no particular order /// \returns An iterator for all elements of the set in no particular order
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator begin() const { constexpr iterator begin() const {
iterator it(this, 0); iterator it(this, 0);
if (not _alloc[it._i].value) { while (not _table[it._i].value) {
++it; ++it;
} }
return it; return it;
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \returns An iterator representing the end of the set /// \returns An iterator representing the end of the set
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() const { constexpr iterator end() const {
return iterator(this, npos); return iterator(this, npos);
} }
@@ -382,7 +484,11 @@ public:
/// @} /// @}
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
class iterator { class iterator {
public: public:
/// ///
@@ -397,7 +503,7 @@ public:
/// \returns \f$it\f$ after having moved to the next element in the list /// \returns \f$it\f$ after having moved to the next element in the list
constexpr friend iterator& operator++(iterator& it) { constexpr friend iterator& operator++(iterator& it) {
while (++it._i < it._set->capacity()) { while (++it._i < it._set->capacity()) {
if (it._set->_alloc[it._i].value) { if (it._set->_table[it._i].value) {
return it; return it;
} }
} }
@@ -419,15 +525,15 @@ public:
/// \brief dereference operator /// \brief dereference operator
/// \returns a reference to the value pointed by the iterator /// \returns a reference to the value pointed by the iterator
constexpr const elem_t& operator*() const { constexpr const elem_t& operator*() const {
return *_set->_alloc[_i].value; return *_set->_table[_i].value;
} }
/// ///
/// \brief pointer access operator /// \brief pointer access operator
/// \returns a pointer to the value pointed by the iterator /// \returns a pointer to the value pointed by the iterator
constexpr const elem_t* operator->() const { constexpr const elem_t* operator->() const {
if (not _set->_alloc[_i].value) return nullptr; if (not _set->_table[_i].value) return nullptr;
return &*_set->_alloc[_i].value; return &*_set->_table[_i].value;
} }
/// ///
@@ -459,24 +565,33 @@ public:
}; };
// PRIVATE ============================================================================================================= // Private Member Variables ============================================================================================
private:
table_t _table;
hash_t _hash;
equal_t _equal;
size_t _size;
size_t _sumpsl;
float _load;
// Private Helpers =====================================================================================================
private: private:
constexpr void _expand() { constexpr void _expand() {
set cpy; // Create a new set set cpy; // Create a new set
cpy._alloc.resize( cpy._table.resize(
fennec::next_prime2(_alloc.capacity()) fennec::next_prime2(_table.capacity())
); );
// rehash // rehash
for (size_t i = 0; i < capacity(); ++i) { for (size_t i = 0; i < capacity(); ++i) {
if (_alloc[i].value) { if (_table[i].value) {
cpy.insert(fennec::move(*_alloc[i].value)); cpy.insert(fennec::move(*_table[i].value));
} }
} }
// Swap buffers // Swap buffers
fennec::swap(_alloc, cpy._alloc); fennec::swap(_table, cpy._table);
} }
template<typename...ArgsT> template<typename...ArgsT>
@@ -488,29 +603,33 @@ private:
elem_t value(fennec::forward<ArgsT>(args)...); elem_t value(fennec::forward<ArgsT>(args)...);
size_t i = _hash(value) % capacity(); // Initial search index size_t i = _hash(value) % capacity(); // Initial search index
int psl = 0; int psl = 0;
while (_alloc[i].value) { // Search for empty cell while (_table[i].value) { // Search for empty cell
if (_equal(*_alloc[i].value, value)) { // Check to see if this element is already inserted if (_equal(*_table[i].value, value)) { // Check to see if this element is already inserted
return iterator(this, i); return iterator(this, i);
} }
if (psl > _alloc[i].psl) { // When psl is higher, swap if (psl > _table[i].psl) { // When psl is higher, swap
_sumpsl += psl - _alloc[i].psl; _sumpsl += psl - _table[i].psl;
fennec::swap(_alloc[i].psl, psl); fennec::swap(_table[i].psl, psl);
fennec::swap(*_alloc[i].value, value); fennec::swap(*_table[i].value, value);
} }
i = (i + 1) % capacity(); ++psl; i = (i + 1) % capacity(); ++psl;
} }
_alloc[i].value = fennec::move(value); _table[i].value = fennec::move(value);
_sumpsl += (_alloc[i].psl = psl); _sumpsl += (_table[i].psl = psl);
++_size; ++_size;
return iterator(this, npos); return iterator(this, npos);
} }
dynarray<node, alloc_t> _alloc;
hash_t _hash; // Private Definitions =================================================================================================
equal_t _equal; private:
size_t _size; struct node {
size_t _sumpsl; optional<elem_t> value;
float _load; int psl;
constexpr node() = default;
constexpr ~node() = default;
};
}; };
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file traversal.h /// \file fennec/containers/traversal.h
/// \brief a header containing constants and utilities related to traversal /// \brief a header containing constants and utilities related to traversal
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -37,9 +37,9 @@ namespace fennec
/// ///
/// \brief A set of constants used in the traverser-visitor pattern /// \brief A set of constants used in the traverser-visitor pattern
enum traversal_control_ { enum traversal_control_ {
traversal_control_continue = 0, traversal_control_continue = 0, //!< Continue to the next element
traversal_control_break = 1, traversal_control_break = 1, //!< Break the traversal loop
traversal_control_jump_over = 2, traversal_control_jump_over = 2, //!< Jump over the next element
}; };
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file tuple.h /// \file fennec/containers/tuple.h
/// \brief A header containing the definition for a container with multiple values of differing types /// \brief A header containing the definition for a container with multiple values of differing types
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -43,7 +43,7 @@ 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 | ✅ |
/// | homogeneous | ⛔ | /// | homogeneous | ⛔ |
@@ -55,6 +55,7 @@ namespace fennec
/// | find | \f$O(1)\f$ | /// | find | \f$O(1)\f$ |
/// | insertion | ⛔ | /// | insertion | ⛔ |
/// | deletion | ⛔ | /// | deletion | ⛔ |
/// | space | \f$O(N)\f$ |
/// ///
/// \tparam TypesT The types to store /// \tparam TypesT The types to store
template<typename...TypesT> struct tuple; template<typename...TypesT> struct tuple;
@@ -86,8 +87,14 @@ constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<T
template<typename ...TypesT> template<typename ...TypesT>
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...> struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...> {
{
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>; //!< the base type using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>; //!< the base type
template<size_t i> template<size_t i>
@@ -95,10 +102,20 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
static constexpr size_t size = sizeof...(TypesT); //!< the number of elements held by the tuple static constexpr size_t size = sizeof...(TypesT); //!< the number of elements held by the tuple
/// @}
// Constructors & Destructor ===========================================================================================
public:
/// ///
/// \brief tuple constructor /// \brief tuple constructor
/// \tparam ArgsT The element types /// \tparam ArgsT The element types
/// \param args The arguments to initialize the tuple with /// \param args The arguments to initialize the tuple with
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> template<typename...ArgsT>
tuple(ArgsT&&...args) tuple(ArgsT&&...args)
: base_t(fennec::forward<ArgsT>(args)...) { : base_t(fennec::forward<ArgsT>(args)...) {
@@ -107,6 +124,10 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
/// ///
/// \brief copy constructor /// \brief copy constructor
/// \param cpy the tuple to copy /// \param cpy the tuple to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
tuple(const tuple& cpy) tuple(const tuple& cpy)
: base_t(cpy) { : base_t(cpy) {
} }
@@ -114,8 +135,12 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
/// ///
/// \brief move constructor /// \brief move constructor
/// \param mov the tuple to move /// \param mov the tuple to move
///
/// \par Complexity
/// \f$O(N)\f$
///
tuple(tuple&& mov) tuple(tuple&& mov)
: base_t(mov) { : base_t(fennec::forward<tuple>(mov)) {
} }
}; };

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file variant.h /// \file fennec/containers/variant.h
/// \brief Contains the definition for a structure that holds a single value from multiple types /// \brief Contains the definition for a structure that holds a single value from multiple types
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -40,10 +40,10 @@ namespace fennec
{ {
/// ///
/// \brief A structure that represents a union between `TypesT...` /// \brief A structure that represents a union between \f$TypesT\ldots\f$
/// \details /// \details
/// | Property | Value | /// | Property | Value |
/// |:-----------:|:-----------:| /// |:-----------:|:----------:|
/// | stable | ✅ | /// | stable | ✅ |
/// | dynamic | ⛔ | /// | dynamic | ⛔ |
/// | homogeneous | ⛔ | /// | homogeneous | ⛔ |
@@ -55,11 +55,13 @@ namespace fennec
/// | find | ⛔ | /// | find | ⛔ |
/// | insertion | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ |
/// | space | \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 {
// Assertions ========================================================================================================== // Assertions ==========================================================================================================
public:
static_assert( static_assert(
is_unique_v<TypesT...> and // No two types in TypesT... may be equivalent is_unique_v<TypesT...> and // No two types in TypesT... may be equivalent
@@ -69,58 +71,86 @@ struct variant {
); );
// Typedefs & Constants ================================================================================================ // Definitions & Constants =============================================================================================
public:
/// \name Constants
/// @{
static constexpr size_t size = max_element_size_v<TypesT...>; //!< size of the variant in bytes static constexpr size_t size = max_element_size_v<TypesT...>; //!< size of the variant in bytes
static constexpr size_t nulltype = sizeof...(TypesT); //!< id for a null type static constexpr size_t nulltype = sizeof...(TypesT); //!< id for a null type
/// @}
// Constructors ======================================================================================================== // Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// ///
/// \brief Default Constructor, constructs the first type in `TypesT...` that is default constructible /// \brief Default Constructor, constructs the first type in \f$TypesT\ldots\f$ that is default constructible
///
/// \par Complexity
/// \f$O(1)\f$
///
variant() variant()
: _bytes {} : _bytes {}
, _handle(&_bytes)
, _type(nulltype) { , _type(nulltype) {
using construct_t = search_element_t<is_default_constructible, TypesT...>; using construct_t = search_element_t<is_default_constructible, TypesT...>;
fennec::construct<construct_t>(_handle); this->_construct<construct_t>();
} }
/// ///
/// \brief Conversion Constructor, constructs the type in `TypesT...` that is identical to \f$T\f$ /// \brief Conversion Constructor, constructs the type in \f$TypesT\ldots\f$ that is identical to \f$T\f$
/// or the first that is constructible with \f$T\f$ /// or the first that is constructible with \f$T\f$
/// \tparam T The type of the value /// \tparam T The type of the value
/// \param t The value to forward /// \param t The value to forward
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> template<typename T>
variant(T&& t) variant(T&& t)
: _bytes {} : _bytes {}
, _handle(&_bytes)
, _type() { , _type() {
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>; using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>::type;
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>; using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>::type;
using construct_t = conditional_t<is_void_v<same_t>, convert_t, convert_t>; using construct_t = conditional_t<is_void_v<same_t>, convert_t, same_t>;
fennec::construct<construct_t>(_handle, fennec::forward<T>(t)); this->_construct<construct_t>(fennec::forward<T>(t));
} }
/// ///
/// \brief Emplace Constructor, constructs the first type in `TypesT...` that is constructible with `ArgsT...` /// \brief Emplace Constructor, constructs a type \f$T\f$ that is in \f$TypesT\ldots\f$ that is constructible with \f$ArgsT\ldots\f$
/// \tparam ArgsT The arguments of the constructor /// \tparam ArgsT The arguments of the constructor
/// \param args The argument values /// \param args The argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT> template<typename T, typename...ArgsT>
variant(type_identity<T>, ArgsT&&...args) variant(type_identity<T>, ArgsT&&...args)
: _bytes{} : _bytes{}
, _handle(&_bytes)
, _type(nulltype) { , _type(nulltype) {
static_assert(contains_element_v<T, TypesT...>, "T must be in TypesT..."); static_assert(contains_element_v<T, TypesT...>, "T must be in TypesT...");
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...); this->_construct<T>(fennec::forward<ArgsT>(args)...);
_type = find_element_v<T>; _type = find_element_v<T>;
} }
/// ///
/// \brief Copy Constructor /// \brief Copy Constructor
/// \param v The variant to copy /// \param v The variant to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
variant(const variant& v) variant(const variant& v)
: _bytes {} : _bytes {}
, _handle(&_bytes)
, _type(nulltype) { , _type(nulltype) {
if (v._type == nulltype) { if (v._type == nulltype) {
@@ -128,8 +158,8 @@ struct variant {
} }
((v._type == find_element_v<TypesT, TypesT...> ? ((v._type == find_element_v<TypesT, TypesT...> ?
fennec::construct<TypesT>(_handle, v.get<TypesT>()) : this->_construct<TypesT>(v.get<TypesT>()) :
(0) ((void)0)
), ...); ), ...);
_type = v._type; _type = v._type;
} }
@@ -137,8 +167,13 @@ struct variant {
/// ///
/// \brief Move Constructor /// \brief Move Constructor
/// \param v The variant to move /// \param v The variant to move
///
/// \par Complexity
/// \f$O(1)\f$
///
variant(variant&& v) noexcept variant(variant&& v) noexcept
: _bytes {} : _bytes {}
, _handle(&_bytes)
, _type() { , _type() {
if (v._type == nulltype) { if (v._type == nulltype) {
@@ -146,37 +181,52 @@ struct variant {
} }
((v._type == find_element_v<TypesT, TypesT...> ? ((v._type == find_element_v<TypesT, TypesT...> ?
fennec::construct<TypesT>(_handle, fennec::move(v.get<TypesT>())) : this->_construct<TypesT>(fennec::move(v.get<TypesT>())) :
(0) ((void)0)
), ...); ), ...);
_type = v._type; _type = v._type;
} }
/// ///
/// \brief Destructor, if a type is held, destruct it. /// \brief Destructor, if a type is held, destruct it.
///
/// \par Complexity
/// \f$O(1)\f$
///
~variant() { ~variant() {
_clear(); _clear();
} }
/// @}
// Assignment ========================================================================================================== // Assignment ==========================================================================================================
public:
/// \name Assignment
/// @{
/// ///
/// \brief value assignment operator /// \brief value assignment operator
/// \tparam T The type to assign /// \tparam T The type to assign
/// \param t the value to assign /// \param t the value to assign
/// \returns a reference to \f$self\f$ after assigning \f$t\f$ /// \returns a reference to \f$self\f$ after assigning \f$t\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> template<typename T>
variant& operator=(T&& t) { variant& operator=(T&& t) {
// First, check if \f$T\f$ is in `TypesT...` // First, check if T is in TypesT...
if constexpr((contains_element_v<T, TypesT> or ...)) { if constexpr((contains_element_v<T, TypesT> or ...)) {
using type_t = remove_reference_t<T>; using type_t = remove_reference_t<T>;
if (_type == find_element_v<type_t, TypesT...>) { if (_type == find_element_v<type_t, TypesT...>) {
*static_cast<type_t*>(_handle) = fennec::forward<T>(t); *_get<type_t>() = fennec::forward<T>(t);
} else { } else {
_clear(); _clear();
fennec::construct<type_t>(_handle, fennec::forward<T>(t)); this->_construct<type_t>(fennec::forward<T>(t));
_type = find_element_v<type_t, TypesT...>; _type = find_element_v<type_t, TypesT...>;
} }
return *this; return *this;
@@ -186,8 +236,8 @@ struct variant {
bool assigned = false; bool assigned = false;
if (_type != nulltype) { if (_type != nulltype) {
((_type == find_element_v<TypesT, TypesT...> ? ((_type == find_element_v<TypesT, TypesT...> ?
(*static_cast<TypesT*>(_handle) = fennec::forward<T>(t), assigned = true) : (*_get<TypesT>() = fennec::forward<T>(t), assigned = true) :
(0) ((void)0)
), ...); ), ...);
} }
@@ -198,7 +248,7 @@ struct variant {
// Otherwise, destruct, then construct // Otherwise, destruct, then construct
_clear(); _clear();
using construct_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>; using construct_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
fennec::construct<construct_t>(_handle, fennec::forward<T>(t)); this->_construct<construct_t>(fennec::forward<T>(t));
return *this; return *this;
} }
@@ -207,80 +257,127 @@ struct variant {
/// \tparam T The type to construct /// \tparam T The type to construct
/// \tparam ArgsT the argument types /// \tparam ArgsT the argument types
/// \param args the argument values /// \param args the argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>) template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
void emplace(ArgsT&&...args) { void emplace(ArgsT&&...args) {
_clear(); _clear();
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...); this->_construct<T>(fennec::forward<ArgsT>(args)...);
} }
/// ///
/// \brief deduced emplace function /// \brief deduced emplace function
/// \tparam ArgsT the argument types /// \tparam ArgsT the argument types
/// \param args the argument values /// \param args the argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<size_t I, typename...ArgsT> template<size_t I, typename...ArgsT>
void emplace(ArgsT&&...args) { void emplace(ArgsT&&...args) {
using type_t = nth_element_t<I, TypesT...>; using type_t = nth_element_t<I, TypesT...>;
_clear(); _clear();
fennec::construct<type_t>(fennec::forward<ArgsT>(args)...); this->_construct<type_t>(fennec::forward<ArgsT>(args)...);
} }
/// @}
// Access ============================================================================================================== // Access ==============================================================================================================
/// \name Access
/// @{
/// ///
/// \brief get the value of the variant interpreted as \f$T\f$ /// \brief get the value of the variant interpreted as \f$T\f$
/// \tparam T the type to interpret as /// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$ /// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> requires(contains_element_v<T, TypesT...>) template<typename T> requires(contains_element_v<T, TypesT...>)
T& get() { T& get() {
return *static_cast<T*>(_handle); return *_get<T>();
} }
/// ///
/// \tparam T the type to interpret as /// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$ /// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> requires(contains_element_v<T, TypesT...>) template<typename T> requires(contains_element_v<T, TypesT...>)
const T& get() const { const T& get() const {
return *static_cast<T*>(_handle); return *_get<T>();
} }
/// ///
/// \tparam T the type to interpret as /// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$ /// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>) template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
T& get() { T& get() {
return *static_cast<T*>(_handle); return *_get<T>();
} }
/// ///
/// \tparam T the type to interpret as /// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$ /// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>) template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
const T& get() const { const T& get() const {
return *static_cast<T*>(_handle); return *_get<T>();
} }
/// @}
// Private Member Variables ============================================================================================
private: private:
union {
byte_t _bytes[size]; byte_t _bytes[size];
void* _handle; void* _handle;
};
size_t _type; size_t _type;
// Private Helpers =====================================================================================================
private:
template<typename T>
T* _get() const {
return static_cast<T*>(_handle);
}
void _clear() { void _clear() {
if (_type == nulltype) { if (_type == nulltype) {
return; return;
} }
((_type == find_element_v<TypesT, TypesT...> ? ((_type == find_element_v<TypesT, TypesT...> ?
fennec::destruct<TypesT>(_handle) : this->_destruct<TypesT>() :
(0) ((void)0)
), ...); ), ...);
_type = nulltype; _type = nulltype;
} }
template<typename ConstructT, typename...ArgsT>
void _construct(ArgsT&&...args) {
fennec::construct<ConstructT>(_get<ConstructT>(), fennec::forward<ArgsT>(args)...);
}
template<typename DestructT>
void _destruct() {
fennec::destruct(_get<DestructT>());
}
}; };
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file engine.h /// \file fennec/core/engine.h
/// \brief fennec::engine definition /// \brief fennec::engine definition
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -49,7 +49,7 @@
/// 2. \ref fennec_memory "Memory Management Library" /// 2. \ref fennec_memory "Memory Management Library"
/// 2. \ref fennec_containers "Containers Library" /// 2. \ref fennec_containers "Containers Library"
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -63,7 +63,7 @@
/// | \subpage fennec_containers | Implementation of common data structures, those that are specified in the C++ STD Library, and custom data structures that fennec uses. | /// | \subpage fennec_containers | Implementation of common data structures, those that are specified in the C++ STD Library, and custom data structures that fennec uses. |
/// ///
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
#ifndef FENNEC_CORE_ENGINE_H #ifndef FENNEC_CORE_ENGINE_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -32,29 +32,84 @@ struct event;
/// ///
/// \brief Class outlining the interface for an object that listens for events /// \brief Class outlining the interface for an object that listens for events
class event_listener { class event_listener {
// Constructors & Destructor ===========================================================================================
public: public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Virtual Destructor
virtual ~event_listener(); virtual ~event_listener();
/// @}
// Event Handling ======================================================================================================
public:
/// \name Event Handling
/// @{
/// ///
/// \brief event handler callback /// \brief event handler callback
/// \param event the event to handle /// \param event the event to handle
virtual void handle_event(event* event) = 0; virtual void handle_event(event* event) = 0;
#ifndef FENNEC_DOXYGEN /// @}
// Private Member Variables ============================================================================================
private:
FENNEC_RTTI_CLASS_ENABLE() { FENNEC_RTTI_CLASS_ENABLE() {
} }
#endif
}; };
/// ///
/// \brief Main event interface, includes static methods for registering listeners and dispatching events /// \brief Main event interface, includes static methods for registering listeners and dispatching events
struct event { struct event {
// Constructor & Destructor ============================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor
event() = default;
///
/// \brief Copy Constructor
event(const event&) = default;
///
/// \brief Move Constructor
event(event&&) noexcept = default;
///
/// \brief Virtual Destructor
virtual ~event() = default; virtual ~event() = default;
/// @}
// Static Event System Interface =======================================================================================
public:
/// \name Event System Interface
/// @{
///
/// \brief Handles the event loop to distribute events.
///
/// \details Blocking
static void handle_events(); static void handle_events();
/// ///
/// \brief Registers a listener for the event type /// \brief Registers a listener for the event type
///
/// \details Blocking
/// \tparam EventT the event type /// \tparam EventT the event type
/// \param listener the listener to register /// \param listener the listener to register
template<typename EventT> template<typename EventT>
@@ -63,20 +118,40 @@ struct event {
} }
/// ///
/// \brief removes a listener from the event system /// \brief Removes a listener from the event system
///
/// \details Blocking
/// \param listener the listener to remove /// \param listener the listener to remove
static void remove_listener(event_listener* listener); static void remove_listener(event_listener* listener);
///
/// \brief Dispatch an event at the beginning of the next tick.
///
/// \details Non-Blocking, Lock-Free, Wait-Free
/// \tparam EventT The event type
/// \tparam ArgsT The argument types
/// \param args The arguments to construct the event with
template<typename EventT, typename...ArgsT> template<typename EventT, typename...ArgsT>
static void dispatch(ArgsT&&...args) { static void dispatch(ArgsT&&...args) {
event::_dispatch(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...)); event::_dispatch(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...));
} }
///
/// \brief Dispatch an event immediately, on the current thread.
///
/// \details Blocking
/// \tparam EventT The event type
/// \tparam ArgsT The argument types
/// \param args The arguments to construct the event with
template<typename EventT, typename...ArgsT> template<typename EventT, typename...ArgsT>
static void dispatch_immediate(ArgsT&&...args) { static void dispatch_immediate(ArgsT&&...args) {
event::_dispatch_immediate(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...)); event::_dispatch_immediate(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...));
} }
/// @}
// Private Helpers =====================================================================================================
private: private:
static void _add_listener(event_listener* listener, uint64_t type); static void _add_listener(event_listener* listener, uint64_t type);
static void _handle_event(unique_ptr<event>& event); static void _handle_event(unique_ptr<event>& event);

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file logger.h /// \file fennec/core/logger.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -42,11 +42,12 @@ namespace fennec
/// ///
/// \brief logger class /// \brief logger class
class logger : public singleton<logger> { class logger : public singleton<logger> {
// Logger System Interface =============================================================================================
public: public:
///
/// \brief default constructor /// \name System Interface
logger(); /// @{
~logger();
/// ///
/// \brief Log a string to the log file and cout /// \brief Log a string to the log file and cout
@@ -92,9 +93,21 @@ public:
inst._cout->println(str); inst._cout->println(str);
} }
/// @}
// Private Member Variables ============================================================================================
private: private:
file _logfile; file _logfile;
file* _cout; file* _cout;
// Private Constructors & Destructor ===================================================================================
private:
logger();
~logger();
friend struct singleton;
}; };
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file version.h /// \file fennec/core/version.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -32,6 +32,16 @@
#ifndef FENNEC_CORE_VERSION_H #ifndef FENNEC_CORE_VERSION_H
#define FENNEC_CORE_VERSION_H #define FENNEC_CORE_VERSION_H
#if FENNEC_COMPILER_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
#if FENNEC_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable:4201)
#endif
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
#include <fennec/string/string.h> #include <fennec/string/string.h>
@@ -41,20 +51,73 @@ 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 = { 1 }; //!< the major version
uint32_t minor = { 0 }; //!< the minor version
uint32_t patch = { 0 }; //!< the patch
string str = { string("") }; //!< string representation of the version
// Public Member Variables =============================================================================================
public:
/// \name Member Variables
/// @{
union {
uint64_t num; //!< long version number
struct {
uint16_t major = { 1 }; //!< the major version
uint16_t minor = { 0 }; //!< the minor version
uint16_t patch = { 0 }; //!< the patch version
uint16_t meta = { 0 }; //!< the meta version, e.g. "rc.1"
};
};
/// @}
// Comparison Operators ================================================================================================
public:
/// \name Comparison Operators
/// @{
///
/// \brief Equality Operator
/// \param lhs The e
friend bool operator==(const version& lhs, const version& rhs) { 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; return lhs.num == rhs.num;
} }
friend bool operator!=(const version& lhs, const version& rhs) { 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; return lhs.num != rhs.num;
} }
///
/// \brief
/// \param lhs
/// \param rhs
/// \return
friend bool operator<(const version& lhs, const version& rhs) {
return lhs.num < rhs.num;
// This generates branching instructions, even in -O4
//return lhs.major < rhs.major or(
// (lhs.major == rhs.major and lhs.minor < rhs.minor) or (
// lhs.minor == rhs.minor and lhs.patch < rhs.patch
// )
//);
}
friend bool operator>(const version& lhs, const version& rhs) {
return lhs.num > rhs.num;
}
/// @}
}; };
#ifdef FENNEC_COMPILER_GCC
#pragma GCC diagnostic pop
#endif
#if FENNEC_COMPILER_MSVC
#pragma warning(pop)
#endif
} }
#endif // FENNEC_CORE_VERSION_H #endif // FENNEC_CORE_VERSION_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -45,23 +45,23 @@ namespace fennec
/// <tr><td style="vertical-align: top">\f$write\f$ /// <tr><td style="vertical-align: top">\f$write\f$
/// <td style="vertical-align: top">Opens file as write-only, writing to end /// <td style="vertical-align: top">Opens file as write-only, writing to end
/// ///
/// <tr><td style="vertical-align: top">`read | write` /// <tr><td style="vertical-align: top">\f$read | write\f$
/// <td style="vertical-align: top">Opens file as read-write, reading from start /// <td style="vertical-align: top">Opens file as read-write, reading from start
/// ///
/// <tr><td style="vertical-align: top">`write | trunc` /// <tr><td style="vertical-align: top">\f$write | trunc\f$
/// <td style="vertical-align: top">Opens file as write-only, destroying contents /// <td style="vertical-align: top">Opens file as write-only, destroying contents
/// ///
/// <tr><td style="vertical-align: top">`read | write | trunc` /// <tr><td style="vertical-align: top">\f$read | write | trunc\f$
/// <td style="vertical-align: top">Opens file as read-write, destroying contents /// <td style="vertical-align: top">Opens file as read-write, destroying contents
/// </table> /// </table>
enum fmode_ : uint8_t enum fmode_ : uint8_t
{ {
fmode_read = 0b00000001 ///< Opens file for reading fmode_read = 0b00000001 //!< Opens file for reading
, fmode_write = 0b00000010 ///< Opens file for writing , fmode_write = 0b00000010 //!< Opens file for writing
, fmode_trunc = 0b00000100 ///< Contents of the file will be destroyed, only compatible with write enabled modes , fmode_trunc = 0b00000100 //!< Contents of the file will be destroyed, only compatible with write enabled modes
, fmode_exclusive = 0b00001000 ///< Generates an error if the opened file is not empty , fmode_exclusive = 0b00001000 //!< Generates an error if the opened file is not empty
, fmode_binary = 0b00010000 ///< Open in binary mode , fmode_binary = 0b00010000 //!< Open in binary mode
, fmode_wide = 0b00100000 ///< Opens a file in wide mode , fmode_wide = 0b00100000 //!< Opens a file in wide mode
}; };
/// ///
@@ -71,12 +71,30 @@ enum fmode_ : uint8_t
/// Use file::get_error() to check if an error is present and return a corresponding string. /// Use file::get_error() to check if an error is present and return a corresponding string.
/// Use file::clear_error() to clear the errored state. /// Use file::clear_error() to clear the errored state.
/// Some operations, specifically file::rename() and file::copy(). /// Some operations, specifically file::rename() and file::copy().
/// <br>
/// This file paradigm is to subvert time-of-check time-of-use (TOCTOU) attacks. This involves a threat actor
/// reading that our application checks if a file exists, and replacing the file with another malicious file
/// or symlink between our call to open the file.
class file class file
{ {
// Constants ===========================================================================================================
public: public:
/// \name Constants
/// @{
/// \brief value of an invalid position /// \brief value of an invalid position
static constexpr size_t npos = -1; static constexpr size_t npos = -1;
/// @}
// Validation Functions ================================================================================================
public:
/// \name Validation Functions
/// @{
/// ///
/// \brief Check if the provided mode bitflags are a valid combination /// \brief Check if the provided mode bitflags are a valid combination
/// \param mode the bitfield /// \param mode the bitfield
@@ -93,24 +111,43 @@ public:
|| !(t || x); || !(t || x);
} }
/// @}
// STD Text Streams ====================================================================================================
public:
/// \name STD Text Streams
/// @{
/// ///
/// \returns the c stdout /// \returns the c stdout stream
static file& cout(); static file& cout();
/// ///
/// \returns the c stdin /// \returns the c stdin stream
static file& cin(); static file& cin();
/// ///
/// \returns the c stderr /// \returns the c stderr stream
static file& cerr(); static file& cerr();
/// @}
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// ///
/// \brief default constructor, initializes an empty stream /// \brief Default constructor
/// \details Initializes an empty stream
file(); file();
/// ///
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$ /// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
/// \param path the path of the file /// \param path the path of the file
/// \param mode the mode to open with /// \param mode the mode to open with
file(const cstring& path, uint8_t mode) file(const cstring& path, uint8_t mode)
@@ -119,7 +156,7 @@ public:
} }
/// ///
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$ /// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
/// \param path the path of the file /// \param path the path of the file
/// \param mode the mode to open with /// \param mode the mode to open with
file(const string& path, uint8_t mode) file(const string& path, uint8_t mode)
@@ -128,7 +165,8 @@ public:
} }
/// ///
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$ /// \brief Path constructor
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
/// \param path the path of the file /// \param path the path of the file
/// \param mode the mode to open with /// \param mode the mode to open with
file(const path& path, uint8_t mode) file(const path& path, uint8_t mode)
@@ -137,141 +175,190 @@ public:
} }
/// ///
/// \brief default destructor, cleans up an open stream /// \brief Move constructor
~file();
///
/// \brief move constructor
/// \param file the stream to take ownership of /// \param file the stream to take ownership of
file(file&& file) noexcept; file(file&& file) noexcept;
/// ///
/// \brief move assignment /// \brief Destructor
/// \details Flushes and closes an open stream
~file();
///
/// \brief Move assignment
/// \param file the stream to take ownership of /// \param file the stream to take ownership of
file& operator=(file&& file) noexcept; file& operator=(file&& file) noexcept;
///@}
private:
// don't allow copying streams // don't allow copying streams
file(const file&) = delete; file(const file&) = delete;
file& operator=(const file&) = delete;
// Properties ========================================================================================================== // Properties ==========================================================================================================
public:
/// \name Properties
/// @{
/// ///
/// \returns the path the stream /// \returns The path the stream
const path& get_path() const { const path& get_path() const {
return _path; return _path;
} }
/// ///
/// \returns the mode of the stream /// \returns The mode of the stream
uint8_t mode() const { uint8_t mode() const {
return _mode; return _mode;
} }
/// ///
/// \returns true if there is a valid, open stream. /// \returns \f$true\f$ if there is a valid, open stream.
bool is_open() const { bool is_open() const {
return _handle != nullptr; return _handle != nullptr;
} }
/// @}
// File Access ========================================================================================================= // File Access =========================================================================================================
public:
/// \name File Access
/// @{
/// ///
/// \brief open a file
/// \param path the path to the file /// \param path the path to the file
/// \param mode the mode flags to open the file with /// \param mode the mode flags to open the file with
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
bool open(const cstring& path, uint8_t mode); bool open(const cstring& path, uint8_t mode);
/// ///
/// \brief open a file
/// \param path the path to the file /// \param path the path to the file
/// \param mode the mode flags to open the file with /// \param mode the mode flags to open the file with
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
bool open(const string& path, uint8_t mode); bool open(const string& path, uint8_t mode);
/// ///
/// \brief open a file /// \brief Open a file
/// \param path the path to the file /// \param path the path to the file
/// \param mode the mode flags to open the file with /// \param mode the mode flags to open the file with
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
bool open(const path& path, uint8_t mode); bool open(const path& path, uint8_t mode);
/// ///
/// \brief close a stream /// \brief Close a stream
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
bool close(); bool close();
/// ///
/// \brief commit the streams buffer to the file /// \brief Commit the streams buffer to the file
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
bool commit(); bool commit();
/// @}
// File Operations ===================================================================================================== // File Operations =====================================================================================================
public:
/// \name File Operations
/// @{
/// ///
/// \brief closes the stream and erases the file /// \brief closes the stream and erases the file
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
bool erase(); bool erase();
/// ///
/// \brief rebinds the stream, copying contents to path, and erasing the old file
/// \param path the new path /// \param path the new path
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
/// ///
/// \details attempts to open a write-only stream at path, /// \details
/// attempts to reopen this file as read-only, /// Copies contents to the new path, and erases the old file.
/// copies the contents of this file to the new stream, /// * Attempts to open a write-only stream at path
/// reopen the new stream with the flags of this file and binds to it, /// * Attempts to reopen this file as read-only
/// closes the old file. /// * Copies the contents of this file to the new stream
/// * Reopen the new stream with the flags of this file and binds to it
/// * Closes the old file
bool rename(const cstring& path); bool rename(const cstring& path);
/// ///
/// \brief rebinds the stream, copying contents to path, and erasing the old file
/// \param path the new path /// \param path the new path
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
/// ///
/// \details attempts to open a write-only stream at path, /// \details
/// attempts to reopen this file as read-only, /// Copies contents to the new path, and erases the old file.
/// copies the contents of this file to the new stream, /// * Attempts to open a write-only stream at path
/// reopen the new stream with the flags of this file and binds to it, /// * Attempts to reopen this file as read-only
/// closes the old file. /// * Copies the contents of this file to the new stream
/// * Reopen the new stream with the flags of this file and binds to it
/// * Closes the old file
bool rename(const string& path); bool rename(const string& path);
/// ///
/// \brief rebinds the stream, copying contents to path, and erasing the old file /// \brief Rebind the stream.
/// \param path the new path /// \param path the new path
/// \returns false on success, true on error /// \returns \f$false\f$ on success, \f$true\f$ on error
/// ///
/// \details attempts to open a write-only stream at path, /// \details
/// attempts to reopen this file as read-only, /// Copies contents to the new path, and erases the old file.
/// copies the contents of this file to the new stream, /// * Attempts to open a write-only stream at path
/// reopen the new stream with the flags of this file and binds to it, /// * Attempts to reopen this file as read-only
/// closes the old file. /// * Copies the contents of this file to the new stream
/// * Reopen the new stream with the flags of this file and binds to it
/// * Closes the old file
bool rename(const path& path); bool rename(const path& path);
/// ///
/// \brief copies the contents of this file to path.
/// \param path the path to copy to /// \param path the path to copy to
/// \returns a file at the new path with the copied contents /// \returns a file at the new path with the copied contents
///
/// \details
/// Copies the contents to a new stream at the provided path.
/// * Attempts to open a write-only stream at path, <br>
/// * Attempts to reopen this file as read-only, <br>
/// * Copies the contents of this file to the new stream, <br>
/// * Reopen the new stream with the flags of this file.
file copy(const cstring& path); file copy(const cstring& path);
/// ///
/// \brief copies the contents of this file to path.
/// \param path the path to copy to /// \param path the path to copy to
/// \returns a file at the new path with the copied contents /// \returns a file at the new path with the copied contents
///
/// \details
/// Copies the contents to a new stream at the provided path.
/// * Attempts to open a write-only stream at path, <br>
/// * Attempts to reopen this file as read-only, <br>
/// * Copies the contents of this file to the new stream, <br>
/// * Reopen the new stream with the flags of this file.
file copy(const string& path); file copy(const string& path);
/// ///
/// \brief copies the contents of this file to path. /// \brief Copy contents to a new file.
/// \details Copies the contents of the current stream into a new stream bound to the file at the provided path.
/// \param path the path to copy to /// \param path the path to copy to
/// \returns a file at the new path with the copied contents /// \returns a file at the new path with the copied contents
///
/// \details
/// Copies the contents to a new stream at the provided path.
/// * Attempts to open a write-only stream at path, <br>
/// * Attempts to reopen this file as read-only, <br>
/// * Copies the contents of this file to the new stream, <br>
/// * Reopen the new stream with the flags of this file.
file copy(const path& path); file copy(const path& path);
/// @}
// File Positioning ==================================================================================================== // File Positioning ====================================================================================================
public:
/// \name File Positioning
/// @{
/// ///
/// \returns the position index in the stream /// \returns the position index in the stream
@@ -291,8 +378,14 @@ public:
/// \returns \f$true\f$ if the stream has reached the end of the file, \f$false\f$ otherwise /// \returns \f$true\f$ if the stream has reached the end of the file, \f$false\f$ otherwise
bool eof() const; bool eof() const;
/// @}
// Binary Read Operations ============================================================================================== // Binary Read Operations ==============================================================================================
public:
/// \name Binary Read Operations
/// @{
/// ///
/// \brief binary read /// \brief binary read
@@ -324,8 +417,14 @@ public:
return read(static_cast<void*>(data), sizeof(T), n); return read(static_cast<void*>(data), sizeof(T), n);
} }
/// @}
// Binary Write Operations ============================================================================================= // Binary Write Operations =============================================================================================
public:
/// \name Binary Write Operations
/// @{
/// ///
/// \brief put a character at the current position in the stream /// \brief put a character at the current position in the stream
@@ -389,27 +488,43 @@ public:
return write(static_cast<const void*>(data), sizeof(T), n); return write(static_cast<const void*>(data), sizeof(T), n);
} }
/// @}
// Read Operations ===================================================================================================== // Read Operations =====================================================================================================
public:
/// \name Read Operations
/// @{
/// ///
/// \returns the character read at the current position in the stream /// \returns the character read at the current position in the stream
/// \details Advances the position by one character
char getc(); char getc();
/// ///
/// \returns the wide character read at the current position in the stream /// \returns the wide character read at the current position in the stream
/// \details Advances the position by one wide character
wchar_t getwc(); wchar_t getwc();
/// ///
/// \returns a string containing all characters from the current position in the stream to the next newline character /// \returns A string containing the characters from the current position to the next newline character
/// \details Advances the position to the character following the next newline character
string getline(); string getline();
/// ///
/// \returns a string containing all characters from the current position in the stream to the next newline character /// \returns A wide string containing the characters from the current position to the next newline character
/// \details Advances the position to the character following the next newline character
wstring getwline(); wstring getwline();
/// @}
// Printing Operations ================================================================================================= // Printing Operations =================================================================================================
public:
/// \name Print Operations
/// @{
/// ///
/// \param str the string to print /// \param str the string to print
@@ -440,19 +555,28 @@ public:
this->print(cstring(fmt.cstr(), fmt.length())); this->print(cstring(fmt.cstr(), fmt.length()));
} }
/// @}
// Error Handling ====================================================================================================== // Error Handling ======================================================================================================
public:
/// \name Error Handling
/// @{
/// ///
/// \returns the current error state of the file /// \brief Returns the current error state.
const char* get_error() const { return _error; } /// \returns A string containing the current error.
cstring get_error() const { return { _error, ::strlen(_error) }; }
/// ///
/// \brief clears the errored state /// \brief clears the errored state
void clear_error() { _error = nullptr; } void clear_error() { _error = nullptr; }
/// @}
private: private:
FILE* _handle; FILE* _handle;
path _path; path _path;

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -30,28 +30,38 @@ namespace fennec
/// ///
/// \details This structure makes no guarantees about the validity of a path. /// \details This structure makes no guarantees about the validity of a path.
/// Operations do not examine the system's file structure. /// Operations do not examine the system's file structure.
struct path struct path {
{
public:
// Definitions ========================================================================================================= // Definitions =========================================================================================================
public:
class iterator; class iterator;
friend class iterator; friend class iterator;
// Static Functions ==================================================================================================== // Current Working Director ============================================================================================
public:
/// \name Current Working Directory
/// @{
/// \brief Get the current working directory /// \brief Get the current working directory
/// \returns a path containing the absolute path to the working directory /// \returns a path containing the absolute path to the working directory
static path current(); static path get_current();
/// \brief Set the current working directory /// \brief Set the current working directory
/// \param path the path to the new working directory /// \param path the path to the new working directory
/// \returns a path containing the absolute path to the working directory /// \returns a path containing the absolute path to the working directory
static path current(const path& path); static path set_current(const path& path);
/// @}
// Constructors ======================================================================================================== // Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// ///
/// \brief Default Constructor, returns the root of the current working directory /// \brief Default Constructor, returns the root of the current working directory
@@ -89,8 +99,18 @@ public:
/// \param p the path to take ownership of /// \param p the path to take ownership of
path(path&& p) noexcept : _str(move(p._str)) { } path(path&& p) noexcept : _str(move(p._str)) { }
///
/// \brief Destructor
~path() = default;
/// @}
// Assignment Operators ================================================================================================ // Assignment Operators ================================================================================================
public:
/// \name Assignment
/// @{
/// ///
/// \brief C-String Assignment Operator /// \brief C-String Assignment Operator
@@ -138,8 +158,31 @@ public:
return *this; return *this;
} }
/// @}
// Append Operators ====================================================================================================
// Comparison ==========================================================================================================
public:
/// \name Comparison
/// @{
///
/// \brief path equality operator
/// \param p the path to compare against
/// \returns \f$true\f$ if the paths are identical, \f$false\f$ otherwise. relative paths are not resolved
bool operator==(const path& p) const {
return _str == p._str;
}
/// @}
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
/// ///
/// \brief path append operator /// \brief path append operator
@@ -165,13 +208,7 @@ public:
return path(_str + '/' + p._str); return path(_str + '/' + p._str);
} }
/// /// @}
/// \brief path equality operator
/// \param p the path to compare against
/// \returns \f$true\f$ if the paths are identical, \f$false\f$ otherwise. relative paths are not resolved
bool operator==(const path& p) const {
return _str == p._str;
}
/// ///
/// \brief the filename of the current path /// \brief the filename of the current path
@@ -240,7 +277,7 @@ public:
#else #else
if (_str[0] != '/') { if (_str[0] != '/') {
#endif #endif
working = current(); working = get_current();
} }
while (not parse.is_empty()) { while (not parse.is_empty()) {
@@ -278,24 +315,28 @@ public:
} }
// Iterator ============================================================================================================ // Iteration ===========================================================================================================
public:
/// \name Iteration
/// @{
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the first filename in the path /// \returns an iterator at the first filename in the path
iterator begin() const { iterator begin() const {
return iterator(this, 0); return iterator(this, 0);
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator to the end of the path /// \returns an iterator to the end of the path
iterator end() const { iterator end() const {
return iterator(this, _str.size()); return iterator(this, _str.size());
} }
/// ///
/// \brief C++ Iterator Specification `iterator` /// \brief C++ Iterator Specification \f$iterator\f$
class iterator { class iterator {
public: public:
/// ///
@@ -386,6 +427,8 @@ public:
friend struct path; friend struct path;
}; };
/// @}
private: private:
string _str; string _str;
}; };

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file charconv.h /// \file fennec/format/charconv.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -16,18 +16,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
///
/// \file _format.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_FORMAT_DETAIL_FORMAT_H #ifndef FENNEC_FORMAT_DETAIL_FORMAT_H
#define FENNEC_FORMAT_DETAIL_FORMAT_H #define FENNEC_FORMAT_DETAIL_FORMAT_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file format.h /// \file fennec/format/format.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -38,6 +38,7 @@
namespace fennec namespace fennec
{ {
/// ///
/// \brief C++ 20 format specification /// \brief C++ 20 format specification
/// \tparam ArgsT The argument types /// \tparam ArgsT The argument types

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file format_arg.h /// \file fennec/format/format_arg.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -35,6 +35,7 @@
namespace fennec namespace fennec
{ {
/// ///
/// \brief helper struct for `fennec::format` /// \brief helper struct for `fennec::format`
struct format_arg { struct format_arg {

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file formatter.h /// \file fennec/format/formatter.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file tokenizer.h /// \file fennec/interpret/tokenizer.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -65,12 +65,12 @@ struct tokenizer {
using escseq = escape_sequence*; using escseq = escape_sequence*;
using escmap = map<char, escape_sequence*>; using escmap = map<char, escape_sequence*>;
string delimiter; // markers that separate tokens string delimiter; //!< markers that separate tokens
string operators; // operators are treated as individual tokens string operators; //!< operators are treated as individual tokens
string brackets; // characters that mark brackets string brackets; //!< characters that mark brackets
string quotes; // characters that mark a string sequence, entire string sequence is treated as one token string quotes; //!< characters that mark a string sequence, entire string sequence is treated as one token
escmap escapes; // characters that mark the start of an escape sequence and validate them escmap escapes; //!< characters that mark the start of an escape sequence and validate them
bool numbers; // Anything that resembles a number bool numbers; //!< Anything that resembles a number
enum token_ : uint8_t { enum token_ : uint8_t {
token_text = 0, token_text = 0,

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file assert.h /// \file fennec/lang/assert.h
/// \brief \ref fennec_lang_assert /// \brief \ref fennec_lang_assert
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file bits.h /// \file fennec/lang/bits.h
/// \brief \ref fennec_lang_bit_manipulation /// \brief \ref fennec_lang_bit_manipulation
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -161,7 +161,7 @@ struct inequality<T0, T1> {
// less ================================================================================================================ // less ================================================================================================================
/// ///
/// \brief Struct to test if a value of type `T0` is less than a value of type `T1` /// \brief Struct to test if a value of type \f$T0\f$ is less than a value of type \f$T1\f$
/// \tparam T0 The first type /// \tparam T0 The first type
/// \tparam T1 The second type /// \tparam T1 The second type
template<typename T0, typename T1 = T0> requires has_less_v<T0, T1> template<typename T0, typename T1 = T0> requires has_less_v<T0, T1>
@@ -180,7 +180,7 @@ struct less {
// less_equal ========================================================================================================== // less_equal ==========================================================================================================
/// ///
/// \brief Struct to test if a value of type `T0` is less than or equal to a value of type `T1` /// \brief Struct to test if a value of type \f$T0\f$ is less than or equal to a value of type \f$T1\f$
/// \tparam T0 The first type /// \tparam T0 The first type
/// \tparam T1 The second type /// \tparam T1 The second type
template<typename T0, typename T1 = T0> requires has_less_equals_v<T0, T1> template<typename T0, typename T1 = T0> requires has_less_equals_v<T0, T1>
@@ -199,7 +199,7 @@ struct less_equals {
// greater ============================================================================================================= // greater =============================================================================================================
/// ///
/// \brief Struct to test if a value of type `T0` is greater than a value of type `T1` /// \brief Struct to test if a value of type \f$T0\f$ is greater than a value of type \f$T1\f$
/// \tparam T0 The first type /// \tparam T0 The first type
/// \tparam T1 The second type /// \tparam T1 The second type
template<typename T0, typename T1 = T0> requires has_greater_v<T0, T1> template<typename T0, typename T1 = T0> requires has_greater_v<T0, T1>
@@ -218,7 +218,7 @@ struct greater {
// less_equal ========================================================================================================== // less_equal ==========================================================================================================
/// ///
/// \brief Struct to test if a value of type `T0` is greater than or equal to a value of type `T1` /// \brief Struct to test if a value of type \f$T0\f$ is greater than or equal to a value of type \f$T1\f$
/// \tparam T0 The first type /// \tparam T0 The first type
/// \tparam T1 The second type /// \tparam T1 The second type
template<typename T0, typename T1 = T0> requires has_greater_equals_v<T0, T1> template<typename T0, typename T1 = T0> requires has_greater_equals_v<T0, T1>

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file conditional_types.h /// \file fennec/lang/conditional_types.h
/// \brief \ref fennec_lang_conditional_types /// \brief \ref fennec_lang_conditional_types
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -75,7 +75,7 @@ namespace fennec
/// \brief select between two types based on a condition /// \brief select between two types based on a condition
/// ///
/// \details Selects between \p TrueT and \p FalseT based on the boolean value \p b. /// \details Selects between \p TrueT and \p FalseT based on the boolean value \p b.
/// The chosen type is stored in `conditional::type`. /// The chosen type is stored in `fennec::conditional::type`.
/// \tparam B the value of the condition /// \tparam B the value of the condition
/// \tparam TrueT type to use when \f$B == true\f$ /// \tparam TrueT type to use when \f$B == true\f$
/// \tparam FalseT type to use when \f$B == false\f$ /// \tparam FalseT type to use when \f$B == false\f$
@@ -84,7 +84,7 @@ struct conditional;
/// ///
/// \brief Shorthand for ```typename conditional<ConditionV, TrueT, FalseT>::type``` /// \brief Shorthand for `typename fennec::conditional<ConditionV, TrueT, FalseT>::type`
template<bool B, typename TrueT, typename FalseT> template<bool B, typename TrueT, typename FalseT>
using conditional_t using conditional_t
= typename conditional<B, TrueT, FalseT>::type; = typename conditional<B, TrueT, FalseT>::type;
@@ -103,13 +103,13 @@ struct conditional<false, T, F> : type_identity<F>{};
// fennec::detect ====================================================================================================== // fennec::detect ======================================================================================================
/// ///
/// \brief Detect whether `DetectT<ArgsT...>` is a valid type /// \brief Detect whether \f$DetectT<ArgsT...>\f$ is a valid type
/// ///
/// \details Selects `DetectT<ArgsT...>` if it exists, otherwise selects \f$DefaultT\f$ The chosen type is stored in `detect::type` and /// \details Selects \f$DetectT<ArgsT...>\f$ if it exists, otherwise selects \f$DefaultT\f$ The chosen type is stored in `fennec::detect::type` and
/// a boolean value is stored in `detect::is_detected` representing whether `DetectT<ArgsT...>` is found. /// a boolean value is stored in `fennec::detect::is_detected` representing whether \f$DetectT<ArgsT...>\f$ is found.
/// \tparam DefaultT Default type /// \tparam DefaultT Default type
/// \tparam DetectT Type to detect /// \tparam DetectT Type to detect
/// \tparam ArgsT Any template arguments for `DetectT<ArgsT>` /// \tparam ArgsT Any template arguments for \f$DetectT<ArgsT>\f$
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT> template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
struct detect struct detect
{ {
@@ -118,7 +118,7 @@ struct detect
}; };
/// ///
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type``` /// \brief Shorthand for `typename fennec::detect<DefaultT, DetectT, ArgsT...>::type`
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT> template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
using detect_t = typename detect<DefaultT, DetectT, ArgsT...>::type; using detect_t = typename detect<DefaultT, DetectT, ArgsT...>::type;
@@ -154,7 +154,7 @@ template<bool B, typename T = void>
struct enable_if {}; struct enable_if {};
/// ///
/// \brief Shorthand for ```typename enable_if<B, T>::type``` /// \brief Shorthand for `typename fennec::enable_if<B, T>::type`
template<bool B, typename T = void> template<bool B, typename T = void>
using enable_if_t = typename enable_if<B, T>::type; using enable_if_t = typename enable_if<B, T>::type;

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file constants.h /// \file fennec/lang/constants.h
/// \brief \ref fennec_lang_constants /// \brief \ref fennec_lang_constants
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file declval.h /// \file fennec/lang/declval.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -16,18 +16,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
///
/// \file _declval.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_DETAIL_DECLVAL_H #ifndef FENNEC_LANG_DETAIL_DECLVAL_H
#define FENNEC_LANG_DETAIL_DECLVAL_H #define FENNEC_LANG_DETAIL_DECLVAL_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -16,18 +16,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
///
/// \file _function.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_DETAIL_FUNCTION_H #ifndef FENNEC_LANG_DETAIL_FUNCTION_H
#define FENNEC_LANG_DETAIL_FUNCTION_H #define FENNEC_LANG_DETAIL_FUNCTION_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -67,7 +67,7 @@ namespace fennec::detail
template<size_t N, typename FindT, typename HeadT> template<size_t N, typename FindT, typename HeadT>
struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {}; struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {};
template<size_t N, typename FindT, typename HeadT, typename...RestT> requires(is_same_v<FindT, HeadT>) template<size_t N, typename FindT, typename HeadT, typename...RestT>
struct _find_element<N, FindT, HeadT, RestT...> struct _find_element<N, FindT, HeadT, RestT...>
: conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {}; : conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {};

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,13 +17,15 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file float.h /// \file fennec/lang/float.h
/// \brief metaprogramming floating point type info /// \brief metaprogramming floating point type info
/// ///
/// ///
/// \details this file is automatically generated for the current build environment /// \details This file is automatically generated for the current build environment.
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// Environment for this build: GNU Linux x86_64
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -58,30 +60,55 @@
#undef FLT_DENORM_MIN #undef FLT_DENORM_MIN
#undef FLT_ROUND_ERR #undef FLT_ROUND_ERR
/// \brief Does \f$float\f$ have an infinity?
#define FLT_HAS_INFINITY 1 #define FLT_HAS_INFINITY 1
/// \brief Does \f$float\f$ have a quiet NaN?
#define FLT_HAS_QUIET_NAN 1 #define FLT_HAS_QUIET_NAN 1
/// \brief Does \f$float\f$ have a signaling NaN?
#define FLT_HAS_SIGNALING_NAN 1 #define FLT_HAS_SIGNALING_NAN 1
/// \brief Does \f$float\f$ use denormalization?
#define FLT_HAS_DENORM 1 #define FLT_HAS_DENORM 1
/// \brief Does \f$float\f$ have loss with denormalization?
#define FLT_HAS_DENORM_LOSS 0 #define FLT_HAS_DENORM_LOSS 0
/// \brief What rounding style does \f$float\f$ use?
#define FLT_ROUNDS 1 #define FLT_ROUNDS 1
/// \brief Does \f$float\f$ use the IEEE floating point specification?
#define FLT_IS_IEC559 1 #define FLT_IS_IEC559 1
/// \brief The number of mantissa bits in \f$float\f$.
#define FLT_MANT_DIG 24 #define FLT_MANT_DIG 24
/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ &rarr; \f$text\f$ &rarr; \f$float\f$.
#define FLT_DIG 6 #define FLT_DIG 6
/// \brief The decimal precision required to serialize and deserialize a \f$float\f$.
#define FLT_DECIMAL_DIG 9 #define FLT_DECIMAL_DIG 9
/// \brief The radix, or integer base, used to represent a \f$float\f$.
#define FLT_RADIX 2 #define FLT_RADIX 2
/// \brief The minimum negative integer such that \f${FLT_RADIX}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.
#define FLT_MIN_EXP -125 #define FLT_MIN_EXP -125
/// \brief The maximum positive integer such that \f${FLT_RADIX}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.
#define FLT_MAX_EXP 128 #define FLT_MAX_EXP 128
/// \brief The minimum negative integer such that \f${10}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.
#define FLT_MIN_10_EXP -37 #define FLT_MIN_10_EXP -37
/// \brief The maximum positive integer such that \f${10}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.
#define FLT_MAX_10_EXP 38 #define FLT_MAX_10_EXP 38
/// \brief Do arithmetics operations with \f$float\f$ trap?
#define FLT_TRAPS 0 #define FLT_TRAPS 0
/// \brief Do arithmetics operations with \f$float\f$ check for underflow?
#define FLT_TINYNESS_BEFORE 0 #define FLT_TINYNESS_BEFORE 0
/// \brief Smallest positive, finite, normal value of \f$float\f$.
#define FLT_MIN fennec::bit_cast<float>(0x800000) #define FLT_MIN fennec::bit_cast<float>(0x800000)
/// \brief Largest positive, finite value of \f$float\f$.
#define FLT_MAX fennec::bit_cast<float>(0x7f7fffff) #define FLT_MAX fennec::bit_cast<float>(0x7f7fffff)
/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$.
#define FLT_EPSILON fennec::bit_cast<float>(0x34000000) #define FLT_EPSILON fennec::bit_cast<float>(0x34000000)
/// \brief A value representing \f$\inf\f$ of type \f$float\f$.
#define FLT_INF fennec::bit_cast<float>(0x7f800000) #define FLT_INF fennec::bit_cast<float>(0x7f800000)
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.
#define FLT_QUIET_NAN fennec::bit_cast<float>(0x7fc00000) #define FLT_QUIET_NAN fennec::bit_cast<float>(0x7fc00000)
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps.
#define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000) #define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000)
/// \brief Smallest positive, finite, subnormal value of \f$float\f$.
#define FLT_DENORM_MIN fennec::bit_cast<float>(0x1) #define FLT_DENORM_MIN fennec::bit_cast<float>(0x1)
/// \brief Maximum rounding error of type \f$float\f$.
#define FLT_ROUND_ERR fennec::bit_cast<float>(0x3f000000) #define FLT_ROUND_ERR fennec::bit_cast<float>(0x3f000000)
#undef DBL_HAS_INFINITY #undef DBL_HAS_INFINITY
@@ -110,30 +137,55 @@
#undef DBL_DENORM_MIN #undef DBL_DENORM_MIN
#undef DBL_ROUND_ERR #undef DBL_ROUND_ERR
/// \brief Does \f$double\f$ have an infinity?
#define DBL_HAS_INFINITY 1 #define DBL_HAS_INFINITY 1
/// \brief Does \f$double\f$ have a quiet NaN?
#define DBL_HAS_QUIET_NAN 1 #define DBL_HAS_QUIET_NAN 1
/// \brief Does \f$double\f$ have a signaling NaN?
#define DBL_HAS_SIGNALING_NAN 1 #define DBL_HAS_SIGNALING_NAN 1
/// \brief Does \f$double\f$ use denormalization?
#define DBL_HAS_DENORM 1 #define DBL_HAS_DENORM 1
/// \brief Does \f$double\f$ have loss with denormalization?
#define DBL_HAS_DENORM_LOSS 0 #define DBL_HAS_DENORM_LOSS 0
/// \brief What rounding style does \f$double\f$ use?
#define DBL_ROUNDS 1 #define DBL_ROUNDS 1
/// \brief Does \f$double\f$ use the IEEE doubleing point specification?
#define DBL_IS_IEC559 1 #define DBL_IS_IEC559 1
/// \brief The number of mantissa bits in \f$double\f$.
#define DBL_MANT_DIG 53 #define DBL_MANT_DIG 53
/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ &rarr; \f$text\f$ &rarr; \f$double\f$.
#define DBL_DIG 15 #define DBL_DIG 15
/// \brief The decimal precision required to serialize and deserialize a \f$double\f$.
#define DBL_DECIMAL_DIG 17 #define DBL_DECIMAL_DIG 17
/// \brief The radix, or integer base, used to represent a \f$double\f$.
#define DBL_RADIX 2 #define DBL_RADIX 2
/// \brief The minimum negative integer such that \f${DBL_RADIX}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.
#define DBL_MIN_EXP -1021 #define DBL_MIN_EXP -1021
/// \brief The maximum positive integer such that \f${DBL_RADIX}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.
#define DBL_MAX_EXP 1024 #define DBL_MAX_EXP 1024
/// \brief The minimum negative integer such that \f${10}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.
#define DBL_MIN_10_EXP -307 #define DBL_MIN_10_EXP -307
/// \brief The maximum positive integer such that \f${10}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.
#define DBL_MAX_10_EXP 308 #define DBL_MAX_10_EXP 308
/// \brief Do arithmetics operations with \f$double\f$ trap?
#define DBL_TRAPS 0 #define DBL_TRAPS 0
/// \brief Do arithmetics operations with \f$double\f$ check for underflow?
#define DBL_TINYNESS_BEFORE 0 #define DBL_TINYNESS_BEFORE 0
/// \brief Smallest positive, finite, normal value of \f$double\f$.
#define DBL_MIN fennec::bit_cast<double>(0x10000000000000ll) #define DBL_MIN fennec::bit_cast<double>(0x10000000000000ll)
/// \brief Largest positive, finite value of \f$double\f$.
#define DBL_MAX fennec::bit_cast<double>(0x7fefffffffffffffll) #define DBL_MAX fennec::bit_cast<double>(0x7fefffffffffffffll)
/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$.
#define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000ll) #define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000ll)
/// \brief A value representing \f$\inf\f$ of type \f$double\f$.
#define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000ll) #define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000ll)
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.
#define DBL_QUIET_NAN fennec::bit_cast<double>(0x7ff8000000000000ll) #define DBL_QUIET_NAN fennec::bit_cast<double>(0x7ff8000000000000ll)
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps.
#define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000ll) #define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000ll)
/// \brief Smallest positive, finite, subnormal value of \f$double\f$.
#define DBL_DENORM_MIN fennec::bit_cast<double>(0x1ll) #define DBL_DENORM_MIN fennec::bit_cast<double>(0x1ll)
/// \brief Maximum rounding error of type \f$double\f$.
#define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000ll) #define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000ll)
#endif // FENNEC_LANG_FLOAT_H #endif // FENNEC_LANG_FLOAT_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file function.h /// \file fennec/lang/function.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,13 +17,15 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file integer.h /// \file fennec/lang/integer.h
/// \brief metaprogramming integer type info /// \brief metaprogramming integer type info
/// ///
/// ///
/// \details this file is automatically generated for the current build environment /// \details This file is automatically generated for the current build environment.
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// Environment for this build: GNU Linux x86_64
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -51,114 +53,212 @@
#undef ULLONG_MIN #undef ULLONG_MIN
#undef ULLONG_MAX #undef ULLONG_MAX
/// \brief Is \f$char\f$ signed?
#define CHAR_IS_SIGNED true #define CHAR_IS_SIGNED true
/// \brief Rounding style of type \f$char\f$.
#define CHAR_ROUNDS 0x0 #define CHAR_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$char\f$.
#define CHAR_RADIX_DIG 0x7 #define CHAR_RADIX_DIG 0x7
/// \brief Number of decimal digits represented by \f$char\f$.
#define CHAR_DIG 0x2 #define CHAR_DIG 0x2
/// \brief Number of decimal digits necessary to differentiate all values of type \f$char\f$.
#define CHAR_DECIMAL_DIG 0x0 #define CHAR_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$char\f$.
#define CHAR_RADIX 0x2 #define CHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$char\f$ trap?
#define CHAR_TRAPS 0xtrue #define CHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$char\f$.
#define CHAR_MIN 0x80 #define CHAR_MIN 0x80
/// \brief Largest finite value of \f$char\f$.
#define CHAR_MAX 0x7f #define CHAR_MAX 0x7f
/// \brief Is \f$wchar_t\f$ signed?
#define WCHAR_IS_SIGNED true #define WCHAR_IS_SIGNED true
/// \brief Rounding style of type \f$wchar_t\f$.
#define WCHAR_ROUNDS 0x0 #define WCHAR_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$wchar_t\f$.
#define WCHAR_RADIX_DIG 0x1f #define WCHAR_RADIX_DIG 0x1f
/// \brief Number of decimal digits represented by \f$wchar_t\f$.
#define WCHAR_DIG 0x9 #define WCHAR_DIG 0x9
/// \brief Number of decimal digits necessary to differentiate all values of type \f$wchar_t\f$.
#define WCHAR_DECIMAL_DIG 0x0 #define WCHAR_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$wchar_t\f$.
#define WCHAR_RADIX 0x2 #define WCHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$wchar_t\f$ trap?
#define WCHAR_TRAPS 0xtrue #define WCHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$wchar_t\f$.
#define WCHAR_MIN 0x80000000 #define WCHAR_MIN 0x80000000
/// \brief Largest finite value of \f$wchar_t\f$.
#define WCHAR_MAX 0x7fffffff #define WCHAR_MAX 0x7fffffff
/// \brief Is \f$signed char\f$ signed?
#define SCHAR_ROUNDS 0x0 #define SCHAR_ROUNDS 0x0
/// \brief Rounding style of type \f$signed char\f$.
#define SCHAR_RADIX_DIG 0x7 #define SCHAR_RADIX_DIG 0x7
/// \brief Number of radix digits represented by \f$signed char\f$.
#define SCHAR_DIG 0x2 #define SCHAR_DIG 0x2
/// \brief Number of decimal digits represented by \f$signed char\f$.
#define SCHAR_DECIMAL_DIG 0x0 #define SCHAR_DECIMAL_DIG 0x0
/// \brief Number of decimal digits necessary to differentiate all values of type \f$signed char\f$.
#define SCHAR_RADIX 0x2 #define SCHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$signed char\f$ trap?
#define SCHAR_TRAPS 0xtrue #define SCHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$signed char\f$.
#define SCHAR_MIN 0x80 #define SCHAR_MIN 0x80
/// \brief Largest finite value of \f$signed char\f$.
#define SCHAR_MAX 0x7f #define SCHAR_MAX 0x7f
/// \brief Is \f$unsigned char\f$ unsigned?
#define UCHAR_ROUNDS 0x0 #define UCHAR_ROUNDS 0x0
/// \brief Rounding style of type \f$unsigned char\f$.
#define UCHAR_RADIX_DIG 0x8 #define UCHAR_RADIX_DIG 0x8
/// \brief Number of radix digits represented by \f$unsigned char\f$.
#define UCHAR_DIG 0x2 #define UCHAR_DIG 0x2
/// \brief Number of decimal digits represented by \f$unsigned char\f$.
#define UCHAR_DECIMAL_DIG 0x0 #define UCHAR_DECIMAL_DIG 0x0
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned char\f$.
#define UCHAR_RADIX 0x2 #define UCHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned char\f$ trap?
#define UCHAR_TRAPS 0xtrue #define UCHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned char\f$.
#define UCHAR_MIN 0x0 #define UCHAR_MIN 0x0
/// \brief Largest finite value of \f$unsigned char\f$.
#define UCHAR_MAX 0xff #define UCHAR_MAX 0xff
/// \brief Rounding style of type \f$short\f$.
#define SHORT_ROUNDS 0x0 #define SHORT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$short\f$.
#define SHORT_RADIX_DIG 0xf #define SHORT_RADIX_DIG 0xf
/// \brief Number of decimal digits represented by \f$short\f$.
#define SHORT_DIG 0x4 #define SHORT_DIG 0x4
/// \brief Number of decimal digits necessary to differentiate all values of type \f$short\f$.
#define SHORT_DECIMAL_DIG 0x0 #define SHORT_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$short\f$.
#define SHORT_RADIX 0x2 #define SHORT_RADIX 0x2
/// \brief Do arithmetics operations with \f$short\f$ trap?
#define SHORT_TRAPS 0xtrue #define SHORT_TRAPS 0xtrue
#define SHORT_MIN 0x8000 /// \brief Smallest finite value of \f$short\f$.
#define SHORT_MIN 0xffff8000
/// \brief Largest finite value of \f$short\f$.
#define SHORT_MAX 0x7fff #define SHORT_MAX 0x7fff
/// \brief Rounding style of type \f$unsigned short\f$.
#define USHORT_ROUNDS 0x0 #define USHORT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned short\f$.
#define USHORT_RADIX_DIG 0x10 #define USHORT_RADIX_DIG 0x10
/// \brief Number of decimal digits represented by \f$unsigned short\f$.
#define USHORT_DIG 0x4 #define USHORT_DIG 0x4
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned short\f$.
#define USHORT_DECIMAL_DIG 0x0 #define USHORT_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$unsigned short\f$.
#define USHORT_RADIX 0x2 #define USHORT_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned short\f$ trap?
#define USHORT_TRAPS 0xtrue #define USHORT_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned short\f$.
#define USHORT_MIN 0x0 #define USHORT_MIN 0x0
/// \brief Largest finite value of \f$unsigned short\f$.
#define USHORT_MAX 0xffff #define USHORT_MAX 0xffff
/// \brief Rounding style of type \f$int\f$.
#define INT_ROUNDS 0x0 #define INT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$int\f$.
#define INT_RADIX_DIG 0x1f #define INT_RADIX_DIG 0x1f
/// \brief Number of decimal digits represented by \f$int\f$.
#define INT_DIG 0x9 #define INT_DIG 0x9
/// \brief Number of decimal digits necessary to differentiate all values of type \f$int\f$.
#define INT_DECIMAL_DIG 0x0 #define INT_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$int\f$.
#define INT_RADIX 0x2 #define INT_RADIX 0x2
/// \brief Do arithmetics operations with \f$int\f$ trap?
#define INT_TRAPS 0xtrue #define INT_TRAPS 0xtrue
/// \brief Smallest finite value of \f$int\f$.
#define INT_MIN 0x80000000 #define INT_MIN 0x80000000
/// \brief Largest finite value of \f$int\f$.
#define INT_MAX 0x7fffffff #define INT_MAX 0x7fffffff
/// \brief Rounding style of type \f$unsigned int\f$.
#define UINT_ROUNDS 0x0 #define UINT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned int\f$.
#define UINT_RADIX_DIG 0x20 #define UINT_RADIX_DIG 0x20
/// \brief Number of decimal digits represented by \f$unsigned int\f$.
#define UINT_DIG 0x9 #define UINT_DIG 0x9
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned int\f$.
#define UINT_DECIMAL_DIG 0x0 #define UINT_DECIMAL_DIG 0x0
/// \brief The radix, or unsigned integer base, used to represent a \f$unsigned int\f$.
#define UINT_RADIX 0x2 #define UINT_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned int\f$ trap?
#define UINT_TRAPS 0xtrue #define UINT_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned int\f$.
#define UINT_MIN 0x0 #define UINT_MIN 0x0
/// \brief Largest finite value of \f$unsigned int\f$.
#define UINT_MAX 0xffffffff #define UINT_MAX 0xffffffff
/// \brief Rounding style of type \f$long int\f$.
#define LONG_ROUNDS 0x0 #define LONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$long int\f$.
#define LONG_RADIX_DIG 0x3f #define LONG_RADIX_DIG 0x3f
/// \brief Number of decimal digits represented by \f$long int\f$.
#define LONG_DIG 0x12 #define LONG_DIG 0x12
/// \brief Number of decimal digits necessary to differentiate all values of type \f$long int\f$.
#define LONG_DECIMAL_DIG 0x0 #define LONG_DECIMAL_DIG 0x0
/// \brief The radix, or long integer base, used to represent a \f$long int\f$.
#define LONG_RADIX 0x2 #define LONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$long int\f$ trap?
#define LONG_TRAPS 0xtrue #define LONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$long int\f$.
#define LONG_MIN 0x8000000000000000 #define LONG_MIN 0x8000000000000000
/// \brief Largest finite value of \f$long int\f$.
#define LONG_MAX 0x7fffffffffffffff #define LONG_MAX 0x7fffffffffffffff
/// \brief Rounding style of type \f$unsigned long int\f$.
#define ULONG_ROUNDS 0x0 #define ULONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned long int\f$.
#define ULONG_RADIX_DIG 0x40 #define ULONG_RADIX_DIG 0x40
/// \brief Number of decimal digits represented by \f$unsigned long int\f$.
#define ULONG_DIG 0x13 #define ULONG_DIG 0x13
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long int\f$.
#define ULONG_DECIMAL_DIG 0x0 #define ULONG_DECIMAL_DIG 0x0
/// \brief The radix, or unsigned long integer base, used to represent a \f$unsigned long int\f$.
#define ULONG_RADIX 0x2 #define ULONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned long int\f$ trap?
#define ULONG_TRAPS 0xtrue #define ULONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned long int\f$.
#define ULONG_MIN 0x0 #define ULONG_MIN 0x0
/// \brief Largest finite value of \f$unsigned long int\f$.
#define ULONG_MAX 0xffffffffffffffff #define ULONG_MAX 0xffffffffffffffff
/// \brief Rounding style of type \f$long long\f$.
#define LLONG_ROUNDS 0x0 #define LLONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$long long\f$.
#define LLONG_RADIX_DIG 0x3f #define LLONG_RADIX_DIG 0x3f
/// \brief Number of decimal digits represented by \f$long long\f$.
#define LLONG_DIG 0x12 #define LLONG_DIG 0x12
/// \brief Number of decimal digits necessary to differentiate all values of type \f$long long\f$.
#define LLONG_DECIMAL_DIG 0x0 #define LLONG_DECIMAL_DIG 0x0
/// \brief The radix, or long longeger base, used to represent a \f$long long\f$.
#define LLONG_RADIX 0x2 #define LLONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$long long\f$ trap?
#define LLONG_TRAPS 0xtrue #define LLONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$long long\f$.
#define LLONG_MIN 0x8000000000000000 #define LLONG_MIN 0x8000000000000000
/// \brief Largest finite value of \f$long long\f$.
#define LLONG_MAX 0x7fffffffffffffff #define LLONG_MAX 0x7fffffffffffffff
/// \brief Rounding style of type \f$unsigned long long\f$.
#define ULLONG_ROUNDS 0x0 #define ULLONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned long long\f$.
#define ULLONG_RADIX_DIG 0x40 #define ULLONG_RADIX_DIG 0x40
/// \brief Number of decimal digits represented by \f$unsigned long long\f$.
#define ULLONG_DIG 0x13 #define ULLONG_DIG 0x13
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long long\f$.
#define ULLONG_DECIMAL_DIG 0x0 #define ULLONG_DECIMAL_DIG 0x0
/// \brief The radix, or unsigned long longeger base, used to represent a \f$unsigned long long\f$.
#define ULLONG_RADIX 0x2 #define ULLONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned long long\f$ trap?
#define ULLONG_TRAPS 0xtrue #define ULLONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned long long\f$.
#define ULLONG_MIN 0x0 #define ULLONG_MIN 0x0
/// \brief Largest finite value of \f$unsigned long long\f$.
#define ULLONG_MAX 0xffffffffffffffff #define ULLONG_MAX 0xffffffffffffffff
#endif // FENNEC_LANG_INTEGER_H #endif // FENNEC_LANG_INTEGER_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,10 +17,10 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file intrinsics.h /// \file fennec/lang/intrinsics.h
/// \brief \ref fennec_lang_intrinsics /// \brief \ref fennec_lang_intrinsics
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -40,59 +40,59 @@
/// <tr><th style="vertical-align: top">Syntax /// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_BIT_CAST` <br> /// \f$FENNEC_HAS_BUILTIN_BIT_CAST\f$ <br>
/// `Y FENNEC_BUILTIN_BIT_CAST(X)` /// \f$Y FENNEC_BUILTIN_BIT_CAST(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// An intrinsic for doing a bitwise cast without using `reinterpret_cast`. /// An intrinsic for doing a bitwise cast without using \f$reinterpret_cast\f$.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_ADDRESSOF` <br> /// \f$FENNEC_HAS_BUILTIN_ADDRESSOF\f$ <br>
/// `Y FENNEC_BUILTIN_ADDRESSOF(X)` /// \f$Y FENNEC_BUILTIN_ADDRESSOF(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Obtains the true address of an object in circumstances where `operator&` is overloaded. /// Obtains the true address of an object in circumstances where \f$operator&\f$ is overloaded.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_CONVERTIBLE` <br> /// \f$FENNEC_HAS_BUILTIN_IS_CONVERTIBLE\f$ <br>
/// `B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)` /// \f$B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Checks if type \f$X\f$ can be converted to type \f$Y\f$. /// Checks if type \f$X\f$ can be converted to type \f$Y\f$.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_EMPTY` <br> /// \f$FENNEC_HAS_BUILTIN_IS_EMPTY\f$ <br>
/// `B FENNEC_BUILTIN_IS_EMPTY(X)` /// \f$B FENNEC_BUILTIN_IS_EMPTY(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Checks if type \f$X\f$ stores no data. /// Checks if type \f$X\f$ stores no data.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_POLYMORPHIC` <br> /// \f$FENNEC_HAS_BUILTIN_IS_POLYMORPHIC\f$ <br>
/// `B FENNEC_BUILTIN_IS_POLYMORPHIC(X)` /// \f$B FENNEC_BUILTIN_IS_POLYMORPHIC(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Checks if type \f$X\f$ is polymorphic, this is for classes only thus checks only for subtyping /// Checks if type \f$X\f$ is polymorphic, this is for classes only thus checks only for subtyping
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_FINAL` <br> /// \f$FENNEC_HAS_BUILTIN_IS_FINAL\f$ <br>
/// `B FENNEC_BUILTIN_IS_FINAL(X)` /// \f$B FENNEC_BUILTIN_IS_FINAL(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Checks if type \f$X\f$ is final, meaning a function or class cannot be derived from. /// Checks if type \f$X\f$ is final, meaning a function or class cannot be derived from.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_ABSTRACT` <br> /// \f$FENNEC_HAS_BUILTIN_IS_ABSTRACT\f$ <br>
/// `B FENNEC_BUILTIN_IS_ABSTRACT(X)` /// \f$B FENNEC_BUILTIN_IS_ABSTRACT(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Opposite of `FENNEC_BUILTIN_IS_FINAL`, checks if abstract, meaning \f$X\f$ has at least one pure virtual function. /// Opposite of \f$FENNEC_BUILTIN_IS_FINAL\f$, checks if abstract, meaning \f$X\f$ has at least one pure virtual function.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT` <br> /// \f$FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT\f$ <br>
/// `B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)` /// \f$B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Checks if \f$X\f$ has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class) /// Checks if \f$X\f$ has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class)
/// for this trait /// for this trait
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// `FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE` <br> /// \f$FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE\f$ <br>
/// `B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)` /// \f$B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)\f$
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Checks if type \f$X\f$ is constructible with args `...`, such that `X::X(...)` exists. /// Checks if type \f$X\f$ is constructible with args \f$\ldots\f$, such that \f$X::X(...)\f$ exists.
/// ///
/// </table> /// </table>
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file lang.h /// \file fennec/lang/lang.h
/// \brief \ref fennec_lang /// \brief \ref fennec_lang
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file limits.h /// \file fennec/lang/limits.h
/// \brief \ref fennec_lang_limits /// \brief \ref fennec_lang_limits
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -222,42 +222,42 @@ enum float_round_style
/// \tparam TypeT Numeric types, may be overloaded for custom types /// \tparam TypeT Numeric types, may be overloaded for custom types
template<typename TypeT> struct numeric_limits template<typename TypeT> struct numeric_limits
{ {
static constexpr bool is_specialized = false; ///< Check if the template is specialized for TypeT static constexpr bool is_specialized = false; //!< Check if the template is specialized for TypeT
static constexpr bool is_signed = false; ///< Check if TypeT is signed static constexpr bool is_signed = false; //!< Check if TypeT is signed
static constexpr bool is_integer = false; ///< Check if TypeT is of an integral type static constexpr bool is_integer = false; //!< Check if TypeT is of an integral type
static constexpr bool is_exact = false; ///< Check if TypeT is exact in its precision static constexpr bool is_exact = false; //!< Check if TypeT is exact in its precision
static constexpr bool has_infinity = false; ///< Check if TypeT can hold a value representing infinity static constexpr bool has_infinity = false; //!< Check if TypeT can hold a value representing infinity
static constexpr bool has_quiet_nan = false; ///< Check if TypeT can hold a non-signaling nan static constexpr bool has_quiet_nan = false; //!< Check if TypeT can hold a non-signaling nan
static constexpr bool has_signaling_nan = false; ///< Check if TypeT can hold a signaling nan static constexpr bool has_signaling_nan = false; //!< Check if TypeT can hold a signaling nan
static constexpr bool has_denorm = false; ///< Check if TypeT denormalizes static constexpr bool has_denorm = false; //!< Check if TypeT denormalizes
static constexpr bool has_denorm_loss = false; ///< Check if TypeT has precision loss when denormalized static constexpr bool has_denorm_loss = false; //!< Check if TypeT has precision loss when denormalized
static constexpr bool is_iec559 = false; ///< Check if a TypeT representing a float is IEC 559 or IEEE 754 static constexpr bool is_iec559 = false; //!< Check if a TypeT representing a float is IEC 559 or IEEE 754
static constexpr bool is_bounded = false; ///< Check if TypeT represents a finite set of values static constexpr bool is_bounded = false; //!< Check if TypeT represents a finite set of values
static constexpr bool is_modulo = false; ///< Check if TypeT can handle modulo arithmetic static constexpr bool is_modulo = false; //!< Check if TypeT can handle modulo arithmetic
static constexpr bool tinyness_before = false; ///< Check if TypeT checks for tinyness before rounding static constexpr bool tinyness_before = false; //!< Check if TypeT checks for tinyness before rounding
static constexpr bool traps = false; ///< Check if TypeT can cause operations to trap static constexpr bool traps = false; //!< Check if TypeT can cause operations to trap
static constexpr int radix = 0; ///< Get the base representation of the type static constexpr int radix = 0; //!< Get the base representation of the type
static constexpr int digits = 0; ///< Get the number of radix digits TypeT represents static constexpr int digits = 0; //!< Get the number of radix digits TypeT represents
static constexpr int digits10 = 0; ///< Get the number of decimal digits TypeT represents static constexpr int digits10 = 0; //!< Get the number of decimal digits TypeT represents
static constexpr int max_digits10 = 0; ///< Get the maximum number of decimal digits TypeT represents static constexpr int max_digits10 = 0; //!< Get the maximum number of decimal digits TypeT represents
static constexpr int min_exponent = 0; ///< Get the minimum number of radix digits that represent the exponent of TypeT static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of TypeT
static constexpr int min_exponent10 = 0; ///< Get the minimum number of decimal digits that represent the exponent of TypeT static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of TypeT
static constexpr int max_exponent = 0; ///< Get the maximum number of radix digits that represent the exponent of TypeT static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of TypeT
static constexpr int max_exponent10 = 0; ///< Get the maximum number of decimal digits that represent the exponent of TypeT static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of TypeT
static constexpr float_round_style rounding_style = round_indeterminate; ///< The rounding style of TypeT static constexpr float_round_style rounding_style = round_indeterminate; //!< The rounding style of TypeT
// This is very poorly named and defined in the C++ Standard so these functions differ // This is very poorly named and defined in the C++ Standard so these functions differ
static constexpr TypeT min() { return TypeT(); } ///< \returns the minimum finite value of TypeT static constexpr TypeT min() { return TypeT(); } //!< \returns the minimum finite value of TypeT
static constexpr TypeT max() { return TypeT(); } ///< \returns the maximum finite value of TypeT static constexpr TypeT max() { return TypeT(); } //!< \returns the maximum finite value of TypeT
static constexpr TypeT lowest() { return TypeT(); } ///< \returns the smallest positive value of TypeT static constexpr TypeT lowest() { return TypeT(); } //!< \returns the smallest positive value of TypeT
static constexpr TypeT epsilon() { return TypeT(); } ///< \returns the difference between 1.0 and the next representable value static constexpr TypeT epsilon() { return TypeT(); } //!< \returns the difference between 1.0 and the next representable value
static constexpr TypeT round_error() { return TypeT(); } ///< \returns the max rounding error of TypeT static constexpr TypeT round_error() { return TypeT(); } //!< \returns the max rounding error of TypeT
static constexpr TypeT infinity() { return TypeT(); } ///< \returns a value of TypeT holding a positive infinity static constexpr TypeT infinity() { return TypeT(); } //!< \returns a value of TypeT holding a positive infinity
static constexpr TypeT quiet_NaN() { return TypeT(); } ///< \returns a value of TypeT holding a quiet NaN static constexpr TypeT quiet_NaN() { return TypeT(); } //!< \returns a value of TypeT holding a quiet NaN
static constexpr TypeT signaling_NaN() { return TypeT(); } ///< \returns a value of TypeT holding a signaling NaN static constexpr TypeT signaling_NaN() { return TypeT(); } //!< \returns a value of TypeT holding a signaling NaN
static constexpr TypeT denorm_min() { return TypeT(); } ///< \returns a value of TypeT holding the smallest positive subnormal static constexpr TypeT denorm_min() { return TypeT(); } //!< \returns a value of TypeT holding the smallest positive subnormal
}; };
// Overload definitions for basic types // Overload definitions for basic types

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file metaprogramming.h /// \file fennec/lang/metaprogramming.h
/// \brief \ref fennec_lang /// \brief \ref fennec_lang
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file metasequences.h /// \file fennec/lang/metasequences.h
/// \brief \ref fennec_lang_metasequences /// \brief \ref fennec_lang_metasequences
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -116,7 +116,7 @@ template<typename ValueT, ValueT...Values> struct metasequence
/// \brief metaprogramming integral metasequence /// \brief metaprogramming integral metasequence
/// ///
/// \details A `fennec::metasequence` specialized integer types. /// \details A `fennec::metasequence` specialized integer types.
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>``` /// \tparam IntT type of the values, must satisfy `fennec::is_integral<T>`
/// \tparam Values sequence values /// \tparam Values sequence values
template<typename IntT, IntT...Values> requires(is_integral_v<IntT>) template<typename IntT, IntT...Values> requires(is_integral_v<IntT>)
struct integer_metasequence : metasequence<IntT, Values...> struct integer_metasequence : metasequence<IntT, Values...>
@@ -141,12 +141,12 @@ struct integer_metasequence : metasequence<IntT, Values...>
/// \brief generate a fennec::integer_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$ /// \brief generate a fennec::integer_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
/// ///
/// \details /// \details
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>``` /// \tparam IntT type of the values, must satisfy `fennec::is_integral<T>`
/// \tparam N size of the metasequence to generate /// \tparam N size of the metasequence to generate
template<typename IntT, size_t N> struct make_integer_metasequence; template<typename IntT, size_t N> struct make_integer_metasequence;
/// ///
/// \brief shorthand for ```typename make_integer_sequence<T, N>::type``` /// \brief shorthand for `typename fennec::make_integer_sequence<T, N>::type`
template<typename IntT, size_t N> using make_integer_metasequence_t = typename make_integer_metasequence<IntT, N>::type; template<typename IntT, size_t N> using make_integer_metasequence_t = typename make_integer_metasequence<IntT, N>::type;
@@ -180,12 +180,12 @@ template<size_t...Indices> struct index_metasequence : integer_metasequence<size
/// \brief generate a fennec::index_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$ /// \brief generate a fennec::index_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
/// ///
/// \details /// \details
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>``` /// \tparam T type of the values, must satisfy `fennec::is_integral<T>`
/// \tparam N size of the sequence to generate /// \tparam N size of the sequence to generate
template<size_t N> struct make_index_metasequence; template<size_t N> struct make_index_metasequence;
/// ///
/// \brief shorthand for ```typename make_index_metasequence<N>::type``` /// \brief shorthand for `typename fennec::make_index_metasequence<N>::type`
template<size_t N> using make_index_metasequence_t = typename make_index_metasequence<N>::type; template<size_t N> using make_index_metasequence_t = typename make_index_metasequence<N>::type;
@@ -201,7 +201,7 @@ template<size_t N> using make_index_metasequence_t = typename make_index_metase
template<typename SequenceT0, typename SequenceT1> struct concat_metasequence; template<typename SequenceT0, typename SequenceT1> struct concat_metasequence;
/// ///
/// \brief shorthand for ```typename concat_metasequence<SequenceT0, SequenceT1>::type``` /// \brief shorthand for `typename fennec::concat_metasequence<SequenceT0, SequenceT1>::type`
template<typename SequenceT0, typename SequenceT1> using concat_metasequence_t template<typename SequenceT0, typename SequenceT1> using concat_metasequence_t
= typename concat_metasequence<SequenceT0, SequenceT1>::type; = typename concat_metasequence<SequenceT0, SequenceT1>::type;

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General License as published by // it under the terms of the GNU General License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file numeric_transforms.h /// \file fennec/lang/numeric_transforms.h
/// \brief \ref fennec_lang_numeric_transforms /// \brief \ref fennec_lang_numeric_transforms
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
#ifndef FENNEC_LANG_NUMERIC_TRANSFORMS_H #ifndef FENNEC_LANG_NUMERIC_TRANSFORMS_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file ranges.h /// \file fennec/lang/ranges.h
/// \brief /// \brief
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -37,7 +37,7 @@ namespace fennec
{ {
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \tparam ContainerT the container type /// \tparam ContainerT the container type
/// \param c the container to iterate on /// \param c the container to iterate on
/// \returns an iterator at the start of the container /// \returns an iterator at the start of the container
@@ -47,7 +47,7 @@ inline constexpr auto begin(ContainerT& c) noexcept(noexcept(c.begin())) -> decl
} }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \tparam ContainerT the container type /// \tparam ContainerT the container type
/// \param c the container to iterate on /// \param c the container to iterate on
/// \returns an iterator at the start of the container /// \returns an iterator at the start of the container
@@ -57,7 +57,7 @@ inline constexpr auto begin(const ContainerT& c) noexcept(noexcept(c.begin())) -
} }
/// ///
/// \brief C++ Iterator Specification `begin()` /// \brief C++ Iterator Specification \f$begin()\f$
/// \tparam T the element type /// \tparam T the element type
/// \tparam N the bounds of the array /// \tparam N the bounds of the array
/// \param arr a bounded array to iterate on /// \param arr a bounded array to iterate on
@@ -69,7 +69,7 @@ inline constexpr T* begin(T (&arr)[N]) noexcept {
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \tparam ContainerT the container type /// \tparam ContainerT the container type
/// \param c the container to iterate on /// \param c the container to iterate on
/// \returns an iterator at the end of the container /// \returns an iterator at the end of the container
@@ -79,7 +79,7 @@ inline constexpr auto end(ContainerT& c) noexcept(noexcept(c.end())) -> decltype
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \tparam ContainerT the container type /// \tparam ContainerT the container type
/// \param c the container to iterate on /// \param c the container to iterate on
/// \returns an iterator at the end of the container /// \returns an iterator at the end of the container
@@ -89,7 +89,7 @@ inline constexpr auto end(const ContainerT& c) noexcept(noexcept(c.end())) -> de
} }
/// ///
/// \brief C++ Iterator Specification `end()` /// \brief C++ Iterator Specification \f$end()\f$
/// \tparam T the element type /// \tparam T the element type
/// \tparam N the bounds of the array /// \tparam N the bounds of the array
/// \param arr a bounded array to iterate on /// \param arr a bounded array to iterate on

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file type_sequences.h /// \file fennec/lang/type_sequences.h
/// \brief \ref fennec_lang_type_sequences /// \brief \ref fennec_lang_type_sequences
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
/// ///
/// \file type_traits.h /// \file fennec/lang/type_traits.h
/// \brief \ref fennec_lang_type_traits /// \brief \ref fennec_lang_type_traits
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General License as published by // it under the terms of the GNU General License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file type_transforms.h /// \file fennec/lang/type_transforms.h
/// \brief \ref fennec_lang_type_transforms /// \brief \ref fennec_lang_type_transforms
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -44,8 +44,22 @@
/// ///
/// \code #include <fennec/lang/type_transforms.h> \endcode /// \code #include <fennec/lang/type_transforms.h> \endcode
/// ///
/// \section fennec_lang_type_transforms_section_decay_conversions Decay Conversions
/// ///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_transforms"> /// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_decay_conversions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::decay "decay<TypeT>::type"<br>
/// \ref fennec::decay_t "decay_t<TypeT>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::decay
///
/// </table>
///
/// \section fennec_lang_type_transforms_section_pointer_conversions Pointer Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_pointer_conversions">
/// <tr><th style="vertical-align: top">Syntax /// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
@@ -61,17 +75,49 @@
/// \copydetails fennec::remove_pointer /// \copydetails fennec::remove_pointer
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::strip_pointers "strip_pointers<TypeT>::type"<br>
/// \ref fennec::strip_pointers_t "strip_pointers<TypeT>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::strip_pointers
///
/// </table>
///
/// \section fennec_lang_type_transforms_section_reference_conversions Reference Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_reference_conversions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_reference "add_reference<TypeT>::type"<br> /// \ref fennec::add_reference "add_reference<TypeT>::type"<br>
/// \ref fennec::add_reference_t "add_reference_t<TypeT>" /// \ref fennec::add_reference_t "add_reference_t<TypeT>"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::add_reference /// \copydetails fennec::add_reference
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_lvalue_reference "add_lvalue_reference<TypeT>::type"<br>
/// \ref fennec::add_lvalue_reference_t "add_lvalue_reference_t<TypeT>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::add_lvalue_reference
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_rvalue_reference "add_rvalue_reference<TypeT>::type"<br>
/// \ref fennec::add_rvalue_reference_t "add_rvalue_reference_t<TypeT>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::add_rvalue_reference
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::remove_reference "remove_reference<TypeT>::type"<br> /// \ref fennec::remove_reference "remove_reference<TypeT>::type"<br>
/// \ref fennec::remove_reference_t "remove_reference_t<TypeT>" /// \ref fennec::remove_reference_t "remove_reference_t<TypeT>"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::remove_reference /// \copydetails fennec::remove_reference
/// ///
/// </table>
///
/// \section fennec_lang_type_transforms_section_cv_conversions Const — Volatile Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_cv_conversions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_const "add_const<TypeT>::type"<br> /// \ref fennec::add_const "add_const<TypeT>::type"<br>
/// \ref fennec::add_const_t "add_const_t<TypeT>" /// \ref fennec::add_const_t "add_const_t<TypeT>"
@@ -120,6 +166,12 @@
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::remove_cvref /// \copydetails fennec::remove_cvref
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::remove_cvrefptr "remove_cvrefptr<TypeT>::type"<br>
/// \ref fennec::remove_cvrefptr_t "remove_cvrefptr_t<TypeT>"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::remove_cvrefptr
///
/// </table> /// </table>
/// ///
@@ -142,9 +194,9 @@ template<typename T> using decay_t = typename decay<T>::type;
// Pointer Conversions ================================================================================================= // Pointer Conversions =================================================================================================
/// ///
/// \brief adds a pointer level to \p T /// \brief adds a pointer level to \f$T\f$
/// ///
/// \details adds a pointer to the provided type such that \f$T\f$ becomes `T*` /// \details adds a pointer to the provided type such that \f$T\f$ becomes \f$T*\f$
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct add_pointer : detail::_add_pointer<T>{}; template<typename T> struct add_pointer : detail::_add_pointer<T>{};
@@ -154,9 +206,9 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
/// ///
/// \brief removes a pointer level from \p T /// \brief removes a pointer level from \f$T\f$
/// ///
/// \details removes a pointer from the provided type such that `T*` becomes \f$T\f$ /// \details removes a pointer from the provided type such that \f$T*\f$ becomes \f$T\f$
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct remove_pointer : detail::_remove_pointer<T> {}; template<typename T> struct remove_pointer : detail::_remove_pointer<T> {};
@@ -166,9 +218,9 @@ template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
/// ///
/// \brief removes all pointer levels from \p T /// \brief removes all pointer levels from \f$T\f$
/// ///
/// \details removes all pointers from the provided type such that `T*`, `T**`, etc. becomes \f$T\f$ /// \details removes all pointers from the provided type such that \f$T*\f$, \f$T**\f$, etc. becomes \f$T\f$
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct strip_pointers : conditional_t< template<typename T> struct strip_pointers : conditional_t<
detail::_is_pointer<T>::value, detail::_is_pointer<T>::value,
@@ -185,155 +237,155 @@ template<typename T> using strip_pointers_t = strip_pointers<T>::type;
// Reference Conversions =============================================================================================== // Reference Conversions ===============================================================================================
/// ///
/// \brief add a reference to \p T /// \brief add a reference to \f$T\f$
/// ///
/// \details adds a pointer to the provided type such that \f$T\f$ becomes `T&` /// \details adds a pointer to the provided type such that \f$T\f$ becomes \f$T\&\f$
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct add_reference : type_identity<T&> {}; template<typename T> struct add_reference : type_identity<T&> {};
/// ///
/// \brief shorthand for `typename add_reference<T>::type` /// \brief shorthand for `typename fennec::add_reference<T>::type`
template<typename T> using add_reference_t = typename add_reference<T>::type; template<typename T> using add_reference_t = typename add_reference<T>::type;
/// ///
/// \brief remove a reference from \p T /// \brief add a lvalue reference to \f$T\f$
/// ///
/// \details removes references from the provided type such that `T&` and `T&&` become \f$T\f$ /// \details adds a lvalue reference to the provided type such that \f$T\f$ becomes \f$T\&\f$
/// \tparam T Reference Type
template<typename T> struct remove_reference : type_identity<T> {};
// specialization for `T&`
template<typename T> struct remove_reference<T&> : type_identity<T> {};
// specialization for `T&&`
template<typename T> struct remove_reference<T&&> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
///
/// \brief add a lvalue reference to \p T
///
/// \details adds a lvalue reference to the provided type such that 'T' becomes 'T&'
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_lvalue_reference : detail::_add_lvalue_reference<T> {}; template<typename T> struct add_lvalue_reference : detail::_add_lvalue_reference<T> {};
/// ///
/// \brief shorthand for `typename remove_reference<T>::type` /// \brief shorthand for `typename fennec::add_lvalue_reference<T>::type`
template<typename T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; template<typename T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
/// ///
/// \brief add a rvalue reference to \p T /// \brief add a rvalue reference to \f$T\f$
/// ///
/// \details adds a rvalue reference to the provided type such that 'T' becomes 'T&&' /// \details adds a rvalue reference to the provided type such that \f$T\f$ becomes \f$T\&\&\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_rvalue_reference : detail::_add_rvalue_reference<T> {}; template<typename T> struct add_rvalue_reference : detail::_add_rvalue_reference<T> {};
/// ///
/// \brief shorthand for `typename remove_reference<T>::type` /// \brief shorthand for `typename fennec::add_rvalue_reference<T>::type`
template<typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; template<typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
///
/// \brief remove a reference from \f$T\f$
///
/// \details removes references from the provided type such that \f$T\&\f$ and \f$T\&\&\f$ become \f$T\f$
/// \tparam T Reference Type
template<typename T> struct remove_reference : type_identity<T> {};
// specialization for T&
template<typename T> struct remove_reference<T&> : type_identity<T> {};
// specialization for T&&
template<typename T> struct remove_reference<T&&> : type_identity<T> {};
///
/// \brief shorthand for `typename fennec::remove_reference<T>::type`
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
// Const & Volatile Conversions ======================================================================================== // Const & Volatile Conversions ========================================================================================
/// ///
/// \brief add the const qualifier to the provided type \p T /// \brief add the const qualifier to the provided type \f$T\f$
/// ///
/// \details adds const qualification to the provided type such that \f$T\f$ becomes `const T` /// \details adds const qualification to the provided type such that \f$T\f$ becomes \f$const\quad T\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_const : detail::_add_const<T> {}; template<typename T> struct add_const : detail::_add_const<T> {};
/// ///
/// \brief shorthand for `typename add_const<T>::type` /// \brief shorthand for `typename fennec::add_const<T>::type`
template<typename T> using add_const_t = typename add_const<T>::type; template<typename T> using add_const_t = typename add_const<T>::type;
/// ///
/// \brief remove the const qualifier from the provided type \p T /// \brief remove the const qualifier from the provided type \f$T\f$
/// ///
/// \details removes const qualification from the provided type such that `const T` becomes \f$T\f$ /// \details removes const qualification from the provided type such that \f$const\quad T\f$ becomes \f$T\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_const : detail::_remove_const<T> {}; template<typename T> struct remove_const : detail::_remove_const<T> {};
/// ///
/// \brief shorthand for `typename remove_const<T>::type` /// \brief shorthand for `typename fennec::remove_const<T>::type`
template<typename T> using remove_const_t = typename remove_const<T>::type; template<typename T> using remove_const_t = typename remove_const<T>::type;
/// ///
/// \brief add the volatile qualifier to the provided type \p T /// \brief add the volatile qualifier to the provided type \f$T\f$
/// ///
/// \details removes references from the provided type such that \f$T\f$ becomes `volatile T` /// \details removes references from the provided type such that \f$T\f$ becomes \f$volatile\quad T\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_volatile : detail::_add_volatile<T> {}; template<typename T> struct add_volatile : detail::_add_volatile<T> {};
/// ///
/// \brief shorthand for `typename add_volatile<T>::type` /// \brief shorthand for `typename fennec::add_volatile<T>::type`
template<typename T> using add_volatile_t = typename add_volatile<T>::type; template<typename T> using add_volatile_t = typename add_volatile<T>::type;
/// ///
/// \brief remove the volatile qualifier from the provided type \p T /// \brief remove the volatile qualifier from the provided type \f$T\f$
/// ///
/// \details removes references from the provided type such that `volatile T` becomes \f$T\f$ /// \details removes references from the provided type such that \f$volatile\quad T\f$ becomes \f$T\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_volatile : detail::_remove_volatile<T> {}; template<typename T> struct remove_volatile : detail::_remove_volatile<T> {};
/// ///
/// \brief shorthand for `typename remove_volatile<T>::type` /// \brief shorthand for `typename fennec::remove_volatile<T>::type`
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type; template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
/// ///
/// \brief remove the volatile qualifier from the provided type \p T /// \brief remove the volatile qualifier from the provided type \f$T\f$
/// ///
/// \details removes references from the provided type such that \f$T\f$, `const T`, and `volatile T` become /// \details removes references from the provided type such that \f$T\f$, \f$const\quad T\f$, and \f$volatile\quad T\f$
/// `const volatile T` /// become \f$const volatile T\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_cv : detail::_add_cv<T> {}; template<typename T> struct add_cv : detail::_add_cv<T> {};
/// ///
/// \brief shorthand for `typename add_cv<T>::type` /// \brief shorthand for `typename fennec::add_cv<T>::type`
template<typename T> using add_cv_t = typename add_cv<T>::type; template<typename T> using add_cv_t = typename add_cv<T>::type;
/// ///
/// \brief remove the const and volatile qualifiers from the provided type \p T /// \brief remove the const and volatile qualifiers from the provided type \f$T\f$
/// ///
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and /// \details removes const and volatile from the provided type such that \f$const\quad T\f$, \f$volatile\quad T\f$, and
/// `const volatile T` become \f$T\f$ /// \f$const\quad volatile\quad T\f$ become \f$T\f$
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_cv : detail::_remove_cv<T> {}; template<typename T> struct remove_cv : detail::_remove_cv<T> {};
/// ///
/// \brief shorthand for `typename remove_cv<T>::type` /// \brief shorthand for `typename fennec::remove_cv<T>::type`
template<typename T> using remove_cv_t = typename remove_cv<T>::type; template<typename T> using remove_cv_t = typename remove_cv<T>::type;
/// ///
/// \brief add a reference and the const volatile qualifiers from the provided type \p T /// \brief add a reference and the const volatile qualifiers from the provided type \f$T\f$
/// ///
/// \details adds references and const volatile qualifiers to the provided type. /// \details adds references and const volatile qualifiers to the provided type.
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_cvref : type_identity<add_reference_t<add_cv_t<T>>> {}; template<typename T> struct add_cvref : type_identity<add_reference_t<add_cv_t<T>>> {};
/// ///
/// \brief shorthand for `typename add_cvr<T>::type` /// \brief shorthand for `typename fennec::add_cvr<T>::type`
template<typename T> using add_cvref_t = typename add_cvref<T>::type; template<typename T> using add_cvref_t = typename add_cvref<T>::type;
/// ///
/// \brief removes references as well as the const and volatile qualifiers from the provided type \p T /// \brief removes references as well as the const and volatile qualifiers from the provided type \f$T\f$
/// ///
/// \details removes const and volatile from the provided type such that /// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type /// \tparam T Reference Type
@@ -341,13 +393,13 @@ template<typename T> struct remove_cvref : type_identity<remove_cv_t<remove_refe
/// ///
/// \brief shorthand for `typename remove_cvr<T>::type` /// \brief shorthand for `typename fennec::remove_cvr<T>::type`
template<typename T> using remove_cvref_t = typename remove_cvref<T>::type; template<typename T> using remove_cvref_t = typename remove_cvref<T>::type;
/// ///
/// \brief removes references and pointers as well as the const and volatile qualifiers from the provided type \p T /// \brief removes references and pointers as well as the const and volatile qualifiers from the provided type \f$T\f$
/// ///
/// \details removes const and volatile from the provided type such that /// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type /// \tparam T Reference Type
@@ -355,7 +407,7 @@ template<typename T> struct remove_cvrefptr : type_identity<remove_cv_t<remove_r
/// ///
/// \brief shorthand for `typename remove_cvrp_t<T>::type` /// \brief shorthand for `typename fennec::remove_cvrp_t<T>::type`
template<typename T> using remove_cvrefptr_t = typename remove_cvrefptr<T>::type; template<typename T> using remove_cvrefptr_t = typename remove_cvrefptr<T>::type;
} }

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file types.h /// \file fennec/lang/types.h
/// \brief \ref fennec_lang_types /// \brief \ref fennec_lang_types
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
@@ -192,6 +192,16 @@
/// \copybrief fennec::ptrdiff_t /// \copybrief fennec::ptrdiff_t
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::empty_t "empty_t"</tt>
/// <td width="50%" style="vertical-align: top">
/// \copybrief fennec::empty_t
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::undefined_t "undefined_t"</tt>
/// <td width="50%" style="vertical-align: top">
/// \copybrief fennec::undefined_t
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::void_t "void_t"</tt> /// <tt>\ref fennec::void_t "void_t"</tt>
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copybrief fennec::void_t /// \copybrief fennec::void_t
@@ -211,28 +221,28 @@ namespace fennec
/// \name Basic Types /// \name Basic Types
/// @{ /// @{
using bool_t = bool; ///< \brief A conditional type using bool_t = bool; //!< \brief A conditional type.
using byte_t = unsigned char; ///< \brief A type capable of holding a single byte using byte_t = unsigned char; //!< \brief A type capable of holding a single byte.
using char_t = char; ///< \brief A type capable of holding an ascii value using char_t = char; //!< \brief A type capable of holding an ascii value.
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer using schar_t = signed char; //!< \brief A type with the size of a char, capable of holding a signed 8-bit integer.
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer using uchar_t = unsigned char; //!< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer.
using short_t = signed short; ///< \brief A signed short type, capable of holding signed 16-bit integer using short_t = signed short; //!< \brief A signed short type, capable of holding signed 16-bit integer.
using ushort_t = unsigned short; ///< \brief An unsigned short type, capable of holding an unsigned signed 16-bit integer using ushort_t = unsigned short; //!< \brief An unsigned short type, capable of holding an unsigned signed 16-bit integer.
using int_t = signed int; ///< \brief A signed integer type, size varies by implementation, but typically 32-bit using int_t = signed int; //!< \brief A signed integer type, size varies by implementation, but typically 32-bit.
using uint_t = unsigned int; ///< \brief An unsigned integer type, size varies by implementation, but typically 32-bit using uint_t = unsigned int; //!< \brief An unsigned integer type, size varies by implementation, but typically 32-bit.
using long_t = signed long; ///< \brief A signed integer type, with a size of at least 32-bits using long_t = signed long; //!< \brief A signed integer type, with a size of at least 32-bits.
using ulong_t = unsigned long; ///< \brief An unsigned integer type, with a size of at least 32-bits using ulong_t = unsigned long; //!< \brief An unsigned integer type, with a size of at least 32-bits.
using llong_t = signed long long; ///< \brief A signed integer type, with a size of 64-bits using llong_t = signed long long; //!< \brief A signed integer type, with a size of 64-bits.
using ullong_t = unsigned long long; ///< \brief An unsigned integer type, with a size of 64-bits using ullong_t = unsigned long long; //!< \brief An unsigned integer type, with a size of 64-bits.
using float_t = float; ///< \brief A single-precision floating-point type, typically with a size of 32-bits using float_t = float; //!< \brief A single-precision floating-point type, typically with a size of 32-bits.
using double_t = double; ///< \brief A double-precision floating-point type, typically with a size of 64-bits using double_t = double; //!< \brief A double-precision floating-point type, typically with a size of 64-bits.
/// @} /// @}
@@ -242,18 +252,18 @@ namespace fennec
/// \name Special Types /// \name Special Types
/// @{ /// @{
using nullptr_t = decltype(nullptr); ///< \brief Null Pointer Type using nullptr_t = decltype(nullptr); //!< \brief Null Pointer Type.
using intptr_t = intptr_t; ///< \brief Signed Integer Capable of Holding a Pointer to void using intptr_t = intptr_t; //!< \brief Signed Integer Capable of Holding a Pointer to void.
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void using uintptr_t = uintptr_t; //!< \brief Unsigned Integer Capable of Holding a Pointer to void.
using intmax_t = intmax_t; ///< \brief Maximum Width Signed Integer Type using intmax_t = intmax_t; //!< \brief Maximum Width Signed Integer Type.
using uintmax_t = uintmax_t; ///< \brief Maximum Width Unsigned Integer Type using uintmax_t = uintmax_t; //!< \brief Maximum Width Unsigned Integer Type.
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By \f$sizeof\f$, `sizeof...`, and \f$alignof\f$ using size_t = size_t; //!< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`.
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers using ptrdiff_t = __PTRDIFF_TYPE__; //!< \brief Signed Integer Type Returned by the Subtraction of two Pointers.
struct empty_t {}; struct empty_t {}; //!< \brief A struct resembling an empty type.
class undefined_t; ///< \brief undefined class for SFINAE class undefined_t; //!< \brief Undefined class for SFINAE.
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE template<typename...> using void_t = void; //!< \brief Void type used for SFINAE.
/// @} /// @}
@@ -264,15 +274,15 @@ namespace fennec
/// \name Sized Integer Types /// \name Sized Integer Types
/// @{ /// @{
using int8_t = ::int8_t; ///< \brief Signed 8-bit integer using int8_t = ::int8_t; //!< \brief Signed 8-bit integer.
using int16_t = ::int16_t; ///< \brief Signed 16-bit integer using int16_t = ::int16_t; //!< \brief Signed 16-bit integer.
using int32_t = ::int32_t; ///< \brief Signed 32-bit integer using int32_t = ::int32_t; //!< \brief Signed 32-bit integer.
using int64_t = ::int64_t; ///< \brief Signed 64-bit integer using int64_t = ::int64_t; //!< \brief Signed 64-bit integer.
using uint8_t = ::uint8_t; ///< \brief Unsigned 8-bit integer using uint8_t = ::uint8_t; //!< \brief Unsigned 8-bit integer.
using uint16_t = ::uint16_t; ///< \brief Unsigned 16-bit integer using uint16_t = ::uint16_t; //!< \brief Unsigned 16-bit integer.
using uint32_t = ::uint32_t; ///< \brief Unsigned 32-bit integer using uint32_t = ::uint32_t; //!< \brief Unsigned 32-bit integer.
using uint64_t = ::uint64_t; ///< \brief Unsigned 64-bit integer using uint64_t = ::uint64_t; //!< \brief Unsigned 64-bit integer.
/// @} /// @}
@@ -282,9 +292,9 @@ namespace fennec
/// \name Sized Floating-Point Types /// \name Sized Floating-Point Types
/// @{ /// @{
//using float16_t = _Float16; ///< \brief A half-precision floating-point scalar //using float16_t = _Float16; //!< \brief A half-precision floating-point scalar
//using float32_t = _Float32; ///< \brief A single-precision floating-point scalar //using float32_t = _Float32; //!< \brief A single-precision floating-point scalar
//using float64_t = _Float64; ///< \brief A double-precision floating-point scalar //using float64_t = _Float64; //!< \brief A double-precision floating-point scalar
/// @} /// @}

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file utility.h /// \file fennec/lang/utility.h
/// \brief \ref fennec_lang_utility /// \brief \ref fennec_lang_utility
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file common.h /// \file fennec/math/common.h
/// \brief \ref fennec_math_common /// \brief \ref fennec_math_common
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -16,8 +16,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
#ifndef FENNEC_MATH_DETAIL_FWD_H #ifndef FENNEC_MATH_DETAIL_FORWARD_H
#define FENNEC_MATH_DETAIL_FWD_H #define FENNEC_MATH_DETAIL_FORWARD_H
#include <fennec/math/detail/_types.h> #include <fennec/math/detail/_types.h>
@@ -36,4 +36,4 @@ template<typename ScalarT, size_t ColsV, size_t RowsV> using mat
} }
#endif // FENNEC_MATH_DETAIL_FWD_H #endif // FENNEC_MATH_DETAIL_FORWARD_H

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
#ifndef FENNEC_MATH_DETAIL_MATRIX_H #ifndef FENNEC_MATH_DETAIL_MATRIX_H
#define FENNEC_MATH_DETAIL_MATRIX_H #define FENNEC_MATH_DETAIL_MATRIX_H
#include <fennec/math/detail/_fwd.h> #include <fennec/math/detail/_forward.h>
namespace fennec namespace fennec
{ {

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
#ifndef FENNEC_MATH_DETAIL_VECTOR_TRAITS_H #ifndef FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
#define FENNEC_MATH_DETAIL_VECTOR_TRAITS_H #define FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
#include <fennec/math/detail/_fwd.h> #include <fennec/math/detail/_forward.h>
#include <fennec/lang/type_traits.h> #include <fennec/lang/type_traits.h>
#include <fennec/math/swizzle.h> #include <fennec/math/swizzle.h>

View File

@@ -1,6 +1,6 @@
// ===================================================================================================================== // =====================================================================================================================
// fennec, a free and open source game engine // fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower // Copyright © 2025 - 2026 Medusa Slockbower
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
// ===================================================================================================================== // =====================================================================================================================
/// ///
/// \file exponential.h /// \file fennec/math/exponential.h
/// \brief \ref fennec_math_exponential /// \brief \ref fennec_math_exponential
/// ///
/// ///
/// \details /// \details
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///

Some files were not shown because too many files have changed in this diff Show More