diff --git a/CMakeLists.txt b/CMakeLists.txt index cad838e..e0d59ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,7 +244,7 @@ fennec_add_sources( 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/_matrix.h include/fennec/math/detail/_types.h @@ -297,7 +297,7 @@ fennec_add_sources( # PLATFORM ============================================================================================================= - include/fennec/platform/interface/fwd.h + include/fennec/platform/interface/forward.h include/fennec/platform/interface/display_server.h include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp include/fennec/platform/interface/window.h source/platform/interface/window.cpp @@ -314,6 +314,7 @@ add_subdirectory(test) add_library(fennec STATIC ${FENNEC_SOURCES} + include/fennec/rtti/this_t.h ) add_dependencies(fennec metaprogramming fennec-dependencies) diff --git a/README.md b/README.md index 6daf8ed..1dc0205 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,24 @@ fennec Standards: * 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. +

diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake index 5cc38d0..72c9496 100644 --- a/cmake/compiler.cmake +++ b/cmake/compiler.cmake @@ -20,6 +20,10 @@ 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") set(FENNEC_COMPILER "GCC") include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake") diff --git a/include/fennec/containers/array.h b/include/fennec/containers/array.h index 9ba65dc..d15b20b 100644 --- a/include/fennec/containers/array.h +++ b/include/fennec/containers/array.h @@ -44,23 +44,24 @@ namespace fennec /// \brief Data Structure that defines a compile-time allocated array /// /// \details -/// | Property | Value | -/// |:-----------:|:-----------:| -/// | stable | ✅ | -/// | dynamic | ⛔ | -/// | homogeneous | ✅ | -/// | distinct | ⛔ | -/// | ordered | ⛔ | -/// | space | \f$O(N)\f$ | -/// | linear | ✅ | -/// | access | \f$O(1)\f$ | -/// | find | \f$O(N)\f$ | -/// | insertion | ⛔ | -/// | deletion | ⛔ | +/// | Property | Value | +/// |:-----------:|:----------:| +/// | stable | ✅ | +/// | dynamic | ⛔ | +/// | homogeneous | ✅ | +/// | distinct | ⛔ | +/// | ordered | ⛔ | +/// | space | \f$O(N)\f$ | +/// | linear | ✅ | +/// | access | \f$O(1)\f$ | +/// | find | \f$O(N)\f$ | +/// | insertion | ⛔ | +/// | deletion | ⛔ | +/// | space | \f$O(N)\f$ | /// /// \tparam ValueT value type -/// \tparam ElemV number of elements -template +/// \tparam N number of elements +template struct array { // Definitions ========================================================================================================= @@ -69,21 +70,19 @@ public: /// \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: - /// \name Public Members + /// \name Member Variables /// @{ - /// - /// \brief backing c-style array handle - value_t data[ElemV]; + value_t data[N]; //!< Backing c-style array handle /// @} @@ -96,14 +95,22 @@ public: /// @{ /// - /// \brief returns the number of elements in the array - /// \returns the number of elements in the array - [[nodiscard]] constexpr size_t size() const { return ElemV; } + /// \brief Returns the number of elements in the array. + /// \returns \f$N\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// + [[nodiscard]] constexpr size_t size() const { return N; } /// - /// \brief returns **true** when the array is empty - /// \return \f$ElemV == 0\f$ - [[nodiscard]] constexpr bool_t is_empty() const { return ElemV == 0; } + /// \brief Returns \f$true\f$ when the array is empty + /// \returns \f$ElemV == 0\f$ + /// + /// \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 /// \return reference to the requested element /// - /// \par Time-Complexity - /// Constant + /// \par Complexity + /// \f$O(1)\f$ /// - /// \par Space-Complexity - /// Constant constexpr value_t& operator[](size_t i) { - assertd(i < ElemV, "Array Out of Bounds"); + assertd(i < N, "Array Out of Bounds"); return data[i]; } /// - /// \brief access specified element + /// \brief Indexed access /// \details Returns a reference to the element at \c i /// \param i index of the element to return /// \return reference to the requested element /// - /// \par Time-Complexity - /// Constant + /// \par Complexity + /// \f$O(1)\f$ /// - /// \par Space-Complexity - /// Constant 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]; } /// - /// \brief Access the first element - /// \returns A reference to the element at \f$elements[0]\f$ + /// \returns A reference to \f$data[0]\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t& front() { return data[0]; } /// - /// \brief Const Access the first element - /// \returns A const-qualified reference to the element at \f$elements[0]\f$ + /// \brief Access the first element + /// \returns A const-qualified reference to \f$data[0]\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t& front() const { return data[0]; } /// - /// \brief Access the first element - /// \returns A reference to the element at \f$elements[ElemV - 1]\f$ + /// \returns A reference to \f$data[N - 1]\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t& back() { - return data[ElemV - 1]; + return data[N - 1]; } /// - /// \brief Const Access the first element - /// \returns A const-qualified reference to the element at \f$elements[ElemV - 1]\f$ + /// \brief Access the last element + /// \returns A const-qualified reference to \f$data[N - 1]\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// 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 + /// + /// \par Complexity + /// \f$O(N)\f$ + /// friend constexpr bool_t operator==(const array& lhs, const array& rhs) { - return array::_compare(lhs, rhs, make_index_metasequence{}); + return array::_compare(lhs, rhs, make_index_metasequence{}); } /// /// \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) { - return not array::_compare(lhs, rhs, make_index_metasequence{}); + return not array::_compare(lhs, rhs, make_index_metasequence{}); } /// @} @@ -206,39 +231,51 @@ public: /// @{ /// - /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns A pointer to the first element of the array + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t* begin() { return data; } /// - /// \brief C++ Iterator Specification \f$end()\f$ - /// \returns A pointer to one after the end of the array - constexpr value_t* end() { - return data + ElemV; - } - - - - /// - /// \brief Const C++ Iterator Specification \f$begin()\f$ + /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns A const-qualified pointer to the first element of the array + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t* begin() const { return data; } /// - /// \brief Const C++ Iterator Specification \f$end()\f$ + /// \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 + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t* end() const { - return data + ElemV; + return data + N; } /// @} -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== private: template static bool _compare(const array& lhs, const array& rhs, index_metasequence) { diff --git a/include/fennec/containers/bintree.h b/include/fennec/containers/bintree.h index ab4e5da..8e92753 100644 --- a/include/fennec/containers/bintree.h +++ b/include/fennec/containers/bintree.h @@ -18,7 +18,7 @@ /// /// \file fennec/containers/bintree.h -/// \brief +/// \brief A header containing the definition for an in-array binary tree. /// /// /// \details @@ -31,8 +31,10 @@ #ifndef FENNEC_CONTAINERS_BINTREE_H #define FENNEC_CONTAINERS_BINTREE_H +#include #include #include +#include #include #include @@ -43,19 +45,20 @@ namespace fennec /// \brief Structure defining a binary tree /// /// \details -/// | Property | Value | -/// |:-----------:|:-----------:| -/// | stable | ⛔ | -/// | dynamic | ✅ | -/// | homogeneous | ✅ | -/// | distinct | ⛔ | -/// | ordered | ⛔ | -/// | space | \f$O(N)\f$ | -/// | linear | ⛔ | -/// | access | \f$O(1)\f$ | -/// | find | \f$O(N)\f$ | -/// | insertion | \f$O(1)\f$ | -/// | deletion | \f$O(1)\f$ | +/// | Property | Value | +/// |:-----------:|:----------:| +/// | stable | ⛔ | +/// | dynamic | ✅ | +/// | homogeneous | ✅ | +/// | distinct | ⛔ | +/// | ordered | ⛔ | +/// | space | \f$O(N)\f$ | +/// | linear | ⛔ | +/// | access | \f$O(1)\f$ | +/// | find | \f$O(N)\f$ | +/// | insertion | \f$O(1)\f$ | +/// | deletion | \f$O(1)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypeT The data type /// \tparam AllocT An allocator class @@ -67,6 +70,7 @@ private: struct node; public: + /// \name Definitions /// @{ @@ -74,39 +78,20 @@ public: using alloc_t = allocator_traits::template rebind; //!< The allocator type 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 const_iterator; + private: - struct node { - value_t value; - size_t parent; - size_t child[2]; - - constexpr node() - : value() - , parent(npos), child{ npos, npos } { - } - - template - constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args) - : value(fennec::forward(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; using freed_t = list; @@ -118,6 +103,12 @@ public: /// /// \brief Default Constructor, initializes an empty tree + /// + /// \details The underlying allocation is not initialized. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bintree() : _table() , _freed() @@ -128,6 +119,12 @@ public: /// /// \brief Move Constructor, takes ownership of a tree /// \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 : _table(fennec::move(tree._table)) , _freed(fennec::move(tree._freed)) @@ -138,15 +135,49 @@ public: /// /// \brief Copy Constructor, copies a tree /// \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) - : _table(tree._table) - , _freed(tree._freed) - , _root(tree._root) - , _size(tree._size) { + : _table(tree._table.capacity()) + , _freed() + , _root(nullid) + , _size(0) { + + // Visitor for copying + struct { + bintree& self; + const bintree& target; + deque> 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( + visitor, tree._root + ); } /// /// \brief Destructor, clears the tree + /// + /// \details Clears the contents of \f$tree\f$. Invokes destructor. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~bintree() { clear(); } @@ -162,24 +193,40 @@ public: /// /// \returns The number of elements in the tree + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \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 { return _size == 0; } /// /// \returns The capacity of the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _table.capacity(); } /// /// \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 { size_t i = _size; if (not _freed.is_empty()) { @@ -190,6 +237,10 @@ public: /// /// \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 { return _root; } @@ -205,58 +256,79 @@ public: /// @{ /// - /// \details \f$O(1)\f$ /// \param i The node id /// \returns The parent of node \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t parent(size_t i) const { return i == npos ? npos : _table[i].parent; } /// - /// \details \f$O(1)\f$ /// \param i The node id /// \returns The grandparent of node \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t grandparent(size_t i) const { return parent(parent(i)); } /// - /// \details \f$O(1)\f$ /// \param i The node id /// \returns The left child of node \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t left(size_t i) const { return i == npos ? npos : _table[i].child[false]; } /// - /// \details \f$O(1)\f$ /// \param i The node id /// \returns The right child of node \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t right(size_t i) const { return i == npos ? npos : _table[i].child[true]; } /// - /// \details \f$O(1)\f$ /// \param i The node id /// \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$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t child(size_t i, bool dir) const { return i == npos ? npos : _table[i].child[dir]; } /// - /// \details \f$O(1)\f$ /// \param i The node id /// \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)); } /// - /// \details \f$O(1)\f$ /// \param i The id of the node /// \returns The id of the sibling of \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t sibling(size_t i) const { if (i == npos) { return npos; @@ -270,9 +342,12 @@ public: } /// - /// \details \f$O(\log n)\f$ /// \param i The node id /// \returns The depth of node \f$i\f$ + /// + /// \par Complexity + /// \f$O(\log n)\f$ + /// constexpr size_t depth(size_t i) const { size_t d = 0; while (i != npos) { @@ -283,9 +358,12 @@ public: } /// - /// \details \f$O(\log n)\f$ /// \param i The node id /// \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 { if (i >= _table.size()) { return npos; @@ -297,9 +375,12 @@ public: } /// - /// \details \f$O(\log n)\f$ /// \param i The node id /// \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 { if (i >= _table.size()) { return npos; @@ -320,18 +401,25 @@ public: /// @{ /// - /// \details \f$O(1)\f$ /// \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) { assertd(i < _table.size(), "Index out of bounds."); return _table[i].value; } /// - /// \details Const Access, \f$O(1)\f$ + /// \details Node access /// \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 { assertd(i < _table.size(), "Index out of bounds."); return _table[i].value; @@ -339,7 +427,9 @@ public: /// @} + // Modifiers =========================================================================================================== +public: /// \name Modifiers /// @{ @@ -349,6 +439,10 @@ public: /// \param p The parent node /// \param val The object to move into 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) { return this->_insert_left(p, fennec::forward(val)); } @@ -358,6 +452,10 @@ public: /// \param p The parent node /// \param val The object to copy to 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) { return this->_insert_left(p, val); } @@ -368,6 +466,10 @@ public: /// \param p The parent node /// \param args The arguments to construct the new node with /// \returns The id of the new node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr size_t emplace_left(size_t p, ArgsT&&...args) { return this->_insert_left(p, fennec::forward(args)...); @@ -378,6 +480,10 @@ public: /// \param p The parent node /// \param val The object to move into 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) { return this->_insert_right(p, fennec::forward(val)); } @@ -387,6 +493,10 @@ public: /// \param p The parent node /// \param val The object to copy to 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) { return this->_insert_right(p, val); } @@ -397,6 +507,10 @@ public: /// \param p The parent node /// \param args The arguments to construct the new node with /// \returns The id of the new node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr size_t emplace_right(size_t p, ArgsT&&...args) { return this->_insert_right(p, fennec::forward(args)...); @@ -409,6 +523,10 @@ public: /// \param sub The root node for the rotation /// \param dir The direction to rotate, \f$true\f$ for right, \f$false\f$ for left /// \returns the new root node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t rotate(size_t sub, bool dir) { if (sub == npos) { return npos; @@ -439,6 +557,10 @@ public: /// \param side The side to insert on /// \param val The object to move into the new node /// \returns The id of the new node + /// + /// \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(val)); } @@ -449,6 +571,10 @@ public: /// \param side The side to insert on /// \param val The object to copy to the new node /// \returns The id of the new node + /// + /// \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); } @@ -460,6 +586,10 @@ public: /// \param side The side to insert on /// \param args The arguments to construct the new node with /// \returns The id of the new node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr size_t emplace(size_t parent, bool side, ArgsT&&...args) { return this->_insert(parent, side, fennec::forward(args)...); @@ -467,6 +597,10 @@ public: /// /// \brief Clears the tree, destroying all elements + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void clear() { list queue; @@ -500,6 +634,35 @@ public: /// \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 + 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 /// @@ -511,8 +674,12 @@ public: /// \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 - constexpr void traverse(VisitorT&& visit, size_t i) { + constexpr void traverse(VisitorT&& visit, size_t i) const { OrderT order; i = order(*this, i); while (i != npos) { @@ -918,6 +1085,10 @@ public: /// /// \returns an iterator at the first element in pre-order traversal + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// iterator begin() { return iterator(this, _root); } @@ -925,12 +1096,20 @@ public: /// /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns an iterator at the first element in pre-order traversal + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// const_iterator begin() const { return iterator(this, _root); } /// /// \returns an iterator at the first element in pre-order traversal + /// + /// \par Complexity + /// \f$O(1)\f$ + /// iterator end() { return iterator(this, _root, nullid); } @@ -938,20 +1117,26 @@ public: /// /// \brief C++ Iterator Specification \f$end()\f$ /// \returns an iterator at the first element in pre-order traversal + /// + /// \par Complexity + /// \f$O(1)\f$ + /// const_iterator end() const { return iterator(this, _root, nullid); } /// @} -// Fields ============================================================================================================== + +// Private Member Variables ============================================================================================ private: table_t _table; freed_t _freed; size_t _root, _size; -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== +private: constexpr size_t _next_free() { size_t i = _size; if (not _freed.is_empty()) { @@ -959,7 +1144,7 @@ private: _freed.pop_front(); } 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; return i; @@ -1047,6 +1232,35 @@ private: bool d = i == _right(p); 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 + constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args) + : value(fennec::forward(args)...) + , parent(p), child{ l, r } { + } + + constexpr ~node() { + parent = npos; + child[0] = npos; + child[1] = npos; + } + + size_t& operator[](bool d) { + return child[d]; + } + }; }; } diff --git a/include/fennec/containers/bitfield.h b/include/fennec/containers/bitfield.h index 26fb289..77e9385 100644 --- a/include/fennec/containers/bitfield.h +++ b/include/fennec/containers/bitfield.h @@ -42,19 +42,20 @@ namespace fennec /// \brief Bitfield Container with basic Bit Ops /// /// \details -/// | Property | Value | -/// |:-----------:|:------------------------------:| -/// | stable | Elements cannot be referenced. | -/// | dynamic | ⛔ | -/// | homogeneous | ✅ | -/// | distinct | ⛔ | -/// | ordered | ⛔ | -/// | space | \f$O(N)\f$ | -/// | linear | ✅ | -/// | access | \f$O(1)\f$ | -/// | find | \f$O(N)\f$ | -/// | insertion | ⛔ | -/// | deletion | ⛔ | +/// | Property | Value | +/// |:-----------:|:----------:| +/// | stable | ⛔ | +/// | dynamic | ⛔ | +/// | homogeneous | ✅ | +/// | distinct | ⛔ | +/// | ordered | ⛔ | +/// | space | \f$O(N)\f$ | +/// | linear | ✅ | +/// | access | \f$O(1)\f$ | +/// | find | \f$O(N)\f$ | +/// | insertion | ⛔ | +/// | deletion | ⛔ | +/// | space | \f$O(N)\f$ | /// /// \tparam N The number of bits in the bitfield template @@ -62,21 +63,41 @@ struct bitfield { // Constants =========================================================================================================== public: + + /// \name Constants + /// @{ + 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 + /// @} -// Constructors ======================================================================================================== + +// Constructors & Destructor =========================================================================================== 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() : _bytes() { } /// - /// \brief boolean array constructor + /// \brief Boolean array constructor. /// \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]) : _bytes() { for (size_t i = 0; i < arr; ++i) { @@ -85,8 +106,13 @@ public: } /// - /// \brief index array constructor - /// \param arr An array of indices values resembling which bits to set. + /// \brief Index array constructor. + /// \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 explicit constexpr bitfield(const size_t (&arr)[I]) : _bytes() { @@ -96,8 +122,13 @@ public: } /// - /// \brief variadic array constructor - /// \param args A set of indices values resembling which bits to set. + /// \param args A set of indices. + /// \details This substitution assumes \f$ArgsT\ldots\f$ can be taken as an array of indices.
+ /// Sets the bits of each index provided in \f$args\ldots\f$. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr bitfield(ArgsT&&...args) : _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.
+ /// Initializes each bit with the respective boolean in \f$args\ldots\f$.
+ /// Does not necessitate the number of arguments be equal to the number of bits. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template requires((is_bool_v or is_convertible_v) and ...) constexpr bitfield(ArgsT&&...args) : _bytes() { @@ -116,6 +155,10 @@ public: /// /// \brief copy constructor /// \param bf bitfield to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// bitfield(const bitfield& bf) : _bytes(bf._bytes) { } @@ -123,6 +166,10 @@ public: /// /// \brief move constructor /// \param bf bitfield to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// bitfield(bitfield&& bf) noexcept : _bytes(bf._bytes) { } @@ -131,22 +178,52 @@ public: /// \brief destructor constexpr ~bitfield() = default; + /// @} + + +// Assignment ========================================================================================================== +public: + + /// \name Assignment Operators + /// @{ + /// /// \brief copy assignment /// \param bf bitfield to copy /// \returns a reference to self + /// + /// \par Complexity + /// \f$O(N)\f$ + /// bitfield& operator=(const bitfield& bf) = default; /// /// \brief move assignment /// \param bf bitfield to move /// \returns a reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// bitfield& operator=(bitfield&& bf) noexcept = default; + /// @} + + +// Access & Modifiers ================================================================================================== +public: + + /// \name Access & Modifiers + /// @{ + /// /// \brief test a bit /// \param i the index of the bit /// \returns the value stored in the bit as a boolean + /// + /// \par Complexity + /// \f$O(1)\f$ + /// bool test(size_t i) const { assertd(i < bits, "Index out of Bounds!"); size_t b = i / 8; @@ -157,6 +234,10 @@ public: /// /// \brief set a bit /// \param i the index of the bit + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void set(size_t i) { assertd(i < bits, "Index out of Bounds!"); size_t b = i / 8; @@ -167,6 +248,10 @@ public: /// /// \brief clear a bit /// \param i the index of the bit + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void clear(size_t i) { assertd(i < bits, "Index out of Bounds!"); size_t b = i / 8; @@ -177,6 +262,10 @@ public: /// /// \brief toggle a bit /// \param i the index of the bit + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void toggle(size_t i) { assertd(i < bits, "Index out of Bounds!"); size_t b = i / 8; @@ -186,8 +275,12 @@ public: /// /// \brief store \f$v\f$ in bit \f$i\f$ - /// \param i - /// \param v + /// \param i the index of the bit + /// \param v the value to store + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void store(size_t i, bool v) { assertd(i < bits, "Index out of Bounds!"); size_t b = i / 8; @@ -198,15 +291,26 @@ public: /// /// \brief not operator /// \returns a bitfield containing the bit-wise inverse + /// + /// \par Complexity + /// \f$O(N)\f$ + /// bitfield operator~() const { bitfield res = *this; res._inv_helper(make_index_metasequence_t{}); return res; } + /// @} + + +// Private Member Variables ============================================================================================ private: array _bytes; + +// Private Helpers ===================================================================================================== +private: template void _inv_helper(index_metasequence) { ((_bytes[I] = ~_bytes[I]), ...); diff --git a/include/fennec/containers/containers.h b/include/fennec/containers/containers.h index 5b6dcb0..f1e0a8f 100644 --- a/include/fennec/containers/containers.h +++ b/include/fennec/containers/containers.h @@ -42,19 +42,20 @@ /// /// \section fennec_containers_container_section_properties Container Properties /// -/// | Property | Meaning | -/// |:-----------:|:----------------------------------------------------------------------------------------------:| -/// | stable | Any pointer reference to an element remains constant for the lifetime of the data structure. | -/// | dynamic | Memory for this data structure is allocated on the heap. | -/// | homogeneous | The types of all elements are either identical, or inherit the same base type. | -/// | distinct | Elements are guaranteed to be unique in their value. | -/// | ordered | Elements are guaranteed to be in order, such that for any index \f$i\f$, \f$E_i < E_{i + 1}\f$ | -/// | space | The amount of memory allocated with respect to the number of elements, in big-O notation. | -/// | linear | Each element is sequential in terms of access. | -/// | access | The runtime of the access operators and functions, in big-O notation. | -/// | find | The runtime of finding an element in the data structure, in big-O notation. | -/// | insertion | The runtime of inserting an element in the data structure, in big-O notation. | -/// | deletion | The runtime of erasing an element in the data structure, in big-O notation. | +/// | Property | Meaning | +/// |:----------------|:-----------------------------------------------------------------------------------------------| +/// | **stable** | Any pointer reference to an element remains constant for the lifetime of the container. | +/// | **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. | +/// | **distinct** | Elements are guaranteed to be unique in their value. | +/// | **ordered** | Elements are guaranteed to be in order, such that for any index \f$i\f$, \f$E_i < E_{i + 1}\f$ | +/// | **space** | The amount of memory allocated with respect to the number of elements, in big-O notation. | +/// | **linear** | Each element is sequential in terms of access. | +/// | **access** | The runtime of the access operators and functions, in big-O notation. | +/// | **find** | The runtime of finding an element in the container, 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 container, in big-O notation. | +/// | **space** | The space complexity of the container. | /// /// /// \section fennec_containers_section_cppstdlib C++ Standard Template Library diff --git a/include/fennec/containers/deque.h b/include/fennec/containers/deque.h index 1dfd232..41870bb 100644 --- a/include/fennec/containers/deque.h +++ b/include/fennec/containers/deque.h @@ -59,34 +59,30 @@ namespace fennec /// | find | \f$O(N)\f$ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypeT value type template> struct deque { // Definitions ========================================================================================================= -public: - using value_t = TypeT; ///< Alias for the value type - class iterator; - private: - struct node { - value_t value; - node *prev, *next; - - template - node(node* prev, node* next, ArgsT&&...args) - : value(fennec::forward(args)...) - , prev(prev), next(next) { - } - - ~node() = default; - }; + struct node; public: + + /// \name Definitions + /// @{ + + using value_t = TypeT; //!< Alias for the value type using alloc_t = allocator_traits::template rebind; //!< The underlying allocator type using elem_t = node*; //!< The underlying element type + /// @} + + + class iterator; + // Constructors ======================================================================================================== @@ -95,6 +91,10 @@ public: /// /// \brief Default Constructor, initializes an empty deque + /// + /// \par Complexity + /// \f$O(1)\f$ + /// deque() : _alloc() , _first(nullptr) @@ -105,6 +105,10 @@ public: /// /// \brief Alloc Constructor, initializes an empty deque with the specified allocator /// \param alloc the allocator to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// deque(const alloc_t& alloc) : _alloc(alloc) , _first(nullptr) @@ -115,6 +119,10 @@ public: /// /// \brief Copy Constructor /// \param deque the deque to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// deque(const deque& deque) : _alloc(deque._alloc) , _first(nullptr) @@ -130,6 +138,10 @@ public: /// /// \brief Deque Move Constructor /// \param deque the deque to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// deque(deque&& deque) noexcept : _alloc(deque._alloc) , _first(deque._first) @@ -141,6 +153,10 @@ public: /// /// \brief Destructor, calls deque::clear + /// + /// \par Complexity + /// \f$O(N)\f$ + /// ~deque() { clear(); } @@ -154,12 +170,20 @@ public: /// /// \returns \f$true\f$ when the deque is empty, \f$false\f$ otherwise + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool is_empty() const { 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 { return _size; } @@ -174,6 +198,10 @@ public: /// /// \returns a reference to the first element in the deque + /// + /// \par Complexity + /// \f$O(1)\f$ + /// value_t& front() { assert(not is_empty(), "Attempted to access an empty deque."); return _first->value; @@ -181,6 +209,10 @@ public: /// /// \returns a const-qualified reference to the first element in the deque + /// + /// \par Complexity + /// \f$O(1)\f$ + /// const value_t& front() const { assert(not is_empty(), "Attempted to access an empty deque."); return _first->value; @@ -188,6 +220,10 @@ public: /// /// \returns a reference to the last element in the deque + /// + /// \par Complexity + /// \f$O(1)\f$ + /// value_t& back() { assert(not is_empty(), "Attempted to access an empty deque."); return _last->value; @@ -195,6 +231,10 @@ public: /// /// \returns a const-qualified reference to the last element in the deque + /// + /// \par Complexity + /// \f$O(1)\f$ + /// const value_t& back() const { assert(not is_empty(), "Attempted to access an empty deque."); return _last->value; @@ -211,6 +251,10 @@ public: /// /// \brief Push Front Move, moves a value to the front of the deque /// \param elem the value to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void push_front(value_t&& elem) { this->_push_front(elem); } @@ -218,6 +262,10 @@ public: /// /// \brief Push Front Copy, copies a value to the front of the deque /// \param elem the value to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void push_front(const value_t& elem) { this->_push_front(elem); } @@ -226,6 +274,10 @@ public: /// \brief Emplace Front, constructs a new value at the front of the deque /// \tparam ArgsT Argument types /// \param args Arguments used to construct the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template void emplace_front(ArgsT&&...args) { this->_push_front(fennec::forward(args)...); @@ -235,6 +287,10 @@ public: /// /// \brief Push Back Move, moves a value to the back of the deque /// \param elem the value to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void push_back(value_t&& elem) { this->_push_back(elem); } @@ -242,6 +298,10 @@ public: /// /// \brief Push Back Copy, copies a value to the back of the deque /// \param elem the value to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void push_back(const value_t& elem) { this->_push_back(elem); } @@ -250,6 +310,10 @@ public: /// \brief Emplace Back, constructs a new value at the back of the deque /// \tparam ArgsT Argument types /// \param args Arguments used to construct the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template void emplace_back(ArgsT&&...args) { this->_push_back(fennec::forward(args)...); @@ -257,6 +321,10 @@ public: /// /// \brief Clears the contents of the deque + /// + /// \par Complexity + /// \f$O(N)\f$ + /// void clear() { elem_t it = _first; while (it) { @@ -272,6 +340,10 @@ public: /// /// \brief Erase the First Element + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void pop_front() { if (_first == nullptr) { return; @@ -286,6 +358,10 @@ public: /// /// \brief Erase the Last Element + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void pop_back() { if (_last == nullptr) { return; @@ -307,11 +383,16 @@ public: * TODO: Decide whether you should be able to iterate over a deque */ + +// Private Member Variables ============================================================================================ private: alloc_t _alloc; node *_first, *_last; size_t _size; + +// Private Helpers ===================================================================================================== +private: template void _push_front(ArgsT&&...args) { elem_t next = _first; @@ -337,6 +418,22 @@ private: } ++_size; } + + +// Private Definitions ================================================================================================= +private: + struct node { + value_t value; + node *prev, *next; + + template + node(node* prev, node* next, ArgsT&&...args) + : value(fennec::forward(args)...) + , prev(prev), next(next) { + } + + ~node() = default; + }; }; diff --git a/include/fennec/containers/dynarray.h b/include/fennec/containers/dynarray.h index 4c82379..8753697 100644 --- a/include/fennec/containers/dynarray.h +++ b/include/fennec/containers/dynarray.h @@ -56,6 +56,7 @@ namespace fennec /// | find | \f$O(N)\f$ | /// | insertion | \f$O(N)\f$ | /// | deletion | \f$O(N)\f$ | +/// | space | \f$O(N)\f$ | /// /// This structure prefers shallow moves and deep copies. /// @@ -65,8 +66,14 @@ struct dynarray { // Definitions ========================================================================================================= 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 ======================================================================================================== @@ -77,6 +84,10 @@ public: /// /// \brief Default Constructor, initializes an empty allocation. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr dynarray() : _alloc(8) , _size(0) { @@ -86,16 +97,11 @@ public: /// \brief Alloc Constructor, initialize empty allocation with allocator instance. /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some /// data. - explicit constexpr dynarray(const alloc_t& alloc) - : _alloc(8, alloc) - , _size(0) { - } - /// - /// \brief Alloc Move Constructor, initialize empty allocation with allocator instance. - /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some - /// data. - explicit constexpr dynarray(alloc_t&& alloc) noexcept + /// \par Complexity + /// \f$O(1)\f$ + /// + explicit constexpr dynarray(const alloc_t& alloc) : _alloc(8, alloc) , _size(0) { } @@ -103,6 +109,10 @@ public: /// /// \brief Sized Allocation, initializes a dynarray with \f$n\f$ elements using the default constructor. /// \param n The number of elements. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// explicit constexpr dynarray(size_t n) : _alloc(n) , _size(n) @@ -118,21 +128,11 @@ public: /// using the default constructor. /// \param n The number of elements /// \param alloc The allocator object to copy - constexpr dynarray(size_t n, const alloc_t& alloc) - : _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 - /// using the default constructor. - /// \param n The number of elements - /// \param alloc The allocator object to copy - constexpr dynarray(size_t n, alloc_t&& alloc) + /// \par Complexity + /// \f$O(N)\f$ + /// + constexpr dynarray(size_t n, const alloc_t& alloc) : _alloc(n, alloc) , _size(n) { value_t* addr = _alloc.data(); @@ -146,6 +146,10 @@ public: /// constructed using the copy constructor /// \param n the number of elements /// \param val the value to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr dynarray(size_t n, const TypeT& val) : _alloc(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 /// \tparam ArgsT A sequence of argument types /// \param n The number of objects to create /// \param args The arguments to create each object with + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr explicit dynarray(size_t n, ArgsT&&...args) : _alloc(n) @@ -177,6 +181,10 @@ public: /// \brief Array Copy Constructor /// \tparam N The length of the array, automatically deduced /// \param arr The array to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr dynarray(const TypeT (&arr)[N]) : _alloc(N) @@ -190,6 +198,10 @@ public: /// \brief Array Move Constructor /// \tparam N The length of the array, automatically deduced /// \param arr The array to move + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr dynarray(TypeT (&&arr)[N]) : _alloc(N) @@ -204,6 +216,10 @@ public: /// \tparam OTypeT The other value type /// \tparam OAlloc The other allocator type /// \param conv The dynarray to convert + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr dynarray(const dynarray& conv) : _alloc(conv.size()) @@ -218,6 +234,10 @@ public: /// \brief Initializer List Constructor /// \param l List of elements to initialize with /// \param alloc An allocator object to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr dynarray(initializer_list l, const alloc_t& alloc = alloc_t()) : _alloc(l.size(), alloc) , _size(l.size()) { @@ -230,6 +250,10 @@ public: /// /// \brief Copy Constructor, uses the copy constructor to copy each element /// \param arr the dynarray to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr dynarray(const dynarray& arr) : _alloc(arr._size) , _size(arr._size) { @@ -241,6 +265,10 @@ public: /// /// \brief Move Constructor, takes ownership of the allocation /// \param arr the dynarray to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr dynarray(dynarray&& arr) noexcept : _alloc(fennec::move(arr._alloc)) , _size(arr._size) { @@ -249,6 +277,10 @@ public: /// /// \brief Default Destructor, destructs all elements and frees the underlying allocation + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~dynarray() { value_t* addr = _alloc.data(); 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 ========================================================================================================== public: @@ -269,9 +308,13 @@ public: /// \brief Copy Assignment Operator /// \param arr the array to copy /// \returns A dynarray after having copied each element of \f$arr\f$ + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr dynarray& operator=(const dynarray& arr) { this->clear(); - _alloc.creallocate(_size = arr._size); + _alloc.reallocate(_size = arr._size); for (size_t i = 0; i < _size; ++i) { fennec::construct(&_alloc[i], fennec::copy(arr[i])); } @@ -282,6 +325,10 @@ public: /// \brief Move Assignment Operator /// \param arr the array to move /// \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 { this->clear(); _alloc = fennec::move(arr._alloc); @@ -295,10 +342,14 @@ public: /// \tparam N the length of the array /// \param arr the array to copy /// \returns A dynarray after having copied each element of \f$arr\f$ + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr dynarray& operator=(const TypeT (&arr)[N]) { this->clear(); - _alloc.creallocate(_size = N); + _alloc.reallocate(_size = N); for (size_t i = 0; i < _size; ++i) { fennec::construct(&_alloc[i], fennec::copy(arr[i])); } @@ -310,10 +361,14 @@ public: /// \tparam N the length of the array /// \param arr the array to copy /// \returns A dynarray after having moved each element of \f$arr\f$ + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr dynarray& operator=(TypeT (&&arr)[N]) { this->clear(); - _alloc.creallocate(_size = N); + _alloc.reallocate(_size = N); for (size_t i = 0; i < _size; ++i) { fennec::construct(&_alloc[i], fennec::move(arr[i])); } @@ -330,18 +385,30 @@ public: /// /// \returns The size of the dynarray in elements + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \returns The current capacity, in elements, of the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _alloc.capacity(); } /// /// \returns True when there are no elements active, otherwise false + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool is_empty() const { return _size == 0; } @@ -359,6 +426,10 @@ public: /// \brief Array Access Operator /// \param i The index to access /// \returns A reference to the element at index \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr TypeT& operator[](size_t i) { assertd(i < _size, "Array Out of Bounds"); return _alloc[i]; @@ -368,6 +439,10 @@ public: /// \brief Array Access Operator (const) /// \param i The index to access /// \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 { assertd(i < _size, "Array Out of Bounds"); return _alloc[i]; @@ -375,36 +450,60 @@ public: /// /// \returns Reference to the first element in the dynarray + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr TypeT& front() { return this->operator[](0); } /// /// \returns A const-qualified reference to the first element in the dynarray + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const TypeT& front() const { return this->operator[](0); } /// /// \returns A reference to the last element in the dynarray + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr TypeT& back() { return this->operator[](size() - 1); } /// /// \returns A const-qualified reference to the last element in the dynarray + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const TypeT& back() const { return this->operator[](size() - 1); } /// /// \returns A pointer to the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr TypeT* data() { return _alloc.data(); } /// /// \returns A pointer to the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const TypeT* data() const { return _alloc.data(); } @@ -422,6 +521,10 @@ public: /// \brief Move Insertion /// \param i index to insert at /// \param val the value to initialize with + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void insert(size_t i, TypeT&& val) { // Grow if the size has reached the capacity of the allocation @@ -446,6 +549,10 @@ public: /// \brief Copy Insertion /// \param i index to insert at /// \param val the value to initialize with + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void insert(size_t i, const TypeT& val) { // Grow if the size has reached the capacity of the allocation @@ -472,6 +579,10 @@ public: /// \param i index to insert at /// \param args Arguments to construct with /// \tparam ArgsT Argument types + /// + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr void emplace(size_t i, ArgsT&&...args) { @@ -496,6 +607,10 @@ public: /// /// \brief Push Back Copy /// \param val Value to initialize with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void push_back(const TypeT& val) { dynarray::insert(_size, val); } @@ -503,6 +618,10 @@ public: /// /// \brief Push Back Move /// \param val Value to initialize with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void push_back(TypeT&& val) { dynarray::insert(_size, fennec::forward(val)); } @@ -511,6 +630,10 @@ public: /// \brief Emplace Back /// \tparam ArgsT Argument Types /// \param args Arguments to construct with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr void emplace_back(ArgsT...args) { dynarray::emplace(_size, fennec::forward(args)...); @@ -518,6 +641,10 @@ public: /// /// \brief Erase last element + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void pop_back() { fennec::destruct(&_alloc[--_size]); } @@ -525,9 +652,15 @@ public: /// /// \brief Resize the dynarray, invoking the default constructor for all new 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) { _reduce(n); - _alloc.creallocate(n); + _alloc.reallocate(n); for (size_t i = _size; i < n; ++i) { fennec::construct(&_alloc[i]); @@ -542,9 +675,13 @@ public: /// \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 + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void resize(size_t n, const TypeT& val) { _reduce(n); - _alloc.creallocate(n); + _alloc.reallocate(n); for (size_t i = _size; i < n; ++i) { fennec::construct(&_alloc[i], val); @@ -558,13 +695,21 @@ public: /// \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 + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void reserve(size_t n) { _reduce(n); - _alloc.creallocate(n); + _alloc.reallocate(n); } /// /// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void clear() { _reduce(0); _alloc.deallocate(); @@ -581,26 +726,42 @@ public: /// /// \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 \f$begin()\f$ /// \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; } /// /// \return A pointer to the address after the last element in the dynarray - constexpr TypeT* end() { return begin() + _size; } + /// + /// \par Complexity + /// \f$O(1)\f$ + /// + constexpr TypeT* end() { return begin() + _size; } /// /// \brief C++ Iterator Specification \f$end()\f$ /// \return A const qualified pointer to the address after the last element in the dynarray - constexpr const TypeT* end() const { return begin() + _size; } + /// + /// \par Complexity + /// \f$O(1)\f$ + /// + constexpr const TypeT* end() const { return begin() + _size; } /// @} -// Private Members ===================================================================================================== +// Public Member Variables ============================================================================================= private: allocation _alloc; size_t _size; @@ -611,7 +772,7 @@ private: // helper to double the capacity of the allocation constexpr void _grow() { - _alloc.creallocate(_alloc.capacity() * 2); + _alloc.reallocate(_alloc.capacity() * 2); } // helper to destruct elements past n diff --git a/include/fennec/containers/generic.h b/include/fennec/containers/generic.h index df26742..ad55500 100644 --- a/include/fennec/containers/generic.h +++ b/include/fennec/containers/generic.h @@ -53,6 +53,7 @@ namespace fennec /// | find | ⛔ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(1)\f$ | struct generic { // Definitions ========================================================================================================= @@ -68,11 +69,18 @@ private: using manager_t = void* (*)(uint8_t, void*); -// Constructors ======================================================================================================== +// Constructors & Destructor =========================================================================================== public: + /// \name Constructors & Destructor + /// @{ + /// /// \brief Default Constructor + /// + /// \par Complexity + /// \f$O(1)\f$ + /// generic() : _handle(nullptr) , _manage(nullptr) { @@ -81,6 +89,10 @@ public: /// /// \brief Copy Constructor /// \param gen The generic object to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// generic(const generic& gen) : _handle(nullptr) , _manage(gen._manage) { @@ -92,6 +104,10 @@ public: /// /// \brief Move Constructor /// \param gen The generic object to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// generic(generic&& gen) : _handle(gen._handle) , _manage(gen._manage) { @@ -103,6 +119,10 @@ public: /// \brief Value Constructor /// \tparam T The type of the value /// \param x The value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template generic(T&& x) : _handle(new T(fennec::forward(x))) @@ -114,6 +134,10 @@ public: /// \tparam T The type to construct /// \tparam ArgsT The argument types /// \param args The argument values + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template generic(type_identity, ArgsT&&...args) : _handle(new T(fennec::forward(args)...)) @@ -126,31 +150,53 @@ public: reset(); } + /// @} + // Properties ========================================================================================================== public: + /// \name Properties + /// @{ + /// /// \brief runtime type acquisition /// \returns a runtime type struct referencing the held type + /// + /// \par Complexity + /// \f$O(1)\f$ + /// type type() const { return *static_cast(_manage(op_type, nullptr)); } /// /// \returns \f$true\f$ if there is a held value, \f$false\f$ otherwise + /// + /// \par Complexity + /// \f$O(1)\f$ + /// bool has_value() const { return _handle != nullptr; } + /// @} + // Assignment ========================================================================================================== public: + /// \name Assignment Operators + /// @{ + /// /// \brief copy assignment /// \param gen the generic to copy /// \returns a reference to self after copying the contents of \f$gen\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// generic& operator=(const generic& gen) { if (this == &gen) { // self-assignment case return *this; @@ -166,6 +212,10 @@ public: /// \brief move assignment /// \param gen the generic to move /// \returns a reference to self after swapping contents with \f$gen\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// generic& operator=(generic&& gen) noexcept { swap(gen); return *this; @@ -176,6 +226,10 @@ public: /// \tparam T the type of the value /// \param x the value to assign /// \returns a reference to self after having assigned \f$x\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template generic& operator=(T&& x) { reset(); @@ -184,17 +238,26 @@ public: return *this; } + /// @} -// Insertion & Deletion ================================================================================================ + +// Modifiers =========================================================================================================== public: + /// \name Modifiers + /// @{ + /// /// \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 ArgsT the argument types /// \param args the argument values + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template void emplace(ArgsT&&...args) { reset(); @@ -205,6 +268,10 @@ public: /// /// \brief reset value /// \details clears the held value using the appropriate destructor + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void reset() { if (_manage) { _handle = _manage(op_destroy, _handle); @@ -212,24 +279,37 @@ public: } } - -// Utility ============================================================================================================= -public: - /// /// \brief C++ 11 Swap Specification /// \param gen the generic to swap with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void swap(generic& gen) noexcept { fennec::swap(_handle, gen._handle); fennec::swap(_manage, gen._manage); } + /// @} + + +// Casting ============================================================================================================= +public: + + /// \name Casting + /// @{ + /// /// \brief cast value /// /// \details equivalent to \f$reinterpret_cast\f$ /// \tparam T The type to cast to /// \returns The contents of generic after having cast to \f$T\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template> T cast() { return static_cast(*static_cast(_handle)); @@ -239,19 +319,25 @@ public: /// \details equivalent to \f$reinterpret_cast\f$ /// \tparam T The type to cast to /// \returns The contents of generic after having cast to \f$T\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template> T cast() const { return static_cast(*static_cast(_handle)); } + /// @} -// Members ============================================================================================================= + +// Private Member Variables ============================================================================================ private: void* _handle; manager_t _manage; -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== private: template static void* _manage_impl(uint8_t op, void* hnd) { diff --git a/include/fennec/containers/graph.h b/include/fennec/containers/graph.h index d799852..d9f87f3 100644 --- a/include/fennec/containers/graph.h +++ b/include/fennec/containers/graph.h @@ -55,19 +55,20 @@ namespace fennec /// \brief Graph Data Structure, describes sets of arbitrarily connected vertices /// /// \details -/// | Property | Value | -/// |:-----------:|:----------:| -/// | stable | ⛔ | -/// | dynamic | ✅ | -/// | homogeneous | ✅ | -/// | distinct | ⛔ | -/// | ordered | ⛔ | -/// | space | \f$O(N)\f$ | -/// | linear | ✅ | -/// | access | \f$O(1)\f$ | -/// | find | \f$O(1)\f$ | -/// | insertion | \f$O(1)\f$ | -/// | deletion | \f$O(M)\f$ | +/// | Property | Value | +/// |:-----------:|:--------------:| +/// | stable | ⛔ | +/// | dynamic | ✅ | +/// | homogeneous | ✅ | +/// | distinct | ⛔ | +/// | ordered | ⛔ | +/// | space | \f$O(N)\f$ | +/// | linear | ✅ | +/// | access | \f$O(1)\f$ | +/// | find | \f$O(1)\f$ | +/// | insertion | \f$O(1)\f$ | +/// | deletion | \f$O(M)\f$ | +/// | space | \f$O(N + M)\f$ | /// /// Graphs contain vertices and edges. Graphs are either directed /// or undirected. This structure allows the creation of both directed and undirected edges. As @@ -92,13 +93,24 @@ struct graph { public: // Definitions ========================================================================================================= - using edge_t = EdgeT; ///< Alias for the edge type - using vertex_t = VertexT; ///< Alias for the vertex type - using vertex_pool_t = object_pool; ///< Alias for a pool of vertices - using edge_map_t = dynarray>; ///< Alias for edge mapping - using edge_pool_t = object_pool; ///< Alias for a pool of edges + /// \name Definitions + /// @{ - 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; //!< Alias for a pool of vertices + using edge_map_t = dynarray>; //!< Alias for edge mapping + using edge_pool_t = object_pool; //!< Alias for a pool of edges + + /// @} + + + /// \name Constants + /// @{ + + static constexpr size_t npos = -1; //!< Constant for a non-existent vertex + + /// @} // Constructors ======================================================================================================== @@ -108,10 +120,18 @@ public: /// /// \brief Default Constructor, initializes empty graph + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr graph() = default; /// /// \brief Destructor + /// + /// \par Complexity + /// \f$O(N + M)\f$ + /// constexpr ~graph() = default; /// @} @@ -124,12 +144,20 @@ public: /// \brief Copy Assignment Operator /// \param g The graph to copy /// \returns A reference to this after assigning g + /// + /// \par Complexity + /// \f$O(N + M)\f$ + /// constexpr graph& operator=(const graph& g) = default; /// /// \brief Move Assignment Operator /// \param g The graph to copy /// \returns A reference to this after assigning g + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr graph& operator=(graph&& g) = default; /// @} @@ -142,24 +170,40 @@ public: /// /// \returns The number of vertices in the graph + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t num_vertices() const { return _vertex_pool.size(); } /// /// \returns The number of edges in the graph + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t num_edges() const { return _edge_pool.size(); } /// /// \returns The capacity of the vertex pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _vertex_pool.capacity(); } /// /// \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 { return num_vertices() == 0; } @@ -169,6 +213,10 @@ public: /// \param a The first vertex /// \param b The second vertex /// \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 { return _edge_map[a][b] != nullptr; } @@ -179,6 +227,10 @@ public: /// \param a The first vertex /// \param b The second vertex /// \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 { return exists(a, b) and exists(b, a); } @@ -188,6 +240,10 @@ public: /// \param a The first vertex /// \param b The second vertex /// \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 { const auto* e0 = _edge_map[a][b]; const auto* e1 = _edge_map[b][a]; @@ -211,6 +267,10 @@ public: /// \brief vertex Access Operator /// \param vertex The id of 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) { return _vertex_pool[vertex]; } @@ -219,6 +279,10 @@ public: /// \brief vertex Const Access Operator /// \param vertex The id of 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 { return _vertex_pool[vertex]; } @@ -228,6 +292,10 @@ public: /// \param a The id of the first 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 + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr edge_t* operator[](size_t a, size_t b) { if (is_empty()) { return nullptr; @@ -244,6 +312,10 @@ public: /// \param a The id of the first 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 + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const edge_t* operator[](size_t a, size_t b) const { if (is_empty()) { 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 \f$x...\f$ + /// \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 - /// \returns A list containing all vertices \f$x\f$ with edges from \f$vertex\f$ to \f$x...\f$ + /// \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 outgoing(size_t vertex) { list res; 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 \f$x...\f$ + /// \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 - /// \returns A list containing all vertices \f$x\f$ with edges from \f$x...\f$ 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 incoming(size_t vertex) { list res; 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 \f$x...\f$ + /// \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 /// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$ + /// + /// \par Complexity + /// \f$O(M)\f$ + /// list symmetric(size_t vertex) { list res; 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 \f$x...\f$ 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 /// "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 /// removing one of the sub-edges. /// \param vertex The id of the vertex /// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$ + /// + /// \par Complexity + /// \f$O(M)\f$ + /// list undirected(size_t vertex) { list res; 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. /// \param vertex The id of the 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) { if (is_empty() || vertex >= _edge_map.size()) { return nullptr; @@ -350,6 +442,10 @@ public: /// \brief Move a new vertex into the graph /// \param vertex The vertex to move into the graph /// \returns The id of the new vertex + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t insert(vertex_t&& vertex) { return this->_insert(fennec::forward(vertex)); } @@ -358,6 +454,10 @@ public: /// \brief Copy a new vertex into the graph /// \param vertex The vertex to copy into the graph /// \returns The id of the new vertex + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t insert(const vertex_t& vertex) { return this->_insert(vertex); } @@ -367,6 +467,10 @@ public: /// \tparam ArgsT The types of the arguments /// \param args The arguments to construct the vertex with /// \returns The id of the new vertex + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr size_t emplace(ArgsT&&...args) { return this->_insert(fennec::forward(args)...); @@ -375,6 +479,10 @@ public: /// /// \brief Erase a vertex from the graph /// \param vertex The id of the vertex to erase + /// + /// \par Complexity + /// \f$O(M)\f$ + /// constexpr void erase(size_t vertex) { cut(vertex); _vertex_pool.erase(vertex); @@ -386,6 +494,10 @@ public: /// \param a The first vertex id /// \param b The second vertex id /// \param args The arguments to construct the edge with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr void make_edge(size_t a, size_t b, ArgsT&&...args) { if (a == b) { @@ -413,6 +525,10 @@ public: /// \param a The first vertex id /// \param b The second vertex id /// \param args The arguments to construct the edge with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr void make_edge2(size_t a, size_t b, ArgsT&&...args) { if (a == b) { @@ -440,6 +556,10 @@ public: /// \brief Disconnect an edge from vertex \f$a\f$ to vertex \f$b\f$ /// \param a The first vertex id /// \param b The second vertex id + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void cut_edge(size_t a, size_t b) { // Find the edge object @@ -463,6 +583,10 @@ public: /// \brief Disconnect both directed edges between vertices \f$a\f$ and \f$b\f$ /// \param a The first vertex id /// \param b The second vertex id + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void cut_edge2(size_t a, size_t b) { const auto* ita = _edge_map[a][b]; const auto* itb = _edge_map[a][b]; @@ -478,6 +602,10 @@ public: /// /// \brief Break *all* edges connected to \f$n\f$ /// \param n The vertex id + /// + /// \par Complexity + /// \f$O(M)\f$ + /// void cut(size_t n) { for (const auto it : outgoing(n)) { cut_edge(n, it); @@ -489,6 +617,10 @@ public: /// /// \brief Clear the graph, destructing all vertices and edges. + /// + /// \par Complexity + /// \f$O(N + M)\f$ + /// void clear() { _vertex_pool.clear(); _edge_pool.clear(); diff --git a/include/fennec/containers/list.h b/include/fennec/containers/list.h index 3cbfa9e..3f29e28 100644 --- a/include/fennec/containers/list.h +++ b/include/fennec/containers/list.h @@ -61,6 +61,7 @@ namespace fennec /// | find | \f$O(N)\f$ | /// | insertion | \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, /// using the iterator pattern yields \f$O(1)\f$ runtime. @@ -70,20 +71,25 @@ template> struct list { // Definitions ========================================================================================================= - private: struct node; public: + + /// \name Definitions + /// @{ + /// \brief Alias for the allocator type, rebound to list nodes using alloc_t = typename allocator_traits::template rebind; - 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: using table_t = dynarray; @@ -98,6 +104,10 @@ public: /// /// \brief Default Constructor, initializes an empty list. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr list() : _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 /// \param l The list to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr list(const list& l) : list() { for (const value_t& it : l) { @@ -116,6 +130,10 @@ public: /// /// \brief Move Constructor, takes ownership of the list /// \param l The list to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr list(list&& l) noexcept : _table(fennec::move(l._table)) , _freed(fennec::move(l._freed)) @@ -126,10 +144,12 @@ public: /// /// \brief Destructor, destructs all elements then releases the allocation. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~list() { - for (size_t i = 0; i < capacity(); ++i) { - _table[i].value = nullopt; - } + clear(); } /// @} @@ -137,13 +157,17 @@ public: // Assignment ========================================================================================================== public: - /// \name Assignment + /// \name Assignment Operators /// @{ /// /// \brief Copy Assignment Operator /// \param l the list to copy /// \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) { this->clear(); for (const value_t& it : l) { @@ -156,6 +180,10 @@ public: /// \brief Move Assignment Operator /// \param l the list to copy /// \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 { this->clear(); _table = fennec::move(l._table); @@ -176,18 +204,30 @@ public: /// /// \returns The size of the list in elements. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \returns The capacity of the list in elements. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _table.size(); } /// /// \returns \f$true\f$ when the list is empty, \f$false\f$ otherwise. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool is_empty() const { return _root == npos; } @@ -206,7 +246,9 @@ public: /// \param i Index to access /// \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) { assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds"); size_t n = _walk(i); @@ -219,7 +261,9 @@ public: /// \param i Index to access /// \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 { assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds"); size_t n = _walk(i); @@ -230,6 +274,10 @@ public: /// /// \brief Access Front Element /// \returns A reference to the first element in the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t& front() { return *_table[_root].value; } @@ -237,6 +285,10 @@ public: /// /// \brief Const Access Front Element /// \returns A const-qualified reference to the first element in the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t& front() const { return *_table[_root].value; } @@ -244,6 +296,10 @@ public: /// /// \brief Access Back Element /// \returns A reference to the last element in the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t& back() { return *_table[_last].value; } @@ -251,6 +307,10 @@ public: /// /// \brief Const Access Back Element /// \returns A const-qualified reference to the last element in the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t& back() const { return *_table[_last].value; } @@ -270,7 +330,9 @@ public: /// \param x value to copy /// \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) { return this->_insert(it._n, x); } @@ -281,7 +343,9 @@ public: /// \param x value to move /// \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) { return this->_insert(it._n, fennec::forward(x)); } @@ -292,7 +356,9 @@ public: /// \param x value to copy /// \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) { assert(i <= size(), "Index out of Bounds"); @@ -306,7 +372,9 @@ public: /// \param x value to move /// \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) { assert(i <= size(), "Index out of Bounds"); @@ -321,7 +389,9 @@ public: /// \param args Arguments to construct with /// \returns The id of the inserted node /// - /// \details \f$O(N)\f$ + /// \par Complexity + /// \f$O(N)\f$ + /// template constexpr iterator emplace(size_t i, ArgsT&&...args) { assert(i <= size(), "Index out of Bounds"); @@ -337,7 +407,9 @@ public: /// \param args Arguments to construct with /// \returns The id of the inserted node /// - /// \details \f$O(N)\f$ + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr iterator emplace(const iterator& it, ArgsT&&...args) { return this->_insert(it._n, fennec::forward(args)...); @@ -347,6 +419,10 @@ public: /// \brief Push Front Copy /// \param x Value to copy /// \returns The id of the inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator push_front(const value_t& x) { return this->_insert(_root, x); } @@ -355,6 +431,10 @@ public: /// \brief Push Front Move /// \param x Value to move /// \returns The id of the inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator push_front(value_t&& x) { return this->_insert(_root, fennec::forward(x)); } @@ -364,6 +444,10 @@ public: /// \param args Arguments to construct with /// \tparam ArgsT Argument types /// \returns The id of the inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr iterator emplace_front(ArgsT&&...args) { return this->_insert(_root, fennec::forward(args)...); @@ -373,6 +457,10 @@ public: /// \brief Push Back Copy /// \param x Value to copy /// \returns The id of the inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator push_back(const value_t& x) { return this->_insert(npos, x); } @@ -381,6 +469,10 @@ public: /// \brief Push Back Move /// \param x Value to move /// \returns The id of the inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator push_back(value_t&& x) { return this->_insert(npos, fennec::forward(x)); } @@ -390,6 +482,10 @@ public: /// \param args Arguments to construct with /// \tparam ArgsT Argument types /// \returns The id of the inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr iterator emplace_back(ArgsT&&...args) { return this->_insert(npos, fennec::forward(args)...); @@ -398,6 +494,10 @@ public: /// /// \brief Erase Element /// \param i Index to erase + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void erase(size_t i) { assert(i < size(), "Index out of Bounds!"); size_t n = _walk(i); @@ -407,24 +507,40 @@ public: /// /// \brief Erase Element /// \param it Location to Erase + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void erase(const iterator& it) { this->_erase(it._n); } /// /// \brief Pop Front, erases first element + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void pop_front() { _erase(_root); } /// /// \brief Pop Back, erases first element + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void pop_back() { _erase(_last); } /// /// \brief Clears the list, destructing all elements in order + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void clear() { size_t i = _root; while (i != npos) { @@ -432,6 +548,8 @@ public: i = this->_next(i); } _table.clear(); + _root = npos; + _size = 0; } /// @} @@ -444,19 +562,31 @@ public: /// /// \returns An iterator for the first element in the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator begin() { return iterator(this, _root); } /// - /// \brief C++ Iterator Specification \f$end()\f$ + /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns A const iterator for the first element in the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const_iterator begin() const { return const_iterator(this, _root); } /// /// \returns An iterator for the end of the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator end() { return iterator(this, npos); } @@ -464,12 +594,14 @@ public: /// /// \brief Const C++ Iterator Specification \f$end()\f$ /// \returns A const iterator for the end of the list + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const_iterator end() const { return const_iterator(this, npos); } - /// @} - /// /// \brief C++ Iterator Specification \f$iterator\f$ class iterator { @@ -613,7 +745,9 @@ public: } }; -// Members ============================================================================================================= + /// @} + +// Private Member Variables ============================================================================================ private: table_t _table; freed_t _freed; @@ -622,7 +756,7 @@ private: friend class iterator; -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== private: constexpr void _expand() { _table.resize(fennec::max(_table.size(), size_t(4)) * 2); diff --git a/include/fennec/containers/map.h b/include/fennec/containers/map.h index e453cf2..f86160c 100644 --- a/include/fennec/containers/map.h +++ b/include/fennec/containers/map.h @@ -71,6 +71,7 @@ namespace fennec /// | find | \f$O(1)\f$ | /// | insertion | \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. /// @@ -83,15 +84,19 @@ struct map { // Definitions ========================================================================================================= public: - struct key_hash; ///< Hash for node keys - struct key_equals; ///< Comparison for node keys - using key_t = KeyT; ///< The key type - using value_t = ValueT; ///< The value type - using elem_t = pair; ///< then node type - using alloc_t = typename allocator_traits::template rebind; ///< Rebinds the allocator type to nodes - using hash_t = Hash; ///< The hash type - using set_t = set; ///< The underlying set - using iterator = set_t::iterator; ///< Iterator type + + /// \name Definitions + /// @{ + + struct key_hash; //!< Hash for node keys + struct key_equals; //!< Comparison for node keys + using key_t = KeyT; //!< The key type + using value_t = ValueT; //!< The value type + using elem_t = pair; //!< then node type + using alloc_t = typename allocator_traits::template rebind; //!< Rebinds the allocator type to nodes + using hash_t = Hash; //!< The hash type + using set_t = set; //!< The underlying set + using iterator = set_t::iterator; //!< Iterator type /// /// \brief key hash helper @@ -118,8 +123,11 @@ public: } }; + /// @} + // Constructors & Destructor =========================================================================================== +public: /// \name Constructors & Destructor /// @{ @@ -136,6 +144,7 @@ public: // Properties ========================================================================================================== +public: /// \name Properties /// @{ @@ -162,6 +171,7 @@ public: // Access ============================================================================================================== +public: /// \name Access /// @{ @@ -170,6 +180,10 @@ public: /// \brief Key Access Operator /// \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. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t* operator[](const KeyT& key) { auto it = _set.at(this->_find(key)); return it ? &it->second : nullptr; @@ -179,6 +193,10 @@ public: /// \brief Key Const Access Operator /// \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. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t* operator[](const KeyT& key) const { auto it = _set.at(this->_find(key)); return it ? &it->second : nullptr; @@ -189,6 +207,10 @@ public: /// \tparam ArgsT Argument Types /// \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. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr value_t* operator[](ArgsT&&...args) { auto it = _set.at(this->_find(fennec::forward(args)...)); @@ -200,6 +222,10 @@ public: /// \tparam ArgsT Argument Type /// \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. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr const value_t* operator[](ArgsT&&...args) const { auto it = _set.at(this->_find(fennec::forward(args)...)); @@ -210,6 +236,7 @@ public: // Modifiers =========================================================================================================== +public: /// \name Modifiers /// @{ @@ -217,6 +244,10 @@ public: /// /// \brief Key-Value Insertion /// \param pair a pair containing the key and its value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void insert(elem_t&& pair) { this->_insert(fennec::forward(pair)); } @@ -225,6 +256,10 @@ public: /// \brief Key-Value Insertion /// \param key key to insert /// \param args Arguments for constructing the key-value pair + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr void emplace(const KeyT& key, ArgsT&&...args) { this->_insert(key, fennec::forward(args)...); @@ -233,6 +268,10 @@ public: /// /// \brief Key-Value Insertion /// \param args Arguments for constructing the key-value pair + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr void emplace(ArgsT&&...args) { this->_insert(fennec::forward(args)...); @@ -241,6 +280,10 @@ public: /// /// \brief Erase a key /// \param key key to erase + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void erase(KeyT&& key) { _set.erase(this->_find(fennec::forward(key))); } @@ -248,6 +291,10 @@ public: /// /// \brief Erase a key /// \param key key to erase + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void erase(const KeyT& key) { _set.erase(this->_find(key)); } @@ -256,6 +303,10 @@ public: /// \brief Argument Erase /// \tparam ArgsT Argument Types /// \param args Arguments to construct a key to erase + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr void erase(ArgsT&&...args) { _set.erase(this->_find(fennec::forward(args)...)); @@ -263,6 +314,10 @@ public: /// /// \brief Clears the map destructing all elements + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void clear() { _set.clear(); } @@ -271,6 +326,7 @@ public: // Iteration =========================================================================================================== +public: /// \name Iteration /// @{ @@ -278,6 +334,10 @@ public: /// /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns an iterator at the start of the map + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator begin() { return _set.begin(); } @@ -286,6 +346,10 @@ public: /// /// \brief C++ Iterator Specification \f$end()\f$ /// \returns an iterator at the end of the map + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator end() { return _set.end(); } @@ -293,9 +357,13 @@ public: /// @} +// Private Member Variables ============================================================================================ private: set_t _set; + +// Private Helpers ===================================================================================================== +private: template set_t::iterator _find(ArgsT&&...args) const { union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers diff --git a/include/fennec/containers/object_pool.h b/include/fennec/containers/object_pool.h index 53cd78d..ac5bfc6 100644 --- a/include/fennec/containers/object_pool.h +++ b/include/fennec/containers/object_pool.h @@ -54,6 +54,7 @@ namespace fennec /// | find | \f$O(N)\f$ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypeT The value type /// \tparam AllocT The allocator type @@ -62,28 +63,43 @@ struct object_pool { // Definitions ========================================================================================================= public: + + /// \name Definitions + /// @{ + using value_t = TypeT; //!< The held object type using elem_t = optional; //!< The element type using table_t = dynarray; //!< The underlying table type using freed_t = list; //!< The underlying free queue + /// @} + class iterator; class const_iterator; // Constructors & Destructor =========================================================================================== +public: /// \name Constructors & Destructor /// @{ /// /// \brief Default Constructor, initializes an empty object pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr object_pool() : _size(0) { } /// /// \brief Default Destructor, destructs objects then releases the allocation. + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~object_pool() = default; /// @} @@ -96,18 +112,30 @@ public: /// /// \returns The number of active objects in the pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \returns The capacity of the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _table.capacity(); } /// /// \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 { 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. /// \returns The id of the next inserted node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t next_id() const { size_t next = _size; if (not _freed.is_empty()) { @@ -136,6 +168,10 @@ public: /// \brief Array Access Operator /// \param i id of the object /// \returns a reference to the object with id \f$i\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr value_t& operator[](size_t i) { assert(i < capacity(), "Index out of Bounds!"); assert(_table[i], "Attempted to access null object.") @@ -146,6 +182,10 @@ public: /// \brief Array Const Access Operator /// \param i id of the object /// \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 { assert(i < capacity(), "Index out of Bounds!"); assert(_table[i], "Attempted to access null object.") @@ -169,6 +209,10 @@ public: /// \brief Move Insertion, inserts \f$x\f$ into the pool /// \param x the object to move /// \returns An integer corresponding to the id of the node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t insert(value_t&& x) { return this->_insert(fennec::forward(x)); } @@ -177,15 +221,23 @@ public: /// \brief Move Insertion, inserts a copy of \f$x\f$ into the pool /// \param x the object to copy /// \returns An integer corresponding to the id of the node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t insert(const value_t& x) { return this->_insert(x); } /// - /// \brief Emplacement, constructs a new object using \f$args...\f$ + /// \brief Emplacement, constructs a new object using \f$args\ldots\f$ /// \param args The arguments to construct the new object with /// \returns An integer corresponding to the id of the node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr size_t emplace(ArgsT&&...args) { return this->_insert(fennec::forward(args)...); @@ -194,6 +246,10 @@ public: /// /// \brief Erase an object from the pool /// \param i The id of the object + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void erase(size_t i) { _table[i] = nullopt; _freed.push_back(i); @@ -202,12 +258,14 @@ public: /// /// \brief Clear the object pool + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void clear() { - for (auto& it : _table) { - it = nullopt; - } - _size = 0; + _table.clear(); _freed.clear(); + _size = 0; } /// @} @@ -217,6 +275,10 @@ public: /// /// \returns an iterator at the start of the object pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// iterator begin() { return iterator(this, 0); } @@ -224,12 +286,20 @@ public: /// /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns an iterator at the start of the object pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// const_iterator begin() const { return const_iterator(this, 0); } /// /// \returns an iterator at the start of the end of the object pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// iterator end() { return iterator(this, _size); } @@ -237,6 +307,10 @@ public: /// /// \brief C++ Iterator Specification \f$end()\f$ /// \returns an iterator at the start of the end of the object pool + /// + /// \par Complexity + /// \f$O(1)\f$ + /// const_iterator end() const { return const_iterator(this, _size); } diff --git a/include/fennec/containers/optional.h b/include/fennec/containers/optional.h index a26806a..cadfac6 100644 --- a/include/fennec/containers/optional.h +++ b/include/fennec/containers/optional.h @@ -66,6 +66,7 @@ constexpr nullopt_t nullopt_v = {}; /// | find | ⛔ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(1)\f$ | /// /// \tparam T template @@ -73,11 +74,17 @@ struct optional { // Definitions ========================================================================================================= public: + + /// \name Definitions + /// @{ + using reference_t = T&; //!< reference type using pointer_t = T*; //!< pointer type using const_reference_t = T&; //!< const reference type using const_pointer_t = const T*; //!< const pointer type + /// @} + // Constructors ======================================================================================================== @@ -86,6 +93,10 @@ public: /// /// \brief Default Constructor + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional() : _root(0) , _set(false) { @@ -93,6 +104,10 @@ public: /// /// \brief Default Constructor + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional(nullopt_t) : _root(0) , _set(false) { @@ -101,6 +116,10 @@ public: /// /// \brief Type Copy Constructor /// \param val the value to initialize the underlying object with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional(const T& val) : _val(val) , _set(true) { @@ -109,6 +128,10 @@ public: /// /// \brief Type Move Constructor /// \param val the value to initialize the underlying object with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional(T&& val) : _val(fennec::forward(val)) , _set(true) { @@ -117,6 +140,10 @@ public: /// /// \brief Copy Constructor /// \param opt the optional to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional(const optional& opt) requires is_copy_assignable_v : optional() { _set = opt._set; @@ -128,6 +155,10 @@ public: /// /// \brief Move Constructor /// \param opt the optional to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional(optional&& opt) noexcept requires is_move_assignable_v : optional() { _set = opt._set; @@ -141,6 +172,10 @@ public: /// \brief Emplace Constructor /// \tparam ArgsT The argument types /// \param args The argument values + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr optional(ArgsT&&...args) : _val(fennec::forward(args)...) @@ -149,6 +184,10 @@ public: /// /// \brief destructor + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr ~optional() { if constexpr(is_fundamental_v) { return; @@ -169,12 +208,20 @@ public: /// /// \brief Implicit Boolean Check /// \returns \f$true\f$ when there is a value contained + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr operator bool() const { return _set; } /// /// \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 { return not _set; } @@ -184,12 +231,16 @@ public: // Assignment Operators ================================================================================================ - /// \name Assignment + /// \name Assignment Operators /// @{ /// /// \brief Null Assignment /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional& operator=(nullopt_t) { if constexpr(not is_fundamental_v) { if (_set) { @@ -205,6 +256,10 @@ public: /// \brief Type Copy Assignment /// \param val The value to set with /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional& operator=(const T& val) requires is_copy_constructible_v and is_copy_assignable_v { if (_set) { _val = val; @@ -219,6 +274,10 @@ public: /// \brief Type Move Assignment /// \param val The value to set with /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional& operator=(T&& val) requires is_move_constructible_v and is_move_assignable_v { if (_set) { _val = fennec::forward(val); @@ -233,6 +292,10 @@ public: /// \brief Copy Assignment /// \param opt The optional to copy /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v and is_copy_assignable_v { if (_set != opt._set) { _set = opt._set; @@ -252,6 +315,10 @@ public: /// \brief Move Assignment /// \param opt The optional to move /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v and is_move_assignable_v { if (_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 + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr pointer_t operator->() noexcept { return _set ? &_val : nullptr; } /// /// \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 { return _set ? &_val : nullptr; } @@ -290,6 +365,10 @@ public: /// /// \brief Dereference Operator /// \returns A reference to the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr T& operator*() & noexcept { assertd(_set, "Attempted to reference the value of an unset optional"); return _val; @@ -298,6 +377,10 @@ public: /// /// \brief Const Dereference Operator /// \returns A const-qualified reference to the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const T& operator*() const& noexcept { assertd(_set, "Attempted to reference the value of an unset optional"); return _val; @@ -306,6 +389,10 @@ public: /// /// \brief Dereference Operator /// \returns A reference to the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr T&& operator*() && noexcept { assertd(_set, "Attempted to reference the value of an unset optional"); return _val; @@ -314,6 +401,10 @@ public: /// /// \brief Const Dereference Operator /// \returns A const-qualified reference to the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const T&& operator*() const&& noexcept { assertd(_set, "Attempted to reference the value of an unset optional"); return _val; @@ -330,6 +421,10 @@ public: /// \brief Emplace Assignment, Move overload /// \param val The object to take ownership of /// \returns A reference to the held value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr T& emplace(T&& val) { if (_set) { _val = fennec::forward(val); @@ -344,6 +439,10 @@ public: /// \brief Emplace Assignment, Copy overload /// \param val The object to copy /// \returns A reference to the held value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr T& emplace(const T& val) { if (_set) { _val = val; @@ -358,6 +457,10 @@ public: /// \brief Emplace Assignment /// \param args The arguments to construct with /// \returns A reference to the held value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr T& emplace(ArgsT&&...args) { if (_set) { @@ -371,6 +474,10 @@ public: /// /// \brief Reset the Optional + /// + /// \par Complexity + /// \f$O(1)\f$ + /// void reset() { this->operator=(nullopt); } diff --git a/include/fennec/containers/pair.h b/include/fennec/containers/pair.h index b9e53c1..7bb8162 100644 --- a/include/fennec/containers/pair.h +++ b/include/fennec/containers/pair.h @@ -56,34 +56,55 @@ namespace fennec /// | find | ⛔ | /// | insertion | ⛔ | /// | deletion | ⛔ | +/// | space | \f$O(1)\f$ | /// /// \tparam TypeT0 The type of the first value /// \tparam TypeT1 The type of the second value template 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 ======================================================================================================== +public: /// \name Constructors & Destructor /// @{ /// /// \brief Default Constructor, invokes default constructor for both elements + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr pair() = default; /// /// \brief Destructor, invokes destructor for both elements + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr ~pair() = default; /// /// \brief Pair Copy Constructor /// \param x 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) : first(x) , second(y) { @@ -93,6 +114,10 @@ struct pair { /// \brief Pair Move Constructor /// \param x 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 : first(fennec::forward(x)) , second(fennec::forward(y)) { @@ -102,6 +127,10 @@ struct pair { /// \brief Pair Implicit Constructor /// \param arg1 Value to initialize the first element /// \param arg2 Value to initialize the first element + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr pair(Arg1T&& arg1, Arg2T&& arg2) : first(fennec::forward(arg1)) @@ -111,6 +140,10 @@ struct pair { /// /// \brief Copy Constructor, copies both elements /// \param pair The pair to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr pair(const pair& pair) : first(fennec::copy(pair.first)) , second(fennec::copy(pair.second)) { @@ -119,6 +152,10 @@ struct pair { /// /// \brief Move Constructor, moves both elements /// \param pair The pair to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr pair(pair&& pair) noexcept : first(fennec::move(pair.first)) , second(fennec::move(pair.second)) { @@ -128,6 +165,10 @@ struct pair { /// \brief Copy Assignment, copies both elements /// \param pair The pair to copy /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr pair& operator=(const pair& pair) { first = fennec::copy(pair.first); second = fennec::copy(pair.second); @@ -138,6 +179,10 @@ struct pair { /// \brief Move Assignment, moves both elements /// \param pair The pair to move /// \returns A reference to self + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr pair& operator=(pair&& pair) { first = fennec::move(pair.first); second = fennec::move(pair.second); @@ -148,6 +193,7 @@ struct pair { // Comparison ========================================================================================================== +public: /// \name Comparison /// @{ @@ -156,6 +202,10 @@ struct pair { /// \brief Equality Operator /// \param p Pair to compare with /// \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 { return first == p.first and second == p.second; } @@ -164,6 +214,10 @@ struct pair { /// \brief Inequality Operator /// \param p Pair to compare with /// \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 { return first != p.first or second != p.second; } @@ -173,6 +227,10 @@ struct pair { /// \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 /// equal and the second element is less + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool operator<(const pair& p) const { return first < p.first or (first == p.first and second < p.second); } @@ -182,6 +240,10 @@ struct pair { /// \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 /// equal and the second element is less or equal + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool operator<=(const pair& p) const { return first < p.first or (first == p.first and second <= p.second); } @@ -191,6 +253,10 @@ struct pair { /// \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 /// equal and the second element is greater + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool operator>(const pair& p) const { return first > p.first or (first == p.first and second > p.second); } @@ -200,6 +266,10 @@ struct pair { /// \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 /// equal and the second element is greater or equal + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool operator>=(const pair& p) const { return first > p.first or (first == p.first and second >= p.second); } diff --git a/include/fennec/containers/priority_queue.h b/include/fennec/containers/priority_queue.h index 196ba90..4980ff2 100644 --- a/include/fennec/containers/priority_queue.h +++ b/include/fennec/containers/priority_queue.h @@ -69,6 +69,7 @@ namespace fennec /// | find | ⛔ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam ValueT The value type /// \tparam CompareT The compare type, defaults to `fennec::less` @@ -78,10 +79,16 @@ struct priority_queue { // Definitions & Constants ============================================================================================= public: + + /// \name Definitions + /// @{ + using value_t = ValueT; //!< Alias for the value type using compare_t = CompareT; //!< Alias for the compare type using alloc_t = allocation; //!< The underlying allocation type + /// @} + static constexpr size_t npos = -1; //!< value representing a null node private: @@ -106,12 +113,20 @@ public: /// /// \brief default constructor /// \details initializes an empty queue + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr priority_queue() : _size(0) { } /// /// \brief destructor + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~priority_queue() { while (_size > 0) { --_size; @@ -125,18 +140,30 @@ public: /// /// \returns the size of the queue + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \returns the capacity of the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _table.capacity(); } /// /// \returns \f$true\f$ if the queue holds no elements + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool is_empty() const { return size() == 0; } @@ -147,6 +174,10 @@ public: /// /// \returns the value at the front of the queue + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const value_t& front() const { return _table[0]; } @@ -158,12 +189,20 @@ public: /// /// \brief push a new key into the queue /// \param key the key to insert + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr void push(const value_t& key) { this->_insert(key); } /// /// \param key the key to insert + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr void push(value_t&& key) { this->_insert(fennec::forward(key)); } @@ -172,6 +211,10 @@ public: /// \brief emplace a new key into the queue /// \tparam ArgsT the argument types /// \param args the argument values + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// template constexpr void emplace(ArgsT&&...args) { this->_insert(fennec::forward(args)...); @@ -179,6 +222,10 @@ public: /// /// \brief pop the element at the front of the queue + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr void pop() { fennec::swap(_table[0], _table[--_size]); fennec::destruct(&_table[_size]); @@ -186,14 +233,14 @@ public: } -// Members ============================================================================================================= +// Private Member Variables ============================================================================================ private: compare_t _compare; alloc_t _table; size_t _size; -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== private: template diff --git a/include/fennec/containers/rdtree.h b/include/fennec/containers/rdtree.h index fe07f3e..249f5a4 100644 --- a/include/fennec/containers/rdtree.h +++ b/include/fennec/containers/rdtree.h @@ -57,6 +57,7 @@ namespace fennec /// | find | \f$O(N)\f$ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypeT Data type /// \tparam AllocT Allocator Type @@ -68,11 +69,24 @@ private: struct node; public: + + /// \name Definitions + /// @{ + using value_t = TypeT; //!< the held value type using alloc_t = typename allocator_traits::template rebind; //!< the underlying allocator type + + /// @} + + + /// \name Constants + /// @{ + static constexpr size_t root = 0; //!< the id of the root node static constexpr size_t npos = -1; //!< the id of a null node + /// @} + private: struct node { value_t value; @@ -80,7 +94,7 @@ private: size_t depth, num_children; constexpr node() - : value(nullopt) + : value() , parent(npos), child(npos) , prev(npos), next(npos) , depth(0), num_children(0) { @@ -103,6 +117,9 @@ private: } }; + using table_t = allocation; + using freed_t = list; + public: // Constructors ======================================================================================================== @@ -114,23 +131,36 @@ public: /// \brief Root Constructor, constructs the root node of the tree /// \tparam ArgsT The argument types /// \param args The arguments to construct the root with + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template explicit constexpr rdtree(ArgsT&&...args) : _table(), _freed(), _size(1) { - _table.creallocate(8); + _table.reallocate(8); fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward(args)...); } /// /// \brief Copy Constructor, copies the contents of \f$tree\f$ /// \param tree the rdtree to copy + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr rdtree(const rdtree& tree) : _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$ /// \param tree the rdtree to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr rdtree(rdtree&& tree) noexcept : _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) { } @@ -140,14 +170,19 @@ public: // Assignment ========================================================================================================== - /// \name Assignment + /// \name Assignment Operators /// @{ /// /// \brief Copy Assignment Operator /// \param rhs the rdtree to copy /// \returns \f$this\f$ after copying the contents of \f$rhs\f$ + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr rdtree& operator=(const rdtree& rhs) { + // TODO: properly invoke copy constructor for all elements for (value_t* it : this->_table) { fennec::destruct(it); } @@ -161,6 +196,10 @@ public: /// \brief Move Assignment Operator /// \param rhs the rdtree to move /// \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 { for (value_t* it : _table) { fennec::destruct(it); @@ -180,28 +219,49 @@ public: /// /// \returns The number of nodes in the tree + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \returns The capacity of the underlying allocation + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { return _table.capacity(); } /// /// \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 { return _size == 0; } + /// @} + // Access ============================================================================================================== + /// \name Access + /// @{ + /// /// \param i The id of the node to check /// \returns The id of the parent node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t parent(size_t i) const { if (i >= _table.capacity()) return npos; return i == npos ? npos : _table[i].parent; @@ -211,6 +271,10 @@ public: /// \param i The id of the node to check /// \param n The index of the child relative to the parent /// \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 { if (i >= _table.capacity() && n != npos) return npos; size_t c = i == npos ? npos : _table[i].child; @@ -223,6 +287,10 @@ public: /// \param i The id of the node to check /// \param n The index of the child relative to the parent /// \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 { if (i >= _table.capacity() && n != npos) return npos; if (i == npos) { @@ -248,6 +316,10 @@ public: /// \param i The id of the node to check /// \param n The index of the child relative to the parent /// \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 { if (i >= _table.capacity()) return npos; if (i == npos) { @@ -272,6 +344,10 @@ public: /// /// \param i the node to start at /// \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 { if (i >= _table.capacity()) return npos; size_t n = i; @@ -289,6 +365,10 @@ public: /// /// \param i the node to start at /// \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 { if (i >= _table.capacity()) return npos; if ((i = child(i)) == npos) { @@ -309,6 +389,10 @@ public: /// /// \param i The id of the node to check /// \returns The depth of the node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t depth(size_t i) const { if (i >= _table.capacity()) return npos; return i == npos ? npos : _table[i].depth; @@ -317,6 +401,10 @@ public: /// /// \param i The id of the node to check /// \returns The number of children the node has + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t num_children(size_t i) const { if (i >= _table.capacity()) return 0; 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 + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t next_id() const { size_t i = _size; if (not _freed.is_empty()) { @@ -335,6 +427,10 @@ public: /// /// \param i The id of the node to access /// \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) { return _table[i].value; } @@ -342,12 +438,21 @@ public: /// /// \param i The id of the node to access /// \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 { return _table[i].value; } + /// @} -// Insertion & Deletion ================================================================================================ + +// Modifiers =========================================================================================================== + + /// \name Modifiers + /// @{ /// /// \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 val the value to insert /// \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) { return this->_insert(parent, next, val); } @@ -365,6 +474,10 @@ public: /// \param next the next node, as an index relative to the parent /// \param val the value to insert /// \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) { return this->_insert(parent, next, fennec::forward(val)); } @@ -375,6 +488,10 @@ public: /// \param next the next node, as an index relative to the parent /// \param tree the tree to insert /// \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) { list> visit; 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 args the args to construct the value to insert /// \returns the index of the created node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr size_t emplace(size_t parent, size_t next, ArgsT&&...args) { return this->_insert(parent, next, fennec::forward(args)...); @@ -413,6 +534,10 @@ public: /// \brief Swap two nodes /// \param i0 The id of the first node /// \param i1 The id of the second node + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void swap(size_t i0, size_t i1) { assertf(i0 != root and i1 != root, "Cannot Swap With Root"); @@ -438,11 +563,14 @@ public: _erase(i); } - + /// @} // Traversal =========================================================================================================== + /// \name Traversal + /// @{ + /// /// \brief Traverse the tree using a specified order and visiting functor /// @@ -454,6 +582,10 @@ public: /// \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 constexpr void traverse(VisitorT&& visit, size_t i = root) { 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 + 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 struct breadth_first { @@ -672,14 +835,21 @@ public: size_t head; }; + /// @} + +// Private Member Variables ============================================================================================ +private: + table_t _table; + freed_t _freed; + size_t _size; + + +// Private Helpers ===================================================================================================== private: - allocation _table; - list _freed; - size_t _size; void _expand() { - _table.creallocate(_table.capacity() * 2); + _table.reallocate(_table.capacity() * 2); } size_t _next_free() { diff --git a/include/fennec/containers/sequence.h b/include/fennec/containers/sequence.h index 1064377..6ae5729 100644 --- a/include/fennec/containers/sequence.h +++ b/include/fennec/containers/sequence.h @@ -69,6 +69,7 @@ namespace fennec /// | find | \f$O(\log N)\f$ | /// | insertion | \f$O(\log N)\f$ | /// | deletion | \f$O(\log N)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypeT The type to contain /// \tparam CompareT Function for comparing two values @@ -91,11 +92,17 @@ private: }; public: + + /// \name Definitions + /// @{ + using value_t = TypeT; //!< the value type using node_t = pair; //!< the node type using alloc_t = allocator_traits::template rebind<_node>; //!< underlying alloc type using compare_t = CompareT; //!< comparison type + /// @} + class iterator; class const_iterator; @@ -215,20 +222,33 @@ public: /// /// \brief Default Constructor, initializes an empty sequence + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr sequence() : _root(nullptr), _size(0) { } /// /// \brief Move Constructor, takes ownership of a sequence + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr sequence(sequence&&) noexcept = default; /// /// \brief Copy Constructor, copies a sequence constexpr sequence(const sequence&) = default; + // TODO: properly implement /// /// \brief Default Destructor, destructs elements *in-order* + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~sequence() { this->clear(); } @@ -244,6 +264,10 @@ public: /// \brief Value Find Function, finds the iterator position for \f$val\f$, otherwise returns \f$end()\f$ /// \param val The value to find /// \returns An iterator at the value + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr iterator find(const value_t& val) { node node = _root; while (node) { @@ -276,12 +300,20 @@ public: /// /// \returns The number of elements in the sequence + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \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 { return _size == 0; } @@ -296,6 +328,10 @@ public: /// /// \brief Move Insertion, moves \f$val\f$ into the sequence /// \param val The value to insert + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr void insert(value_t&& val) { node i = _insert_bst(fennec::forward(val)); _fix_insert(i); @@ -304,6 +340,10 @@ public: /// /// \brief Copy Insertion, inserts a copy of \f$val\f$ into the sequence /// \param val The value to insert + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr void insert(const value_t& val) { node i = _insert_bst(val); _fix_insert(i); @@ -313,6 +353,10 @@ public: /// \brief Emplacement, constructs and adds a value into the sequence /// \tparam ArgsT The argument types /// \param args The arguments to construct with + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// template constexpr void emplace(ArgsT&&...args) { node i = _insert_bst(fennec::forward(args)...); @@ -322,12 +366,20 @@ public: /// /// \brief Erase the specified value from the sequence /// \param val the value to erase + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr void erase(const value_t& val) { _erase(find(val)._node); } /// /// \brief Destructs all elements, *in-order*, contained in the sequence + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void clear() { list visit; for (iterator it = begin(); it != end(); ++it) { @@ -346,6 +398,10 @@ public: /// /// \returns An iterator at the smallest element in the sequence + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr iterator begin() { return sequence::iterator(this, _root); } @@ -353,12 +409,20 @@ public: /// /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns An iterator at the smallest element in the sequence + /// + /// \par Complexity + /// \f$O(\log N)\f$ + /// constexpr const_iterator begin() const { return sequence::const_iterator(this, _root); } /// /// \returns An iterator after the largest element in the sequence + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator end() { return sequence::iterator(this, _root, nullptr); } @@ -366,6 +430,10 @@ public: /// /// \brief Const C++ Iterator Specification \f$end()\f$ /// \returns An iterator after the largest element in the sequence + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr const_iterator end() const { return sequence::const_iterator(this, _root, nullptr); } @@ -373,24 +441,6 @@ public: /// /// \brief C++ Iterator Specification \f$iterator\f$ class iterator { - private: - sequence* _seq; - node _head; - node _node; - list _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: /// @@ -466,30 +516,30 @@ public: return lhs._seq != rhs._seq or lhs._node != rhs._node; } + private: + sequence* _seq; + node _head; + node _node; + list _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) { + } + friend struct sequence; }; /// /// \brief C++ Iterator Specification \f$iterator\f$ class const_iterator { - private: - const sequence* _seq; - node _head; - node _node; - list _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) { - } - public: /// @@ -565,18 +615,37 @@ public: return lhs._seq != rhs._seq or lhs._node != rhs._node; } + private: + const sequence* _seq; + node _head; + node _node; + list _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; }; -// Fields ============================================================================================================== +// Private Member Variables ============================================================================================ private: alloc_t _alloc; node _root; compare_t _compare; size_t _size; -// Helpers ============================================================================================================= + +// Private Helpers ===================================================================================================== private: template diff --git a/include/fennec/containers/set.h b/include/fennec/containers/set.h index 69726f3..8c1dc1c 100644 --- a/include/fennec/containers/set.h +++ b/include/fennec/containers/set.h @@ -62,32 +62,46 @@ namespace fennec /// | find | \f$O(1)\f$ | /// | insertion | \f$O(1)\f$ | /// | deletion | \f$O(1)\f$ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypeT The type to contain template, class Equals = equality, class Alloc = allocator> struct set { // Definitions ========================================================================================================= +private: + struct node; + public: - using alloc_t = typename allocator_traits::template rebind; //!< the allocator type + + /// \name Definitions + /// @{ + + using alloc_t = typename allocator_traits::template rebind; //!< the allocator type + using hash_t = Hash; //!< the hash type using equal_t = Equals; //!< the equality type using elem_t = TypeT; //!< the element type + /// @} + + + /// \name Constants + /// @{ + static constexpr double default_load = 0.8; //!< the default load factor for reallocation + + /// @} + + class iterator; private: - struct node { - optional value; - int psl; - - constexpr node() = default; - constexpr ~node() = default; - }; - static constexpr size_t npos = -1; + using table_t = dynarray; + + // Constructors ======================================================================================================== public: @@ -96,8 +110,12 @@ public: /// /// \brief Default Constructor, initializes empty set + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr set() - : _alloc() + : _table() , _hash() , _size(0) , _sumpsl(0) @@ -107,8 +125,12 @@ public: /// /// \brief Hash Copy Constructor, initializes empty set with a hash /// \param hash the hash object + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr set(const hash_t& hash) - : _alloc() + : _table() , _hash(hash) , _size(0) , _sumpsl(0) @@ -118,8 +140,12 @@ public: /// /// \brief Alloc Copy Constructor, initializes empty set with an allocator /// \param alloc the allocator object + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr set(const alloc_t& alloc) - : _alloc(alloc) + : _table(alloc) , _hash() , _size(0) , _sumpsl(0) @@ -130,8 +156,12 @@ public: /// \brief Hash Alloc Copy Constructor, initializes empty set with a hash and allocator /// \param hash the hash object /// \param alloc the allocator object + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr set(const hash_t& hash, const alloc_t& alloc) - : _alloc(alloc) + : _table(alloc) , _hash(hash) , _size(0) , _sumpsl(0) @@ -141,8 +171,12 @@ public: /// /// \brief Set Copy Constructor /// \param set Set to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr set(const set& set) - : _alloc(set._alloc) + : _table(set._table) , _hash(set._hash) , _size(set._size) , _sumpsl(set._sumpsl) @@ -152,8 +186,12 @@ public: /// /// \brief Set Move Constructor /// \param set Set to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr set(set&& set) noexcept - : _alloc(fennec::move(set._alloc)) + : _table(fennec::move(set._table)) , _hash(fennec::move(set._hash)) , _size(fennec::move(set._size)) , _sumpsl(set._sumpsl) @@ -162,9 +200,13 @@ public: /// /// \brief Destructor, destructs all elements and releases the allocation + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr ~set() { 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 + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t size() const { return _size; } /// /// \returns \f$true\f$ when the set is empty, \f$false\f$ otherwise + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr bool is_empty() const { return _size == 0; } /// /// \returns Capacity of the set in elements + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr size_t capacity() const { - return _alloc.size(); + return _table.size(); } /// @} @@ -206,6 +260,10 @@ public: /// \brief Find an Element /// \param val Value to find /// \returns An iterator at the location of the value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator find(const elem_t& val) const { if (capacity() == 0) { return end(); @@ -216,8 +274,8 @@ public: size_t n = 0; // Check the first element; - if (_alloc[i].psl >= psl && _alloc[i].value) { - if (_equal(*_alloc[i].value, val)) { + if (_table[i].psl >= psl && _table[i].value) { + if (_equal(*_table[i].value, val)) { return iterator(this, i); } } @@ -228,16 +286,16 @@ public: size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow size_t i1 = (i + n) % capacity(); 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 (_equal(*_alloc[i0].value, val)) { + if (c0 && _table[i0].value) { + if (_equal(*_table[i0].value, val)) { return iterator(this, i0); } } - if (c1 && _alloc[i1].value) { - if (_equal(*_alloc[i1].value, val)) { + if (c1 && _table[i1].value) { + if (_equal(*_table[i1].value, val)) { return iterator(this, i1); } } @@ -254,6 +312,10 @@ public: /// \brief Check if a set contains a value /// \param val Value to check /// \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 { return this->find(val) != end(); } @@ -263,23 +325,31 @@ public: /// \param it Location to access /// \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. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr elem_t* at(const iterator& it) { if (it == end()) { return nullptr; } - if (not _alloc[it._i].value) { + if (not _table[it._i].value) { return nullptr; } - return &*_alloc[it._i].value; + return &*_table[it._i].value; } /// /// \brief Iterator Const Access /// \param it Location to access /// \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 { - if (not _alloc[it._i].value) return nullptr; - return &*_alloc[it._i].value; + if (not _table[it._i].value) return nullptr; + return &*_table[it._i].value; } /// @} @@ -293,6 +363,10 @@ public: /// \brief Move Insertion /// \param val Value to insert /// \returns An iterator at the held value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator insert(elem_t&& val) { return this->_insert(fennec::forward(val)); } @@ -301,6 +375,10 @@ public: /// \brief Copy Insertion /// \param val Value to insert /// \returns An iterator at the held value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator insert(const elem_t& val) { return this->_insert(val); } @@ -310,6 +388,10 @@ public: /// \tparam ArgsT Argument types /// \param args Arguments to construct with /// \returns An iterator at the held value + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template constexpr iterator emplace(ArgsT&&...args) { return this->_insert(fennec::forward(args)...); @@ -318,24 +400,28 @@ public: /// /// \brief Element Erase /// \param it Location to erase + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void erase(iterator it) { size_t i = it._i; if (i >= capacity()) { return; } // These are separated due to compilers being inconsistent - if (not _alloc[i].value) { + if (not _table[i].value) { return; } - _alloc[i].value = nullopt; - _sumpsl -= _alloc[i].psl; + _table[i].value = nullopt; + _sumpsl -= _table[i].psl; --_size; size_t p = i; - while (_alloc[i = (i + 1) % capacity()].value) { - if (_alloc[i].psl == 0) break; + while (_table[i = (i + 1) % capacity()].value) { + if (_table[i].psl == 0) break; - fennec::swap(_alloc[p].value, _alloc[i].value); - --_alloc[p].psl, --_sumpsl; + fennec::swap(_table[p].value, _table[i].value); + --_table[p].psl, --_sumpsl; p = i; } } @@ -343,14 +429,22 @@ public: /// /// \brief Element Erase /// \param val Value to erase + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr void erase(const elem_t& val) { this->erase(this->find(val)); } /// /// \brief Clear all elements from the set, destructing them + /// + /// \par Complexity + /// \f$O(N)\f$ + /// constexpr void clear() { - _alloc.clear(); + _table.clear(); } /// @} @@ -364,9 +458,13 @@ public: /// /// \brief C++ Iterator Specification \f$begin()\f$ /// \returns An iterator for all elements of the set in no particular order + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator begin() const { iterator it(this, 0); - if (not _alloc[it._i].value) { + while (not _table[it._i].value) { ++it; } return it; @@ -375,6 +473,10 @@ public: /// /// \brief C++ Iterator Specification \f$end()\f$ /// \returns An iterator representing the end of the set + /// + /// \par Complexity + /// \f$O(1)\f$ + /// constexpr iterator end() const { return iterator(this, npos); } @@ -383,6 +485,10 @@ public: /// /// \brief C++ Iterator Specification \f$iterator\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// class iterator { public: /// @@ -397,7 +503,7 @@ public: /// \returns \f$it\f$ after having moved to the next element in the list constexpr friend iterator& operator++(iterator& it) { while (++it._i < it._set->capacity()) { - if (it._set->_alloc[it._i].value) { + if (it._set->_table[it._i].value) { return it; } } @@ -419,15 +525,15 @@ public: /// \brief dereference operator /// \returns a reference to the value pointed by the iterator constexpr const elem_t& operator*() const { - return *_set->_alloc[_i].value; + return *_set->_table[_i].value; } /// /// \brief pointer access operator /// \returns a pointer to the value pointed by the iterator constexpr const elem_t* operator->() const { - if (not _set->_alloc[_i].value) return nullptr; - return &*_set->_alloc[_i].value; + if (not _set->_table[_i].value) return nullptr; + 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: constexpr void _expand() { set cpy; // Create a new set - cpy._alloc.resize( - fennec::next_prime2(_alloc.capacity()) + cpy._table.resize( + fennec::next_prime2(_table.capacity()) ); // rehash for (size_t i = 0; i < capacity(); ++i) { - if (_alloc[i].value) { - cpy.insert(fennec::move(*_alloc[i].value)); + if (_table[i].value) { + cpy.insert(fennec::move(*_table[i].value)); } } // Swap buffers - fennec::swap(_alloc, cpy._alloc); + fennec::swap(_table, cpy._table); } template @@ -488,29 +603,33 @@ private: elem_t value(fennec::forward(args)...); size_t i = _hash(value) % capacity(); // Initial search index int psl = 0; - while (_alloc[i].value) { // Search for empty cell - if (_equal(*_alloc[i].value, value)) { // Check to see if this element is already inserted + while (_table[i].value) { // Search for empty cell + if (_equal(*_table[i].value, value)) { // Check to see if this element is already inserted return iterator(this, i); } - if (psl > _alloc[i].psl) { // When psl is higher, swap - _sumpsl += psl - _alloc[i].psl; - fennec::swap(_alloc[i].psl, psl); - fennec::swap(*_alloc[i].value, value); + if (psl > _table[i].psl) { // When psl is higher, swap + _sumpsl += psl - _table[i].psl; + fennec::swap(_table[i].psl, psl); + fennec::swap(*_table[i].value, value); } i = (i + 1) % capacity(); ++psl; } - _alloc[i].value = fennec::move(value); - _sumpsl += (_alloc[i].psl = psl); + _table[i].value = fennec::move(value); + _sumpsl += (_table[i].psl = psl); ++_size; return iterator(this, npos); } - dynarray _alloc; - hash_t _hash; - equal_t _equal; - size_t _size; - size_t _sumpsl; - float _load; + +// Private Definitions ================================================================================================= +private: + struct node { + optional value; + int psl; + + constexpr node() = default; + constexpr ~node() = default; + }; }; } diff --git a/include/fennec/containers/traversal.h b/include/fennec/containers/traversal.h index 826845b..eee21cf 100644 --- a/include/fennec/containers/traversal.h +++ b/include/fennec/containers/traversal.h @@ -37,9 +37,9 @@ namespace fennec /// /// \brief A set of constants used in the traverser-visitor pattern enum traversal_control_ { - traversal_control_continue = 0, - traversal_control_break = 1, - traversal_control_jump_over = 2, + traversal_control_continue = 0, //!< Continue to the next element + traversal_control_break = 1, //!< Break the traversal loop + traversal_control_jump_over = 2, //!< Jump over the next element }; } diff --git a/include/fennec/containers/tuple.h b/include/fennec/containers/tuple.h index a3cebab..ddb6584 100644 --- a/include/fennec/containers/tuple.h +++ b/include/fennec/containers/tuple.h @@ -42,19 +42,20 @@ namespace fennec /// /// \brief Tuple, holds a collection of values of different types /// \details -/// | Property | Value | -/// |:-----------:|:-----------:| -/// | stable | ⛔ | -/// | dynamic | ✅ | -/// | homogeneous | ⛔ | -/// | distinct | ⛔ | -/// | ordered | ⛔ | -/// | space | \f$O(N)\f$ | -/// | linear | ✅ | -/// | access | \f$O(1)\f$ | -/// | find | \f$O(1)\f$ | -/// | insertion | ⛔ | -/// | deletion | ⛔ | +/// | Property | Value | +/// |:-----------:|:----------:| +/// | stable | ⛔ | +/// | dynamic | ✅ | +/// | homogeneous | ⛔ | +/// | distinct | ⛔ | +/// | ordered | ⛔ | +/// | space | \f$O(N)\f$ | +/// | linear | ✅ | +/// | access | \f$O(1)\f$ | +/// | find | \f$O(1)\f$ | +/// | insertion | ⛔ | +/// | deletion | ⛔ | +/// | space | \f$O(N)\f$ | /// /// \tparam TypesT The types to store template struct tuple; @@ -86,8 +87,14 @@ constexpr const typename tuple::template elem_t& get(const tuple -struct tuple : public detail::_tuple, TypesT...> -{ +struct tuple : public detail::_tuple, TypesT...> { + +// Definitions ========================================================================================================= +public: + + /// \name Definitions + /// @{ + using base_t = detail::_tuple, TypesT...>; //!< the base type template @@ -95,10 +102,20 @@ struct tuple : public detail::_tuple tuple(ArgsT&&...args) : base_t(fennec::forward(args)...) { @@ -107,6 +124,10 @@ struct tuple : public detail::_tuple(mov)) { } }; diff --git a/include/fennec/containers/variant.h b/include/fennec/containers/variant.h index 22ce637..fcab270 100644 --- a/include/fennec/containers/variant.h +++ b/include/fennec/containers/variant.h @@ -40,26 +40,28 @@ namespace fennec { /// -/// \brief A structure that represents a union between \f$TypesT...\f$ +/// \brief A structure that represents a union between \f$TypesT\ldots\f$ /// \details -/// | Property | Value | -/// |:-----------:|:-----------:| -/// | stable | ✅ | -/// | dynamic | ⛔ | -/// | homogeneous | ⛔ | -/// | distinct | ⛔ | -/// | ordered | ⛔ | -/// | space | \f$O(N)\f$ | -/// | linear | ⛔ | -/// | access | \f$O(1)\f$ | -/// | find | ⛔ | -/// | insertion | \f$O(1)\f$ | -/// | deletion | \f$O(1)\f$ | +/// | Property | Value | +/// |:-----------:|:----------:| +/// | stable | ✅ | +/// | dynamic | ⛔ | +/// | homogeneous | ⛔ | +/// | distinct | ⛔ | +/// | ordered | ⛔ | +/// | space | \f$O(N)\f$ | +/// | linear | ⛔ | +/// | access | \f$O(1)\f$ | +/// | find | ⛔ | +/// | insertion | \f$O(1)\f$ | +/// | deletion | \f$O(1)\f$ | +/// | space | \f$O(1)\f$ | /// /// \tparam TypesT The types to hold in the variant template struct variant { // Assertions ========================================================================================================== +public: static_assert( is_unique_v 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; //!< size of the variant in bytes static constexpr size_t nulltype = sizeof...(TypesT); //!< id for a null type - + /// @} // Constructors ======================================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ /// - /// \brief Default Constructor, constructs the first type in \f$TypesT...\f$ 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() : _bytes {} + , _handle(&_bytes) , _type(nulltype) { using construct_t = search_element_t; - fennec::construct(_handle); + this->_construct(); } /// - /// \brief Conversion Constructor, constructs the type in \f$TypesT...\f$ 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$ /// \tparam T The type of the value /// \param t The value to forward + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template variant(T&& t) : _bytes {} + , _handle(&_bytes) , _type() { - using same_t = search_element_args, TypesT...>; - using convert_t = search_element_args, TypesT...>; - using construct_t = conditional_t, convert_t, convert_t>; - fennec::construct(_handle, fennec::forward(t)); + using same_t = search_element_args, TypesT...>::type; + using convert_t = search_element_args, TypesT...>::type; + using construct_t = conditional_t, convert_t, same_t>; + this->_construct(fennec::forward(t)); } /// - /// \brief Emplace Constructor, constructs a type \f$T\f$ that is in \f$TypesT...\f$ that is constructible with \f$ArgsT...\f$ + /// \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 /// \param args The argument values + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template variant(type_identity, ArgsT&&...args) : _bytes{} + , _handle(&_bytes) , _type(nulltype) { static_assert(contains_element_v, "T must be in TypesT..."); - fennec::construct(_handle, fennec::forward(args)...); + this->_construct(fennec::forward(args)...); _type = find_element_v; } /// /// \brief Copy Constructor /// \param v The variant to copy + /// + /// \par Complexity + /// \f$O(1)\f$ + /// variant(const variant& v) : _bytes {} + , _handle(&_bytes) , _type(nulltype) { if (v._type == nulltype) { @@ -128,8 +158,8 @@ struct variant { } ((v._type == find_element_v ? - fennec::construct(_handle, v.get()) : - (0) + this->_construct(v.get()) : + ((void)0) ), ...); _type = v._type; } @@ -137,8 +167,13 @@ struct variant { /// /// \brief Move Constructor /// \param v The variant to move + /// + /// \par Complexity + /// \f$O(1)\f$ + /// variant(variant&& v) noexcept : _bytes {} + , _handle(&_bytes) , _type() { if (v._type == nulltype) { @@ -146,26 +181,41 @@ struct variant { } ((v._type == find_element_v ? - fennec::construct(_handle, fennec::move(v.get())) : - (0) + this->_construct(fennec::move(v.get())) : + ((void)0) ), ...); _type = v._type; } /// /// \brief Destructor, if a type is held, destruct it. + /// + /// \par Complexity + /// \f$O(1)\f$ + /// ~variant() { _clear(); } + /// @} + // Assignment ========================================================================================================== +public: + + /// \name Assignment + /// @{ + /// /// \brief value assignment operator /// \tparam T The type to assign /// \param t the value to assign /// \returns a reference to \f$self\f$ after assigning \f$t\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template variant& operator=(T&& t) { @@ -173,10 +223,10 @@ struct variant { if constexpr((contains_element_v or ...)) { using type_t = remove_reference_t; if (_type == find_element_v) { - *static_cast(_handle) = fennec::forward(t); + *_get() = fennec::forward(t); } else { _clear(); - fennec::construct(_handle, fennec::forward(t)); + this->_construct(fennec::forward(t)); _type = find_element_v; } return *this; @@ -186,8 +236,8 @@ struct variant { bool assigned = false; if (_type != nulltype) { ((_type == find_element_v ? - (*static_cast(_handle) = fennec::forward(t), assigned = true) : - (0) + (*_get() = fennec::forward(t), assigned = true) : + ((void)0) ), ...); } @@ -198,7 +248,7 @@ struct variant { // Otherwise, destruct, then construct _clear(); using construct_t = search_element_args, TypesT...>; - fennec::construct(_handle, fennec::forward(t)); + this->_construct(fennec::forward(t)); return *this; } @@ -207,80 +257,127 @@ struct variant { /// \tparam T The type to construct /// \tparam ArgsT the argument types /// \param args the argument values + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template requires(contains_element_v) void emplace(ArgsT&&...args) { _clear(); - fennec::construct(_handle, fennec::forward(args)...); + this->_construct(fennec::forward(args)...); } /// /// \brief deduced emplace function /// \tparam ArgsT the argument types /// \param args the argument values + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template void emplace(ArgsT&&...args) { using type_t = nth_element_t; _clear(); - fennec::construct(fennec::forward(args)...); + this->_construct(fennec::forward(args)...); } + /// @} + // Access ============================================================================================================== + /// \name Access + /// @{ + /// /// \brief get the value of the variant interpreted as \f$T\f$ /// \tparam T the type to interpret as /// \returns The value interpreted as \f$T\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template requires(contains_element_v) T& get() { - return *static_cast(_handle); + return *_get(); } /// /// \tparam T the type to interpret as /// \returns The value interpreted as \f$T\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template requires(contains_element_v) const T& get() const { - return *static_cast(_handle); + return *_get(); } /// /// \tparam T the type to interpret as /// \returns The value interpreted as \f$T\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template> requires(contains_element_v) T& get() { - return *static_cast(_handle); + return *_get(); } /// /// \tparam T the type to interpret as /// \returns The value interpreted as \f$T\f$ + /// + /// \par Complexity + /// \f$O(1)\f$ + /// template> requires(contains_element_v) const T& get() const { - return *static_cast(_handle); + return *_get(); } + /// @} - +// Private Member Variables ============================================================================================ private: - union { - byte_t _bytes[size]; - void* _handle; - }; + byte_t _bytes[size]; + void* _handle; size_t _type; + +// Private Helpers ===================================================================================================== +private: + + template + T* _get() const { + return static_cast(_handle); + } + void _clear() { if (_type == nulltype) { return; } ((_type == find_element_v ? - fennec::destruct(_handle) : - (0) + this->_destruct() : + ((void)0) ), ...); _type = nulltype; } + + template + void _construct(ArgsT&&...args) { + fennec::construct(_get(), fennec::forward(args)...); + } + + template + void _destruct() { + fennec::destruct(_get()); + } }; } diff --git a/include/fennec/core/event.h b/include/fennec/core/event.h index 596ba9e..d10bec8 100644 --- a/include/fennec/core/event.h +++ b/include/fennec/core/event.h @@ -32,14 +32,35 @@ struct event; /// /// \brief Class outlining the interface for an object that listens for events class event_listener { +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + + /// + /// \brief Virtual Destructor virtual ~event_listener(); + /// @} + + +// Event Handling ====================================================================================================== +public: + + /// \name Event Handling + /// @{ + /// /// \brief event handler callback /// \param event the event to handle virtual void handle_event(event* event) = 0; + /// @} + + +// Private Member Variables ============================================================================================ +private: FENNEC_RTTI_CLASS_ENABLE() { } }; @@ -47,12 +68,48 @@ public: /// /// \brief Main event interface, includes static methods for registering listeners and dispatching events 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; + /// @} + + +// Static Event System Interface ======================================================================================= +public: + + /// \name Event System Interface + /// @{ + + /// + /// \brief Handles the event loop to distribute events. + /// + /// \details Blocking static void handle_events(); /// /// \brief Registers a listener for the event type + /// + /// \details Blocking /// \tparam EventT the event type /// \param listener the listener to register template @@ -61,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 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 static void dispatch(ArgsT&&...args) { event::_dispatch(fennec::make_unique(fennec::forward(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 static void dispatch_immediate(ArgsT&&...args) { event::_dispatch_immediate(fennec::make_unique(fennec::forward(args)...)); } + /// @} + + +// Private Helpers ===================================================================================================== private: static void _add_listener(event_listener* listener, uint64_t type); static void _handle_event(unique_ptr& event); diff --git a/include/fennec/core/logger.h b/include/fennec/core/logger.h index 504dc0e..ea770c3 100644 --- a/include/fennec/core/logger.h +++ b/include/fennec/core/logger.h @@ -42,11 +42,12 @@ namespace fennec /// /// \brief logger class class logger : public singleton { + +// Logger System Interface ============================================================================================= public: - /// - /// \brief default constructor - logger(); - ~logger(); + + /// \name System Interface + /// @{ /// /// \brief Log a string to the log file and cout @@ -92,9 +93,21 @@ public: inst._cout->println(str); } + /// @} + + +// Private Member Variables ============================================================================================ private: file _logfile; file* _cout; + + +// Private Constructors & Destructor =================================================================================== +private: + logger(); + ~logger(); + + friend struct singleton; }; } diff --git a/include/fennec/core/version.h b/include/fennec/core/version.h index b0969e1..106cd44 100644 --- a/include/fennec/core/version.h +++ b/include/fennec/core/version.h @@ -32,6 +32,16 @@ #ifndef 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 #include @@ -41,20 +51,73 @@ namespace fennec /// /// \brief simple version struct for drivers and systems 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) { - 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) { - 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 \ No newline at end of file diff --git a/include/fennec/filesystem/file.h b/include/fennec/filesystem/file.h index 626fecd..611ba86 100644 --- a/include/fennec/filesystem/file.h +++ b/include/fennec/filesystem/file.h @@ -56,12 +56,12 @@ namespace fennec /// enum fmode_ : uint8_t { - fmode_read = 0b00000001 ///< Opens file for reading -, fmode_write = 0b00000010 ///< Opens file for writing -, 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_binary = 0b00010000 ///< Open in binary mode -, fmode_wide = 0b00100000 ///< Opens a file in wide mode + fmode_read = 0b00000001 //!< Opens file for reading +, fmode_write = 0b00000010 //!< Opens file for writing +, 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_binary = 0b00010000 //!< Open in binary 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::clear_error() to clear the errored state. /// Some operations, specifically file::rename() and file::copy(). +///
+/// 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 { +// Constants =========================================================================================================== public: + + /// \name Constants + /// @{ + /// \brief value of an invalid position static constexpr size_t npos = -1; + /// @} + + +// Validation Functions ================================================================================================ +public: + + /// \name Validation Functions + /// @{ + /// /// \brief Check if the provided mode bitflags are a valid combination /// \param mode the bitfield @@ -93,24 +111,43 @@ public: || !(t || x); } + /// @} + + +// STD Text Streams ==================================================================================================== +public: + + /// \name STD Text Streams + /// @{ + /// - /// \returns the c stdout + /// \returns the c stdout stream static file& cout(); /// - /// \returns the c stdin + /// \returns the c stdin stream static file& cin(); /// - /// \returns the c stderr + /// \returns the c stderr stream 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(); /// - /// \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 mode the mode to open with 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 mode the mode to open with 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 mode the mode to open with file(const path& path, uint8_t mode) @@ -137,141 +175,190 @@ public: } /// - /// \brief default destructor, cleans up an open stream - ~file(); - - /// - /// \brief move constructor + /// \brief Move constructor /// \param file the stream to take ownership of 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 file& operator=(file&& file) noexcept; + ///@} + +private: // don't allow copying streams file(const file&) = delete; + file& operator=(const file&) = delete; // Properties ========================================================================================================== +public: + + /// \name Properties + /// @{ /// - /// \returns the path the stream + /// \returns The path the stream const path& get_path() const { return _path; } /// - /// \returns the mode of the stream + /// \returns The mode of the stream uint8_t mode() const { 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 { return _handle != nullptr; } + /// @} + // File Access ========================================================================================================= +public: + + /// \name File Access + /// @{ /// - /// \brief open a file /// \param path the path to the file /// \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); /// - /// \brief open a file /// \param path the path to the file /// \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); /// - /// \brief open a file + /// \brief Open a file /// \param path the path to the file /// \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); /// - /// \brief close a stream - /// \returns false on success, true on error + /// \brief Close a stream + /// \returns \f$false\f$ on success, \f$true\f$ on error bool close(); /// - /// \brief commit the streams buffer to the file - /// \returns false on success, true on error + /// \brief Commit the streams buffer to the file + /// \returns \f$false\f$ on success, \f$true\f$ on error bool commit(); + /// @} + // File Operations ===================================================================================================== +public: + + /// \name File Operations + /// @{ /// /// \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(); /// - /// \brief rebinds the stream, copying contents to path, and erasing the old file /// \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, - /// attempts to reopen this file as read-only, - /// 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. + /// \details + /// Copies contents to the new path, and erases the old file. + /// * Attempts to open a write-only stream at path + /// * Attempts to reopen this file as read-only + /// * 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); /// - /// \brief rebinds the stream, copying contents to path, and erasing the old file /// \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, - /// attempts to reopen this file as read-only, - /// 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. + /// \details + /// Copies contents to the new path, and erases the old file. + /// * Attempts to open a write-only stream at path + /// * Attempts to reopen this file as read-only + /// * 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); /// - /// \brief rebinds the stream, copying contents to path, and erasing the old file + /// \brief Rebind the stream. /// \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, - /// attempts to reopen this file as read-only, - /// 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. + /// \details + /// Copies contents to the new path, and erases the old file. + /// * Attempts to open a write-only stream at path + /// * Attempts to reopen this file as read-only + /// * 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); /// - /// \brief copies the contents of this file to path. /// \param path the path to copy to /// \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,
+ /// * Attempts to reopen this file as read-only,
+ /// * Copies the contents of this file to the new stream,
+ /// * Reopen the new stream with the flags of this file. file copy(const cstring& path); /// - /// \brief copies the contents of this file to path. /// \param path the path to copy to /// \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,
+ /// * Attempts to reopen this file as read-only,
+ /// * Copies the contents of this file to the new stream,
+ /// * Reopen the new stream with the flags of this file. 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 /// \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,
+ /// * Attempts to reopen this file as read-only,
+ /// * Copies the contents of this file to the new stream,
+ /// * Reopen the new stream with the flags of this file. file copy(const path& path); + /// @} + // File Positioning ==================================================================================================== +public: + + /// \name File Positioning + /// @{ /// /// \returns the position index in the stream @@ -280,19 +367,25 @@ public: /// /// \param i the new index to move to /// \returns \f$false\f$ on success, \f$true\f$ otherwise - bool set_pos(size_t i); + bool set_pos(size_t i); /// /// \brief return to the start of the stream /// \returns \f$false\f$ on success, \f$true\f$ otherwise - bool rewind(); + bool rewind(); /// /// \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 ============================================================================================== +public: + + /// \name Binary Read Operations + /// @{ /// /// \brief binary read @@ -324,8 +417,14 @@ public: return read(static_cast(data), sizeof(T), n); } + /// @} + // Binary Write Operations ============================================================================================= +public: + + /// \name Binary Write Operations + /// @{ /// /// \brief put a character at the current position in the stream @@ -389,27 +488,43 @@ public: return write(static_cast(data), sizeof(T), n); } + /// @} + // Read Operations ===================================================================================================== +public: + + /// \name Read Operations + /// @{ /// /// \returns the character read at the current position in the stream + /// \details Advances the position by one character char getc(); /// /// \returns the wide character read at the current position in the stream + /// \details Advances the position by one wide character 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(); /// - /// \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(); + /// @} + // Printing Operations ================================================================================================= +public: + + /// \name Print Operations + /// @{ /// /// \param str the string to print @@ -440,19 +555,28 @@ public: this->print(cstring(fmt.cstr(), fmt.length())); } + /// @} + // Error Handling ====================================================================================================== +public: + + /// \name Error Handling + /// @{ /// - /// \returns the current error state of the file - const char* get_error() const { return _error; } + /// \brief Returns the current error state. + /// \returns A string containing the current error. + cstring get_error() const { return { _error, ::strlen(_error) }; } /// /// \brief clears the errored state void clear_error() { _error = nullptr; } + /// @} + private: FILE* _handle; path _path; diff --git a/include/fennec/filesystem/path.h b/include/fennec/filesystem/path.h index b215549..5d7fffc 100644 --- a/include/fennec/filesystem/path.h +++ b/include/fennec/filesystem/path.h @@ -30,28 +30,38 @@ namespace fennec /// /// \details This structure makes no guarantees about the validity of a path. /// Operations do not examine the system's file structure. -struct path -{ -public: +struct path { + // Definitions ========================================================================================================= +public: class iterator; friend class iterator; -// Static Functions ==================================================================================================== +// Current Working Director ============================================================================================ +public: + + /// \name Current Working Directory + /// @{ /// \brief Get the current 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 /// \param path the path to the new 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 @@ -89,8 +99,18 @@ public: /// \param p the path to take ownership of path(path&& p) noexcept : _str(move(p._str)) { } + /// + /// \brief Destructor + ~path() = default; + + /// @} + // Assignment Operators ================================================================================================ +public: + + /// \name Assignment + /// @{ /// /// \brief C-String Assignment Operator @@ -138,8 +158,31 @@ public: 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 @@ -165,13 +208,7 @@ public: 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 @@ -240,7 +277,7 @@ public: #else if (_str[0] != '/') { #endif - working = current(); + working = get_current(); } while (not parse.is_empty()) { @@ -278,7 +315,11 @@ public: } -// Iterator ============================================================================================================ +// Iteration =========================================================================================================== +public: + + /// \name Iteration + /// @{ /// /// \brief C++ Iterator Specification \f$begin()\f$ @@ -386,6 +427,8 @@ public: friend struct path; }; + /// @} + private: string _str; }; diff --git a/include/fennec/format/format.h b/include/fennec/format/format.h index 0b6cf05..b328317 100644 --- a/include/fennec/format/format.h +++ b/include/fennec/format/format.h @@ -38,6 +38,7 @@ namespace fennec { + /// /// \brief C++ 20 format specification /// \tparam ArgsT The argument types diff --git a/include/fennec/format/format_arg.h b/include/fennec/format/format_arg.h index 5fc6ea1..58f1625 100644 --- a/include/fennec/format/format_arg.h +++ b/include/fennec/format/format_arg.h @@ -35,6 +35,7 @@ namespace fennec { + /// /// \brief helper struct for `fennec::format` struct format_arg { diff --git a/include/fennec/interpret/tokenizer.h b/include/fennec/interpret/tokenizer.h index 2558269..b980315 100644 --- a/include/fennec/interpret/tokenizer.h +++ b/include/fennec/interpret/tokenizer.h @@ -65,12 +65,12 @@ struct tokenizer { using escseq = escape_sequence*; using escmap = map; - string delimiter; // markers that separate tokens - string operators; // operators are treated as individual tokens - string brackets; // characters that mark brackets - 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 - bool numbers; // Anything that resembles a number + string delimiter; //!< markers that separate tokens + string operators; //!< operators are treated as individual tokens + string brackets; //!< characters that mark brackets + 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 + bool numbers; //!< Anything that resembles a number enum token_ : uint8_t { token_text = 0, diff --git a/include/fennec/lang/detail/_type_sequences.h b/include/fennec/lang/detail/_type_sequences.h index 7270f22..f010f12 100644 --- a/include/fennec/lang/detail/_type_sequences.h +++ b/include/fennec/lang/detail/_type_sequences.h @@ -67,7 +67,7 @@ namespace fennec::detail template struct _find_element : integral_constant ? N : N + 1> {}; - template requires(is_same_v) + template struct _find_element : conditional_t, integral_constant, _find_element> {}; diff --git a/include/fennec/lang/float.h b/include/fennec/lang/float.h index 1b53c7f..a1c8fc9 100644 --- a/include/fennec/lang/float.h +++ b/include/fennec/lang/float.h @@ -21,7 +21,9 @@ /// \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. +/// +/// 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_ROUND_ERR +/// \brief Does \f$float\f$ have an infinity? #define FLT_HAS_INFINITY 1 +/// \brief Does \f$float\f$ have a quiet NaN? #define FLT_HAS_QUIET_NAN 1 +/// \brief Does \f$float\f$ have a signaling NaN? #define FLT_HAS_SIGNALING_NAN 1 +/// \brief Does \f$float\f$ use denormalization? #define FLT_HAS_DENORM 1 +/// \brief Does \f$float\f$ have loss with denormalization? #define FLT_HAS_DENORM_LOSS 0 +/// \brief What rounding style does \f$float\f$ use? #define FLT_ROUNDS 1 +/// \brief Does \f$float\f$ use the IEEE floating point specification? #define FLT_IS_IEC559 1 +/// \brief The number of mantissa bits in \f$float\f$. #define FLT_MANT_DIG 24 +/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ → \f$text\f$ → \f$float\f$. #define FLT_DIG 6 +/// \brief The decimal precision required to serialize and deserialize a \f$float\f$. #define FLT_DECIMAL_DIG 9 +/// \brief The radix, or integer base, used to represent a \f$float\f$. #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 +/// \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 +/// \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 +/// \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 +/// \brief Do arithmetics operations with \f$float\f$ trap? #define FLT_TRAPS 0 +/// \brief Do arithmetics operations with \f$float\f$ check for underflow? #define FLT_TINYNESS_BEFORE 0 +/// \brief Smallest positive, finite, normal value of \f$float\f$. #define FLT_MIN fennec::bit_cast(0x800000) +/// \brief Largest positive, finite value of \f$float\f$. #define FLT_MAX fennec::bit_cast(0x7f7fffff) +/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$. #define FLT_EPSILON fennec::bit_cast(0x34000000) +/// \brief A value representing \f$\inf\f$ of type \f$float\f$. #define FLT_INF fennec::bit_cast(0x7f800000) +/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap. #define FLT_QUIET_NAN fennec::bit_cast(0x7fc00000) +/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps. #define FLT_SIGNALING_NAN fennec::bit_cast(0x7fa00000) +/// \brief Smallest positive, finite, subnormal value of \f$float\f$. #define FLT_DENORM_MIN fennec::bit_cast(0x1) +/// \brief Maximum rounding error of type \f$float\f$. #define FLT_ROUND_ERR fennec::bit_cast(0x3f000000) #undef DBL_HAS_INFINITY @@ -110,30 +137,55 @@ #undef DBL_DENORM_MIN #undef DBL_ROUND_ERR +/// \brief Does \f$double\f$ have an infinity? #define DBL_HAS_INFINITY 1 +/// \brief Does \f$double\f$ have a quiet NaN? #define DBL_HAS_QUIET_NAN 1 +/// \brief Does \f$double\f$ have a signaling NaN? #define DBL_HAS_SIGNALING_NAN 1 +/// \brief Does \f$double\f$ use denormalization? #define DBL_HAS_DENORM 1 +/// \brief Does \f$double\f$ have loss with denormalization? #define DBL_HAS_DENORM_LOSS 0 +/// \brief What rounding style does \f$double\f$ use? #define DBL_ROUNDS 1 +/// \brief Does \f$double\f$ use the IEEE doubleing point specification? #define DBL_IS_IEC559 1 +/// \brief The number of mantissa bits in \f$double\f$. #define DBL_MANT_DIG 53 +/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ → \f$text\f$ → \f$double\f$. #define DBL_DIG 15 +/// \brief The decimal precision required to serialize and deserialize a \f$double\f$. #define DBL_DECIMAL_DIG 17 +/// \brief The radix, or integer base, used to represent a \f$double\f$. #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 +/// \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 +/// \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 +/// \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 +/// \brief Do arithmetics operations with \f$double\f$ trap? #define DBL_TRAPS 0 +/// \brief Do arithmetics operations with \f$double\f$ check for underflow? #define DBL_TINYNESS_BEFORE 0 +/// \brief Smallest positive, finite, normal value of \f$double\f$. #define DBL_MIN fennec::bit_cast(0x10000000000000ll) +/// \brief Largest positive, finite value of \f$double\f$. #define DBL_MAX fennec::bit_cast(0x7fefffffffffffffll) +/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$. #define DBL_EPSILON fennec::bit_cast(0x3cb0000000000000ll) +/// \brief A value representing \f$\inf\f$ of type \f$double\f$. #define DBL_INF fennec::bit_cast(0x7ff0000000000000ll) +/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap. #define DBL_QUIET_NAN fennec::bit_cast(0x7ff8000000000000ll) +/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps. #define DBL_SIGNALING_NAN fennec::bit_cast(0x7ff4000000000000ll) +/// \brief Smallest positive, finite, subnormal value of \f$double\f$. #define DBL_DENORM_MIN fennec::bit_cast(0x1ll) +/// \brief Maximum rounding error of type \f$double\f$. #define DBL_ROUND_ERR fennec::bit_cast(0x3fe0000000000000ll) #endif // FENNEC_LANG_FLOAT_H diff --git a/include/fennec/lang/integer.h b/include/fennec/lang/integer.h index fe9861f..f263aef 100644 --- a/include/fennec/lang/integer.h +++ b/include/fennec/lang/integer.h @@ -21,7 +21,9 @@ /// \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. +/// +/// 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_MAX +/// \brief Is \f$char\f$ signed? #define CHAR_IS_SIGNED true +/// \brief Rounding style of type \f$char\f$. #define CHAR_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$char\f$. #define CHAR_RADIX_DIG 0x7 +/// \brief Number of decimal digits represented by \f$char\f$. #define CHAR_DIG 0x2 +/// \brief Number of decimal digits necessary to differentiate all values of type \f$char\f$. #define CHAR_DECIMAL_DIG 0x0 +/// \brief The radix, or integer base, used to represent a \f$char\f$. #define CHAR_RADIX 0x2 +/// \brief Do arithmetics operations with \f$char\f$ trap? #define CHAR_TRAPS 0xtrue +/// \brief Smallest finite value of \f$char\f$. #define CHAR_MIN 0x80 +/// \brief Largest finite value of \f$char\f$. #define CHAR_MAX 0x7f +/// \brief Is \f$wchar_t\f$ signed? #define WCHAR_IS_SIGNED true +/// \brief Rounding style of type \f$wchar_t\f$. #define WCHAR_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$wchar_t\f$. #define WCHAR_RADIX_DIG 0x1f +/// \brief Number of decimal digits represented by \f$wchar_t\f$. #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 +/// \brief The radix, or integer base, used to represent a \f$wchar_t\f$. #define WCHAR_RADIX 0x2 +/// \brief Do arithmetics operations with \f$wchar_t\f$ trap? #define WCHAR_TRAPS 0xtrue +/// \brief Smallest finite value of \f$wchar_t\f$. #define WCHAR_MIN 0x80000000 +/// \brief Largest finite value of \f$wchar_t\f$. #define WCHAR_MAX 0x7fffffff +/// \brief Is \f$signed char\f$ signed? #define SCHAR_ROUNDS 0x0 +/// \brief Rounding style of type \f$signed char\f$. #define SCHAR_RADIX_DIG 0x7 +/// \brief Number of radix digits represented by \f$signed char\f$. #define SCHAR_DIG 0x2 +/// \brief Number of decimal digits represented by \f$signed char\f$. #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 +/// \brief Do arithmetics operations with \f$signed char\f$ trap? #define SCHAR_TRAPS 0xtrue +/// \brief Smallest finite value of \f$signed char\f$. #define SCHAR_MIN 0x80 +/// \brief Largest finite value of \f$signed char\f$. #define SCHAR_MAX 0x7f +/// \brief Is \f$unsigned char\f$ unsigned? #define UCHAR_ROUNDS 0x0 +/// \brief Rounding style of type \f$unsigned char\f$. #define UCHAR_RADIX_DIG 0x8 +/// \brief Number of radix digits represented by \f$unsigned char\f$. #define UCHAR_DIG 0x2 +/// \brief Number of decimal digits represented by \f$unsigned char\f$. #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 +/// \brief Do arithmetics operations with \f$unsigned char\f$ trap? #define UCHAR_TRAPS 0xtrue +/// \brief Smallest finite value of \f$unsigned char\f$. #define UCHAR_MIN 0x0 +/// \brief Largest finite value of \f$unsigned char\f$. #define UCHAR_MAX 0xff +/// \brief Rounding style of type \f$short\f$. #define SHORT_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$short\f$. #define SHORT_RADIX_DIG 0xf +/// \brief Number of decimal digits represented by \f$short\f$. #define SHORT_DIG 0x4 +/// \brief Number of decimal digits necessary to differentiate all values of type \f$short\f$. #define SHORT_DECIMAL_DIG 0x0 +/// \brief The radix, or integer base, used to represent a \f$short\f$. #define SHORT_RADIX 0x2 +/// \brief Do arithmetics operations with \f$short\f$ trap? #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 +/// \brief Rounding style of type \f$unsigned short\f$. #define USHORT_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$unsigned short\f$. #define USHORT_RADIX_DIG 0x10 +/// \brief Number of decimal digits represented by \f$unsigned short\f$. #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 +/// \brief The radix, or integer base, used to represent a \f$unsigned short\f$. #define USHORT_RADIX 0x2 +/// \brief Do arithmetics operations with \f$unsigned short\f$ trap? #define USHORT_TRAPS 0xtrue +/// \brief Smallest finite value of \f$unsigned short\f$. #define USHORT_MIN 0x0 +/// \brief Largest finite value of \f$unsigned short\f$. #define USHORT_MAX 0xffff +/// \brief Rounding style of type \f$int\f$. #define INT_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$int\f$. #define INT_RADIX_DIG 0x1f +/// \brief Number of decimal digits represented by \f$int\f$. #define INT_DIG 0x9 +/// \brief Number of decimal digits necessary to differentiate all values of type \f$int\f$. #define INT_DECIMAL_DIG 0x0 +/// \brief The radix, or integer base, used to represent a \f$int\f$. #define INT_RADIX 0x2 +/// \brief Do arithmetics operations with \f$int\f$ trap? #define INT_TRAPS 0xtrue +/// \brief Smallest finite value of \f$int\f$. #define INT_MIN 0x80000000 +/// \brief Largest finite value of \f$int\f$. #define INT_MAX 0x7fffffff +/// \brief Rounding style of type \f$unsigned int\f$. #define UINT_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$unsigned int\f$. #define UINT_RADIX_DIG 0x20 +/// \brief Number of decimal digits represented by \f$unsigned int\f$. #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 +/// \brief The radix, or unsigned integer base, used to represent a \f$unsigned int\f$. #define UINT_RADIX 0x2 +/// \brief Do arithmetics operations with \f$unsigned int\f$ trap? #define UINT_TRAPS 0xtrue +/// \brief Smallest finite value of \f$unsigned int\f$. #define UINT_MIN 0x0 +/// \brief Largest finite value of \f$unsigned int\f$. #define UINT_MAX 0xffffffff +/// \brief Rounding style of type \f$long int\f$. #define LONG_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$long int\f$. #define LONG_RADIX_DIG 0x3f +/// \brief Number of decimal digits represented by \f$long int\f$. #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 +/// \brief The radix, or long integer base, used to represent a \f$long int\f$. #define LONG_RADIX 0x2 +/// \brief Do arithmetics operations with \f$long int\f$ trap? #define LONG_TRAPS 0xtrue +/// \brief Smallest finite value of \f$long int\f$. #define LONG_MIN 0x8000000000000000 +/// \brief Largest finite value of \f$long int\f$. #define LONG_MAX 0x7fffffffffffffff +/// \brief Rounding style of type \f$unsigned long int\f$. #define ULONG_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$unsigned long int\f$. #define ULONG_RADIX_DIG 0x40 +/// \brief Number of decimal digits represented by \f$unsigned long int\f$. #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 +/// \brief The radix, or unsigned long integer base, used to represent a \f$unsigned long int\f$. #define ULONG_RADIX 0x2 +/// \brief Do arithmetics operations with \f$unsigned long int\f$ trap? #define ULONG_TRAPS 0xtrue +/// \brief Smallest finite value of \f$unsigned long int\f$. #define ULONG_MIN 0x0 +/// \brief Largest finite value of \f$unsigned long int\f$. #define ULONG_MAX 0xffffffffffffffff +/// \brief Rounding style of type \f$long long\f$. #define LLONG_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$long long\f$. #define LLONG_RADIX_DIG 0x3f +/// \brief Number of decimal digits represented by \f$long long\f$. #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 +/// \brief The radix, or long longeger base, used to represent a \f$long long\f$. #define LLONG_RADIX 0x2 +/// \brief Do arithmetics operations with \f$long long\f$ trap? #define LLONG_TRAPS 0xtrue +/// \brief Smallest finite value of \f$long long\f$. #define LLONG_MIN 0x8000000000000000 +/// \brief Largest finite value of \f$long long\f$. #define LLONG_MAX 0x7fffffffffffffff +/// \brief Rounding style of type \f$unsigned long long\f$. #define ULLONG_ROUNDS 0x0 +/// \brief Number of radix digits represented by \f$unsigned long long\f$. #define ULLONG_RADIX_DIG 0x40 +/// \brief Number of decimal digits represented by \f$unsigned long long\f$. #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 +/// \brief The radix, or unsigned long longeger base, used to represent a \f$unsigned long long\f$. #define ULLONG_RADIX 0x2 +/// \brief Do arithmetics operations with \f$unsigned long long\f$ trap? #define ULLONG_TRAPS 0xtrue +/// \brief Smallest finite value of \f$unsigned long long\f$. #define ULLONG_MIN 0x0 +/// \brief Largest finite value of \f$unsigned long long\f$. #define ULLONG_MAX 0xffffffffffffffff #endif // FENNEC_LANG_INTEGER_H diff --git a/include/fennec/lang/intrinsics.h b/include/fennec/lang/intrinsics.h index 8d1f7b7..a5417e3 100644 --- a/include/fennec/lang/intrinsics.h +++ b/include/fennec/lang/intrinsics.h @@ -92,7 +92,7 @@ /// \f$FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE\f$
/// \f$B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)\f$ /// -/// Checks if type \f$X\f$ is constructible with args \f$...\f$, such that \f$X::X(...)\f$ exists. +/// Checks if type \f$X\f$ is constructible with args \f$\ldots\f$, such that \f$X::X(...)\f$ exists. /// /// /// diff --git a/include/fennec/lang/limits.h b/include/fennec/lang/limits.h index 288f235..71cf9b6 100644 --- a/include/fennec/lang/limits.h +++ b/include/fennec/lang/limits.h @@ -222,42 +222,42 @@ enum float_round_style /// \tparam TypeT Numeric types, may be overloaded for custom types template struct numeric_limits { - 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_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 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_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_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_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 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 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_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 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_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_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_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 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 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 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 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 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 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 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 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 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 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 - 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 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 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 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 denorm_min() { return TypeT(); } ///< \returns a value of TypeT holding the smallest positive subnormal + 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 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 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 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 denorm_min() { return TypeT(); } //!< \returns a value of TypeT holding the smallest positive subnormal }; // Overload definitions for basic types diff --git a/include/fennec/lang/types.h b/include/fennec/lang/types.h index 356a8da..5ac66db 100644 --- a/include/fennec/lang/types.h +++ b/include/fennec/lang/types.h @@ -192,6 +192,16 @@ /// \copybrief fennec::ptrdiff_t /// ///
+/// \ref fennec::empty_t "empty_t" +/// +/// \copybrief fennec::empty_t +/// +///
+/// \ref fennec::undefined_t "undefined_t" +/// +/// \copybrief fennec::undefined_t +/// +///
/// \ref fennec::void_t "void_t" /// /// \copybrief fennec::void_t @@ -211,28 +221,28 @@ namespace fennec /// \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 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 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 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 ushort_t = unsigned short; ///< \brief An unsigned short type, capable of holding an unsigned 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 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 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 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 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 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 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 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 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. /// @} @@ -242,18 +252,18 @@ namespace fennec /// \name Special Types /// @{ - 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 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 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 ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers - struct empty_t {}; + 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 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 uintmax_t = uintmax_t; //!< \brief Maximum Width Unsigned Integer Type. + 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. + struct empty_t {}; //!< \brief A struct resembling an empty type. - class undefined_t; ///< \brief undefined class for SFINAE - template using void_t = void; ///< \brief Void type used for SFINAE + class undefined_t; //!< \brief Undefined class for SFINAE. + template using void_t = void; //!< \brief Void type used for SFINAE. /// @} @@ -264,15 +274,15 @@ namespace fennec /// \name Sized Integer Types /// @{ - using int8_t = ::int8_t; ///< \brief Signed 8-bit integer - using int16_t = ::int16_t; ///< \brief Signed 16-bit integer - using int32_t = ::int32_t; ///< \brief Signed 32-bit integer - using int64_t = ::int64_t; ///< \brief Signed 64-bit integer + using int8_t = ::int8_t; //!< \brief Signed 8-bit integer. + using int16_t = ::int16_t; //!< \brief Signed 16-bit integer. + using int32_t = ::int32_t; //!< \brief Signed 32-bit integer. + using int64_t = ::int64_t; //!< \brief Signed 64-bit integer. - using uint8_t = ::uint8_t; ///< \brief Unsigned 8-bit integer - using uint16_t = ::uint16_t; ///< \brief Unsigned 16-bit integer - using uint32_t = ::uint32_t; ///< \brief Unsigned 32-bit integer - using uint64_t = ::uint64_t; ///< \brief Unsigned 64-bit integer + using uint8_t = ::uint8_t; //!< \brief Unsigned 8-bit integer. + using uint16_t = ::uint16_t; //!< \brief Unsigned 16-bit integer. + using uint32_t = ::uint32_t; //!< \brief Unsigned 32-bit integer. + using uint64_t = ::uint64_t; //!< \brief Unsigned 64-bit integer. /// @} @@ -282,9 +292,9 @@ namespace fennec /// \name Sized Floating-Point Types /// @{ - //using float16_t = _Float16; ///< \brief A half-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 float16_t = _Float16; //!< \brief A half-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 /// @} diff --git a/include/fennec/math/detail/_fwd.h b/include/fennec/math/detail/_forward.h similarity index 94% rename from include/fennec/math/detail/_fwd.h rename to include/fennec/math/detail/_forward.h index 5eaef51..75b85f6 100644 --- a/include/fennec/math/detail/_fwd.h +++ b/include/fennec/math/detail/_forward.h @@ -16,8 +16,8 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_MATH_DETAIL_FWD_H -#define FENNEC_MATH_DETAIL_FWD_H +#ifndef FENNEC_MATH_DETAIL_FORWARD_H +#define FENNEC_MATH_DETAIL_FORWARD_H #include @@ -36,4 +36,4 @@ template using mat } -#endif // FENNEC_MATH_DETAIL_FWD_H +#endif // FENNEC_MATH_DETAIL_FORWARD_H diff --git a/include/fennec/math/detail/_matrix.h b/include/fennec/math/detail/_matrix.h index 7b12a90..7131448 100644 --- a/include/fennec/math/detail/_matrix.h +++ b/include/fennec/math/detail/_matrix.h @@ -19,7 +19,7 @@ #ifndef FENNEC_MATH_DETAIL_MATRIX_H #define FENNEC_MATH_DETAIL_MATRIX_H -#include +#include namespace fennec { diff --git a/include/fennec/math/detail/_vector_traits.h b/include/fennec/math/detail/_vector_traits.h index e9f321f..c7d5d1d 100644 --- a/include/fennec/math/detail/_vector_traits.h +++ b/include/fennec/math/detail/_vector_traits.h @@ -19,7 +19,7 @@ #ifndef FENNEC_MATH_DETAIL_VECTOR_TRAITS_H #define FENNEC_MATH_DETAIL_VECTOR_TRAITS_H -#include +#include #include #include diff --git a/include/fennec/math/ext/constants.h b/include/fennec/math/ext/constants.h index 2a0cc46..cb99ff2 100644 --- a/include/fennec/math/ext/constants.h +++ b/include/fennec/math/ext/constants.h @@ -546,81 +546,81 @@ namespace fennec // Rational Constants ================================================================================================== -template constexpr genType zero() { return genType(0); } ///< \returns The value of \f$0\f$ -template constexpr genType one() { return genType(1); } ///< \returns The value of \f$1\f$ -template constexpr genType one_half() { return genType(0.5); } ///< \returns The value of \f$\frac{1}{2}\f$ -template constexpr genType three_over_two() { return genType(1.5); } ///< \returns The value of \f$\frac{3}{2}\f$ +template constexpr genType zero() { return genType(0); } //!< \returns The value of \f$0\f$ +template constexpr genType one() { return genType(1); } //!< \returns The value of \f$1\f$ +template constexpr genType one_half() { return genType(0.5); } //!< \returns The value of \f$\frac{1}{2}\f$ +template constexpr genType three_over_two() { return genType(1.5); } //!< \returns The value of \f$\frac{3}{2}\f$ // Irrational Constants ================================================================================================ -template constexpr genType one_third() { return 0.33333333333333333333333333333333333333333333333333; } ///< \returns The value of \f$\frac{1}{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType two_thirds() { return 0.66666666666666666666666666666666666666666666666666; } ///< \returns The value of \f$\frac{2}{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } ///< \returns The value of \f$\sqrt{2}\f$ with the highest precision for \f$genType\f$ -template constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } ///< \returns The value of \f$\sqrt{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } ///< \returns The value of \f$\sqrt{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } ///< \returns The value of \f$\sqrt{7}\f$ with the highest precision for \f$genType\f$ -template constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } ///< \returns The value of \f$\sqrt{10}\f$ with the highest precision for \f$genType\f$ -template constexpr genType one_over_sqrt_two() { return 0.70710678118654752440084436210484903928483593768847; } ///< \returns The value of \f$\frac{1}{\sqrt{2}}\f$ with the highest precision for \f$genType\f$ -template constexpr genType one_over_sqrt_three() { return 0.57735026918962576450914878050195745564760175127012; } ///< \returns The value of \f$\frac{1}{\sqrt{3}}\f$ with the highest precision for \f$genType\f$ -template constexpr genType one_over_sqrt_five() { return 0.44721359549995793928183473374625524708812367192230; } ///< \returns The value of \f$\frac{1}{\sqrt{5}}\f$ with the highest precision for \f$genType\f$ -template constexpr genType cbrt_two() { return 1.25992104989487316476721060727822835057025146470150; } ///< \returns The value of \f$\sqrt[3]{2}\f$ with the highest precision for \f$genType\f$ -template constexpr genType qdrt_two() { return 1.18920711500272106671749997056047591529297209246381; } ///< \returns The value of \f$\sqrt[4]{2}\f$ with the highest precision for \f$genType\f$ -template constexpr genType two_raised_sqrt_two() { return 2.66514414269022518865029724987313984827421131371465; } ///< \returns The value of \f${2}^{\sqrt{2}}\f$ with the highest precision for \f$genType\f$ +template constexpr genType one_third() { return 0.33333333333333333333333333333333333333333333333333; } //!< \returns The value of \f$\frac{1}{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType two_thirds() { return 0.66666666666666666666666666666666666666666666666666; } //!< \returns The value of \f$\frac{2}{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } //!< \returns The value of \f$\sqrt{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } //!< \returns The value of \f$\sqrt{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } //!< \returns The value of \f$\sqrt{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } //!< \returns The value of \f$\sqrt{7}\f$ with the highest precision for \f$genType\f$ +template constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } //!< \returns The value of \f$\sqrt{10}\f$ with the highest precision for \f$genType\f$ +template constexpr genType one_over_sqrt_two() { return 0.70710678118654752440084436210484903928483593768847; } //!< \returns The value of \f$\frac{1}{\sqrt{2}}\f$ with the highest precision for \f$genType\f$ +template constexpr genType one_over_sqrt_three() { return 0.57735026918962576450914878050195745564760175127012; } //!< \returns The value of \f$\frac{1}{\sqrt{3}}\f$ with the highest precision for \f$genType\f$ +template constexpr genType one_over_sqrt_five() { return 0.44721359549995793928183473374625524708812367192230; } //!< \returns The value of \f$\frac{1}{\sqrt{5}}\f$ with the highest precision for \f$genType\f$ +template constexpr genType cbrt_two() { return 1.25992104989487316476721060727822835057025146470150; } //!< \returns The value of \f$\sqrt[3]{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType qdrt_two() { return 1.18920711500272106671749997056047591529297209246381; } //!< \returns The value of \f$\sqrt[4]{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType two_raised_sqrt_two() { return 2.66514414269022518865029724987313984827421131371465; } //!< \returns The value of \f${2}^{\sqrt{2}}\f$ with the highest precision for \f$genType\f$ // Pi ================================================================================================================== // Pi & Tau -template constexpr genType pi() { return 3.14159265358979323846264338327950288419716939937510; } ///< \returns The value of \f$\pi\f$ with the highest precision for \f$genType\f$ -template constexpr genType tau() { return 6.28318530717958647692528676655900576839433879875021; } ///< \returns The value of \f$\tau\f$ with the highest precision for \f$genType\f$ +template constexpr genType pi() { return 3.14159265358979323846264338327950288419716939937510; } //!< \returns The value of \f$\pi\f$ with the highest precision for \f$genType\f$ +template constexpr genType tau() { return 6.28318530717958647692528676655900576839433879875021; } //!< \returns The value of \f$\tau\f$ with the highest precision for \f$genType\f$ // Multiples of Pi -template constexpr genType two_pi() { return 6.28318530717958647692528676655900576839433879875021; } ///< \returns The value of \f$2\pi\f$ with the highest precision for \f$genType\f$ -template constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } ///< \returns The value of \f$3\pi\f$ with the highest precision for \f$genType\f$ -template constexpr genType four_pi() { return 12.56637061435917295385057353311801153678867759750042; } ///< \returns The value of \f$4\pi\f$ with the highest precision for \f$genType\f$ +template constexpr genType two_pi() { return 6.28318530717958647692528676655900576839433879875021; } //!< \returns The value of \f$2\pi\f$ with the highest precision for \f$genType\f$ +template constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } //!< \returns The value of \f$3\pi\f$ with the highest precision for \f$genType\f$ +template constexpr genType four_pi() { return 12.56637061435917295385057353311801153678867759750042; } //!< \returns The value of \f$4\pi\f$ with the highest precision for \f$genType\f$ // Fractions of Pi -template constexpr genType half_pi() { return 1.57079632679489661923132169163975144209858469968755; } ///< \returns The value of \f$\frac{\pi}{2}\f$ with the highest precision for \f$genType\f$ -template constexpr genType three_halves_pi() { return 4.71238898038468985769396507491925432629575409906265; } ///< \returns The value of \f$\frac{3\pi}{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType half_pi() { return 1.57079632679489661923132169163975144209858469968755; } //!< \returns The value of \f$\frac{\pi}{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType three_halves_pi() { return 4.71238898038468985769396507491925432629575409906265; } //!< \returns The value of \f$\frac{3\pi}{2}\f$ with the highest precision for \f$genType\f$ -template constexpr genType third_pi() { return 1.04719755119659774615421446109316762806572313312503; } ///< \returns The value of \f$\frac{\pi}{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType two_thirds_pi() { return 2.09439510239319549230842892218633525613144626625007; } ///< \returns The value of \f$\frac{2\pi}{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType four_thirds_pi() { return 4.18879020478639098461685784437267051226289253250014; } ///< \returns The value of \f$\frac{4\pi}{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType five_thirds_pi() { return 5.23598775598298873077107230546583814032861566562517; } ///< \returns The value of \f$\frac{5\pi}{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType third_pi() { return 1.04719755119659774615421446109316762806572313312503; } //!< \returns The value of \f$\frac{\pi}{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType two_thirds_pi() { return 2.09439510239319549230842892218633525613144626625007; } //!< \returns The value of \f$\frac{2\pi}{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType four_thirds_pi() { return 4.18879020478639098461685784437267051226289253250014; } //!< \returns The value of \f$\frac{4\pi}{3}\f$ with the highest precision for \f$genType\f$ +template constexpr genType five_thirds_pi() { return 5.23598775598298873077107230546583814032861566562517; } //!< \returns The value of \f$\frac{5\pi}{3}\f$ with the highest precision for \f$genType\f$ -template constexpr genType quarter_pi() { return 0.78539816339744830961566084581987572104929234984377; } ///< \returns The value of \f$\frac{\pi}{4}\f$ with the highest precision for \f$genType\f$ -template constexpr genType three_quarters_pi() { return 2.35619449019234492884698253745962716314787704953132; } ///< \returns The value of \f$\frac{3\pi}{4}\f$ with the highest precision for \f$genType\f$ -template constexpr genType five_quarters_pi() { return 3.92699081698724154807830422909937860524646174921888; } ///< \returns The value of \f$\frac{5\pi}{4}\f$ with the highest precision for \f$genType\f$ -template constexpr genType seven_quarters_pi() { return 5.49778714378213816730962592073913004734504644890643; } ///< \returns The value of \f$\frac{7\pi}{4}\f$ with the highest precision for \f$genType\f$ +template constexpr genType quarter_pi() { return 0.78539816339744830961566084581987572104929234984377; } //!< \returns The value of \f$\frac{\pi}{4}\f$ with the highest precision for \f$genType\f$ +template constexpr genType three_quarters_pi() { return 2.35619449019234492884698253745962716314787704953132; } //!< \returns The value of \f$\frac{3\pi}{4}\f$ with the highest precision for \f$genType\f$ +template constexpr genType five_quarters_pi() { return 3.92699081698724154807830422909937860524646174921888; } //!< \returns The value of \f$\frac{5\pi}{4}\f$ with the highest precision for \f$genType\f$ +template constexpr genType seven_quarters_pi() { return 5.49778714378213816730962592073913004734504644890643; } //!< \returns The value of \f$\frac{7\pi}{4}\f$ with the highest precision for \f$genType\f$ -template constexpr genType fifth_pi() { return 0.62831853071795864769252867665590057683943387987502; } ///< \returns The value of \f$\frac{\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType two_fifths_pi() { return 1.25663706143591729538505735331180115367886775975004; } ///< \returns The value of \f$\frac{2\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType three_fifths_pi() { return 1.88495559215387594307758602996770173051830163962506; } ///< \returns The value of \f$\frac{3\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType four_fifths_pi() { return 2.51327412287183459077011470662360230735773551950008; } ///< \returns The value of \f$\frac{4\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType six_fifths_pi() { return 3.76991118430775188615517205993540346103660327925012; } ///< \returns The value of \f$\frac{6\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType seven_fifths_pi() { return 4.39822971502571053384770073659130403787603715912514; } ///< \returns The value of \f$\frac{7\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType eight_fifths_pi() { return 5.02654824574366918154022941324720461471547103900016; } ///< \returns The value of \f$\frac{8\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType nine_fifths_pi() { return 5.65486677646162782923275808990310519155490491887519; } ///< \returns The value of \f$\frac{9\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType fifth_pi() { return 0.62831853071795864769252867665590057683943387987502; } //!< \returns The value of \f$\frac{\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType two_fifths_pi() { return 1.25663706143591729538505735331180115367886775975004; } //!< \returns The value of \f$\frac{2\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType three_fifths_pi() { return 1.88495559215387594307758602996770173051830163962506; } //!< \returns The value of \f$\frac{3\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType four_fifths_pi() { return 2.51327412287183459077011470662360230735773551950008; } //!< \returns The value of \f$\frac{4\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType six_fifths_pi() { return 3.76991118430775188615517205993540346103660327925012; } //!< \returns The value of \f$\frac{6\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType seven_fifths_pi() { return 4.39822971502571053384770073659130403787603715912514; } //!< \returns The value of \f$\frac{7\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType eight_fifths_pi() { return 5.02654824574366918154022941324720461471547103900016; } //!< \returns The value of \f$\frac{8\pi}{5}\f$ with the highest precision for \f$genType\f$ +template constexpr genType nine_fifths_pi() { return 5.65486677646162782923275808990310519155490491887519; } //!< \returns The value of \f$\frac{9\pi}{5}\f$ with the highest precision for \f$genType\f$ -template constexpr genType sixth_pi() { return 0.52359877559829887307710723054658381403286156656251; } ///< \returns The value of \f$\frac{\pi}{6}\f$ with the highest precision for \f$genType\f$ -template constexpr genType five_sixths_pi() { return 2.61799387799149436538553615273291907016430783281258; } ///< \returns The value of \f$\frac{5\pi}{6}\f$ with the highest precision for \f$genType\f$ -template constexpr genType seven_sixths_pi() { return 3.66519142918809211153975061382608669823003096593762; } ///< \returns The value of \f$\frac{7\pi}{6}\f$ with the highest precision for \f$genType\f$ -template constexpr genType eleven_sixths_pi() { return 5.75958653158128760384817953601242195436147723218769; } ///< \returns The value of \f$\frac{11\pi}{6}\f$ with the highest precision for \f$genType\f$ +template constexpr genType sixth_pi() { return 0.52359877559829887307710723054658381403286156656251; } //!< \returns The value of \f$\frac{\pi}{6}\f$ with the highest precision for \f$genType\f$ +template constexpr genType five_sixths_pi() { return 2.61799387799149436538553615273291907016430783281258; } //!< \returns The value of \f$\frac{5\pi}{6}\f$ with the highest precision for \f$genType\f$ +template constexpr genType seven_sixths_pi() { return 3.66519142918809211153975061382608669823003096593762; } //!< \returns The value of \f$\frac{7\pi}{6}\f$ with the highest precision for \f$genType\f$ +template constexpr genType eleven_sixths_pi() { return 5.75958653158128760384817953601242195436147723218769; } //!< \returns The value of \f$\frac{11\pi}{6}\f$ with the highest precision for \f$genType\f$ // Reciprocals of Pi -template constexpr genType one_over_pi() { return 0.31830988618379067153776752674502872406891929148091; } ///< \returns The value of \f$\frac{1}{\pi}\f$ with the highest precision for \f$genType\f$ -template constexpr genType two_over_pi() { return 0.63661977236758134307553505349005744813783858296182; } ///< \returns The value of \f$\frac{2}{\pi}\f$ with the highest precision for \f$genType\f$ +template constexpr genType one_over_pi() { return 0.31830988618379067153776752674502872406891929148091; } //!< \returns The value of \f$\frac{1}{\pi}\f$ with the highest precision for \f$genType\f$ +template constexpr genType two_over_pi() { return 0.63661977236758134307553505349005744813783858296182; } //!< \returns The value of \f$\frac{2}{\pi}\f$ with the highest precision for \f$genType\f$ // Exponentiations Pi -template constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } ///< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$ -template constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } ///< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } //!< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$ +template constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } //!< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$ template constexpr genType sqrt_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \f$\sqrt{\pi}\f$ with the highest precision for \f$genType\f$ template constexpr genType one_over_sqrt_pi() { return 0.56418958354775628694807945156077258584405062932899; } ///< \returns The value of \f$\frac{1}{\sqrt{\pi}}\f$ with the highest precision for \f$genType\f$ template constexpr genType sqrt_two_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \f$\sqrt{2\pi}\f$ with the highest precision for \f$genType\f$ diff --git a/include/fennec/math/matrix.h b/include/fennec/math/matrix.h index 9ea7e1f..c0b27b2 100644 --- a/include/fennec/math/matrix.h +++ b/include/fennec/math/matrix.h @@ -43,7 +43,7 @@ /// /// -#include +#include #include #include @@ -78,43 +78,43 @@ constexpr vec row(const matrix& template -using tmat2x2 = mat; ///< helper for creating 2x2 matrices of the specified type. -template using tmat2x3 = mat; ///< helper for creating 2x3 matrices of the specified type. -template using tmat2x4 = mat; ///< helper for creating 2x4 matrices of the specified type. -template using tmat3x2 = mat; ///< helper for creating 3x2 matrices of the specified type. -template using tmat3x3 = mat; ///< helper for creating 3x3 matrices of the specified type. -template using tmat3x4 = mat; ///< helper for creating 3x4 matrices of the specified type. -template using tmat4x2 = mat; ///< helper for creating 4x2 matrices of the specified type. -template using tmat4x3 = mat; ///< helper for creating 4x3 matrices of the specified type. -template using tmat4x4 = mat; ///< helper for creating 4x4 matrices of the specified type. +using tmat2x2 = mat; //!< helper for creating 2x2 matrices of the specified type. +template using tmat2x3 = mat; //!< helper for creating 2x3 matrices of the specified type. +template using tmat2x4 = mat; //!< helper for creating 2x4 matrices of the specified type. +template using tmat3x2 = mat; //!< helper for creating 3x2 matrices of the specified type. +template using tmat3x3 = mat; //!< helper for creating 3x3 matrices of the specified type. +template using tmat3x4 = mat; //!< helper for creating 3x4 matrices of the specified type. +template using tmat4x2 = mat; //!< helper for creating 4x2 matrices of the specified type. +template using tmat4x3 = mat; //!< helper for creating 4x3 matrices of the specified type. +template using tmat4x4 = mat; //!< helper for creating 4x4 matrices of the specified type. -using mat2 = tmat2x2; ///< Specification for glsl float matrices -using mat3 = tmat3x3; ///< Specification for glsl float matrices -using mat4 = tmat4x4; ///< Specification for glsl float matrices +using mat2 = tmat2x2; //!< Specification for glsl float matrices +using mat3 = tmat3x3; //!< Specification for glsl float matrices +using mat4 = tmat4x4; //!< Specification for glsl float matrices -using mat2x2 = tmat2x2; ///< Specification for sized glsl float matrices -using mat2x3 = tmat2x3; ///< Specification for sized glsl float matrices -using mat2x4 = tmat2x4; ///< Specification for sized glsl float matrices -using mat3x2 = tmat3x2; ///< Specification for sized glsl float matrices -using mat3x3 = tmat3x3; ///< Specification for sized glsl float matrices -using mat3x4 = tmat3x4; ///< Specification for sized glsl float matrices -using mat4x2 = tmat4x2; ///< Specification for sized glsl float matrices -using mat4x3 = tmat4x3; ///< Specification for sized glsl float matrices -using mat4x4 = tmat4x4; ///< Specification for sized glsl float matrices +using mat2x2 = tmat2x2; //!< Specification for sized glsl float matrices +using mat2x3 = tmat2x3; //!< Specification for sized glsl float matrices +using mat2x4 = tmat2x4; //!< Specification for sized glsl float matrices +using mat3x2 = tmat3x2; //!< Specification for sized glsl float matrices +using mat3x3 = tmat3x3; //!< Specification for sized glsl float matrices +using mat3x4 = tmat3x4; //!< Specification for sized glsl float matrices +using mat4x2 = tmat4x2; //!< Specification for sized glsl float matrices +using mat4x3 = tmat4x3; //!< Specification for sized glsl float matrices +using mat4x4 = tmat4x4; //!< Specification for sized glsl float matrices -using dmat2 = tmat2x2; ///< Specification for glsl double matrices -using dmat3 = tmat3x3; ///< Specification for glsl double matrices -using dmat4 = tmat3x3; ///< Specification for glsl double matrices +using dmat2 = tmat2x2; //!< Specification for glsl double matrices +using dmat3 = tmat3x3; //!< Specification for glsl double matrices +using dmat4 = tmat3x3; //!< Specification for glsl double matrices -using dmat2x2 = tmat2x2; ///< Specification for size glsl double matrices -using dmat2x3 = tmat2x3; ///< Specification for size glsl double matrices -using dmat2x4 = tmat2x4; ///< Specification for size glsl double matrices -using dmat3x2 = tmat3x2; ///< Specification for size glsl double matrices -using dmat3x3 = tmat3x3; ///< Specification for size glsl double matrices -using dmat3x4 = tmat3x4; ///< Specification for size glsl double matrices -using dmat4x2 = tmat4x2; ///< Specification for size glsl double matrices -using dmat4x3 = tmat4x3; ///< Specification for size glsl double matrices -using dmat4x4 = tmat4x4; ///< Specification for size glsl double matrices +using dmat2x2 = tmat2x2; //!< Specification for size glsl double matrices +using dmat2x3 = tmat2x3; //!< Specification for size glsl double matrices +using dmat2x4 = tmat2x4; //!< Specification for size glsl double matrices +using dmat3x2 = tmat3x2; //!< Specification for size glsl double matrices +using dmat3x3 = tmat3x3; //!< Specification for size glsl double matrices +using dmat3x4 = tmat3x4; //!< Specification for size glsl double matrices +using dmat4x2 = tmat4x2; //!< Specification for size glsl double matrices +using dmat4x3 = tmat4x3; //!< Specification for size glsl double matrices +using dmat4x4 = tmat4x4; //!< Specification for size glsl double matrices /// @@ -676,7 +676,7 @@ struct matrix -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== public: diff --git a/include/fennec/math/scalar.h b/include/fennec/math/scalar.h index 7e0d950..e14bb44 100644 --- a/include/fennec/math/scalar.h +++ b/include/fennec/math/scalar.h @@ -59,7 +59,7 @@ #include -#include +#include #include namespace fennec diff --git a/include/fennec/math/swizzle.h b/include/fennec/math/swizzle.h index 9f717b7..7267529 100644 --- a/include/fennec/math/swizzle.h +++ b/include/fennec/math/swizzle.h @@ -68,10 +68,10 @@ public: /// /// \name aliases for the size /// @{ - inline static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle - inline static constexpr size_t num_components = sizeof...(IndicesV); ///< \brief number of components - inline static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle - inline static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle + inline static constexpr size_t dimension = sizeof...(IndicesV); //!< \brief dimension of the swizzle + inline static constexpr size_t num_components = sizeof...(IndicesV); //!< \brief number of components + inline static constexpr size_t size = sizeof...(IndicesV); //!< \brief size of the swizzle + inline static constexpr size_t N = sizeof...(IndicesV); //!< \brief size of the swizzle /// @} /// diff --git a/include/fennec/math/vector.h b/include/fennec/math/vector.h index 5fc988c..b638056 100644 --- a/include/fennec/math/vector.h +++ b/include/fennec/math/vector.h @@ -104,7 +104,7 @@ /// #include -#include +#include #include #include @@ -146,31 +146,31 @@ template using tvec4 = vec; -using bvec2 = tvec2; ///< \brief A two-component boolean \ref fennec_math_vector "vector" -using bvec3 = tvec3; ///< \brief A three-component boolean \ref fennec_math_vector "vector" -using bvec4 = tvec4; ///< \brief A four-component boolean \ref fennec_math_vector "vector" +using bvec2 = tvec2; //!< \brief A two-component boolean \ref fennec_math_vector "vector" +using bvec3 = tvec3; //!< \brief A three-component boolean \ref fennec_math_vector "vector" +using bvec4 = tvec4; //!< \brief A four-component boolean \ref fennec_math_vector "vector" -using ivec2 = tvec2; ///< \brief A two-component signed integer \ref fennec_math_vector "vector" -using ivec3 = tvec3; ///< \brief A three-component signed integer \ref fennec_math_vector "vector" -using ivec4 = tvec4; ///< \brief A four-component signed integer \ref fennec_math_vector "vector" +using ivec2 = tvec2; //!< \brief A two-component signed integer \ref fennec_math_vector "vector" +using ivec3 = tvec3; //!< \brief A three-component signed integer \ref fennec_math_vector "vector" +using ivec4 = tvec4; //!< \brief A four-component signed integer \ref fennec_math_vector "vector" -using uvec2 = tvec2; ///< \brief A two-component unsigned integer \ref fennec_math_vector "vector" -using uvec3 = tvec3; ///< \brief A three-component unsigned integer \ref fennec_math_vector "vector" -using uvec4 = tvec4; ///< \brief A four-component unsigned integer \ref fennec_math_vector "vector" +using uvec2 = tvec2; //!< \brief A two-component unsigned integer \ref fennec_math_vector "vector" +using uvec3 = tvec3; //!< \brief A three-component unsigned integer \ref fennec_math_vector "vector" +using uvec4 = tvec4; //!< \brief A four-component unsigned integer \ref fennec_math_vector "vector" using vec2 = tvec2; -///< \brief A two-component single-precision floating-point \ref fennec_math_vector "vector" +//!< \brief A two-component single-precision floating-point \ref fennec_math_vector "vector" using vec3 = tvec3; -///< \brief A three-component single-precision floating-point \ref fennec_math_vector "vector" +//!< \brief A three-component single-precision floating-point \ref fennec_math_vector "vector" using vec4 = tvec4; -///< \brief A four-component single-precision floating-point \ref fennec_math_vector "vector" +//!< \brief A four-component single-precision floating-point \ref fennec_math_vector "vector" using dvec2 = tvec2; -///< \brief A two-component double-precision floating-point \ref fennec_math_vector "vector" +//!< \brief A two-component double-precision floating-point \ref fennec_math_vector "vector" using dvec3 = tvec3; -///< \brief A three-component double-precision floating-point \ref fennec_math_vector "vector" +//!< \brief A three-component double-precision floating-point \ref fennec_math_vector "vector" using dvec4 = tvec4; -///< \brief A four-component double-precision floating-point \ref fennec_math_vector "vector" +//!< \brief A four-component double-precision floating-point \ref fennec_math_vector "vector" /// @@ -186,9 +186,21 @@ struct vector : detail::vector_base_type static_assert(is_arithmetic_v); -// Forward Defs ======================================================================================================== +// Definitions & Constants ============================================================================================= - /// \name Forward Definitions & Constants + + /// \name Constants + /// @{ + + static constexpr size_t dimension = sizeof...(IndicesV); //!< \brief dimension of the swizzle + static constexpr size_t num_components = sizeof...(IndicesV); //!< \brief number of components + static constexpr size_t size = sizeof...(IndicesV); //!< \brief size of the swizzle + static constexpr size_t N = sizeof...(IndicesV); //!< \brief size of the swizzle + + /// @} + + + /// \name Definitions /// @{ /// @@ -207,14 +219,8 @@ struct vector : detail::vector_base_type /// \brief alias for this type using vector_t = vector; - // Size Aliases - static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle - static constexpr size_t num_components = sizeof...(IndicesV); ///< \brief number of components - static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle - static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle - using decay_t = conditional_t; - ///< Type that the \ref fennec_math_vector "vector" should Decay into + //!< Type that the \ref fennec_math_vector "vector" should Decay into /// @} @@ -362,9 +368,9 @@ struct vector : detail::vector_base_type /// @} -// Public Member Functions ============================================================================================= +// Utility Functions =================================================================================================== - /// \name Public Member Functions + /// \name Utility Functions /// @{ /// @@ -1096,7 +1102,7 @@ struct vector : detail::vector_base_type /// @} -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== private: template diff --git a/include/fennec/math/vector_base.h b/include/fennec/math/vector_base.h index 44e1036..1460fac 100644 --- a/include/fennec/math/vector_base.h +++ b/include/fennec/math/vector_base.h @@ -20,7 +20,7 @@ #ifndef FENNEC_MATH_VECTOR_BASE_H #define FENNEC_MATH_VECTOR_BASE_H -#include +#include #include #include diff --git a/include/fennec/memory/allocator.h b/include/fennec/memory/allocator.h index 4366692..ed29331 100644 --- a/include/fennec/memory/allocator.h +++ b/include/fennec/memory/allocator.h @@ -334,9 +334,14 @@ public: /// initialize any values as if they were the provided data type. Any operations present work /// only on individual bytes. template> -struct allocation -{ +struct allocation { + +// Definitions ========================================================================================================= public: + + /// \name Definitions + /// @{ + /// \brief alias for the allocator type using alloc_t = typename allocator_traits::template rebind; @@ -349,8 +354,14 @@ public: /// \brief diff type definition for ptr_traits using diff_t = ptrdiff_t; + /// @} - // Cosntructors ======================================================================================================== + +// Constructors & Destructor =========================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ /// /// \brief Default Constructor, initializes internal data to \f$null\f$ and the capacity to \f$0\f$ @@ -363,7 +374,7 @@ public: /// \param n The number of elements of type \f$T\f$ to allocate for explicit constexpr allocation(size_t n) noexcept : _data(nullptr), _capacity(0), _alignment(zero()) { - callocate(n); + allocate(n); } /// @@ -384,7 +395,7 @@ public: : _data(nullptr) , _capacity(0) , _alignment(align) { - callocate(n, align); + allocate(n, align); } /// @@ -421,7 +432,7 @@ public: , _data(nullptr) , _capacity(0) , _alignment(zero()) { - callocate(n); + allocate(n); } /// @@ -449,7 +460,7 @@ public: , _data(nullptr) , _capacity(0) , _alignment(zero()) { - callocate(n, align); + allocate(n, align); } /// @@ -499,8 +510,14 @@ public: } } + /// @} + // Assignment ========================================================================================================== +public: + + /// \name Assignment + /// @{ /// /// \brief Copy Assignment Operator @@ -527,12 +544,49 @@ public: return *this; } + /// @} -// Allocation and Deallocation ========================================================================================= + +// Properties ========================================================================================================== +public: + + /// \name Properties + /// @{ + + /// + /// \brief Getter for the byte size of the allocation. + /// \returns the size of the allocation in bytes + constexpr size_t size() const { + return _capacity * sizeof(T); + } + + /// + /// \brief Getter for the number of elements \f$n\f$ of type \f$T\f$ that the allocation can hold. + /// \returns the size of the allocation in elements + constexpr size_t capacity() const { + return _capacity; + } + + /// + /// \brief Getter for the alignment of the allocation. + /// \returns the alignment of the allocation + constexpr align_t alignment() const { + return _alignment; + } + + /// @} + + +// Modifiers =========================================================================================================== +public: + + /// \name Modifiers + /// @{ /// /// \brief Allocate a block of memory for the allocation. - /// If there is already an allocated block of memory, the previous allocation is released. + /// \details If there is already an allocated block of memory, the previous allocation is released. + /// /// /// \param n The number of elements of type \f$T\f$ to allocate for /// \param align The alignment to use @@ -546,17 +600,6 @@ public: } } - /// - /// \brief Allocate a block of memory for the allocation. - /// If there is already an allocated block of memory, the previous allocation is released. - /// - /// \param n The number of elements of type \f$T\f$ to allocate for - /// \param align The alignment to use - constexpr void callocate(size_t n, align_t align = zero()) noexcept { - allocate(n, align); - fennec::memset(static_cast(_data), 0, _capacity * sizeof(T)); - } - /// /// \brief Release the block of memory. constexpr void deallocate() noexcept { @@ -596,33 +639,19 @@ public: } /// - /// \brief Reallocate the block with a new size. - /// Contents are copied to the new allocation. - /// - /// \param n The number of elements of type \f$T\f$ to allocate for - /// \param align The alignment to use - constexpr void creallocate(size_t n, align_t align = zero()) noexcept { - if (_data == nullptr) { - callocate(n, align); - return; - } - - value_t* old = _data; size_t old_cap = _capacity; - _data = nullptr; - allocate(n, align); - - fennec::memmove(static_cast(_data), old, min(_capacity, old_cap) * sizeof(T)); - - if (_capacity > old_cap) { - fennec::memset(static_cast(_data + old_cap), 0, _capacity - old_cap); - } - - _alloc.deallocate(old); - _capacity = n; + /// \brief Clear the block of memory, setting all bytes to 0. + constexpr void clear() noexcept { + fennec::memset(static_cast(_data), 0, _capacity * sizeof(T)); } + /// @} + // Access ============================================================================================================== +public: + + /// \name Access + /// @{ /// /// \param i The index to access @@ -654,55 +683,6 @@ public: return _data; } - /// - /// \returns A pointer to the start of the allocation. - value_t* begin() { - return _data; - } - - /// - /// \brief Iterator Begin - /// \returns A pointer to the start of the allocation. - const value_t* begin() const { - return _data; - } - - /// - /// \returns A pointer to the element one after the last. - value_t* end() { - return _data + capacity(); - } - - /// - /// \brief Iterator End - /// \returns A pointer to the element one after the last. - const value_t* end() const { - return _data + capacity(); - } - - -// Modification ======================================================================================================== - - /// - /// \brief Clear the block of memory, setting all bytes to 0. - constexpr void clear() noexcept { - fennec::memset(static_cast(_data), 0, _capacity * sizeof(T)); - } - - /// - /// \brief Getter for the byte size of the allocation. - /// \returns the size of the allocation in bytes - constexpr size_t size() const { - return _capacity * sizeof(T); - } - - /// - /// \brief Getter for the number of elements \f$n\f$ of type \f$T\f$ that the allocation can hold. - /// \returns the size of the allocation in elements - constexpr size_t capacity() const { - return _capacity; - } - /// /// \brief Getter for the real pointer to the allocated block of memory /// \returns Pointer to the allocated memory. @@ -718,12 +698,33 @@ public: } /// - /// \brief Getter for the alignment of the allocation. - /// \returns the alignment of the allocation - constexpr align_t alignment() const { - return _alignment; + /// \returns A pointer to the start of the allocation. + value_t* begin() { + return _data; } + /// + /// \brief C++ Iterator Begin + /// \returns A pointer to the start of the allocation. + const value_t* begin() const { + return _data; + } + + /// + /// \returns A pointer to the element one after the last. + value_t* end() { + return _data + capacity(); + } + + /// + /// \brief C++ Iterator End + /// \returns A pointer to the element one after the last. + const value_t* end() const { + return _data + capacity(); + } + + /// @} + private: alloc_t _alloc; // Allocator object value_t* _data; // Handle for the memory block diff --git a/include/fennec/memory/pointers.h b/include/fennec/memory/pointers.h index 5b0eb7a..896bf30 100644 --- a/include/fennec/memory/pointers.h +++ b/include/fennec/memory/pointers.h @@ -84,9 +84,14 @@ struct default_delete /// \tparam TypeT /// \tparam DeleteT template> -class unique_ptr -{ +class unique_ptr { + +// Definitions ========================================================================================================= public: + + /// \name Definitions + /// @{ + /// \brief the element type using element_t = TypeT; @@ -99,6 +104,15 @@ public: /// \brief the deleter using delete_t = DeleteT; + /// @} + + +// Constructors ======================================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ + /// /// \brief Default Constructor, creates a unique_ptr that owns nothing. constexpr unique_ptr() : unique_ptr(nullptr) {} @@ -140,7 +154,14 @@ public: reset(); } - constexpr unique_ptr& operator=(const unique_ptr&) = delete; + /// @} + + +// Assignment ========================================================================================================== +public: + + /// \name Assignment + /// @{ /// /// \brief move constructor @@ -152,6 +173,75 @@ public: return *this; } + /// @} + +private: + constexpr unique_ptr& operator=(const unique_ptr&) = delete; + + +// Properties ========================================================================================================== +public: + + /// \name Properties + /// @{ + + /// + /// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise + bool is_empty() { + return _handle == nullptr; + } + + /// + /// \brief implicit boolean conversion + /// \returns \f$true\f$ if there is a held pointer, \f$false\f$ otherwise + operator bool() const { + return _handle != nullptr; + } + + /// @} + + +// Access ============================================================================================================== +public: + + /// \name Access + /// @{ + + /// + /// \returns a reference to the held pointer + pointer_t get() const { + return _handle; + } + + /// + /// \returns the held object for access + pointer_t operator->() { + return _handle; + } + + /// + /// \brief access operator + /// \returns the held object for access + const_pointer_t operator->() const { + return _handle; + } + + /// + /// \brief dereference operator + /// \returns a reference to the held value + element_t& operator*() const { + return *_handle; + } + + /// @} + + +// Modifiers =========================================================================================================== +public: + + /// \name Modifiers + /// @{ + /// /// \brief reset the pointer, destroying the held object /// \param ptr the new pointer to own @@ -180,44 +270,7 @@ public: return retval; } - /// - /// \returns a reference to the held pointer - pointer_t get() const { - return _handle; - } - - /// - /// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise - bool is_empty() { - return _handle == nullptr; - } - - /// - /// \returns the held object for access - pointer_t operator->() { - return _handle; - } - - /// - /// \brief access operator - /// \returns the held object for access - const_pointer_t operator->() const { - return _handle; - } - - /// - /// \brief implicit boolean conversion - /// \returns \f$true\f$ if there is a held pointer, \f$false\f$ otherwise - operator bool() const { - return _handle != nullptr; - } - - /// - /// \brief dereference operator - /// \returns a reference to the held value - element_t& operator*() const { - return *_handle; - } + /// @} private: delete_t _delete; diff --git a/include/fennec/platform/interface/display_server.h b/include/fennec/platform/interface/display_server.h index 9ad9243..e4a1402 100644 --- a/include/fennec/platform/interface/display_server.h +++ b/include/fennec/platform/interface/display_server.h @@ -33,7 +33,7 @@ #include -#include +#include #include #include @@ -55,9 +55,12 @@ class display_server; /// must provide a constructor that accepts a `DisplayT*`. `DisplayT::ctx_registry::register_type` must then be /// called for the \f$gfxcontext\f$ implementation. class display_server : public type_registry { -// Typedefs/Constants/Enums ============================================================================================ +// Definitions & Constants ============================================================================================= public: + /// \name Definitions + /// @{ + /// /// \brief enum representing features to test support for against the display server enum feature_ : uint32_t { @@ -96,10 +99,20 @@ public: using featureset_t = bitfield; //!< a bitset holding the supported feature set + /// @} -// Public Members ====================================================================================================== + +// Public Member Variables ============================================================================================= +public: platform* const platform; //!< the parent platform + +// Constructors ======================================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ + /// /// \brief display server constructor /// \param p the parent platform @@ -109,8 +122,16 @@ public: /// /// \brief base destructor - virtual ~display_server() { - } + virtual ~display_server() = default; + + /// @} + + +// Properties ========================================================================================================== +public: + + /// \name Properties + /// @{ /// /// \brief feature support checking function @@ -120,6 +141,19 @@ public: return features.test(feature); } + /// + /// \returns \f$true\f$ if connected to the display server, \f$false\f$ otherwise + virtual bool connected() const = 0; + + /// @} + + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + /// /// \brief create a new window with the specified configuration and parent /// \param cfg the configuration @@ -135,10 +169,6 @@ public: /// \brief disconnect from the display server virtual void disconnect() = 0; - /// - /// \returns \f$true\f$ if connected to the display server, \f$false\f$ otherwise - virtual bool connected() const = 0; - /// /// \brief dispatch the current context to the display server virtual void dispatch() = 0; @@ -153,10 +183,14 @@ public: return gfx_context.get(); } + /// @} + +// Protected Member Variables ========================================================================================== protected: featureset_t features; //!< the feature set of the display server unique_ptr gfx_context; //!< the graphics context of the display server +private: FENNEC_RTTI_CLASS_ENABLE() { } }; diff --git a/include/fennec/platform/interface/fwd.h b/include/fennec/platform/interface/forward.h similarity index 91% rename from include/fennec/platform/interface/fwd.h rename to include/fennec/platform/interface/forward.h index 4fe78a8..c87e1b4 100644 --- a/include/fennec/platform/interface/fwd.h +++ b/include/fennec/platform/interface/forward.h @@ -16,8 +16,8 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_PLATFORM_INTERFACE_FWD_H -#define FENNEC_PLATFORM_INTERFACE_FWD_H +#ifndef FENNEC_PLATFORM_INTERFACE_FORWARD_H +#define FENNEC_PLATFORM_INTERFACE_FORWARD_H namespace fennec { @@ -31,4 +31,4 @@ class gfxsurface; // Handles the GFX surface of a window for a specific gfxc } -#endif // FENNEC_PLATFORM_INTERFACE_FWD_H +#endif // FENNEC_PLATFORM_INTERFACE_FORWARD_H diff --git a/include/fennec/platform/interface/platform.h b/include/fennec/platform/interface/platform.h index 62363a3..1abacd5 100644 --- a/include/fennec/platform/interface/platform.h +++ b/include/fennec/platform/interface/platform.h @@ -64,10 +64,25 @@ namespace fennec /// /// \brief Main platform class class platform : public singleton { + +// Definitions ========================================================================================================= public: + + /// \name Definitions + /// @{ + using shared_object = struct shared_object; //!< handle for shared object code using symbol = void*; //!< handle for a symbol loaded from a shared object + /// @} + + +// Constructors & Destructors ========================================================================================== +public: + + /// \name Constructors & Destructors + /// @{ + /// /// \brief constructor platform(); @@ -76,8 +91,31 @@ public: /// \brief destructor virtual ~platform() = default; + +private: platform(const platform&) = delete; + /// @} + + +// Initialization ====================================================================================================== +public: + + /// \name Initialization + /// @{ + + virtual void initialize(); //!< Initialize Drivers and Contexts + virtual void shutdown(); //!< Close Drivers and Contexts + + /// @} + + +// Shared Objects ====================================================================================================== +public: + + /// \name Shared Objects + /// @{ + /// /// \brief shared object linker /// \param file the name of the shared object to link @@ -96,10 +134,23 @@ public: /// \returns a reference to the symbol virtual symbol find_symbol(shared_object* obj, const cstring& name) = 0; - virtual void initialize(); //!< Initialize Drivers and Contexts - virtual void shutdown(); //!< Close Drivers and Contexts + /// @} - virtual window_manager& get_window_manager() const { return *wmanager; } + +// Window Management =================================================================================================== +public: + + /// \name Window Management + /// @{ + + /// + /// \brief Returns the window manager for the platform + /// \returns Reference to the window manager. + virtual window_manager& get_window_manager() const { + return *wmanager; + } + + /// @} protected: unique_ptr wmanager; //!< the window manager diff --git a/include/fennec/platform/interface/window.h b/include/fennec/platform/interface/window.h index bcabcd1..794b0d2 100644 --- a/include/fennec/platform/interface/window.h +++ b/include/fennec/platform/interface/window.h @@ -31,7 +31,7 @@ #ifndef FENNEC_PLATFORM_INTERFACE_WINDOW_H #define FENNEC_PLATFORM_INTERFACE_WINDOW_H -#include +#include #include @@ -49,6 +49,10 @@ namespace fennec class window { // Definitions ========================================================================================================= public: + + /// \name Definitions + /// @{ + /// /// \brief window mode enum mode_ : uint8_t { @@ -127,9 +131,15 @@ public: double_t fractional_scaling; //!< current fractional scaling factor }; + /// @} + // Constructors & Destructor =========================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ /// /// \brief window constructor @@ -142,9 +152,15 @@ public: /// \brief base destructor virtual ~window(); + /// @} + // Properties ========================================================================================================== +public: + + /// \name Properties + /// @{ /// /// \returns the current configuration of the window @@ -162,18 +178,33 @@ public: /// \returns the underlying handle of the window virtual void* get_native_handle() = 0; + /// @} + // Positional Info ===================================================================================================== +public: + + /// \name Screen Bounds + /// @{ /// /// \returns the size of the window - const ivec2& get_size() const { return state.rect.size; } + const ivec2& get_size() const { + return state.rect.size; + } /// /// \returns the position of the window - const ivec2& get_position() const { return state.rect.position; } + const ivec2& get_position() const { + return state.rect.position; + } + /// + /// \returns the bounds of the window + const irect& get_bounds() const { + return state.rect; + } /// /// \returns the width of the window @@ -191,9 +222,15 @@ public: /// \returns the y position of the window int get_pos_y() const { return state.rect.position.y; } + /// @} + // Status ============================================================================================================== +public: + + /// \name Status + /// @{ /// /// \brief tests if the window is visible @@ -215,9 +252,15 @@ public: /// \returns \f$true\f$ if the window is suspended, \f$false\f$ otherwise bool is_suspended() const { return state.flags.test(state_suspended); } + /// @} + // Behaviour =========================================================================================================== +public: + + /// \name Behaviour Flags + /// @{ /// /// \brief tests a specific flag @@ -234,12 +277,12 @@ public: /// /// \brief check if the window is flagged to have no window decorations /// \returns \f$true\f$ if set, \f$false\f$ otherwise - bool is_borderless() const { return get_flag(flag_borderless); } + bool is_borderless() const { return get_flag(flag_borderless); } /// /// \brief check if the window is flagged to be modal /// \returns \f$true\f$ if set, \f$false\f$ otherwise - bool is_modal() const { return get_flag(flag_modal); } + bool is_modal() const { return get_flag(flag_modal); } /// /// \brief check if the window is flagged to pass mouse input to windows underneath from the same application @@ -249,22 +292,22 @@ public: /// /// \brief check if the window is flagged as a popup /// \returns \f$true\f$ if set, \f$false\f$ otherwise - bool is_popup() const { return get_flag(flag_popup); } + bool is_popup() const { return get_flag(flag_popup); } /// /// \brief check if the window is flagged to be resizable /// \returns \f$true\f$ if set, \f$false\f$ otherwise - bool is_resizable() const { return get_flag(flag_resizable); } + bool is_resizable() const { return get_flag(flag_resizable); } /// /// \brief check if the window is flagged to be transparent /// \returns \f$true\f$ if set, \f$false\f$ otherwise - bool is_transparent() const { return get_flag(flag_transparent); } + bool is_transparent() const { return get_flag(flag_transparent); } /// /// \brief check if the window is flagged to be unfocusable /// \returns \f$true\f$ if set, \f$false\f$ otherwise - bool is_no_focus() const { return get_flag(flag_no_focus); } + bool is_no_focus() const { return get_flag(flag_no_focus); } /// @@ -284,48 +327,53 @@ public: /// \brief sets whether to have no window decorations /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_borderless(bool val) { return set_flag(flag_borderless, val); } + bool set_borderless(bool val) { return set_flag(flag_borderless, val); } /// /// \brief sets whether to be modal /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_modal(bool val) { return set_flag(flag_modal, val); } + bool set_modal(bool val) { return set_flag(flag_modal, val); } /// /// \brief sets whether to pass mouse input to windows underneath from the same application /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_passing_mouse(bool val) { return set_flag(flag_pass_mouse, val); } + bool set_passing_mouse(bool val) { return set_flag(flag_pass_mouse, val); } /// /// \brief sets whether the window is a popup /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_popup(bool val) { return set_flag(flag_popup, val); } + bool set_popup(bool val) { return set_flag(flag_popup, val); } /// /// \brief sets whether to be resizable /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_resizable(bool val) { return set_flag(flag_resizable, val); } + bool set_resizable(bool val) { return set_flag(flag_resizable, val); } /// /// \brief sets whetherto be transparent /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_transparent(bool val) { return set_flag(flag_transparent, val); } + bool set_transparent(bool val) { return set_flag(flag_transparent, val); } /// /// \brief sets whether to be unfocusable /// \param val the value to set the flag to /// \returns \f$true\f$ on success, \f$false\f$ otherwise - bool set_no_focus(bool val) { return set_flag(flag_no_focus, val); } + bool set_no_focus(bool val) { return set_flag(flag_no_focus, val); } + + /// @} -// Window Management Functions ========================================================================================= +// Initialization & Update ============================================================================================= +public: + /// \name Initialization & Update + /// @{ virtual void initialize() = 0; //!< initialization function virtual void shutdown() = 0; //!< shutdown function @@ -333,6 +381,10 @@ public: virtual void begin_frame(); //!< start a frame for the window, setting the correct graphics context virtual void end_frame(); //!< end a frame for the window, swapping the underlying buffers + /// @} + + +// Protected Member Variables ========================================================================================== protected: display_server* const server; //!< the display server the window belongs to window* const parent; //!< the parent window diff --git a/include/fennec/platform/linux/platform.h b/include/fennec/platform/linux/platform.h index cc1404e..20a1596 100644 --- a/include/fennec/platform/linux/platform.h +++ b/include/fennec/platform/linux/platform.h @@ -24,12 +24,23 @@ namespace fennec { class linux_platform : public unix_platform { + +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor ================================================================================ + /// @{ + /// \brief constructor linux_platform() : unix_platform() { } + /// @} + + +// + void initialize() override; //!< platform initialization void shutdown() override; //!< platform shutdown diff --git a/include/fennec/platform/linux/wayland/egl/context.h b/include/fennec/platform/linux/wayland/egl/context.h index c756ad3..e96878d 100644 --- a/include/fennec/platform/linux/wayland/egl/context.h +++ b/include/fennec/platform/linux/wayland/egl/context.h @@ -40,7 +40,12 @@ namespace fennec /// /// \brief wayland egl context class wayland_eglcontext : public eglcontext { +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + /// \brief constructor /// \param display the display server explicit wayland_eglcontext(display_server* display); @@ -48,11 +53,23 @@ public: /// \brief destructor ~wayland_eglcontext(); + /// @} + + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + /// \brief create a surface for a window /// \param window the window /// \returns a new surface for the window gfxsurface* create_surface(window* window) override; + /// @} + +// Private Member Variables ============================================================================================ private: FENNEC_RTTI_CLASS_ENABLE(eglcontext) { wayland_server::ctx_registry::register_type(); diff --git a/include/fennec/platform/linux/wayland/egl/surface.h b/include/fennec/platform/linux/wayland/egl/surface.h index 4213719..518d7e9 100644 --- a/include/fennec/platform/linux/wayland/egl/surface.h +++ b/include/fennec/platform/linux/wayland/egl/surface.h @@ -33,7 +33,7 @@ #define LATFORM_LINUX_WAYLAND_EGL_SURFACE_H #include -#include +#include namespace fennec { @@ -41,7 +41,13 @@ namespace fennec /// /// \brief wayland egl surface class wayland_eglsurface : public eglsurface { + +// Constructors ======================================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + /// \brief constructor /// \param win the wayland window /// \param ctx the egl context @@ -50,10 +56,22 @@ public: /// \brief destructor ~wayland_eglsurface(); + /// @} + + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + + /// /// \brief resize the surface /// \param size the new size void resize(const ivec2& size) override; + /// @} + private: }; diff --git a/include/fennec/platform/linux/wayland/fwd.h b/include/fennec/platform/linux/wayland/forward.h similarity index 86% rename from include/fennec/platform/linux/wayland/fwd.h rename to include/fennec/platform/linux/wayland/forward.h index 6c19b05..d397623 100644 --- a/include/fennec/platform/linux/wayland/fwd.h +++ b/include/fennec/platform/linux/wayland/forward.h @@ -17,7 +17,7 @@ // ===================================================================================================================== /// -/// \file fennec/platform/linux/wayland/fwd.h +/// \file fennec/platform/linux/wayland/forward.h /// \brief /// /// @@ -29,8 +29,8 @@ /// -#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H -#define FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H +#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H +#define FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H namespace fennec { @@ -40,4 +40,4 @@ class wayland_window; } -#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H \ No newline at end of file +#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H \ No newline at end of file diff --git a/include/fennec/platform/linux/wayland/server.h b/include/fennec/platform/linux/wayland/server.h index d98a5d1..c644cc4 100644 --- a/include/fennec/platform/linux/wayland/server.h +++ b/include/fennec/platform/linux/wayland/server.h @@ -31,7 +31,7 @@ #ifndef FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H #define FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H -#include +#include #include #if FENNEC_HAS_LIBDECOR @@ -56,7 +56,13 @@ namespace fennec /// /// \brief Class for handling the Wayland Display Server class wayland_server : public display_server_base { + +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + /// \brief constructor /// \param p the platform explicit wayland_server(fennec::platform* p); @@ -64,6 +70,15 @@ public: /// \brief destructor ~wayland_server() override; + /// @} + + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + void connect() override; //!< connect to wayland void disconnect() override; //!< disconnect from wayland bool connected() const override; //!< check if connected to wayland \returns \f$true\f$ if connected, \f$false\f$ otherwise @@ -79,8 +94,9 @@ public: /// \returns the native wl_display handle void* get_native_handle() override { return display; } + /// @} -// Fields ============================================================================================================== +// Private Member Variables ============================================================================================ private: wl_display* display; wl_registry* registry; @@ -96,6 +112,7 @@ private: // Listeners =========================================================================================================== +private: static void _wl_registry_listen_global(void*, wl_registry*, uint32_t, const char*, uint32_t); static void _wl_registry_on_global_remove(void*, wl_registry*, uint32_t); diff --git a/include/fennec/platform/linux/wayland/window.h b/include/fennec/platform/linux/wayland/window.h index f608ff6..ca87684 100644 --- a/include/fennec/platform/linux/wayland/window.h +++ b/include/fennec/platform/linux/wayland/window.h @@ -31,7 +31,7 @@ #ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H #define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H -#include +#include #include #ifndef FENNEC_DOXYGEN @@ -55,21 +55,32 @@ namespace fennec /// /// \brief Class for handling a Wayland window class wayland_window : public window_base { + +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + + /// /// \brief constructor /// \param server the display server /// \param cfg the configuration /// \param parent the parent window wayland_window(display_server* server, const config& cfg, window* parent); + /// /// \brief destructor ~wayland_window(); - void initialize() override; //!< initialize the window - void shutdown() override; //!< shutdown the window + /// @} - /// \returns the native wl_surface handle - void* get_native_handle() override; + +// Behaviour Flags ===================================================================================================== +public: + + /// \name Behaviour Flags + /// @{ /// /// \brief sets a specific flag @@ -78,8 +89,25 @@ public: /// \returns \f$true\f$ on success, \f$false\f$ otherwise bool set_flag(uint8_t flag, bool val) override; + /// @} -// Fields ============================================================================================================== + +// Initialization & Update ============================================================================================= +public: + + /// \name Initialization & Update + /// @{ + + void initialize() override; //!< initialize the window + void shutdown() override; //!< shutdown the window + + /// \returns the native wl_surface handle + void* get_native_handle() override; + + /// @} + + +// Private Member Variables ============================================================================================ private: wl_surface* surface; xdg_surface* xdgsurface; @@ -92,12 +120,13 @@ private: #endif -// Helpers ============================================================================================================= - +// Private Helpers ===================================================================================================== +private: void _update_size(const ivec2& size); // Listeners =========================================================================================================== +private: static void _wl_surface_listen_enter(void*, wl_surface*, wl_output*); static void _wl_surface_listen_leave(void*, wl_surface*, wl_output*); diff --git a/include/fennec/platform/opengl/egl/context.h b/include/fennec/platform/opengl/egl/context.h index 94484d1..c67bd2b 100644 --- a/include/fennec/platform/opengl/egl/context.h +++ b/include/fennec/platform/opengl/egl/context.h @@ -41,16 +41,31 @@ namespace fennec { +/// /// \brief base egl context with platform-independent behaviour class eglcontext : public glcontext { + +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + + /// /// \brief constructor /// \param display the corresponding display server eglcontext(display_server* display); + /// /// \brief destructor ~eglcontext(); + /// @} + + +// + + /// /// \returns \f$true\f$ if the context is valid, \f$false\f$ otherwise bool is_valid() override; diff --git a/include/fennec/platform/opengl/egl/fwd.h b/include/fennec/platform/opengl/egl/forward.h similarity index 87% rename from include/fennec/platform/opengl/egl/fwd.h rename to include/fennec/platform/opengl/egl/forward.h index af41c65..a441309 100644 --- a/include/fennec/platform/opengl/egl/fwd.h +++ b/include/fennec/platform/opengl/egl/forward.h @@ -17,7 +17,7 @@ // ===================================================================================================================== /// -/// \file fennec/platform/opengl/egl/fwd.h +/// \file fennec/platform/opengl/egl/forward.h /// \brief /// /// @@ -29,8 +29,8 @@ /// -#ifndef FENNEC_PLATFORM_OPENGL_EGL_FWD_H -#define FENNEC_PLATFORM_OPENGL_EGL_FWD_H +#ifndef FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H +#define FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H namespace fennec { @@ -40,4 +40,4 @@ class eglsurface; } -#endif // FENNEC_PLATFORM_OPENGL_EGL_FWD_H \ No newline at end of file +#endif // FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H \ No newline at end of file diff --git a/include/fennec/platform/opengl/egl/surface.h b/include/fennec/platform/opengl/egl/surface.h index 5b82d49..b7b1782 100644 --- a/include/fennec/platform/opengl/egl/surface.h +++ b/include/fennec/platform/opengl/egl/surface.h @@ -33,7 +33,7 @@ #define FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H #include -#include +#include #include @@ -42,17 +42,37 @@ namespace fennec { /// \brief base egl surface with platform-independent behaviour class eglsurface : public gfxsurface { + +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + /// \brief constructor /// \param win the associated window /// \param ctx the associated context /// \param eglwindow the create egl window eglsurface(fennec::window* win, eglcontext* ctx, void* eglwindow); + + /// + /// \brief Destructor ~eglsurface(); + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + void make_current() override; //!< makes this surface the current target of the context void swap() override; //!< swaps the front and back buffers + /// @} + + +// Protected Member Variables ========================================================================================== protected: void* _eglwindow; //!< the underlying handle to the window EGLSurface _eglsurface; //!< the handle for the surface diff --git a/include/fennec/platform/unix/platform.h b/include/fennec/platform/unix/platform.h index 05a8f65..2907ad7 100644 --- a/include/fennec/platform/unix/platform.h +++ b/include/fennec/platform/unix/platform.h @@ -25,13 +25,27 @@ namespace fennec { /// \brief base unix platform for generic unix functionality class unix_platform : public platform { +// Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + /// /// \brief constructor explicit unix_platform() : platform() { } + /// @} + + +// Shared Objects ====================================================================================================== +public: + + /// \name Shared Objects + /// @{ + /// /// \brief shared object linker /// \param file the name of the shared object to link @@ -50,7 +64,13 @@ public: /// \returns a reference to the symbol symbol find_symbol(shared_object* obj, const cstring& name) override; + /// @} + + +// Private Member Variables ============================================================================================ private: + + FENNEC_RTTI_CLASS_ENABLE(platform) { } }; diff --git a/include/fennec/platform/window_manager.h b/include/fennec/platform/window_manager.h index dfb2ace..affbe22 100644 --- a/include/fennec/platform/window_manager.h +++ b/include/fennec/platform/window_manager.h @@ -32,10 +32,11 @@ #ifndef FENNEC_PLATFORM_WINDOWMANAGER_H #define FENNEC_PLATFORM_WINDOWMANAGER_H -#include +#include #include #include +#include #include #include #include @@ -50,20 +51,33 @@ using window_id = size_t; //!< type representing an id for a window /// /// \brief class for handling display servers and windows class window_manager { -// Definitions ========================================================================================================= +// Definitions & Constants ============================================================================================= public: + + /// \name Constants + /// @{ + static constexpr window_id nullid = -1; //!< constant representing a null window + /// @} + private: enum command_ : uint8_t { command_set_flag = 0, command_resize }; + struct flag_val { + uint8_t index; + bool val; + }; + + using cmd_data_t = variant; + struct command { - uint8_t cmd; - window_id win; - void* data; + uint8_t cmd; + window_id win; + cmd_data_t data; }; static constexpr size_t max_commands = 512; @@ -78,6 +92,9 @@ private: // Constructors & Destructor =========================================================================================== public: + /// \name Constructors & Destructor + /// @{ + /// /// \brief constructor /// \param platform the platform @@ -87,73 +104,379 @@ public: /// \brief destructor ~window_manager(); + /// @} + + +private: window_manager(const window_manager&) = delete; -// Thread-Specific Functions =========================================================================================== +// Initialization & Update ============================================================================================= +public: - void initialize(); //!< initialize the window system - void shutdown(); //!< shutdown the window system - void dispatch(); //!< dispatch the commands to the system + /// \name Initialization & Update + /// @{ + /// + /// \brief Initialization + /// + /// \details Initializes the windowing system on the current thread. + void initialize(); + + + /// + /// \brief Shutdown + /// + /// \details Shuts down the windowing system, must be called on the same thread as `window_manager::initialize`. + void shutdown(); + + /// + /// \brief Command Dispatch + /// + /// \details Dispatches commands to the server, must be called on the same thread as `window_manager::initialize`. + void dispatch(); + + /// @} + + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + + /// + /// \brief Create a new window. + /// + /// \details Must be called on the same thread as `window_manager::initialize`. + /// \param config The configuration for the new window. + /// \param parent The parent window. window_id create_window(const config& config, window_id parent = nullid); - void begin(window_id window); - void end(window_id window); + + /// + /// \brief Start a frame for a window. + /// \param window The window. + /// + /// \details Begins a new frame for the specified window. This will make the context and surface associated with + /// this window the new current context. Must be called on the same thread as `window_manager::initialize`. + void begin_frame(window_id window); + + /// + /// \brief Ends a frame for the window. + /// \param window The window. + /// + /// \details Ends the current frame for the specified window. This will swap the front and back buffers for the + /// window. Must be called on the same thread as `window_manager::initialize`. + void end_frame(window_id window); + + /// + /// \brief Closes a window. + /// \param window The window. + /// + /// \details Closes the window, cleaning up the surface associated with the window. void close(window_id window); + /// @} -// Thread-Safe Functions =============================================================================================== +// Window Properties =================================================================================================== +public: + + /// \name Window Properties + /// @{ + + /// + /// \param window The window. + /// \returns the parent window window_id get_parent(window_id window) const { lock_guard guard(_lock); return _parent(window); } + + /// + /// \param window The window. + /// \returns the nearest top-level window in the hierarchy window_id get_root(window_id window) const { lock_guard guard(_lock); return _root(window); } + /// @} + + +// Window Bounds ======================================================================================================= +public: + + /// \name Window Bounds + /// @{ + + /// + /// \param window The window. + /// \returns the size of the window ivec2 get_size(window_id window) const { lock_guard guard(_lock); return _get_size(window); } + + /// + /// \param window The window. + /// \returns the position of the window ivec2 get_position(window_id window) const { lock_guard guard(_lock); return _get_position(window); } - bool is_visible(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_visible); } - bool is_child(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_child); } - bool is_running(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_running); } - bool is_suspended(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_suspended); } + /// + /// \param window The window. + /// \returns the bounds of the window + irect get_bounds(window_id window) const { + lock_guard guard(_lock); + return _get_bounds(window); + } + /// @} + + +// Window Status ======================================================================================================= +public: + + /// \name Window Status + /// @{ + + /// + /// \brief tests if the window is visible + /// + /// \param window The window. + /// \returns \f$true\f$ if the window is visible, \f$false\f$ otherwise + bool is_visible(window_id window) const { + lock_guard guard(_lock); + return _check_state(window, window::state_visible); + } + + /// + /// \brief tests if the window is a child + /// + /// \param window The window. + /// \returns \f$true\f$ if the window is a child, \f$false\f$ otherwise + bool is_child(window_id window) const { + lock_guard guard(_lock); + return _check_state(window, window::state_child); + } + + /// + /// \brief tests if the window is running + /// + /// \param window The window. + /// \returns \f$true\f$ if the window is running, \f$false\f$ otherwise + bool is_running(window_id window) const { + lock_guard guard(_lock); + return _check_state(window, window::state_running); + } + + /// + /// \brief tests if the window is suspended + /// + /// \param window The window. + /// \returns \f$true\f$ if the window is suspended, \f$false\f$ otherwise + bool is_suspended(window_id window) const { + lock_guard guard(_lock); + return _check_state(window, window::state_suspended); + } + + /// @} + + +// Window Behaviour Flags ============================================================================================== +public: + + /// \name Window Behaviour Flags + /// @{ + + /// + /// \brief tests a specific flag + /// + /// \param window The window. + /// \param flag the flag from `window::flag_` + /// \returns \f$true\f$ if the flag is set, \f$false\f$ otherwise bool get_flag(window_id window, uint8_t flag) { lock_guard guard(_lock); return _get_flag(window, flag); } - bool is_always_on_top(window_id window) { return get_flag(window, window::flag_always_on_top); } - bool is_borderless(window_id window) { return get_flag(window, window::flag_borderless); } - bool is_modal(window_id window) { return get_flag(window, window::flag_modal); } - bool is_passing_mouse(window_id window) { return get_flag(window, window::flag_pass_mouse); } - bool is_popup(window_id window) { return get_flag(window, window::flag_popup); } - bool is_resizable(window_id window) { return get_flag(window, window::flag_resizable); } - bool is_transparent(window_id window) { return get_flag(window, window::flag_transparent); } - bool is_no_focus(window_id window) { return get_flag(window, window::flag_no_focus); } + + /// + /// \brief check if the window is flagged to always be on top of other windows + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_always_on_top(window_id window) { + return get_flag(window, window::flag_always_on_top); + } + + /// + /// \brief check if the window is flagged to have no window decorations + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_borderless(window_id window) { + return get_flag(window, window::flag_borderless); + } + + /// + /// \brief check if the window is flagged to be modal + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_modal(window_id window) { + return get_flag(window, window::flag_modal); + } + + /// + /// \brief check if the window is flagged to pass mouse input to windows underneath from the same application + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_passing_mouse(window_id window) { + return get_flag(window, window::flag_pass_mouse); + } + + /// + /// \brief check if the window is flagged as a popup + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_popup(window_id window) { + return get_flag(window, window::flag_popup); + } + + /// + /// \brief check if the window is flagged to be resizable + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_resizable(window_id window) { + return get_flag(window, window::flag_resizable); + } + + /// + /// \brief check if the window is flagged to be transparent + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_transparent(window_id window) { + return get_flag(window, window::flag_transparent); + } + + /// + /// \brief check if the window is flagged to be unfocusable + /// + /// \param window The window. + /// \returns \f$true\f$ if set, \f$false\f$ otherwise + bool is_no_focus(window_id window) { + return get_flag(window, window::flag_no_focus); + } - bool set_flag(window_id window, uint8_t flag, bool val); + /// + /// \brief sets a specific flag + /// + /// \param window The window. + /// \param flag the flag from `window::flag_` + /// \param val the value to set the flag to + void set_flag(window_id window, uint8_t flag, bool val) { + lock_guard guard(_lock); - bool set_always_on_top(window_id window, bool val) { return set_flag(window, window::flag_always_on_top, val); } - bool set_borderless(window_id window, bool val) { return set_flag(window, window::flag_borderless, val); } - bool set_modal(window_id window, bool val) { return set_flag(window, window::flag_modal, val); } - bool set_passing_mouse(window_id window, bool val) { return set_flag(window, window::flag_pass_mouse, val); } - bool set_popup(window_id window, bool val) { return set_flag(window, window::flag_popup, val); } - bool set_resizable(window_id window, bool val) { return set_flag(window, window::flag_resizable, val); } - bool set_transparent(window_id window, bool val) { return set_flag(window, window::flag_transparent, val); } - bool set_no_focus(window_id window, bool val) { return set_flag(window, window::flag_no_focus, val); } + _commands.push(command { + .cmd = command_set_flag, + .win = window, + .data = flag_val{ .index = flag, .val = val } + }); + } + + /// + /// \brief sets whether to always be on top of other windows + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_always_on_top(window_id window, bool val) { + return set_flag(window, window::flag_always_on_top, val); + } + + /// + /// \brief sets whether to have no window decorations + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_borderless(window_id window, bool val) { + return set_flag(window, window::flag_borderless, val); + } + + /// + /// \brief sets whether to be modal + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_modal(window_id window, bool val) { + return set_flag(window, window::flag_modal, val); + } + + /// + /// \brief sets whether to pass mouse input to windows underneath from the same application + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_passing_mouse(window_id window, bool val) { + return set_flag(window, window::flag_pass_mouse, val); + } + + /// + /// \brief sets whether the window is a popup + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_popup(window_id window, bool val) { + return set_flag(window, window::flag_popup, val); + } + + /// + /// \brief sets whether to be resizable + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_resizable(window_id window, bool val) { + return set_flag(window, window::flag_resizable, val); + } + + /// + /// \brief sets whetherto be transparent + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_transparent(window_id window, bool val) { + return set_flag(window, window::flag_transparent, val); + } + + /// + /// \brief sets whether to be unfocusable + /// + /// \param window The window. + /// \param val the value to set the flag to + /// \returns \f$true\f$ on success, \f$false\f$ otherwise + void set_no_focus(window_id window, bool val) { + return set_flag(window, window::flag_no_focus, val); + } + + /// @} +// Private Member Variables ============================================================================================ private: mutable mutex _lock; thread::id _thread; @@ -163,12 +486,14 @@ private: command_queue_t _commands; - +// Private Helpers ===================================================================================================== +private: window_id _parent(window_id id) const; window_id _root(window_id id) const; ivec2 _get_size(window_id id) const; ivec2 _get_position(window_id id) const; + irect _get_bounds(window_id id) const; bool _check_state(window_id id, uint8_t state) const; diff --git a/include/fennec/renderers/interface/gfxcontext.h b/include/fennec/renderers/interface/gfxcontext.h index 70bb185..9fb8c2c 100644 --- a/include/fennec/renderers/interface/gfxcontext.h +++ b/include/fennec/renderers/interface/gfxcontext.h @@ -31,7 +31,7 @@ #ifndef FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H #define FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H -#include +#include #include #include @@ -44,32 +44,76 @@ namespace fennec { +/// +/// \brief Interface resembling a broader context for a graphics API class gfxcontext { -public: - using handle_t = uint32_t; +// Constructors & Destructor =========================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ + + /// + /// \brief Context Constructor + /// \param display The display server this context was created from gfxcontext(display_server* display) : display(display) - , version(0, 0, 0, string("")) { + , version() { } + /// + /// \brief Virtual Destructor virtual ~gfxcontext() = default; - gfxcontext& operator=(const gfxcontext&) = delete; - gfxcontext& operator=(gfxcontext&&) = delete; + /// @} + +// Properties ========================================================================================================== +public: + + /// \name Properties + /// @{ + + /// + /// \returns \f$true\f$ if this virtual bool is_valid() = 0; - virtual gfxsurface* create_surface(window* window) = 0; + /// + /// \returns A version struct containing the version of the graphics API. + virtual const version& get_version() const { return version; } - virtual const version& get_version() const { return version; }; + /// @} + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + + /// + /// \brief Create a surface under the context of the graphics API for the provided window. + /// \param window The window to create a surface for. + /// \returns A new graphics surface for the API. + virtual gfxsurface* create_surface(window* window) = 0; + + /// @} + + +// Protected Member Variables ========================================================================================== protected: - display_server* display; - version version; + display_server* const display; //!< The display server this context was created from. + version version; //!< The version of the underlying graphics API. FENNEC_RTTI_CLASS_ENABLE() { } + + +// Assignment Operators ================================================================================================ +private: + gfxcontext& operator=(const gfxcontext&) = delete; + gfxcontext& operator=(gfxcontext&&) = delete; }; } diff --git a/include/fennec/renderers/interface/gfxsurface.h b/include/fennec/renderers/interface/gfxsurface.h index 5fad9b9..b5702fb 100644 --- a/include/fennec/renderers/interface/gfxsurface.h +++ b/include/fennec/renderers/interface/gfxsurface.h @@ -37,22 +37,61 @@ namespace fennec { +/// +/// \brief Interface representing a renderable surface for a graphics API. class gfxsurface { -public: - virtual ~gfxsurface() = default; +// Constructors & Destructor =========================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ + + /// + /// \brief Graphics Surface Constructor. + /// \param win The window the surface belongs to. + /// \param ctx The graphics context the surface belongs to. gfxsurface(window* win, gfxcontext* ctx) : window(win), context(ctx) { } + /// + /// \brief Virtual Destructor + virtual ~gfxsurface() = default; + + /// @} + + +// Properties ========================================================================================================== +public: + + +// Operations ========================================================================================================== +public: + + /// \name Operations + /// @{ + + /// + /// \brief Make this surface, and the context that it belongs to, the current rendering target for the graphics API. virtual void make_current() = 0; + + /// + /// \brief Swap the surface's front & back buffers. virtual void swap() = 0; + /// + /// \brief Resize the backing buffers of the surface. + /// \param size The new size. virtual void resize(const ivec2& size) = 0; + /// @} + + +// Protected Member Variables ========================================================================================== protected: - window* window; - gfxcontext* context; + window* const window; //!< The window the surface belongs to. + gfxcontext* const context; //!< The graphics context the surface belongs to. }; } diff --git a/include/fennec/renderers/opengl/lib/buffer.h b/include/fennec/renderers/opengl/lib/buffer.h index fd5fc75..79a769b 100644 --- a/include/fennec/renderers/opengl/lib/buffer.h +++ b/include/fennec/renderers/opengl/lib/buffer.h @@ -16,11 +16,24 @@ // along with this program. If not, see . // ===================================================================================================================== +/// +/// \file fennec/renderers/opengl/lib/buffer.h +/// \brief +/// +/// +/// \details +/// \author Medusa Slockbower +/// +/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) +/// +/// + #ifndef FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H #define FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H #include -#include + +#include #include namespace fennec @@ -29,27 +42,120 @@ namespace fennec namespace gl { -template using vertex_buffer = buffer; -template using element_buffer = buffer; -template using uniform_buffer = buffer; -template using shader_storage_buffer = buffer; -template using query_buffer = buffer; -template using texture_buffer = buffer; -template using transform_feedback_buffer = buffer; -template using atomic_counter_buffer = buffer; -template using parameter_buffer = buffer; -template using indirect_draw_buffer = buffer; -template using indirect_dispatch_buffer = buffer; -template using copy_read_buffer = buffer; -template using copy_write_buffer = buffer; -template using pixel_pack_buffer = buffer; -template using pixel_unpack_buffer = buffer; +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using vertex_buffer = buffer; +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using element_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using uniform_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using shader_storage_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using query_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using texture_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using transform_feedback_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using atomic_counter_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using parameter_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using indirect_draw_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using indirect_dispatch_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using copy_read_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using copy_write_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using pixel_pack_buffer = buffer; + +/// +/// \brief Vertex Buffer Alias +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability +template +using pixel_unpack_buffer = buffer; + +/// +/// \brief +/// \tparam TypeV The buffer type, see \ref fennec::gl::buffer_types "buffer_types" +/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags" +/// \tparam ImmutableV Mutability template class buffer { -// HELPER FUNCTIONS ==================================================================================================== - +// Private Helpers ===================================================================================================== private: static constexpr GLenum get_mutable_traits() { GLenum res; @@ -76,33 +182,105 @@ private: } -// CONSTANTS =========================================================================================================== - +// Constants =========================================================================================================== public: - static constexpr GLenum type = TypeV; - static constexpr GLboolean immutable = ImmutableV; - static constexpr GLbitfield flags = FlagsV; - static constexpr GLboolean indexed = type == ATOMIC_COUNTER or type == SHADER_STORAGE or type == TRANSFORM_FEEDBACK or type == UNIFORM; - static constexpr GLboolean map_read = flags & READ; + + /// \name Constants + /// @{ + + /// + /// \brief Enum value containing the buffer type. + /// \see fennec::gl::buffer_types + static constexpr GLenum type = TypeV; + + /// + /// \brief Boolean value representing whether this buffer is immutable. + /// \note Immutable buffers may not be resized. + static constexpr GLboolean immutable = ImmutableV; + + /// + /// \brief Bitfield value containing the buffer flags. + /// \see fennec::gl::buffer_map_flags + static constexpr GLbitfield flags = FlagsV; + + /// + /// \brief Boolean value representing whether this buffer has indexed binding targets. + /// \note Indexed buffer types must be bound to an indexed binding target to be used in shaders. + /// \see fennec::gl::buffer::bind + /// \see fennec::gl::buffer::bind_range + static constexpr GLboolean indexed = type == ATOMIC_COUNTER or type == SHADER_STORAGE or type == TRANSFORM_FEEDBACK or type == UNIFORM; + + /// + /// \brief Boolean value representing whether this buffer is mapped for reading. + /// \note Not to be confused with `read()`, which is specifically for dynamic buffers. + /// \see fennec::gl::buffer::map + static constexpr GLboolean map_read = flags & READ; + + /// + /// \brief Boolean value representing whether this buffer is mapped for writing. + /// \note Not to be confused with `write()`, which is specifically for dynamic buffers. + /// \see fennec::gl::buffer::map static constexpr GLboolean map_write = flags & WRITE; - static constexpr GLboolean mapped = map_read or map_write; - static constexpr GLboolean dynamic = flags & DYNAMIC; - static constexpr GLboolean persistent = flags & PERSISTENT; - static constexpr GLboolean coherent = flags & COHERENT; - static constexpr GLboolean client = flags & CLIENT; - static constexpr GLenum usage = get_mutable_traits(); - static_assert(not persistent or persistent == mapped); - static_assert(not coherent or coherent == persistent); + /// + /// \brief Boolean value representing whether this buffer is mapped + /// \see fennec::gl::buffer::map + static constexpr GLboolean mapped = map_read or map_write; + + /// + /// \brief Boolean value representing whether this buffer is dynamic. + /// \note This allows use of the dynamic `read()` and `write()` functions. + /// \see fennec::gl::buffer::read + /// \see fennec::gl::buffer::write + static constexpr GLboolean dynamic = flags & DYNAMIC; + + /// + /// \brief Boolean value representing whether this buffer is persistent, i.e. can be used while mapped. + /// \see fennec::gl::buffer::map + static constexpr GLboolean persistent = flags & PERSISTENT; + + /// + /// \brief Boolean value representing whether this buffer is coherent when mapped. + /// \see fennec::gl::buffer::map + static constexpr GLboolean coherent = flags & COHERENT; + + /// + /// \brief Boolean value representing whether this buffers memory is on the client. + /// \note This is only a hint for the driver, which may be ignored. + static constexpr GLboolean client = flags & CLIENT; + + /// + /// \brief Enum value containing the mutable usage traits. + /// \see fennec::gl::buffer::immutable + static constexpr GLenum usage = get_mutable_traits(); + + /// @} -// CONSTRUCTORS & ASSIGNMENT =========================================================================================== +// Assertions ========================================================================================================== +public: - constexpr buffer(const void* data, GLsizeiptr size) + static_assert(not persistent or persistent == mapped, "Persistent buffer must be mappable."); + static_assert(not coherent or coherent == persistent, "Coherent buffer must be persistent."); + + +// Constructors & Destructor =========================================================================================== +public: + + /// \name Constructors & Destructor + /// @{ + + /// + /// \brief Buffer Data Constructor + /// \param data Data to upload to the buffer, may be \f$nullptr\f$. + /// \param size Size of the buffer. + buffer(const void* data, GLsizeiptr size) : _handle() - , _size(size) { + , _size(size) + , _data(nullptr) + , _mapflags(0) { glGenBuffers(1, &_handle); - start(); + use(); if constexpr(immutable) { glBufferStorage(type, _size, data, flags); } else { @@ -110,34 +288,84 @@ public: } } - constexpr buffer(buffer&& buff) noexcept + /// + /// \brief Buffer Move Constructor + /// \param buff The buffer to take ownership of + buffer(buffer&& buff) noexcept : _handle(buff) , _size(buff._size) - , _mapping(nullptr) { + , _data(nullptr) + , _mapflags(0) { } - constexpr buffer& operator=(buffer&& buff) noexcept { + /// + /// \brief Buffer Destructor + /// + /// \details Cleans up buffer data and object + ~buffer() { glDeleteBuffers(1, &_handle); - _handle = buff._handle; - _size = buff._size; + } + + /// @} + +private: + buffer(const buffer&) = delete; + + +// Assignment ========================================================================================================== +public: + + /// \name Assignment + /// @{ + + /// + /// \brief Buffer Move Assignment + /// \param buff The buffer to take ownership of. + /// \returns A reference to self after having taken ownership of \f$buff\f$. + buffer& operator=(buffer&& buff) noexcept { + fennec::swap(_handle, buff._handle); + fennec::swap(_size, buff._size); return *this; } - constexpr buffer(const buffer&) = delete; - constexpr buffer& operator=(const buffer&) = delete; + /// @} -// OBJECT FUNCTIONS ==================================================================================================== +private: + buffer& operator=(const buffer&) = delete; - constexpr void start() const { + +// Use & Binding ======================================================================================================= +public: + + /// \name Use & Binding + /// @{ + + /// + /// \brief Use this buffer for buffer operations. + void use() const { glBindBuffer(type, _handle); } - constexpr void end() const { - glBindBuffer(type, NULL); + /// + /// \brief Bind this buffer to an indexed target. + /// + /// \param i The index to bind to. + /// \see fennec::gl::buffer::type. + void bind(GLuint i) { + static_assert(indexed, "Buffer must have an indexed binding target."); + + glBindBufferBase(type, i, _handle); } - constexpr void bind(GLuint i, GLsizeiptr size = -1, GLintptr offset = 0) { + /// + /// \brief Bind a range of this buffer to an indexed target. + /// \param i The index to bind to. + /// \param size The size of the range to bind. + /// \param offset The offset of the range to bind. + void bind_range(GLuint i, GLsizeiptr size = -1, GLintptr offset = 0) { + static_assert(indexed, "Buffer must have an indexed binding target."); + offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; size = min(size, _size - offset); @@ -145,40 +373,83 @@ public: glBindBufferRange(type, i, _handle, offset, size); } + /// @} -// BASIC BUFFER FUNCTIONS ============================================================================================== - constexpr void resize(GLsizei size) requires(not immutable) { - unmap(); - glBufferData(type, _size = size, nullptr, usage); - } +// Mapping ============================================================================================================= +public: + /// \name Mapping + /// @{ - constexpr void* map(GLbitfield access, GLsizeiptr size, GLintptr offset = 0) { - if (_mapping) { - return _mapping; + /// + /// \brief Map a range of the buffer to be used by the client. + /// \param access The access specifiers. + /// \param size The size of the range to map. + /// \param offset The offset of the range to map. + /// \return + void* map(GLbitfield access, GLsizeiptr size = -1, GLintptr offset = 0) { + if (_data) { + return _data; } + offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; size = min(size, _size - offset); if (size <= 0) return nullptr; - return _mapping = glMapBufferRange(type, offset, size, _mapflags = access); + return _data = glMapBufferRange(type, offset, size, _mapflags = flags | access); } - constexpr void unmap() { + /// + /// \brief Release the mapping of the buffer. + void unmap() { glUnmapBuffer(type); - _mapping = nullptr; + _data = nullptr; } - constexpr void clear(GLsizeiptr size = -1, GLintptr offset = 0, const void* data = nullptr, GLenum data_type = BYTE, GLenum format = R, GLenum internal = R8) { + /// @} + + +// Operations ========================================================================================================== +public: + + /// + /// \brief Resize the buffer. + /// + /// \param size The new size for the buffer. + /// \note Buffer must be mutable. Clears buffer with zeroes. + /// \see fennec::gl::buffer::immutable + void resize(GLsizei size) requires(not immutable) { + unmap(); + glBufferData(type, _size = size, nullptr, usage); + } + + /// + /// \brief Clear the buffer. + /// \param size The number of elements to clear + /// \param offset The offset into the buffer to begin clearing. + /// \param value The value to clear with. Must be a pointer to an object of appropriate size for the type and format. + /// \param value_type The type of the data. + /// \param format The format of the data. + /// \param internal The assumed internal format of the buffer. + void clear(GLsizeiptr size = -1, GLintptr offset = 0, const void* value = nullptr, GLenum value_type = BYTE, GLenum format = R, GLenum internal = R8) { offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; size = min(size, _size - offset); if (size <= 0) return; - glClearBufferSubData(type, internal, offset, size, format, data_type, data); + glClearBufferSubData(type, internal, offset, size, format, value_type, value); } + /// + /// \brief Copy data from another buffer. + /// \tparam OTypeV The type of the buffer to copy from. + /// \tparam OFlagsV The flags of the buffer being copied from. + /// \tparam OImmutableV The mutability of the buffer being copied from. + /// \param cpy The buffer to copy. + /// \param size The size of the region to copy + /// \param write_offset The offset into this buffer to begin writing at. + /// \param read_offset The offset into \f$cpy\f$ to begin reading from. template - constexpr void copy(const buffer& cpy, GLsizeiptr size = -1, GLintptr write_offset = 0, GLintptr read_offset = 0) { + void copy(const buffer& cpy, GLsizeiptr size = -1, GLintptr write_offset = 0, GLintptr read_offset = 0) { write_offset = max(write_offset, GLintptr(0)); read_offset = max(read_offset, GLintptr(0)); size = size < 0 ? _size : size; @@ -192,8 +463,13 @@ public: glBindBuffer(COPY_WRITE, NULL); } - constexpr void read(void* data, GLsizeiptr size, GLintptr offset = 0) const { - static_assert((dynamic or persistent) and not (client or coherent)); + /// + /// \brief Read data from the buffer. + /// \param data The handle to the client buffer to read into. + /// \param size The size of the region to read. + /// \param offset The offset into the buffer to begin reading from. + void read(void* data, GLsizeiptr size, GLintptr offset = 0) const { + static_assert(dynamic); offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; size = min(size, _size - offset); @@ -201,8 +477,13 @@ public: glGetBufferSubData(type, offset, size, data); } - constexpr void write(const void* data, GLsizeiptr size, GLintptr offset = 0) { - static_assert((dynamic or persistent) and not (client or coherent)); + /// + /// \brief Write data to the buffer. + /// \param data The handle to the client buffer to write from. + /// \param size The size of the region to write. + /// \param offset The offset into the buffer to begin writing at. + void write(const void* data, GLsizeiptr size, GLintptr offset = 0) { + static_assert(dynamic); offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; size = min(size, _size - offset); @@ -210,8 +491,13 @@ public: glBufferSubData(type, offset, size, data); } - constexpr void flush(GLsizeiptr size = -1, GLintptr offset = 0) { - if (not _mapping) return; + /// + /// \brief Flush a range of the buffer. + /// \param size The size of the range. + /// \param offset The offset of the range. + /// \note The buffer must be mapped with the \ref fennec::gl::buffer_map_flags::EXPLICIT_FLUSH "EXPLICIT_FLUSH" flag. + void flush(GLsizeiptr size = -1, GLintptr offset = 0) { + if (not _data) return; if (not (_mapflags & EXPLICIT_FLUSH)) return; offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; @@ -220,7 +506,7 @@ public: glFlushMappedBufferRange(type, offset, size); } - constexpr void invalidate(GLsizeiptr size, GLintptr offset = 0) { + void invalidate(GLsizeiptr size, GLintptr offset = 0) { offset = max(offset, GLintptr(0)); size = size < 0 ? _size : size; size = min(size, _size - offset); @@ -232,14 +518,14 @@ public: // TYPED FUNCTIONS ===================================================================================================== template - constexpr TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) { + TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) { return static_cast(map(access, n * sizeof(TypeT), offset * sizeof(TypeT))); } private: GLuint _handle; GLsizeiptr _size; - void* _mapping; + void* _data; GLbitfield _mapflags; }; diff --git a/include/fennec/renderers/opengl/lib/enum.h b/include/fennec/renderers/opengl/lib/enum.h index ac876a6..f7b843a 100644 --- a/include/fennec/renderers/opengl/lib/enum.h +++ b/include/fennec/renderers/opengl/lib/enum.h @@ -16,10 +16,22 @@ // along with this program. If not, see . // ===================================================================================================================== +/// +/// \file fennec/renderers/opengl/lib/enum.h +/// \brief +/// +/// +/// \details +/// \author Medusa Slockbower +/// +/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) +/// +/// + #ifndef FENNEC_RENDERERS_OPENGL_LIB_ENUM_H #define FENNEC_RENDERERS_OPENGL_LIB_ENUM_H -#include +#include namespace fennec { @@ -27,287 +39,343 @@ namespace fennec namespace gl { -enum buffer_ : GLenum { - VERTEX = GL_ARRAY_BUFFER, - ELEMENT = GL_ELEMENT_ARRAY_BUFFER, - UNIFORM = GL_UNIFORM_BUFFER, - SHADER_STORAGE = GL_SHADER_STORAGE_BUFFER, - QUERY = GL_QUERY_BUFFER, - TEXTURE = GL_TEXTURE_BUFFER, - TRANSFORM_FEEDBACK = GL_TRANSFORM_FEEDBACK_BUFFER, - ATOMIC_COUNTER = GL_ATOMIC_COUNTER_BUFFER, - PARAMETER = GL_PARAMETER_BUFFER, - INDIRECT_DRAW = GL_DRAW_INDIRECT_BUFFER, INDIRECT_DISPATCH = GL_DISPATCH_INDIRECT_BUFFER, - COPY_READ = GL_COPY_READ_BUFFER, COPY_WRITE = GL_COPY_WRITE_BUFFER, - PIXEL_PACK = GL_PIXEL_PACK_BUFFER, PIXEL_UNPACK = GL_PIXEL_UNPACK_BUFFER, +// Buffer Types ======================================================================================================== + +/// +/// \brief OpenGL Buffer Types +enum buffer_types : GLenum { + VERTEX = GL_ARRAY_BUFFER, //!< Vertex Buffer + ELEMENT = GL_ELEMENT_ARRAY_BUFFER, //!< Element Array Buffer + UNIFORM = GL_UNIFORM_BUFFER, //!< Uniform Buffer + SHADER_STORAGE = GL_SHADER_STORAGE_BUFFER, //!< Shader Storage Buffer + QUERY = GL_QUERY_BUFFER, //!< Query Buffer + BUFFER_TEXTURE = GL_TEXTURE_BUFFER, //!< Texture Buffer + TRANSFORM_FEEDBACK = GL_TRANSFORM_FEEDBACK_BUFFER, //!< Transform Feedback Buffer + ATOMIC_COUNTER = GL_ATOMIC_COUNTER_BUFFER, //!< Atomic Counter Buffer + PARAMETER = GL_PARAMETER_BUFFER, //!< Parameter Buffer + INDIRECT_DRAW = GL_DRAW_INDIRECT_BUFFER, //!< Indirect Draw Buffer + INDIRECT_DISPATCH = GL_DISPATCH_INDIRECT_BUFFER, //!< Indirect Dispatch Buffer + COPY_READ = GL_COPY_READ_BUFFER, //!< Copy Read Buffer + COPY_WRITE = GL_COPY_WRITE_BUFFER, //!< Copy Write Buffer + PIXEL_PACK = GL_PIXEL_PACK_BUFFER, //!< Pixel Pack Buffer + PIXEL_UNPACK = GL_PIXEL_UNPACK_BUFFER, //!< Pixel Unpack Buffer }; -enum buffer_flag_ : GLbitfield { - READ = GL_MAP_READ_BIT, - WRITE = GL_MAP_WRITE_BIT, - DYNAMIC = GL_DYNAMIC_STORAGE_BIT, - PERSISTENT = GL_MAP_PERSISTENT_BIT, - COHERENT = GL_MAP_COHERENT_BIT, - CLIENT = GL_CLIENT_STORAGE_BIT, - EXPLICIT_FLUSH = GL_MAP_FLUSH_EXPLICIT_BIT, - INVALIDATE = GL_MAP_INVALIDATE_BUFFER_BIT, + +// Buffer Flags ======================================================================================================== + +/// +/// \brief OpenGL Buffer Flags +enum buffer_map_flags : GLbitfield { + READ = GL_MAP_READ_BIT, //!< Buffer Read Flag + WRITE = GL_MAP_WRITE_BIT, //!< Buffer Write Flag + DYNAMIC = GL_DYNAMIC_STORAGE_BIT, //!< Dynamic Buffer Flag + PERSISTENT = GL_MAP_PERSISTENT_BIT, //!< Persistent Buffer Flag + COHERENT = GL_MAP_COHERENT_BIT, //!< Coherent Buffer Flag + CLIENT = GL_CLIENT_STORAGE_BIT, //!< Client Allocated Buffer Flag + EXPLICIT_FLUSH = GL_MAP_FLUSH_EXPLICIT_BIT, //!< Explicit Flush Flag + INVALIDATE = GL_MAP_INVALIDATE_BUFFER_BIT, //!< Invalidation Flag }; -enum access_ : GLbitfield { - READ_ONLY = GL_READ_ONLY, - WRITE_ONLY = GL_WRITE_ONLY, - READ_WRITE = GL_READ_WRITE, + +// Buffer Access ======================================================================================================= + +/// +/// \brief OpenGL Buffer Access +enum buffer_access : GLbitfield { + READ_ONLY = GL_READ_ONLY, //!< Read Only Flag + WRITE_ONLY = GL_WRITE_ONLY, //!< Write Only Flag + READ_WRITE = GL_READ_WRITE, //!< Read & Write Flag }; -enum texture_ : GLenum { - TEX_1D = GL_TEXTURE_1D, - TEX_1D_ARRAY = GL_TEXTURE_1D_ARRAY, - TEX_2D = GL_TEXTURE_2D, - TEX_2D_ARRAY = GL_TEXTURE_2D_ARRAY, - TEX_2D_MS = GL_TEXTURE_2D_MULTISAMPLE, - TEX_2D_MS_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY, - TEX_RECT = GL_TEXTURE_RECTANGLE, +// Texture Types ======================================================================================================= - TEX_CUBEMAP = GL_TEXTURE_CUBE_MAP, - TEX_CUBEMAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY, - - TEX_3D = GL_TEXTURE_3D, - - TEX_BUFFER = GL_TEXTURE_BUFFER, +/// +/// \brief OpenGL Texture Types +enum texture_types : GLenum { + TEXTURE_1D = GL_TEXTURE_1D, //!< 1D Texture + TEXTURE_1D_ARRAY = GL_TEXTURE_1D_ARRAY, //!< 1D Texture Array + TEXTURE_2D = GL_TEXTURE_2D, //!< 2D Texture + TEXTURE_2D_ARRAY = GL_TEXTURE_2D_ARRAY, //!< 2D Texture Array + TEXTURE_2D_MS = GL_TEXTURE_2D_MULTISAMPLE, //!< 2D Multisampled Texture + TEXTURE_2D_MS_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY, //!< 2D Multisampled Texture Array + TEXTURE_RECTANGLE = GL_TEXTURE_RECTANGLE, //!< 2D Texture Rectangle + CUBEMAP = GL_TEXTURE_CUBE_MAP, //!< Cubemap + CUBEMAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY, //!< Cubemap Array + TEXTURE_3D = GL_TEXTURE_3D, //!< 3D Texture }; -enum type_ : GLenum { - BOOL = GL_BOOL, - BVEC2 = GL_BOOL_VEC2, - BVEC3 = GL_BOOL_VEC3, - BVEC4 = GL_BOOL_VEC4, - BYTE = GL_BYTE, - SHORT = GL_SHORT, - INT = GL_INT, - IVEC2 = GL_INT_VEC2, - IVEC3 = GL_INT_VEC3, - IVEC4 = GL_INT_VEC4, +// Built-In Types ====================================================================================================== - UBYTE = GL_UNSIGNED_BYTE, - USHORT = GL_UNSIGNED_SHORT, - UINT = GL_UNSIGNED_INT, - UVEC2 = GL_UNSIGNED_INT_VEC2, - UVEC3 = GL_UNSIGNED_INT_VEC3, - UVEC4 = GL_UNSIGNED_INT_VEC4, +/// +/// \brief OpenGL Built-In Types +enum types : GLenum { - HALF = GL_HALF_FLOAT, - FLOAT = GL_FLOAT, - VEC2 = GL_FLOAT_VEC2, - VEC3 = GL_FLOAT_VEC3, - VEC4 = GL_FLOAT_VEC4, - DOUBLE = GL_DOUBLE, - DVEC2 = GL_DOUBLE_VEC2, - DVEC3 = GL_DOUBLE_VEC3, - DVEC4 = GL_DOUBLE_VEC4, +// Basic Types --------------------------------------------------------------------------------------------------------- - UBYTE332 = GL_UNSIGNED_BYTE_3_3_2, - UBYTE233R = GL_UNSIGNED_BYTE_2_3_3_REV, - USHORT565 = GL_UNSIGNED_SHORT_5_6_5, - USHORT565R = GL_UNSIGNED_SHORT_5_6_5_REV, - USHORT4444 = GL_UNSIGNED_SHORT_4_4_4_4, - USHORT4444R = GL_UNSIGNED_SHORT_4_4_4_4_REV, - USHORT5551 = GL_UNSIGNED_SHORT_5_5_5_1, - USHORT1555R = GL_UNSIGNED_SHORT_1_5_5_5_REV, - UINT8888 = GL_UNSIGNED_INT_8_8_8_8, - UINT8888R = GL_UNSIGNED_INT_8_8_8_8_REV, - UINTAAA2 = GL_UNSIGNED_INT_10_10_10_2, - UINT2AAAR = GL_UNSIGNED_INT_2_10_10_10_REV, - UINT24_8 = GL_UNSIGNED_INT_24_8, + BOOL = GL_BOOL, //!< Boolean Type + BYTE = GL_BYTE, //!< Byte Type + UBYTE = GL_UNSIGNED_BYTE, //!< Unsigned Byte Type + SHORT = GL_SHORT, //!< Short Type + USHORT = GL_UNSIGNED_SHORT, //!< Unsigned Short Type + INT = GL_INT, //!< Integer Type + UINT = GL_UNSIGNED_INT, //!< Unsigned Integer Type + HALF = GL_HALF_FLOAT, //!< Half Precision Floating Point Type + FLOAT = GL_FLOAT, //!< Floating Point Type + DOUBLE = GL_DOUBLE, //!< Double Precision Floating Point Type - UINTABBFR = GL_UNSIGNED_INT_10F_11F_11F_REV, - UINT5999R = GL_UNSIGNED_INT_5_9_9_9_REV, - FLOAT32UINT24 = GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - SAMPLER_1D = GL_SAMPLER_1D, - SAMPLER_1D_V = GL_SAMPLER_1D_ARRAY, - SHADOW_SAMPLER_1D = GL_SAMPLER_1D_SHADOW, - SHADOW_SAMPLER_1D_V = GL_SAMPLER_1D_ARRAY_SHADOW, +// Vector Types -------------------------------------------------------------------------------------------------------- - SAMPLER_2D = GL_SAMPLER_2D, - SAMPLER_2D_V = GL_SAMPLER_2D_ARRAY, - SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT, - SAMPLER_2D_MS = GL_SAMPLER_2D_MULTISAMPLE, - SAMPLER_2D_MS_V = GL_SAMPLER_2D_MULTISAMPLE_ARRAY, - SHADOW_SAMPLER_2D = GL_SAMPLER_2D_SHADOW, - SHADOW_SAMPLER_2D_V = GL_SAMPLER_2D_ARRAY_SHADOW, - SHADOW_SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT_SHADOW, - SAMPLER_CUBEMAP = GL_SAMPLER_CUBE, - SHADOW_SAMPLER_CUBEMAP = GL_SAMPLER_CUBE_SHADOW, - SAMPLER_3D = GL_SAMPLER_3D, - SAMPLER_BUFFER = GL_SAMPLER_BUFFER, + BVEC2 = GL_BOOL_VEC2, //!< 2D Boolean Vector Type + BVEC3 = GL_BOOL_VEC3, //!< 3D Boolean Vector Type + BVEC4 = GL_BOOL_VEC4, //!< 4D Boolean Vector Type - ISAMPLER_1D = GL_INT_SAMPLER_1D, - ISAMPLER_1D_V = GL_INT_SAMPLER_1D_ARRAY, - ISAMPLER_2D = GL_INT_SAMPLER_2D, - ISAMPLER_2D_V = GL_INT_SAMPLER_2D_ARRAY, - ISAMPLER_RECT_2D = GL_INT_SAMPLER_2D_RECT, - ISAMPLER_2D_MS = GL_INT_SAMPLER_2D_MULTISAMPLE, - ISAMPLER_2D_MS_V = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, - ISAMPLER_CUBEMAP = GL_INT_SAMPLER_CUBE, - ISAMPLER_3D = GL_INT_SAMPLER_3D, - ISAMPLER_BUFFER = GL_INT_SAMPLER_BUFFER, + IVEC2 = GL_INT_VEC2, //!< 2D Integer Vector Type + IVEC3 = GL_INT_VEC3, //!< 3D Integer Vector Type + IVEC4 = GL_INT_VEC4, //!< 4D Integer Vector Type - USAMPLER_1D = GL_INT_SAMPLER_1D, - USAMPLER_1D_V = GL_INT_SAMPLER_1D_ARRAY, - USAMPLER_2D = GL_INT_SAMPLER_2D, - USAMPLER_2D_V = GL_INT_SAMPLER_2D_ARRAY, - USAMPLER_RECT_2D = GL_INT_SAMPLER_2D_RECT, - USAMPLER_2D_MS = GL_INT_SAMPLER_2D_MULTISAMPLE, - USAMPLER_2D_MS_V = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, - USAMPLER_CUBEMAP = GL_INT_SAMPLER_CUBE, - USAMPLER_3D = GL_INT_SAMPLER_3D, - USAMPLER_BUFFER = GL_INT_SAMPLER_BUFFER, + UVEC2 = GL_UNSIGNED_INT_VEC2, //!< 2D Unsigned Integer Vector Type + UVEC3 = GL_UNSIGNED_INT_VEC3, //!< 3D Unsigned Integer Vector Type + UVEC4 = GL_UNSIGNED_INT_VEC4, //!< 4D Unsigned Integer Vector Type - IMAGE_1D = GL_IMAGE_1D, - IMAGE_1D_V = GL_IMAGE_1D_ARRAY, - IMAGE_2D = GL_IMAGE_2D, - IMAGE_2D_V = GL_IMAGE_2D_ARRAY, - IMAGE_RECT_2D = GL_IMAGE_2D_RECT, - IMAGE_2D_MS = GL_IMAGE_2D_MULTISAMPLE, - IMAGE_2D_MS_V = GL_IMAGE_2D_MULTISAMPLE_ARRAY, - IMAGE_CUBEMAP = GL_IMAGE_CUBE, - IMAGE_3D = GL_IMAGE_3D, - IMAGE_BUFFER = GL_IMAGE_BUFFER, + VEC2 = GL_FLOAT_VEC2, //!< 2D Floating Point Vector Type + VEC3 = GL_FLOAT_VEC3, //!< 3D Floating Point Vector Type + VEC4 = GL_FLOAT_VEC4, //!< 4D Floating Point Vector Type - IIMAGE_1D = GL_INT_IMAGE_1D, - IIMAGE_1D_V = GL_INT_IMAGE_1D_ARRAY, - IIMAGE_2D = GL_INT_IMAGE_2D, - IIMAGE_2D_V = GL_INT_IMAGE_2D_ARRAY, - IIMAGE_RECT_2D = GL_INT_IMAGE_2D_RECT, - IIMAGE_2D_MS = GL_INT_IMAGE_2D_MULTISAMPLE, - IIMAGE_2D_MS_V = GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, - IIMAGE_CUBEMAP = GL_INT_IMAGE_CUBE, - IIMAGE_3D = GL_INT_IMAGE_3D, - IIMAGE_BUFFER = GL_INT_IMAGE_BUFFER, + DVEC2 = GL_DOUBLE_VEC2, //!< 2D Double Precision Floating Point Type + DVEC3 = GL_DOUBLE_VEC3, //!< 3D Double Precision Floating Point Type + DVEC4 = GL_DOUBLE_VEC4, //!< 4D Double Precision Floating Point Type - UIMAGE_1D = GL_UNSIGNED_INT_IMAGE_1D, - UIMAGE_1D_V = GL_UNSIGNED_INT_IMAGE_1D_ARRAY, - UIMAGE_2D = GL_UNSIGNED_INT_IMAGE_2D, - UIMAGE_2D_V = GL_UNSIGNED_INT_IMAGE_2D_ARRAY, - UIMAGE_RECT_2D = GL_UNSIGNED_INT_IMAGE_2D_RECT, - UIMAGE_2D_MS = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, - UIMAGE_2D_MS_V = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, - UIMAGE_CUBEMAP = GL_UNSIGNED_INT_IMAGE_CUBE, - UIMAGE_3D = GL_UNSIGNED_INT_IMAGE_3D, - UIMAGE_BUFFER = GL_UNSIGNED_INT_IMAGE_BUFFER, - AtomicCounter = GL_UNSIGNED_INT_ATOMIC_COUNTER, +// Packed Types -------------------------------------------------------------------------------------------------------- + + UBYTE332 = GL_UNSIGNED_BYTE_3_3_2, //!< Packed RGB Type with 3 Red, 3 Green, and 2 Blue bits. + UBYTE233R = GL_UNSIGNED_BYTE_2_3_3_REV, //!< Packed BGR Type with 3 Red, 3 Green, and 2 Blue bits. + USHORT565 = GL_UNSIGNED_SHORT_5_6_5, //!< Packed RGB Type with 5 Red, 6 Green, and 5 Blue bits. + USHORT565R = GL_UNSIGNED_SHORT_5_6_5_REV, //!< Packed BGR Type with 5 Red, 6 Green, and 5 Blue bits. + + USHORT4444 = GL_UNSIGNED_SHORT_4_4_4_4, //!< Packed RGBA Type with 4 Red, 4 Green, 4 Blue, and 4 Alpha bits. + USHORT4444R = GL_UNSIGNED_SHORT_4_4_4_4_REV, //!< Packed BGRA Type with 4 Red, 4 Green, 4 Blue, and 4 Alpha bits. + USHORT5551 = GL_UNSIGNED_SHORT_5_5_5_1, //!< Packed RGBA Type with 5 Red, 5 Green, 5 Blue, and 1 Alpha bits. + USHORT1555R = GL_UNSIGNED_SHORT_1_5_5_5_REV, //!< Packed BGRA Type with 5 Red, 5 Green, 5 Blue, and 1 Alpha bits. + UINT8888 = GL_UNSIGNED_INT_8_8_8_8, //!< Packed RGBA Type with 8 Red, 8 Green, 8 Blue, and 8 Alpha bits. + UINT8888R = GL_UNSIGNED_INT_8_8_8_8_REV, //!< Packed BGRA Type with 8 Red, 8 Green, 8 Blue, and 8 Alpha bits. + UINT5999R = GL_UNSIGNED_INT_5_9_9_9_REV, //!< Packed BGRA Type with 9 Red, 9 Green, 9 Blue, and 5 Alpha bits. + UINTAAA2 = GL_UNSIGNED_INT_10_10_10_2, //!< Packed RGBA Type with 10 Red, 10 Green, 10 Blue, and 2 Alpha bits. + UINT2AAAR = GL_UNSIGNED_INT_2_10_10_10_REV, //!< Packed BGRA Type with 10 Red, 10 Green, 10 Blue, and 2 Alpha bits. + + UINT24_8 = GL_UNSIGNED_INT_24_8, //!< Packed DS Type with 24 Depth and 8 Stencil bits. + FLOAT32UINT24 = GL_FLOAT_32_UNSIGNED_INT_24_8_REV, //!< Packed DS Type with 32 Depth and 8 Stencil bits. + + UINTABBFR = GL_UNSIGNED_INT_10F_11F_11F_REV, //!< Packed ZXY Type with 10 X, 11 Y, and 11 Z bits. + + +// Samplers Types ------------------------------------------------------------------------------------------------------ + + SAMPLER_1D = GL_SAMPLER_1D, //!< 1D Texture Sampler + SAMPLER_1D_ARRAY = GL_SAMPLER_1D_ARRAY, //!< 1D Texture Sampler Array + SHADOW_SAMPLER_1D = GL_SAMPLER_1D_SHADOW, //!< 1D Shadow Texture Sampler + SHADOW_SAMPLER_1D_ARRAY = GL_SAMPLER_1D_ARRAY_SHADOW, //!< 1D Shadow Texture Sampler Array + SAMPLER_2D = GL_SAMPLER_2D, //!< 2D Texture Sampler + SAMPLER_2D_ARRAY = GL_SAMPLER_2D_ARRAY, //!< 2D Texture Sampler Array + SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT, //!< 2D Texture Rectangle Sampler + SAMPLER_2D_MS = GL_SAMPLER_2D_MULTISAMPLE, //!< 2D Multi-Sampled Texture Sampler + SAMPLER_2D_MS_ARRAY = GL_SAMPLER_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Texture Sampler Array + SHADOW_SAMPLER_2D = GL_SAMPLER_2D_SHADOW, //!< 2D Shadow Texture Sampler + SHADOW_SAMPLER_2D_ARRAY = GL_SAMPLER_2D_ARRAY_SHADOW, //!< 2D Shadow Texture Sampler Array + SHADOW_SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT_SHADOW, //!< 2D Shadow Texture Rectangle Sampler + CUBEMAP_SAMPLER = GL_SAMPLER_CUBE, //!< Cubemap Sampler + CUBEMAP_SAMPLER_ARRAY = GL_SAMPLER_CUBE_MAP_ARRAY, //!< Cubemap Sampler Array + SHADOW_CUBEMAP_SAMPLER = GL_SAMPLER_CUBE_SHADOW, //!< Shadow Cubemap Sampler + SHADOW_CUBEMAP_SAMPLER_ARRAY = GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, //!< Shadow Cubemap Sampler Array + SAMPLER_3D = GL_SAMPLER_3D, //!< 3D Texture Sampler + BUFFER_SAMPLER = GL_SAMPLER_BUFFER, //!< Buffer Texture Sampler + + ISAMPLER_1D = GL_INT_SAMPLER_1D, //!< 1D Integer Texture Sampler + ISAMPLER_1D_ARRAY = GL_INT_SAMPLER_1D_ARRAY, //!< 1D Integer Texture Sampler Array + ISAMPLER_2D = GL_INT_SAMPLER_2D, //!< 2D Integer Texture Sampler + ISAMPLER_2D_ARRAY = GL_INT_SAMPLER_2D_ARRAY, //!< 2D Integer Texture Sampler Array + ISAMPLER_RECT_2D = GL_INT_SAMPLER_2D_RECT, //!< 2D Integer Texture Rectangle Sampler + ISAMPLER_2D_MS = GL_INT_SAMPLER_2D_MULTISAMPLE, //!< 2D Integer Multi-Sampled Texture Sampler + ISAMPLER_2D_MS_ARRAY = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, //!< 2D Integer Multi-Sampled Texture Sampler Array + ISAMPLER_3D = GL_INT_SAMPLER_3D, //!< 3D Integer Texture Sampler + BUFFER_ISAMPLER = GL_INT_SAMPLER_BUFFER, //!< Integer Buffer Texture Sampler + CUBEMAP_ISAMPLER = GL_INT_SAMPLER_CUBE, //!< Integer Cubemap Sampler + CUBEMAP_ISAMPLER_ARRAY = GL_INT_SAMPLER_CUBE_MAP_ARRAY, //!< Integer Cubemap Sampler Array + + + USAMPLER_1D = GL_UNSIGNED_INT_SAMPLER_1D, //!< 1D Unsigned Integer Texture Sampler + USAMPLER_1D_ARRAY = GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, //!< 1D Unsigned Integer Texture Sampler Array + USAMPLER_2D = GL_UNSIGNED_INT_SAMPLER_2D, //!< 2D Unsigned Integer Texture Sampler + USAMPLER_2D_ARRAY = GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, //!< 2D Unsigned Integer Texture Sampler Array + USAMPLER_RECT_2D = GL_UNSIGNED_INT_SAMPLER_2D_RECT, //!< 2D Unsigned Integer Texture Rectangle Sampler + USAMPLER_2D_MS = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, //!< 2D Unsigned Integer Multi-Sampled Texture Sampler + USAMPLER_2D_MS_ARRAY = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, //!< 2D Unsigned Integer Multi-Sampled Texture Sampler Array + USAMPLER_3D = GL_UNSIGNED_INT_SAMPLER_3D, //!< 3D Unsigned Integer Texture Sampler + BUFFER_USAMPLER = GL_UNSIGNED_INT_SAMPLER_BUFFER, //!< Unsigned Integer Buffer Texture Sampler + CUBEMAP_USAMPLER = GL_UNSIGNED_INT_SAMPLER_CUBE, //!< Unsigned Integer Cubemap Sampler + CUBEMAP_USAMPLER_ARRAY = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, //!< Unsigned Integer Cubemap Sampler Array + + +// Image Types --------------------------------------------------------------------------------------------------------- + + IMAGE_1D = GL_IMAGE_1D, //!< 1D Image + IMAGE_1D_ARRAY = GL_IMAGE_1D_ARRAY, //!< 1D Image Array + IMAGE_2D = GL_IMAGE_2D, //!< 2D Image + IMAGE_2D_ARRAY = GL_IMAGE_2D_ARRAY, //!< 2D Image Array + IMAGE_RECT_2D = GL_IMAGE_2D_RECT, //!< 2D Image Rectangle + IMAGE_2D_MS = GL_IMAGE_2D_MULTISAMPLE, //!< 2D Multi-Sampled Image + IMAGE_2D_MS_ARRAY = GL_IMAGE_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Image Array + IMAGE_3D = GL_IMAGE_3D, //!< 3D Image + IMAGE_BUFFER = GL_IMAGE_BUFFER, //!< Image Buffer + IMAGE_CUBEMAP = GL_IMAGE_CUBE, //!< Cubemap Image + IMAGE_CUBEMAP_ARRAY = GL_IMAGE_CUBE_MAP_ARRAY, //!< Cubemap Image Array + + IIMAGE_1D = GL_INT_IMAGE_1D, //!< 1D Integer Image + IIMAGE_1D_ARRAY = GL_INT_IMAGE_1D_ARRAY, //!< 1D Integer Image Array + IIMAGE_2D = GL_INT_IMAGE_2D, //!< 2D Integer Image + IIMAGE_2D_ARRAY = GL_INT_IMAGE_2D_ARRAY, //!< 2D Integer Image Array + IIMAGE_RECT_2D = GL_INT_IMAGE_2D_RECT, //!< 2D Integer Image Rectangle + IIMAGE_2D_MS = GL_INT_IMAGE_2D_MULTISAMPLE, //!< 2D Multi-Sampled Integer Image + IIMAGE_2D_MS_ARRAY = GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Integer Image Array + IIMAGE_3D = GL_INT_IMAGE_3D, //!< 3D Integer Image + IIMAGE_BUFFER = GL_INT_IMAGE_BUFFER, //!< Integer Image Buffer + IIMAGE_CUBEMAP = GL_INT_IMAGE_CUBE, //!< Integer Cubemap Image + + UIMAGE_1D = GL_UNSIGNED_INT_IMAGE_1D, //!< 1D Unsigned Integer Image + UIMAGE_1D_ARRAY = GL_UNSIGNED_INT_IMAGE_1D_ARRAY, //!< 1D Unsigned Integer Image Array + UIMAGE_2D = GL_UNSIGNED_INT_IMAGE_2D, //!< 2D Unsigned Integer Image + UIMAGE_2D_ARRAY = GL_UNSIGNED_INT_IMAGE_2D_ARRAY, //!< 2D Unsigned Integer Image Array + UIMAGE_RECT_2D = GL_UNSIGNED_INT_IMAGE_2D_RECT, //!< 2D Unsigned Integer Image Rectangle + UIMAGE_2D_MS = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, //!< 2D Multi-Sampled Unsigned Integer Image + UIMAGE_2D_MS_ARRAY = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Unsigned Integer Image Array + UIMAGE_3D = GL_UNSIGNED_INT_IMAGE_3D, //!< 3D Unsigned Integer Image + UIMAGE_BUFFER = GL_UNSIGNED_INT_IMAGE_BUFFER, //!< Unsigned Integer Image Buffer + UIMAGE_CUBEMAP = GL_UNSIGNED_INT_IMAGE_CUBE, //!< Unsigned Integer Cubemap Image + + UINT_ATOMIC_COUNTER = GL_UNSIGNED_INT_ATOMIC_COUNTER, //!< Atomic Counter }; -enum component_ : GLenum { - ZERO = GL_ZERO, - ONE = GL_ONE, - R = GL_RED, - G = GL_GREEN, - B = GL_BLUE, - A = GL_ALPHA, - RGB = GL_RGB, - BGR = GL_BGR, - RGBA = GL_RGBA, - BGRA = GL_BGRA, - RI = GL_RED_INTEGER, - GI = GL_GREEN_INTEGER, - BI = GL_BLUE_INTEGER, - AI = GL_ALPHA_INTEGER, - RGBI = GL_RGB_INTEGER, - BGRI = GL_BGR_INTEGER, - RGBAI = GL_RGBA_INTEGER, - BGRAI = GL_BGRA_INTEGER, - STENCIL = GL_STENCIL_INDEX, - DEPTH = GL_DEPTH_COMPONENT, - DEPTH_STENCIL = GL_DEPTH_STENCIL, +/// +/// \brief OpenGL Pixel Components +enum pixel_components : GLenum { + ZERO = GL_ZERO, //!< Interpret as 0 + ONE = GL_ONE, //!< Interpret as 1 + R = GL_RED, //!< Red Component + G = GL_GREEN, //!< Green Component + B = GL_BLUE, //!< Blue Component + A = GL_ALPHA, //!< Alpha Component + RGB = GL_RGB, //!< Combined Red-Green-Blue + BGR = GL_BGR, //!< Combined Blue-Green-Red + RGBA = GL_RGBA, //!< Combined Red-Green-Blue-Alpha + BGRA = GL_BGRA, //!< Combined Blue-Green-Red-Alpha + + R_INT = GL_RED_INTEGER, //!< Integral Red Component + G_INT = GL_GREEN_INTEGER, //!< Integral Green Component + B_INT = GL_BLUE_INTEGER, //!< Integral Blue Component + A_INT = GL_ALPHA_INTEGER_EXT, //!< Integral Alpha Component + RGB_INT = GL_RGB_INTEGER, //!< Combined Red-Green-Blue + BGR_INT = GL_BGR_INTEGER, //!< Combined Blue-Green-Red + RGBA_INT = GL_RGBA_INTEGER, //!< Combined Red-Green-Blue-Alpha + BGRA_INT = GL_BGRA_INTEGER, //!< Combined Blue-Green-Red-Alpha + + STENCIL = GL_STENCIL_INDEX, //!< Stencil Component + DEPTH = GL_DEPTH_COMPONENT, //!< Depth Component + DEPTH_STENCIL = GL_DEPTH_STENCIL, //!< Combined Depth-Stencil }; -enum format_ : GLint { - R8 = GL_R8, - R8_SNORM = GL_R8_SNORM, - R16 = GL_R16, - R16_SNORM = GL_R16_SNORM, +/// +/// \brief OpenGL Color Formats +/// \note UNORM formats are integers interpreted in the normalized range \f$[0.0, 1.0]\f$ +/// \note SNORM formats are integers interpreted in the normalized range \f$[-1.0, 1.0]\f$ +enum pixel_formats : GLint { + R8_UNORM = GL_R8, //!< 8-Bit Unsigned Normalized Single Component Color + R8_SNORM = GL_R8_SNORM, //!< 8-Bit Signed Normalized Single Component Color + R16_UNORM = GL_R16, //!< 16-Bit Unsigned Normalized Single Component Color + R16_SNORM = GL_R16_SNORM, //!< 16-Bit Signed Normalized Single Component Color - RG8 = GL_RG8, - RG8_SNORM = GL_RG8_SNORM, - RG16 = GL_RG16, - RG16_SNORM = GL_RG16_SNORM, + RG8_UNORM = GL_RG8, //!< 8-Bit Unsigned Normalized Two Component Color + RG8_SNORM = GL_RG8_SNORM, //!< 8-Bit Signed Normalized Two Component Color + RG16_UNORM = GL_RG16, //!< 16-Bit Unsigned Normalized Two Component Color + RG16_SNORM = GL_RG16_SNORM, //!< 16-Bit Signed Normalized Two Component Color - RGB332 = GL_R3_G3_B2, - RGB4 = GL_RGB4, - RGB5 = GL_RGB5, - RGB8 = GL_RGB8, - RGB8_SNORM = GL_RGB8_SNORM, - RGB10 = GL_RGB10, - RGB12 = GL_RGB12, - RGB16 = GL_RGB16, - RGB16_SNORM = GL_RGB16_SNORM, + RGB4_UNORM = GL_RGB4, //!< 4-Bit Unsigned Normalized Three Component Color + RGB5_UNORM = GL_RGB5, //!< 5-Bit Unsigned Normalized Three Component Color + RGB8_UNORM = GL_RGB8, //!< 8-Bit Unsigned Normalized Three Component Color + RGB8_SNORM = GL_RGB8_SNORM, //!< 8-Bit Signed Normalized Three Component Color + RGB10_UNORM = GL_RGB10, //!< 10-Bit Unsigned Normalized Three Component Color + RGB12_UNORM = GL_RGB12, //!< 12-Bit Unsigned Normalized Three Component Color + RGB16_UNORM = GL_RGB16, //!< 16-Bit Unsigned Normalized Three Component Color + RGB16_SNORM = GL_RGB16_SNORM, //!< 16-Bit Signed Normalized Three Component Color - RGBA2 = GL_RGBA2, - RGBA4 = GL_RGBA4, - RGB5_A1 = GL_RGB5_A1, - RGBA8 = GL_RGBA8, - RGBA8_SNORM = GL_RGBA8_SNORM, - RGB10_A2 = GL_RGB10_A2, - RGB10_A2UI = GL_RGB10_A2UI, - RGBA12 = GL_RGBA12, - RGBA16 = GL_RGBA16, + RGB332_UNORM = GL_R3_G3_B2, //!< Packed 8-Bit Unsigned Normalized Three Component Color - SRGB8 = GL_SRGB8, - SRGBA8 = GL_SRGB8_ALPHA8, + RGBA2_UNORM = GL_RGBA2, //!< 2-Bit Unsigned Normalized Four Component Color + RGBA4_UNORM = GL_RGBA4, //!< 4-Bit Unsigned Normalized Four Component Color + RGBA8_UNORM = GL_RGBA8, //!< 8-Bit Unsigned Normalized Four Component Color + RGBA8_SNORM = GL_RGBA8_SNORM, //!< 8-Bit Unsigned Normalized Four Signed Normalized Component Color + RGBA12_UNORM = GL_RGBA12, //!< 12-Bit Unsigned Normalized Four Component Color + RGBA16_UNORM = GL_RGBA16, //!< 16-Bit Unsigned Normalized Four Component Color - R16F = GL_R16F, - RG16F = GL_RG16F, - RGB16F = GL_RGB16F, - RGBA16F = GL_RGBA16F, + RGB5_A1_UNORM = GL_RGB5_A1, //!< Packed 16-Bit Unsigned Normalized Four Component Color + RGB10_A2_UNORM = GL_RGB10_A2, //!< Packed 32-Bit Unsigned Normalized Four Component Color - R32F = GL_R32F, - RG32F = GL_RG32F, - RGB32F = GL_RGB32F, - RGBA32F = GL_RGBA32F, + SRGB8 = GL_SRGB8, //!< 8-Bit sRGB Color + SRGBA8 = GL_SRGB8_ALPHA8, //!< 8-Bit sRGB Color With Linear Alpha - R8I = GL_R8I, - RG8I = GL_RG8I, - RGB8I = GL_RGB8I, - RGBA8I = GL_RGBA8I, + R16_FLOAT = GL_R16F, //!< 16-Bit Floating-Point Single Component Color + RG16_FLOAT = GL_RG16F, //!< 16-Bit Floating-Point Two Component Color + RGB16_FLOAT = GL_RGB16F, //!< 16-Bit Floating-Point Three Component Color + RGBA16_FLOAT = GL_RGBA16F, //!< 16-Bit Floating-Point Four Component Color - R16I = GL_R16I, - RG16I = GL_RG16I, - RGB16I = GL_RGB16I, - RGBA16I = GL_RGBA16I, + R32_FLOAT = GL_R32F, //!< 32-Bit Floating-Point Single Component Color + RG32_FLOAT = GL_RG32F, //!< 32-Bit Floating-Point Two Component Color + RGB32_FLOAT = GL_RGB32F, //!< 32-Bit Floating-Point Three Component Color + RGBA32_FLOAT = GL_RGBA32F, //!< 32-Bit Floating-Point Four Component Color - R32I = GL_R32I, - RG32I = GL_RG32I, - RGB32I = GL_RGB32I, - RGBA32I = GL_RGBA32I, + R8_INT = GL_R8I, //!< 8-Bit Integral Single Component Color + RG8_INT = GL_RG8I, //!< 8-Bit Integral Two Component Color + RGB8_INT = GL_RGB8I, //!< 8-Bit Integral Three Component Color + RGBA8_INT = GL_RGBA8I, //!< 8-Bit Integral Four Component Color - R8UI = GL_R8UI, - RG8UI = GL_RG8UI, - RGB8UI = GL_RGB8UI, - RGBA8UI = GL_RGBA8UI, + R16_INT = GL_R16I, //!< 16-Bit Integral Single Component Color + RG16_INT = GL_RG16I, //!< 16-Bit Integral Two Component Color + RGB16_INT = GL_RGB16I, //!< 16-Bit Integral Three Component Color + RGBA16_INT = GL_RGBA16I, //!< 16-Bit Integral Four Component Color - R16UI = GL_R16UI, - RG16UI = GL_RG16UI, - RGB16UI = GL_RGB16UI, - RGBA16UI = GL_RGBA16UI, + R32_INT = GL_R32I, //!< 32-Bit Integral Single Component Color + RG32_INT = GL_RG32I, //!< 32-Bit Integral Two Component Color + RGB32_INT = GL_RGB32I, //!< 32-Bit Integral Three Component Color + RGBA32_INT = GL_RGBA32I, //!< 32-Bit Integral Four Component Color - R32UI = GL_R32UI, - RG32UI = GL_RG32UI, - RGB32UI = GL_RGB32UI, - RGBA32UI = GL_RGBA32UI, + R8_UINT = GL_R8UI, //!< 8-Bit Unsigned Integral Single Component Color + RG8_UINT = GL_RG8UI, //!< 8-Bit Unsigned Integral Two Component Color + RGB8_UINT = GL_RGB8UI, //!< 8-Bit Unsigned Integral Three Component Color + RGBA8_UINT = GL_RGBA8UI, //!< 8-Bit Unsigned Integral Four Component Color - RGB_DXT1 = GL_COMPRESSED_RGB_S3TC_DXT1_EXT, - RGBA_DXT1 = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, - RGBA_DXT3 = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, - RGBA_DXT5 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + R16_UINT = GL_R16UI, //!< 16-Bit Unsigned Integral Single Component Color + RG16_UINT = GL_RG16UI, //!< 16-Bit Unsigned Integral Two Component Color + RGB16_UINT = GL_RGB16UI, //!< 16-Bit Unsigned Integral Three Component Color + RGBA16_UINT = GL_RGBA16UI, //!< 16-Bit Unsigned Integral Four Component Color + RGB10_A2_UINT = GL_RGB10_A2UI, //!< Packed 32-Bit Unsigned Integral Four Component Color - SRGB_DXT1 = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, - SRGBA_DXT1 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, - SRGBA_DXT3 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, - SRGBA_DXT5 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, + R32UI = GL_R32UI, //!< 32-Bit Unsigned Integral Single Component Color + RG32UI = GL_RG32UI, //!< 32-Bit Unsigned Integral Two Component Color + RGB32UI = GL_RGB32UI, //!< 32-Bit Unsigned Integral Three Component Color + RGBA32UI = GL_RGBA32UI, //!< 32-Bit Unsigned Integral Four Component Color + + RGB_DXT1 = GL_COMPRESSED_RGB_S3TC_DXT1_EXT, //!< Compressed RGB DXT1 Color + RGBA_DXT1 = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, //!< Compressed RGBA DXT1 Color + RGBA_DXT3 = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, //!< Compressed RGBA DXT3 Color + RGBA_DXT5 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, //!< Compressed RGBA DXT5 Color + + SRGB_DXT1 = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, //!< Compressed sRGB DXT1 Color + SRGBA_DXT1 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, //!< Compressed sRGBA DXT1 Color + SRGBA_DXT3 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, //!< Compressed sRGBA DXT3 Color + SRGBA_DXT5 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, //!< Compressed sRGBA DXT5 Color }; } diff --git a/include/fennec/renderers/opengl/lib/fwd.h b/include/fennec/renderers/opengl/lib/forward.h similarity index 76% rename from include/fennec/renderers/opengl/lib/fwd.h rename to include/fennec/renderers/opengl/lib/forward.h index d2a8bb5..cfc98cf 100644 --- a/include/fennec/renderers/opengl/lib/fwd.h +++ b/include/fennec/renderers/opengl/lib/forward.h @@ -16,8 +16,20 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_RENDERERS_OPENGL_LIB_FWD_H -#define FENNEC_RENDERERS_OPENGL_LIB_FWD_H +/// +/// \file fennec/renderers/opengl/lib/forward.h +/// \brief +/// +/// +/// \details +/// \author Medusa Slockbower +/// +/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) +/// +/// + +#ifndef FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H +#define FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H #include @@ -35,4 +47,4 @@ template class texture; } -#endif // FENNEC_RENDERERS_OPENGL_LIB_FWD_H +#endif // FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H diff --git a/include/fennec/renderers/opengl/lib/texture.h b/include/fennec/renderers/opengl/lib/texture.h index 4855a4f..eb6176d 100644 --- a/include/fennec/renderers/opengl/lib/texture.h +++ b/include/fennec/renderers/opengl/lib/texture.h @@ -16,6 +16,18 @@ // along with this program. If not, see . // ===================================================================================================================== +/// +/// \file fennec/renderers/opengl/lib/texture.h +/// \brief +/// +/// +/// \details +/// \author Medusa Slockbower +/// +/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) +/// +/// + #ifndef FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H #define FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H @@ -56,23 +68,23 @@ namespace fennec namespace gl { -template using texture1d = texture; -template using texture1d_array = texture; -template using texture2d = texture; -template using texture2d_array = texture; -template using texture_rect = texture; -template using texture2d_ms = texture; -template using texture2d_ms_array = texture; -template using cubemap = texture; -template using cubemap_array = texture; -template using texture3d = texture; -template using buffer_texture = texture; +template using texture1d = texture; +template using texture1d_array = texture; +template using texture2d = texture; +template using texture2d_array = texture; +template using texture_rect = texture; +template using texture2d_ms = texture; +template using texture2d_ms_array = texture; +template using cubemap = texture; +template using cubemap_array = texture; +template using texture3d = texture; +template using buffer_texture = texture; /// /// \brief Wrapper for OpenGL Texture Objects /// \tparam TypeV The type of the texture -/// \tparam FormatV The internal format of the texels -/// \tparam ImmutableV Whether the texture is immutable, i.e. cannot be resized after creation +/// \tparam FormatV The internal pixel format +/// \tparam ImmutableV Mutability /// /// \details Immutable textures require EXT_texture_storage or ARB_texture_storage /// Immutable multisample textures require ARB_texture_storage_multisample of OES_texture_storage_multisample_2d_array @@ -85,14 +97,14 @@ public: static constexpr GLenum type = TypeV; static constexpr GLint format = FormatV; static constexpr GLboolean immutable = ImmutableV; - static constexpr GLboolean is_rect = type == TEX_RECT; - static constexpr GLboolean is_buffered = type == TEX_BUFFER; - static constexpr GLboolean sampled = type == TEX_2D_MS or type == TEX_2D_MS_ARRAY; - static constexpr GLboolean cubemap = type == TEX_CUBEMAP or type == TEX_CUBEMAP_ARRAY; - static constexpr GLboolean is_1d = type == TEX_1D or type == TEX_1D_ARRAY; - static constexpr GLboolean is_2d = sampled or is_rect or type == TEX_2D or type == TEX_2D_ARRAY or cubemap; - static constexpr GLboolean is_array = TypeV == TEX_1D_ARRAY or TypeV == TEX_2D_ARRAY or type == TEX_2D_MS_ARRAY or type == TEX_CUBEMAP_ARRAY; - static constexpr GLboolean is_3d = TypeV == TEX_3D; + static constexpr GLboolean is_rect = type == TEXTURE_RECTANGLE; + static constexpr GLboolean is_buffered = type == BUFFER_TEXTURE; + static constexpr GLboolean sampled = type == TEXTURE_2D_MS or type == TEXTURE_2D_MS_ARRAY; + static constexpr GLboolean cubemap = type == CUBEMAP or type == CUBEMAP_ARRAY; + static constexpr GLboolean is_1d = type == TEXTURE_1D or type == TEXTURE_1D_ARRAY; + static constexpr GLboolean is_2d = sampled or is_rect or type == TEXTURE_2D or type == TEXTURE_2D_ARRAY or cubemap; + static constexpr GLboolean is_array = type == TEXTURE_1D_ARRAY or type == TEXTURE_2D_ARRAY or type == TEXTURE_2D_MS_ARRAY or type == CUBEMAP_ARRAY; + static constexpr GLboolean is_3d = type == TEXTURE_3D; static constexpr GLboolean has_mipmaps = not(sampled or is_rect or is_buffered); static constexpr GLboolean use_1d = is_1d and not is_array; @@ -290,17 +302,13 @@ public: // Basic Functions ===================================================================================================== - void start() { + void use() { glBindTexture(type, _handle); } - void end() { - glBindTexture(type, NULL); - } - void bind(GLint i) { glActiveTexture(GL_TEXTURE0 + i); - start(); + use(); } void genmips() { diff --git a/include/fennec/renderers/opengl/lib/vertex_array.h b/include/fennec/renderers/opengl/lib/vertex_array.h index 67472ca..d5d0228 100644 --- a/include/fennec/renderers/opengl/lib/vertex_array.h +++ b/include/fennec/renderers/opengl/lib/vertex_array.h @@ -16,6 +16,18 @@ // along with this program. If not, see . // ===================================================================================================================== +/// +/// \file fennec/renderers/opengl/lib/vertex_array.h +/// \brief +/// +/// +/// \details +/// \author Medusa Slockbower +/// +/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) +/// +/// + #ifndef FENNEC_RENDERERS_OPENGL_LIB_VERTEX_ARRAY_H #define FENNEC_RENDERERS_OPENGL_LIB_VERTEX_ARRAY_H @@ -39,14 +51,10 @@ public: glDeleteVertexArrays(1, &_handle); } - constexpr void start() const { + constexpr void use() const { glBindVertexArray(_handle); } - constexpr void end() const { - glBindVertexArray(NULL); - } - constexpr void set_attribute(GLuint i, GLenum type, GLint n, GLintptr offset, GLboolean normalized = false) { glVertexAttribFormat(i, n, type, normalized, offset); glEnableVertexAttribArray(i); diff --git a/include/fennec/renderers/vulkan/lib/app_info.h b/include/fennec/renderers/vulkan/lib/app_info.h index a52e267..7b15631 100644 --- a/include/fennec/renderers/vulkan/lib/app_info.h +++ b/include/fennec/renderers/vulkan/lib/app_info.h @@ -46,6 +46,10 @@ struct app_info : private VkApplicationInfo { // Constructors & Destructor =========================================================================================== public: + + /// \name Constructors & Destructor + /// @{ + /// /// \brief Create a Vulkan application information structure /// \param app_name the name of the application, this cstring must exist for the lifetime of this object @@ -86,37 +90,58 @@ public: /// \brief Destructor ~app_info() noexcept = default; + /// @} + // Assignment Operators ================================================================================================ public: + /// \name Assignment Operators + /// @{ + /// /// \brief Copy Assignment - app_info& operator=(const app_info&) noexcept = default; + /// \param info The app_info object to move + /// \returns A reference to self + app_info& operator=(const app_info& info) noexcept = default; /// /// \brief Move Assignment - app_info& operator=(app_info&&) noexcept = default; + /// \param info The app_info object to move + /// \returns A reference to self + app_info& operator=(app_info&& info) noexcept = default; + + /// @} // Implicit Conversions ================================================================================================ public: + /// \name Implicit Conversions + /// @{ + /// + /// \returns \f$this\f$ as if it were a pointer to the underlying type, \f$VkApplicationInfo\f$. operator VkApplicationInfo*() noexcept { return this; } /// /// \brief Implicit Pointer Conversion + /// \returns \f$this\f$ as if it were a pointer to the underlying type, \f$VkApplicationInfo\f$. operator const VkApplicationInfo*() const noexcept { return this; } + /// @} + // Properties ========================================================================================================== public: + /// \name Properties + /// @{ + /// /// \returns A cstring containing the application name cstring get_app_name() const { @@ -202,8 +227,10 @@ public: pNext = nullptr; } + /// @} -// Private Members ===================================================================================================== + +// Private Member Variables ============================================================================================ private: }; diff --git a/include/fennec/renderers/vulkan/vkcontext.h b/include/fennec/renderers/vulkan/vkcontext.h index dbe105e..1816b00 100644 --- a/include/fennec/renderers/vulkan/vkcontext.h +++ b/include/fennec/renderers/vulkan/vkcontext.h @@ -32,7 +32,7 @@ #ifndef FENNEC_PLATFORM_VULKAN_VKCONTEXT_H #define FENNEC_PLATFORM_VULKAN_VKCONTEXT_H -#include +#include #include namespace fennec diff --git a/include/fennec/rtti/detail/_this_t.h b/include/fennec/rtti/detail/_this_t.h index aecee20..6a3e240 100644 --- a/include/fennec/rtti/detail/_this_t.h +++ b/include/fennec/rtti/detail/_this_t.h @@ -18,14 +18,8 @@ #ifndef FENNEC_RTTI_DETAIL_THIS_T_H #define FENNEC_RTTI_DETAIL_THIS_T_H -#include -#define FENNEC_DEFINE_THIS_T \ -private: \ - struct _this_t_tag {}; \ - constexpr auto _this_t_helper() -> decltype(fennec::detail::_this::writer<_this_t_tag, decltype(this)>{}, void()) {} \ -public: \ - using this_t = fennec::detail::_this::read<_this_t_tag> +#include namespace fennec::detail { diff --git a/include/fennec/rtti/enable.h b/include/fennec/rtti/enable.h index 61a3f2a..4e2e8f9 100644 --- a/include/fennec/rtti/enable.h +++ b/include/fennec/rtti/enable.h @@ -36,8 +36,12 @@ #include #include -#include +#include +/// +/// \brief Enable the class of the current scope for Run-Time Type Information +/// +/// \details Any base classes that need to be reflected on should be included as parameters. #define FENNEC_RTTI_CLASS_ENABLE(...) \ public: \ /*! \name RTTI */ \ @@ -47,7 +51,6 @@ public: \ using super_class_list = fennec::typelist<__VA_ARGS__>; \ /*! \brief Getter for the object type */ \ virtual inline fennec::type get_type() const { return fennec::type::get_from_instance(this); } \ - /*! \brief Definition of \f$this\_t\f$, used for RTTI */ \ FENNEC_DEFINE_THIS_T; \ /*! @} */ \ private: \ diff --git a/include/fennec/rtti/this_t.h b/include/fennec/rtti/this_t.h new file mode 100644 index 0000000..035b92d --- /dev/null +++ b/include/fennec/rtti/this_t.h @@ -0,0 +1,47 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +/// +/// \file this_t.h +/// \brief +/// +/// +/// \details +/// \author Medusa Slockbower +/// +/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) +/// +/// + + +#ifndef FENNEC_RTTI_THIS_T_H +#define FENNEC_RTTI_THIS_T_H + +#include + +/// +/// \brief Deduces the type of the current class / struct scope and aliases it as \f$this\_t\f$. +#define FENNEC_DEFINE_THIS_T \ +private: \ +struct _this_t_tag {}; \ +constexpr auto _this_t_helper() -> decltype(fennec::detail::_this::writer<_this_t_tag, decltype(this)>{}, void()) {} \ +public: \ +/*! \brief Definition of \f$this\_t\f$, used for RTTI */ \ +using this_t = fennec::detail::_this::read<_this_t_tag> + +#endif // FENNEC_RTTI_THIS_T_H \ No newline at end of file diff --git a/include/fennec/scene/component.h b/include/fennec/scene/component.h index 9c5eb36..64cd3ea 100644 --- a/include/fennec/scene/component.h +++ b/include/fennec/scene/component.h @@ -31,7 +31,7 @@ namespace fennec class component { public: -// MEMBERS ============================================================================================================= +// Public Member Variables ============================================================================================= public: /// /// \brief reference to the diff --git a/include/fennec/scene/node2d.h b/include/fennec/scene/node2d.h index f8865ac..1ad6ae2 100644 --- a/include/fennec/scene/node2d.h +++ b/include/fennec/scene/node2d.h @@ -165,7 +165,7 @@ public: return _global; } -// Fields ============================================================================================================== +// Private Member Variables ============================================================================================ private: bool _mobility; vec2 _position; @@ -175,7 +175,7 @@ private: mat3 _local, _global; -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== constexpr void _recalculate(const mat3& parent) { _local = fennec::rotation(_rotation); diff --git a/include/fennec/scene/scene_node.h b/include/fennec/scene/scene_node.h index a4f52de..9bbdc8c 100644 --- a/include/fennec/scene/scene_node.h +++ b/include/fennec/scene/scene_node.h @@ -42,7 +42,7 @@ namespace fennec struct scene_node { -// Public Members ====================================================================================================== +// Public Member Variables ============================================================================================= public: scene* const scene; const size_t id; diff --git a/include/fennec/string/cstring.h b/include/fennec/string/cstring.h index 63eb4df..6dcde44 100644 --- a/include/fennec/string/cstring.h +++ b/include/fennec/string/cstring.h @@ -269,7 +269,7 @@ public: /// /// \brief String Equality /// \param str the string to compare against - /// \returns True if all characters are equal, false otherwise + /// \returns \f$true\f$ if all characters are equal, \f$false\f$ otherwise template constexpr bool operator==(const char (&str)[n]) const { return compare(cstring(str)) == 0; @@ -278,11 +278,18 @@ public: /// /// \brief String Equality /// \param str the string to compare against - /// \returns True if all characters are equal, false otherwise + /// \returns \f$true\f$ if all characters are equal, \f$false\f$ otherwise constexpr bool operator==(const cstring& str) const { return compare(str) == 0; } + /// + /// \brief nullptr Equality + /// \returns \f$true\f$ if there is no held string, \f$false\f$ otherwise. + constexpr bool operator==(nullptr_t) const { + return _cstr == nullptr; + } + /// /// \brief Finds the index of the first occurrence of \f$c\f$ in the string /// \param c the character to find diff --git a/include/fennec/string/string.h b/include/fennec/string/string.h index ca2753e..3e96999 100644 --- a/include/fennec/string/string.h +++ b/include/fennec/string/string.h @@ -42,7 +42,11 @@ using string = _string<>; template struct _string { +// Definitions ========================================================================================================= public: + + + static constexpr size_t npos = -1; //!< null position using char_t = char; //!< the character type using alloc_t = allocation; //!< the allocator type @@ -61,7 +65,7 @@ public: /// \param n the number of characters /// \param c the character to fill with /// - /// \details adds additional character for null termination. + /// \details Adds additional character for null termination. constexpr _string(size_t n, char c = '\0') : _str(n + 1) { fennec::memset(_str, c, n); @@ -80,7 +84,7 @@ public: /// \param c the character to fill with /// \param alloc The allocator to use /// - /// \details adds additional character for null termination. + /// \details Adds additional character for null termination. constexpr _string(size_t n, char c, const alloc_t& alloc) : _str(n + 1, alloc) { fennec::memset(_str, c, n); @@ -149,7 +153,7 @@ public: /// \param cstr The C-Style string to assign. /// \returns A reference to self constexpr _string& operator=(const cstring& cstr) { - _str.callocate(cstr.capacity()); + _str.allocate(cstr.capacity()); fennec::memcpy(_str, cstr, cstr.capacity()); return *this; } @@ -404,7 +408,7 @@ public: } n = fennec::min(n, size() - i); _string res; - res._str.callocate(n + 1); + res._str.allocate(n + 1); fennec::memcpy(res.data(), _str + i, n); return res; } @@ -418,7 +422,7 @@ public: /// \brief Resizes the underlying allocation to hold \f$n\f$ characters and a null terminator. /// \param n The new size of the string constexpr void resize(size_t n) { - _str.creallocate(n + 1); + _str.reallocate(n + 1); _str[size()] = '\0'; } @@ -431,7 +435,7 @@ public: return _string(1, c); } _string res; - res._str.callocate(capacity() + 1); + res._str.allocate(capacity() + 1); fennec::memcpy(res.data(), _str, size()); res[size()] = c; return res; @@ -456,7 +460,7 @@ public: return _string(cstr); } _string res; - res._str.callocate(size() + cstr.size() + 1); + res._str.allocate(size() + cstr.size() + 1); fennec::memcpy(res.data(), _str, size()); fennec::memcpy(res.data() + size(), cstr, cstr.size()); return res; @@ -474,7 +478,7 @@ public: return _string(*this); } _string res; - res._str.callocate(size() + str.size() + 1); + res._str.allocate(size() + str.size() + 1); fennec::memcpy(res.data(), _str, size()); fennec::memcpy(res.data() + size(), str.data(), str.size()); return res; @@ -486,11 +490,11 @@ public: /// \returns \f$this\f$ string containing an additional character \f$c\f$. constexpr _string& operator+=(char c) { if (_str == nullptr) { - _str.callocate(2); + _str.allocate(2); _str[0] = c; return *this; } - _str.creallocate(capacity() + 1); + _str.reallocate(capacity() + 1); _str[size() - 1] = c; return *this; } @@ -503,7 +507,7 @@ public: return *this = cstr; } size_t middle = size(); - _str.creallocate(middle + cstr.size() + 1); + _str.reallocate(middle + cstr.size() + 1); fennec::memcpy(_str + middle, cstr, cstr.size()); return *this; } @@ -520,7 +524,7 @@ public: return *this; } size_t middle = size(); - _str.creallocate(middle + str.size() + 1); + _str.reallocate(middle + str.size() + 1); fennec::memcpy(_str + middle, str.data(), str.size()); return *this; } diff --git a/include/fennec/string/wcstring.h b/include/fennec/string/wcstring.h index 609a456..65c2e91 100644 --- a/include/fennec/string/wcstring.h +++ b/include/fennec/string/wcstring.h @@ -266,6 +266,13 @@ public: return compare(str) == 0; } + /// + /// \brief nullptr Equality + /// \returns \f$true\f$ if there is no held string, \f$false\f$ otherwise. + constexpr bool operator==(nullptr_t) const { + return _cstr == nullptr; + } + /// /// \brief Finds the index of the first occurrence of \f$c\f$ in the string /// \param c the character to find diff --git a/include/fennec/string/wstring.h b/include/fennec/string/wstring.h index e6e65b7..5f28ca0 100644 --- a/include/fennec/string/wstring.h +++ b/include/fennec/string/wstring.h @@ -142,7 +142,7 @@ public: /// \param cstr The C-Style string to assign. /// \returns A reference to self constexpr _wstring& operator=(const wcstring& cstr) { - _str.callocate(cstr.capacity()); + _str.allocate(cstr.capacity()); fennec::memcpy(_str, cstr, cstr.capacity()); return *this; } @@ -397,7 +397,7 @@ public: } n = fennec::min(n, size() - i); _wstring res; - res._str.callocate(n + 1); + res._str.allocate(n + 1); fennec::wmemcpy(res.data(), _str + i, n); return res; } @@ -411,7 +411,7 @@ public: /// \brief Resizes the underlying allocation to hold \f$n\f$ characters and a null terminator. /// \param n The new size of the string constexpr void resize(size_t n) { - _str.creallocate(n + 1); + _str.reallocate(n + 1); _str[size()] = '\0'; } @@ -424,7 +424,7 @@ public: return _wstring(1, c); } _wstring res; - res._str.callocate(capacity() + 1); + res._str.allocate(capacity() + 1); fennec::wmemcpy(res.data(), _str, size()); res[size()] = c; return res; @@ -447,7 +447,7 @@ public: return _wstring(cstr); } _wstring res; - res._str.callocate(size() + cstr.size() + 1); + res._str.allocate(size() + cstr.size() + 1); fennec::wmemcpy(res.data(), _str, size()); fennec::wmemcpy(res.data() + size(), cstr, cstr.size()); return res; @@ -465,7 +465,7 @@ public: return _wstring(*this); } _wstring res; - res._str.callocate(size() + str.size() + 1); + res._str.allocate(size() + str.size() + 1); fennec::wmemcpy(res.data(), _str, size()); fennec::wmemcpy(res.data() + size(), str.data(), str.size()); return res; @@ -477,11 +477,11 @@ public: /// \returns \f$this\f$ string containing an additional character \f$c\f$. constexpr _wstring& operator+=(wchar_t c) { if (_str == nullptr) { - _str.callocate(2); + _str.allocate(2); _str[0] = c; return *this; } - _str.creallocate(capacity() + 1); + _str.reallocate(capacity() + 1); _str[size() - 1] = c; return *this; } @@ -494,7 +494,7 @@ public: return *this = cstr; } size_t middle = size(); - _str.creallocate(middle + cstr.size() + 1); + _str.reallocate(middle + cstr.size() + 1); fennec::wmemcpy(_str + middle, cstr, cstr.size()); return *this; } @@ -511,7 +511,7 @@ public: return *this; } size_t middle = size(); - _str.creallocate(middle + str.size() + 1); + _str.reallocate(middle + str.size() + 1); fennec::wmemcpy(_str + middle, str.data(), str.size()); return *this; } diff --git a/metaprogramming/float.h b/metaprogramming/float.h index 72ce485..2b4ec4e 100644 --- a/metaprogramming/float.h +++ b/metaprogramming/float.h @@ -26,165 +26,268 @@ inline void float_h() { std::ofstream out("fennec/lang/float.h"); - out << "// =====================================================================================================================" << std::endl; - out << "// fennec, a free and open source game engine" << std::endl; - out << "// Copyright © 2025 - 2026 Medusa Slockbower" << std::endl; - out << "//" << std::endl; - out << "// This program is free software: you can redistribute it and/or modify" << std::endl; - out << "// it under the terms of the GNU General Public License as published by" << std::endl; - out << "// the Free Software Foundation, either version 3 of the License, or" << std::endl; - out << "// (at your option) any later version." << std::endl; - out << "//" << std::endl; - out << "// This program is distributed in the hope that it will be useful," << std::endl; - out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl; - out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl; - out << "// GNU General Public License for more details." << std::endl; - out << "//" << std::endl; - out << "// You should have received a copy of the GNU General Public License" << std::endl; - out << "// along with this program. If not, see ." << std::endl; - out << "// =====================================================================================================================" << std::endl; + out << "// =====================================================================================================================" << '\n'; + out << "// fennec, a free and open source game engine" << '\n'; + out << "// Copyright © 2025 - 2026 Medusa Slockbower" << '\n'; + out << "//" << '\n'; + out << "// This program is free software: you can redistribute it and/or modify" << '\n'; + out << "// it under the terms of the GNU General Public License as published by" << '\n'; + out << "// the Free Software Foundation, either version 3 of the License, or" << '\n'; + out << "// (at your option) any later version." << '\n'; + out << "//" << '\n'; + out << "// This program is distributed in the hope that it will be useful," << '\n'; + out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << '\n'; + out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << '\n'; + out << "// GNU General Public License for more details." << '\n'; + out << "//" << '\n'; + out << "// You should have received a copy of the GNU General Public License" << '\n'; + out << "// along with this program. If not, see ." << '\n'; + out << "// =====================================================================================================================" << '\n'; - out << "" << std::endl; + out << "" << '\n'; - out << "///" << std::endl; - out << "/// \\file fennec/lang/float.h" << std::endl; - out << "/// \\brief metaprogramming floating point type info" << std::endl; - out << "///" << std::endl; - out << "///" << std::endl; - out << "/// \\details this file is automatically generated for the current build environment" << std::endl; - out << "///" << std::endl; - out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl; - out << "///" << std::endl; - out << "///" << std::endl; + out << "///" << '\n'; + out << "/// \\file fennec/lang/float.h" << '\n'; + out << "/// \\brief metaprogramming floating point type info" << '\n'; + out << "///" << '\n'; + out << "///" << '\n'; + out << "/// \\details This file is automatically generated for the current build environment." << '\n'; + out << "///" << '\n'; + out << "/// Environment for this build: " FENNEC_LONG_COMPILER_NAME << '\n'; + out << "///" << '\n'; + out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << '\n'; + out << "///" << '\n'; + out << "///" << '\n'; - out << "" << std::endl; + out << "" << '\n'; - out << "#ifndef FENNEC_LANG_FLOAT_H" << std::endl; - out << "#define FENNEC_LANG_FLOAT_H" << std::endl; + out << "#ifndef FENNEC_LANG_FLOAT_H" << '\n'; + out << "#define FENNEC_LANG_FLOAT_H" << '\n'; - out << "" << std::endl; + out << "" << '\n'; - out << "#include " << std::endl; + out << "#include " << '\n'; - out << "" << std::endl; + out << "" << '\n'; // MAYBE TODO: Generate info without C++ STDLIB to compile natively on platforms without support - out << "#undef FLT_HAS_INFINITY" << std::endl; - out << "#undef FLT_HAS_QUIET_NAN" << std::endl; - out << "#undef FLT_HAS_SIGNALING_NAN" << std::endl; - out << "#undef FLT_HAS_DENORM" << std::endl; - out << "#undef FLT_HAS_DENORM_LOSS" << std::endl; - out << "#undef FLT_ROUNDS" << std::endl; - out << "#undef FLT_IS_IEC559" << std::endl; - out << "#undef FLT_MANT_DIG" << std::endl; - out << "#undef FLT_DIG" << std::endl; - out << "#undef FLT_DECIMAL_DIG" << std::endl; - out << "#undef FLT_RADIX" << std::endl; - out << "#undef FLT_MIN_EXP" << std::endl; - out << "#undef FLT_MAX_EXP" << std::endl; - out << "#undef FLT_MIN_10_EXP" << std::endl; - out << "#undef FLT_MAX_10_EXP" << std::endl; - out << "#undef FLT_TRAPS" << std::endl; - out << "#undef FLT_TINYNESS_BEFORE" << std::endl; - out << "#undef FLT_MIN" << std::endl; - out << "#undef FLT_MAX" << std::endl; - out << "#undef FLT_EPSILON" << std::endl; - out << "#undef FLT_INF" << std::endl; - out << "#undef FLT_QUIET_NAN" << std::endl; - out << "#undef FLT_SIGNALING_NAN" << std::endl; - out << "#undef FLT_DENORM_MIN" << std::endl; - out << "#undef FLT_ROUND_ERR" << std::endl; + out << "#undef FLT_HAS_INFINITY" << '\n'; + out << "#undef FLT_HAS_QUIET_NAN" << '\n'; + out << "#undef FLT_HAS_SIGNALING_NAN" << '\n'; + out << "#undef FLT_HAS_DENORM" << '\n'; + out << "#undef FLT_HAS_DENORM_LOSS" << '\n'; + out << "#undef FLT_ROUNDS" << '\n'; + out << "#undef FLT_IS_IEC559" << '\n'; + out << "#undef FLT_MANT_DIG" << '\n'; + out << "#undef FLT_DIG" << '\n'; + out << "#undef FLT_DECIMAL_DIG" << '\n'; + out << "#undef FLT_RADIX" << '\n'; + out << "#undef FLT_MIN_EXP" << '\n'; + out << "#undef FLT_MAX_EXP" << '\n'; + out << "#undef FLT_MIN_10_EXP" << '\n'; + out << "#undef FLT_MAX_10_EXP" << '\n'; + out << "#undef FLT_TRAPS" << '\n'; + out << "#undef FLT_TINYNESS_BEFORE" << '\n'; + out << "#undef FLT_MIN" << '\n'; + out << "#undef FLT_MAX" << '\n'; + out << "#undef FLT_EPSILON" << '\n'; + out << "#undef FLT_INF" << '\n'; + out << "#undef FLT_QUIET_NAN" << '\n'; + out << "#undef FLT_SIGNALING_NAN" << '\n'; + out << "#undef FLT_DENORM_MIN" << '\n'; + out << "#undef FLT_ROUND_ERR" << '\n'; - out << "" << std::endl; - out << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits::has_infinity << std::endl; - out << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits::has_quiet_NaN << std::endl; - out << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits::has_signaling_NaN << std::endl; - out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits::has_denorm << std::endl; - out << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits::has_denorm_loss << std::endl; - out << "#define FLT_ROUNDS " << std::dec << std::numeric_limits::round_style << std::endl; - out << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits::is_iec559 << std::endl; - out << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits::digits << std::endl; - out << "#define FLT_DIG " << std::dec << std::numeric_limits::digits10 << std::endl; - out << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits::max_digits10 << std::endl; - out << "#define FLT_RADIX " << std::dec << std::numeric_limits::radix << std::endl; - out << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits::min_exponent << std::endl; - out << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits::max_exponent << std::endl; - out << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits::min_exponent10 << std::endl; - out << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits::max_exponent10 << std::endl; - out << "#define FLT_TRAPS " << std::dec << std::numeric_limits::traps << std::endl; - out << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits::tinyness_before << std::endl; + out << "" << '\n'; - out << "#define FLT_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::min() ) << ")" << std::endl; - out << "#define FLT_MAX " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::max() ) << ")" << std::endl; - out << "#define FLT_EPSILON " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::epsilon() ) << ")" << std::endl; - out << "#define FLT_INF " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::infinity() ) << ")" << std::endl; - out << "#define FLT_QUIET_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::quiet_NaN() ) << ")" << std::endl; - out << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::signaling_NaN()) << ")" << std::endl; - out << "#define FLT_DENORM_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::denorm_min() ) << ")" << std::endl; - out << "#define FLT_ROUND_ERR " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::round_error() ) << ")" << std::endl; - out << "" << std::endl; + out << R"(/// \brief Does \f$float\f$ have an infinity?)" << '\n'; + out << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits::has_infinity << '\n'; - out << "#undef DBL_HAS_INFINITY" << std::endl; - out << "#undef DBL_HAS_QUIET_NAN" << std::endl; - out << "#undef DBL_HAS_SIGNALING_NAN" << std::endl; - out << "#undef DBL_HAS_DENORM" << std::endl; - out << "#undef DBL_HAS_DENORM_LOSS" << std::endl; - out << "#undef DBL_ROUNDS" << std::endl; - out << "#undef DBL_IS_IEC559" << std::endl; - out << "#undef DBL_MANT_DIG" << std::endl; - out << "#undef DBL_DIG" << std::endl; - out << "#undef DBL_DECIMAL_DIG" << std::endl; - out << "#undef DBL_RADIX" << std::endl; - out << "#undef DBL_MIN_EXP" << std::endl; - out << "#undef DBL_MAX_EXP" << std::endl; - out << "#undef DBL_MIN_10_EXP" << std::endl; - out << "#undef DBL_MAX_10_EXP" << std::endl; - out << "#undef DBL_TRAPS" << std::endl; - out << "#undef DBL_TINYNESS_BEFORE" << std::endl; - out << "#undef DBL_MIN" << std::endl; - out << "#undef DBL_MAX" << std::endl; - out << "#undef DBL_EPSILON" << std::endl; - out << "#undef DBL_INF" << std::endl; - out << "#undef DBL_QUIET_NAN" << std::endl; - out << "#undef DBL_SIGNALING_NAN" << std::endl; - out << "#undef DBL_DENORM_MIN" << std::endl; - out << "#undef DBL_ROUND_ERR" << std::endl; + out << R"(/// \brief Does \f$float\f$ have a quiet NaN?)" << '\n'; + out << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits::has_quiet_NaN << '\n'; - out << "" << std::endl; + out << R"(/// \brief Does \f$float\f$ have a signaling NaN?)" << '\n'; + out << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits::has_signaling_NaN << '\n'; - out << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits::has_infinity << std::endl; - out << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits::has_quiet_NaN << std::endl; - out << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits::has_signaling_NaN << std::endl; - out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits::has_denorm << std::endl; - out << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits::has_denorm_loss << std::endl; - out << "#define DBL_ROUNDS " << std::dec << std::numeric_limits::round_style << std::endl; - out << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits::is_iec559 << std::endl; - out << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits::digits << std::endl; - out << "#define DBL_DIG " << std::dec << std::numeric_limits::digits10 << std::endl; - out << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits::max_digits10 << std::endl; - out << "#define DBL_RADIX " << std::dec << std::numeric_limits::radix << std::endl; - out << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits::min_exponent << std::endl; - out << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits::max_exponent << std::endl; - out << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits::min_exponent10 << std::endl; - out << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits::max_exponent10 << std::endl; - out << "#define DBL_TRAPS " << std::dec << std::numeric_limits::traps << std::endl; - out << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits::tinyness_before << std::endl; + out << R"(/// \brief Does \f$float\f$ use denormalization?)" << '\n'; + out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits::has_denorm << '\n'; - out << "#define DBL_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::min() ) << "ll)" << std::endl; - out << "#define DBL_MAX " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::max() ) << "ll)" << std::endl; - out << "#define DBL_EPSILON " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::epsilon() ) << "ll)" << std::endl; - out << "#define DBL_INF " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::infinity() ) << "ll)" << std::endl; - out << "#define DBL_QUIET_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::quiet_NaN() ) << "ll)" << std::endl; - out << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::signaling_NaN()) << "ll)" << std::endl; - out << "#define DBL_DENORM_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::denorm_min() ) << "ll)" << std::endl; - out << "#define DBL_ROUND_ERR " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::round_error() ) << "ll)" << std::endl; + out << R"(/// \brief Does \f$float\f$ have loss with denormalization?)" << '\n'; + out << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits::has_denorm_loss << '\n'; - out << "" << std::endl; + out << R"(/// \brief What rounding style does \f$float\f$ use?)" << '\n'; + out << "#define FLT_ROUNDS " << std::dec << std::numeric_limits::round_style << '\n'; - out << "#endif // FENNEC_LANG_FLOAT_H" << std::endl; + out << R"(/// \brief Does \f$float\f$ use the IEEE floating point specification?)" << '\n'; + out << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits::is_iec559 << '\n'; + + out << R"(/// \brief The number of mantissa bits in \f$float\f$.)" << '\n'; + out << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ → \f$text\f$ → \f$float\f$.)" << '\n'; + out << "#define FLT_DIG " << std::dec << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief The decimal precision required to serialize and deserialize a \f$float\f$.)" << '\n'; + out << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or integer base, used to represent a \f$float\f$.)" << '\n'; + out << "#define FLT_RADIX " << std::dec << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief The minimum negative integer such that \f${FLT_RADIX}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.)" << '\n'; + out << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits::min_exponent << '\n'; + + out << R"(/// \brief The maximum positive integer such that \f${FLT_RADIX}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.)" << '\n'; + out << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits::max_exponent << '\n'; + + out << R"(/// \brief The minimum negative integer such that \f${10}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.)" << '\n'; + out << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits::min_exponent10 << '\n'; + + out << R"(/// \brief The maximum positive integer such that \f${10}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.)" << '\n'; + out << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits::max_exponent10 << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$float\f$ trap?)" << '\n'; + out << "#define FLT_TRAPS " << std::dec << std::numeric_limits::traps << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$float\f$ check for underflow?)" << '\n'; + out << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits::tinyness_before << '\n'; + + + out << R"(/// \brief Smallest positive, finite, normal value of \f$float\f$.)" << '\n'; + out << "#define FLT_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::min() ) << ")" << '\n'; + + out << R"(/// \brief Largest positive, finite value of \f$float\f$.)" << '\n'; + out << "#define FLT_MAX " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::max() ) << ")" << '\n'; + + out << R"(/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$.)" << '\n'; + out << "#define FLT_EPSILON " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::epsilon() ) << ")" << '\n'; + + out << R"(/// \brief A value representing \f$\inf\f$ of type \f$float\f$.)" << '\n'; + out << "#define FLT_INF " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::infinity() ) << ")" << '\n'; + + out << R"(/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.)" << '\n'; + out << "#define FLT_QUIET_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::quiet_NaN() ) << ")" << '\n'; + + out << R"(/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps.)" << '\n'; + out << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::signaling_NaN()) << ")" << '\n'; + + out << R"(/// \brief Smallest positive, finite, subnormal value of \f$float\f$.)" << '\n'; + out << "#define FLT_DENORM_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::denorm_min() ) << ")" << '\n'; + + out << R"(/// \brief Maximum rounding error of type \f$float\f$.)" << '\n'; + out << "#define FLT_ROUND_ERR " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::round_error() ) << ")" << '\n'; + + out << "" << '\n'; + + out << "#undef DBL_HAS_INFINITY" << '\n'; + out << "#undef DBL_HAS_QUIET_NAN" << '\n'; + out << "#undef DBL_HAS_SIGNALING_NAN" << '\n'; + out << "#undef DBL_HAS_DENORM" << '\n'; + out << "#undef DBL_HAS_DENORM_LOSS" << '\n'; + out << "#undef DBL_ROUNDS" << '\n'; + out << "#undef DBL_IS_IEC559" << '\n'; + out << "#undef DBL_MANT_DIG" << '\n'; + out << "#undef DBL_DIG" << '\n'; + out << "#undef DBL_DECIMAL_DIG" << '\n'; + out << "#undef DBL_RADIX" << '\n'; + out << "#undef DBL_MIN_EXP" << '\n'; + out << "#undef DBL_MAX_EXP" << '\n'; + out << "#undef DBL_MIN_10_EXP" << '\n'; + out << "#undef DBL_MAX_10_EXP" << '\n'; + out << "#undef DBL_TRAPS" << '\n'; + out << "#undef DBL_TINYNESS_BEFORE" << '\n'; + out << "#undef DBL_MIN" << '\n'; + out << "#undef DBL_MAX" << '\n'; + out << "#undef DBL_EPSILON" << '\n'; + out << "#undef DBL_INF" << '\n'; + out << "#undef DBL_QUIET_NAN" << '\n'; + out << "#undef DBL_SIGNALING_NAN" << '\n'; + out << "#undef DBL_DENORM_MIN" << '\n'; + out << "#undef DBL_ROUND_ERR" << '\n'; + + out << "" << '\n'; + + + out << R"(/// \brief Does \f$double\f$ have an infinity?)" << '\n'; + out << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits::has_infinity << '\n'; + + out << R"(/// \brief Does \f$double\f$ have a quiet NaN?)" << '\n'; + out << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits::has_quiet_NaN << '\n'; + + out << R"(/// \brief Does \f$double\f$ have a signaling NaN?)" << '\n'; + out << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits::has_signaling_NaN << '\n'; + + out << R"(/// \brief Does \f$double\f$ use denormalization?)" << '\n'; + out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits::has_denorm << '\n'; + + out << R"(/// \brief Does \f$double\f$ have loss with denormalization?)" << '\n'; + out << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits::has_denorm_loss << '\n'; + + out << R"(/// \brief What rounding style does \f$double\f$ use?)" << '\n'; + out << "#define DBL_ROUNDS " << std::dec << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Does \f$double\f$ use the IEEE doubleing point specification?)" << '\n'; + out << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits::is_iec559 << '\n'; + + out << R"(/// \brief The number of mantissa bits in \f$double\f$.)" << '\n'; + out << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ → \f$text\f$ → \f$double\f$.)" << '\n'; + out << "#define DBL_DIG " << std::dec << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief The decimal precision required to serialize and deserialize a \f$double\f$.)" << '\n'; + out << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or integer base, used to represent a \f$double\f$.)" << '\n'; + out << "#define DBL_RADIX " << std::dec << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief The minimum negative integer such that \f${DBL_RADIX}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.)" << '\n'; + out << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits::min_exponent << '\n'; + + out << R"(/// \brief The maximum positive integer such that \f${DBL_RADIX}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.)" << '\n'; + out << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits::max_exponent << '\n'; + + out << R"(/// \brief The minimum negative integer such that \f${10}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.)" << '\n'; + out << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits::min_exponent10 << '\n'; + + out << R"(/// \brief The maximum positive integer such that \f${10}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.)" << '\n'; + out << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits::max_exponent10 << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$double\f$ trap?)" << '\n'; + out << "#define DBL_TRAPS " << std::dec << std::numeric_limits::traps << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$double\f$ check for underflow?)" << '\n'; + out << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits::tinyness_before << '\n'; + + + out << R"(/// \brief Smallest positive, finite, normal value of \f$double\f$.)" << '\n'; + out << "#define DBL_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::min() ) << "ll)" << '\n'; + + out << R"(/// \brief Largest positive, finite value of \f$double\f$.)" << '\n'; + out << "#define DBL_MAX " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::max() ) << "ll)" << '\n'; + + out << R"(/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$.)" << '\n'; + out << "#define DBL_EPSILON " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::epsilon() ) << "ll)" << '\n'; + + out << R"(/// \brief A value representing \f$\inf\f$ of type \f$double\f$.)" << '\n'; + out << "#define DBL_INF " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::infinity() ) << "ll)" << '\n'; + + out << R"(/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.)" << '\n'; + out << "#define DBL_QUIET_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::quiet_NaN() ) << "ll)" << '\n'; + + out << R"(/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps.)" << '\n'; + out << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::signaling_NaN()) << "ll)" << '\n'; + + out << R"(/// \brief Smallest positive, finite, subnormal value of \f$double\f$.)" << '\n'; + out << "#define DBL_DENORM_MIN " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::denorm_min() ) << "ll)" << '\n'; + + out << R"(/// \brief Maximum rounding error of type \f$double\f$.)" << '\n'; + out << "#define DBL_ROUND_ERR " << "fennec::bit_cast(0x" << std::hex << std::bit_cast(std::numeric_limits::round_error() ) << "ll)" << '\n'; + + out << "" << '\n'; + + out << "#endif // FENNEC_LANG_FLOAT_H" << '\n'; out.close(); diff --git a/metaprogramming/integer.h b/metaprogramming/integer.h index 078d915..cc807b1 100644 --- a/metaprogramming/integer.h +++ b/metaprogramming/integer.h @@ -26,218 +26,425 @@ inline void integer_h() std::ofstream out("fennec/lang/integer.h"); - out << "// =====================================================================================================================" << std::endl; - out << "// fennec, a free and open source game engine" << std::endl; - out << "// Copyright © 2025 - 2026 Medusa Slockbower" << std::endl; - out << "//" << std::endl; - out << "// This program is free software: you can redistribute it and/or modify" << std::endl; - out << "// it under the terms of the GNU General Public License as published by" << std::endl; - out << "// the Free Software Foundation, either version 3 of the License, or" << std::endl; - out << "// (at your option) any later version." << std::endl; - out << "//" << std::endl; - out << "// This program is distributed in the hope that it will be useful," << std::endl; - out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl; - out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl; - out << "// GNU General Public License for more details." << std::endl; - out << "//" << std::endl; - out << "// You should have received a copy of the GNU General Public License" << std::endl; - out << "// along with this program. If not, see ." << std::endl; - out << "// =====================================================================================================================" << std::endl; + out << "// =====================================================================================================================" << '\n'; + out << "// fennec, a free and open source game engine" << '\n'; + out << "// Copyright © 2025 - 2026 Medusa Slockbower" << '\n'; + out << "//" << '\n'; + out << "// This program is free software: you can redistribute it and/or modify" << '\n'; + out << "// it under the terms of the GNU General Public License as published by" << '\n'; + out << "// the Free Software Foundation, either version 3 of the License, or" << '\n'; + out << "// (at your option) any later version." << '\n'; + out << "//" << '\n'; + out << "// This program is distributed in the hope that it will be useful," << '\n'; + out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << '\n'; + out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << '\n'; + out << "// GNU General Public License for more details." << '\n'; + out << "//" << '\n'; + out << "// You should have received a copy of the GNU General Public License" << '\n'; + out << "// along with this program. If not, see ." << '\n'; + out << "// =====================================================================================================================" << '\n'; - out << "" << std::endl; + out << "" << '\n'; - out << "///" << std::endl; - out << "/// \\file fennec/lang/integer.h" << std::endl; - out << "/// \\brief metaprogramming integer type info" << std::endl; - out << "///" << std::endl; - out << "///" << std::endl; - out << "/// \\details this file is automatically generated for the current build environment" << std::endl; - out << "///" << std::endl; - out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl; - out << "///" << std::endl; - out << "///" << std::endl; + out << "///" << '\n'; + out << "/// \\file fennec/lang/integer.h" << '\n'; + out << "/// \\brief metaprogramming integer type info" << '\n'; + out << "///" << '\n'; + out << "///" << '\n'; + out << "/// \\details This file is automatically generated for the current build environment." << '\n'; + out << "///" << '\n'; + out << "/// Environment for this build: " FENNEC_LONG_COMPILER_NAME << '\n'; + out << "///" << '\n'; + out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << '\n'; + out << "///" << '\n'; + out << "///" << '\n'; - out << "" << std::endl; + out << "" << '\n'; - out << "#ifndef FENNEC_LANG_INTEGER_H" << std::endl; - out << "#define FENNEC_LANG_INTEGER_H" << std::endl; + out << "#ifndef FENNEC_LANG_INTEGER_H" << '\n'; + out << "#define FENNEC_LANG_INTEGER_H" << '\n'; - out << "" << std::endl; + out << "" << '\n'; - out << "#undef CHAR_MIN" << std::endl; - out << "#undef CHAR_MAX" << std::endl; - out << "#undef WCHAR_MIN" << std::endl; - out << "#undef WCHAR_MAX" << std::endl; - out << "#undef SCHAR_MIN" << std::endl; - out << "#undef SCHAR_MAX" << std::endl; - out << "#undef UCHAR_MIN" << std::endl; - out << "#undef UCHAR_MAX" << std::endl; - out << "#undef INT_MIN" << std::endl; - out << "#undef INT_MAX" << std::endl; - out << "#undef UINT_MIN" << std::endl; - out << "#undef UINT_MAX" << std::endl; - out << "#undef LONG_MIN" << std::endl; - out << "#undef LONG_MAX" << std::endl; - out << "#undef ULONG_MIN" << std::endl; - out << "#undef ULONG_MAX" << std::endl; - out << "#undef LLONG_MIN" << std::endl; - out << "#undef LLONG_MAX" << std::endl; - out << "#undef ULLONG_MIN" << std::endl; - out << "#undef ULLONG_MAX" << std::endl; + out << "#undef CHAR_MIN" << '\n'; + out << "#undef CHAR_MAX" << '\n'; + out << "#undef WCHAR_MIN" << '\n'; + out << "#undef WCHAR_MAX" << '\n'; + out << "#undef SCHAR_MIN" << '\n'; + out << "#undef SCHAR_MAX" << '\n'; + out << "#undef UCHAR_MIN" << '\n'; + out << "#undef UCHAR_MAX" << '\n'; + out << "#undef INT_MIN" << '\n'; + out << "#undef INT_MAX" << '\n'; + out << "#undef UINT_MIN" << '\n'; + out << "#undef UINT_MAX" << '\n'; + out << "#undef LONG_MIN" << '\n'; + out << "#undef LONG_MAX" << '\n'; + out << "#undef ULONG_MIN" << '\n'; + out << "#undef ULONG_MAX" << '\n'; + out << "#undef LLONG_MIN" << '\n'; + out << "#undef LLONG_MAX" << '\n'; + out << "#undef ULLONG_MIN" << '\n'; + out << "#undef ULLONG_MAX" << '\n'; - out << "" << std::endl; + out << "" << '\n'; // TODO: Fix this to generate info without using the c++stdlib for platforms without this available. - out << "#define CHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits::is_signed << std::endl; + out << R"(/// \brief Is \f$char\f$ signed?)" << '\n'; + out << "#define CHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits::is_signed << '\n'; - out << "#define CHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits::round_style << std::endl; - out << "#define CHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits << std::endl; - out << "#define CHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits10 << std::endl; - out << "#define CHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits::max_digits10 << std::endl; - out << "#define CHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits::radix << std::endl; - out << "#define CHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief Rounding style of type \f$char\f$.)" << '\n'; + out << "#define CHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits::round_style << '\n'; - out << "#define CHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits::min()) << std::endl; - out << "#define CHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits::max()) << std::endl; + out << R"(/// \brief Number of radix digits represented by \f$char\f$.)" << '\n'; + out << "#define CHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits << '\n'; - out << "" << std::endl; + out << R"(/// \brief Number of decimal digits represented by \f$char\f$.)" << '\n'; + out << "#define CHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits10 << '\n'; - out << "#define WCHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits::is_signed << std::endl; + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$char\f$.)" << '\n'; + out << "#define CHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits::max_digits10 << '\n'; - out << "#define WCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define WCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define WCHAR_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define WCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define WCHAR_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define WCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief The radix, or integer base, used to represent a \f$char\f$.)" << '\n'; + out << "#define CHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits::radix << '\n'; - out << "#define WCHAR_MIN " << "0x" << std::hex << +std::numeric_limits::min() << std::endl; - out << "#define WCHAR_MAX " << "0x" << std::hex << +std::numeric_limits::max() << std::endl; + out << R"(/// \brief Do arithmetics operations with \f$char\f$ trap?)" << '\n'; + out << "#define CHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; - out << "" << std::endl; - out << "#define SCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits::round_style << std::endl; - out << "#define SCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits << std::endl; - out << "#define SCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits10 << std::endl; - out << "#define SCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits::max_digits10 << std::endl; - out << "#define SCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits::radix << std::endl; - out << "#define SCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief Smallest finite value of \f$char\f$.)" << '\n'; + out << "#define CHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits::min()) << '\n'; - out << "#define SCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits::min()) << std::endl; - out << "#define SCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits::max()) << std::endl; + out << R"(/// \brief Largest finite value of \f$char\f$.)" << '\n'; + out << "#define CHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits::max()) << '\n'; - out << "" << std::endl; - out << "#define UCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define UCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define UCHAR_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define UCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define UCHAR_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define UCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << "" << '\n'; - out << "#define UCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits::min()) << std::endl; - out << "#define UCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits::max()) << std::endl; - out << "" << std::endl; + out << R"(/// \brief Is \f$wchar_t\f$ signed?)" << '\n'; + out << "#define WCHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits::is_signed << '\n'; - out << "#define SHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define SHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define SHORT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define SHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define SHORT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define SHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief Rounding style of type \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; - out << "#define SHORT_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define SHORT_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << R"(/// \brief Number of radix digits represented by \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; - out << "" << std::endl; + out << R"(/// \brief Number of decimal digits represented by \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; - out << "#define USHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define USHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define USHORT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define USHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define USHORT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define USHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; - out << "#define USHORT_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define USHORT_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << R"(/// \brief The radix, or integer base, used to represent a \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; - out << "" << std::endl; + out << R"(/// \brief Do arithmetics operations with \f$wchar_t\f$ trap?)" << '\n'; + out << "#define WCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; - out << "#define INT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define INT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define INT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define INT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define INT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define INT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; - out << "#define INT_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define INT_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << R"(/// \brief Smallest finite value of \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; - out << "" << std::endl; + out << R"(/// \brief Largest finite value of \f$wchar_t\f$.)" << '\n'; + out << "#define WCHAR_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; - out << "#define UINT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define UINT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define UINT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define UINT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define UINT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define UINT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; - out << "#define UINT_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define UINT_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << "" << '\n'; - out << "" << std::endl; - out << "#define LONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define LONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define LONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define LONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define LONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define LONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief Is \f$signed char\f$ signed?)" << '\n'; + out << "#define SCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits::round_style << '\n'; - out << "#define LONG_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define LONG_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << R"(/// \brief Rounding style of type \f$signed char\f$.)" << '\n'; + out << "#define SCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits << '\n'; - out << "" << std::endl; + out << R"(/// \brief Number of radix digits represented by \f$signed char\f$.)" << '\n'; + out << "#define SCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits10 << '\n'; - out << "#define ULONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define ULONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define ULONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define ULONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define ULONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define ULONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; + out << R"(/// \brief Number of decimal digits represented by \f$signed char\f$.)" << '\n'; + out << "#define SCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits::max_digits10 << '\n'; - out << "#define ULONG_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define ULONG_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$signed char\f$.)" << '\n'; + out << "#define SCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits::radix << '\n'; - out << "" << std::endl; + out << R"(/// \brief Do arithmetics operations with \f$signed char\f$ trap?)" << '\n'; + out << "#define SCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; - out << "#define LLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define LLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define LLONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define LLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define LLONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define LLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; - out << "#define LLONG_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define LLONG_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << R"(/// \brief Smallest finite value of \f$signed char\f$.)" << '\n'; + out << "#define SCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits::min()) << '\n'; - out << "" << std::endl; + out << R"(/// \brief Largest finite value of \f$signed char\f$.)" << '\n'; + out << "#define SCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits::max()) << '\n'; - out << "#define ULLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << std::endl; - out << "#define ULLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << std::endl; - out << "#define ULLONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << std::endl; - out << "#define ULLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << std::endl; - out << "#define ULLONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << std::endl; - out << "#define ULLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << std::endl; - out << "#define ULLONG_MIN " << "0x" << std::hex << std::numeric_limits::min() << std::endl; - out << "#define ULLONG_MAX " << "0x" << std::hex << std::numeric_limits::max() << std::endl; + out << "" << '\n'; - out << "" << std::endl; - out << "#endif // FENNEC_LANG_INTEGER_H" << std::endl; + out << R"(/// \brief Is \f$unsigned char\f$ unsigned?)" << '\n'; + out << "#define UCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Rounding style of type \f$unsigned char\f$.)" << '\n'; + out << "#define UCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$unsigned char\f$.)" << '\n'; + out << "#define UCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$unsigned char\f$.)" << '\n'; + out << "#define UCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned char\f$.)" << '\n'; + out << "#define UCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$unsigned char\f$ trap?)" << '\n'; + out << "#define UCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$unsigned char\f$.)" << '\n'; + out << "#define UCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits::min()) << '\n'; + + out << R"(/// \brief Largest finite value of \f$unsigned char\f$.)" << '\n'; + out << "#define UCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits::max()) << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$short\f$.)" << '\n'; + out << "#define SHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$short\f$.)" << '\n'; + out << "#define SHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$short\f$.)" << '\n'; + out << "#define SHORT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$short\f$.)" << '\n'; + out << "#define SHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or integer base, used to represent a \f$short\f$.)" << '\n'; + out << "#define SHORT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$short\f$ trap?)" << '\n'; + out << "#define SHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$short\f$.)" << '\n'; + out << "#define SHORT_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$short\f$.)" << '\n'; + out << "#define SHORT_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or integer base, used to represent a \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$unsigned short\f$ trap?)" << '\n'; + out << "#define USHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$unsigned short\f$.)" << '\n'; + out << "#define USHORT_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$int\f$.)" << '\n'; + out << "#define INT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$int\f$.)" << '\n'; + out << "#define INT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$int\f$.)" << '\n'; + out << "#define INT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$int\f$.)" << '\n'; + out << "#define INT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or integer base, used to represent a \f$int\f$.)" << '\n'; + out << "#define INT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$int\f$ trap?)" << '\n'; + out << "#define INT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$int\f$.)" << '\n'; + out << "#define INT_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$int\f$.)" << '\n'; + out << "#define INT_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or unsigned integer base, used to represent a \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$unsigned int\f$ trap?)" << '\n'; + out << "#define UINT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$unsigned int\f$.)" << '\n'; + out << "#define UINT_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$long int\f$.)" << '\n'; + out << "#define LONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$long int\f$.)" << '\n'; + out << "#define LONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$long int\f$.)" << '\n'; + out << "#define LONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$long int\f$.)" << '\n'; + out << "#define LONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or long integer base, used to represent a \f$long int\f$.)" << '\n'; + out << "#define LONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$long int\f$ trap?)" << '\n'; + out << "#define LONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$long int\f$.)" << '\n'; + out << "#define LONG_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$long int\f$.)" << '\n'; + out << "#define LONG_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or unsigned long integer base, used to represent a \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$unsigned long int\f$ trap?)" << '\n'; + out << "#define ULONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$unsigned long int\f$.)" << '\n'; + out << "#define ULONG_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$long long\f$.)" << '\n'; + out << "#define LLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$long long\f$.)" << '\n'; + out << "#define LLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$long long\f$.)" << '\n'; + out << "#define LLONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$long long\f$.)" << '\n'; + out << "#define LLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or long longeger base, used to represent a \f$long long\f$.)" << '\n'; + out << "#define LLONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$long long\f$ trap?)" << '\n'; + out << "#define LLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$long long\f$.)" << '\n'; + out << "#define LLONG_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$long long\f$.)" << '\n'; + out << "#define LLONG_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + + out << R"(/// \brief Rounding style of type \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits::round_style << '\n'; + + out << R"(/// \brief Number of radix digits represented by \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits::digits << '\n'; + + out << R"(/// \brief Number of decimal digits represented by \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_DIG " << "0x" << std::hex << std::numeric_limits::digits10 << '\n'; + + out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits::max_digits10 << '\n'; + + out << R"(/// \brief The radix, or unsigned long longeger base, used to represent a \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_RADIX " << "0x" << std::hex << std::numeric_limits::radix << '\n'; + + out << R"(/// \brief Do arithmetics operations with \f$unsigned long long\f$ trap?)" << '\n'; + out << "#define ULLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits::traps << '\n'; + + + out << R"(/// \brief Smallest finite value of \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_MIN " << "0x" << std::hex << +std::numeric_limits::min() << '\n'; + + out << R"(/// \brief Largest finite value of \f$unsigned long long\f$.)" << '\n'; + out << "#define ULLONG_MAX " << "0x" << std::hex << +std::numeric_limits::max() << '\n'; + + + out << "" << '\n'; + + out << "#endif // FENNEC_LANG_INTEGER_H" << '\n'; out.close(); diff --git a/source/filesystem/path.cpp b/source/filesystem/path.cpp index 7457fee..89615f4 100644 --- a/source/filesystem/path.cpp +++ b/source/filesystem/path.cpp @@ -37,7 +37,7 @@ path path::current() { #include #include -path path::current() { +path path::get_current() { char cstr[PATH_MAX]; if (getcwd(cstr, sizeof(cstr)) == nullptr) { return path(""); @@ -45,11 +45,11 @@ path path::current() { return path(cstring(cstr, strlen(cstr))); } -path path::current(const path& path) { +path path::set_current(const path& path) { if (chdir(path._str.cstr())) { return fennec::path(""); } - return current(); + return get_current(); } #endif diff --git a/source/memory/new.cpp b/source/memory/new.cpp index dc2b694..f652145 100644 --- a/source/memory/new.cpp +++ b/source/memory/new.cpp @@ -76,10 +76,10 @@ void* operator new[](fennec::size_t size, fennec::align_t align, const fennec::n #endif // Allocation functions -void* operator new (fennec::size_t size) { return ::malloc(size); } -void* operator new[](fennec::size_t size) { return ::malloc(size); } -void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); } -void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); } +void* operator new (fennec::size_t size) { return ::calloc(size, 1); } +void* operator new[](fennec::size_t size) { return ::calloc(size, 1); } +void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return ::calloc(size, 1); } +void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return ::calloc(size, 1); } // Deallocation Functions void operator delete (void* ptr, fennec::size_t) noexcept { ::free(ptr); } diff --git a/source/platform/linux/wayland/window.cpp b/source/platform/linux/wayland/window.cpp index b682dc8..eb19ce6 100644 --- a/source/platform/linux/wayland/window.cpp +++ b/source/platform/linux/wayland/window.cpp @@ -245,7 +245,7 @@ bool wayland_window::set_flag(uint8_t flag, bool value) { } -// Helpers ============================================================================================================= +// Private Helpers ===================================================================================================== void wayland_window::_update_size(const ivec2& size) { //bool size_changed = any(notEqual(size, state.rect.size)); diff --git a/source/platform/opengl/egl/context.cpp b/source/platform/opengl/egl/context.cpp index 28571b6..2ce2397 100644 --- a/source/platform/opengl/egl/context.cpp +++ b/source/platform/opengl/egl/context.cpp @@ -107,8 +107,8 @@ eglcontext::eglcontext(display_server* display) version.major = _eglvmajor; version.minor = _eglvminor; version.patch = 0; - version.str = format("{} v{}.{}", egl_translate_type(_eglctype), _eglvmajor, _eglvminor); - logger::log(format("Created OpenGL Context: {}", version.str)); + version.meta = _eglctype; + logger::log(format("Created OpenGL Context: {} v{}.{}", egl_translate_type(version.meta), version.major, version.minor)); } eglcontext::~eglcontext() { @@ -138,7 +138,7 @@ eglcontext::~eglcontext() { version.major = 0; version.minor = 0; version.patch = 0; - version.str = ""; + version.meta = 0; } bool eglcontext::is_valid() { diff --git a/source/platform/window_manager.cpp b/source/platform/window_manager.cpp index 84e04c7..f3835c2 100644 --- a/source/platform/window_manager.cpp +++ b/source/platform/window_manager.cpp @@ -109,7 +109,7 @@ window_id window_manager::create_window(const window::config& config, window_id return id; } -void window_manager::begin(window_id window) { +void window_manager::begin_frame(window_id window) { if (not _display) { return; } @@ -120,7 +120,7 @@ void window_manager::begin(window_id window) { _windows[window]->begin_frame(); } -void window_manager::end(window_id window) { +void window_manager::end_frame(window_id window) { if (not _display) { return; } @@ -160,6 +160,10 @@ ivec2 window_manager::_get_position(window_id id) const { return _windows[id]->get_position(); } +irect window_manager::_get_bounds(window_id id) const { + return _windows[id]->get_bounds(); +} + bool window_manager::_check_state(window_id id, uint8_t state) const { switch (state) { case window::state_running: return _windows[id]->is_running(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 335d98e..40b8ab8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(fennec-test tests/test_threading.h tests/test_core.h tests/core/test_event.h + tests/core/test_version.h ) target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}" diff --git a/test/tests/core/test_version.h b/test/tests/core/test_version.h new file mode 100644 index 0000000..90ff486 --- /dev/null +++ b/test/tests/core/test_version.h @@ -0,0 +1,52 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + + +#ifndef FENNEC_TEST_CORE_VERSION_H +#define FENNEC_TEST_CORE_VERSION_H + +#include + +#include "../../test.h" + +namespace fennec::test +{ + +inline void fennec_test_core_version() { + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) == (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), true); + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) == (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), false); + + fennec_test_spacer(1); + + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) != (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), false); + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) != (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), true); + + fennec_test_spacer(1); + + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) < (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), false); + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) < (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), true); + + fennec_test_spacer(1); + + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) > (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), false); + fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) > (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), false); +} + +} + +#endif // FENNEC_TEST_CORE_VERSION_H \ No newline at end of file diff --git a/test/tests/math/test_matrix.h b/test/tests/math/test_matrix.h index 11d2052..6f0d4c2 100644 --- a/test/tests/math/test_matrix.h +++ b/test/tests/math/test_matrix.h @@ -20,7 +20,7 @@ #ifndef FENNEC_TEST_MATRIX_H #define FENNEC_TEST_MATRIX_H -#include +#include #include diff --git a/test/tests/test_core.h b/test/tests/test_core.h index 04c36ab..a7f466d 100644 --- a/test/tests/test_core.h +++ b/test/tests/test_core.h @@ -20,18 +20,22 @@ #define FENNEC_TEST_CORE_H #include "../test.h" + #include "core/test_event.h" +#include "core/test_version.h" namespace fennec::test { inline void fennec_test_core() { - fennec_test_subheader("events"); - fennec_test_spacer(2); - fennec_test_core_event(); - fennec_test_spacer(3); - + fennec_test_subheader("version"); + fennec_test_spacer(2); + fennec_test_core_version(); + fennec_test_spacer(3); + fennec_test_subheader("events"); + fennec_test_spacer(2); + fennec_test_core_event(); } } diff --git a/test/tests/test_filesystem.h b/test/tests/test_filesystem.h index e6761c0..4174a87 100644 --- a/test/tests/test_filesystem.h +++ b/test/tests/test_filesystem.h @@ -33,10 +33,10 @@ namespace fennec::test fennec_test_spacer(1); - fennec_test_run(path::current(), path(FENNEC_TEST_CWD)); + fennec_test_run(path::get_current(), path(FENNEC_TEST_CWD)); fennec_test_run(path("../" FENNEC_BUILD_NAME "/./test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh"); fennec_test_run(path("./test/../test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh"); - fennec_test_run(path::current().parent(), path("../").absolute()); + fennec_test_run(path::get_current().parent(), path("../").absolute()); fennec_test_spacer(2); diff --git a/test/tests/test_platform.h b/test/tests/test_platform.h index 7472731..e04283a 100644 --- a/test/tests/test_platform.h +++ b/test/tests/test_platform.h @@ -51,8 +51,8 @@ inline void fennec_test_platform() { while (wm.is_running(window)) { - wm.begin(window); - wm.end(window); + wm.begin_frame(window); + wm.end_frame(window); wm.dispatch(); }