- More Documentation
This commit is contained in:
@@ -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)
|
||||
|
||||
18
README.md
18
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.
|
||||
|
||||
<br><br>
|
||||
|
||||
<a id="f1"></a>
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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<typename ValueT, size_t ElemV>
|
||||
/// \tparam N number of elements
|
||||
template<typename ValueT, size_t N>
|
||||
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<ElemV>{});
|
||||
return array::_compare(lhs, rhs, make_index_metasequence<N>{});
|
||||
}
|
||||
|
||||
///
|
||||
/// \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<ElemV>{});
|
||||
return not array::_compare(lhs, rhs, make_index_metasequence<N>{});
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -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<size_t...i>
|
||||
static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) {
|
||||
|
||||
@@ -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 <fennec/containers/deque.h>
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/optional.h>
|
||||
#include <fennec/containers/pair.h>
|
||||
#include <fennec/containers/traversal.h>
|
||||
#include <fennec/memory/allocator.h>
|
||||
|
||||
@@ -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<AllocT>::template rebind<node>; //!< 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<typename...ArgsT>
|
||||
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
|
||||
: value(fennec::forward<ArgsT>(args)...)
|
||||
, parent(p), child{ l, r } {
|
||||
}
|
||||
|
||||
constexpr ~node() {
|
||||
parent = npos;
|
||||
child[0] = npos;
|
||||
child[1] = npos;
|
||||
}
|
||||
|
||||
size_t& operator[](bool d) {
|
||||
return child[d];
|
||||
}
|
||||
};
|
||||
|
||||
using table_t = allocation<node, alloc_t>;
|
||||
using freed_t = list<size_t, alloc_t>;
|
||||
|
||||
@@ -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<pair<size_t, size_t>> stack;
|
||||
|
||||
uint8_t operator()(const value_t& x, size_t n) {
|
||||
while (stack.back().second != target.parent(n)) {
|
||||
stack.pop_back();
|
||||
}
|
||||
stack.emplace_back(self.insert(stack.back().first, target.side(n), x), n);
|
||||
return traversal_control_continue;
|
||||
}
|
||||
} visitor = {
|
||||
.self = *this,
|
||||
.target = tree
|
||||
};
|
||||
|
||||
tree.template traverse<pre_order>(
|
||||
visitor, tree._root
|
||||
);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Destructor, clears the tree
|
||||
///
|
||||
/// \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<value_t>(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<typename...ArgsT>
|
||||
constexpr size_t emplace_left(size_t p, ArgsT&&...args) {
|
||||
return this->_insert_left(p, fennec::forward<ArgsT>(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<value_t>(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<typename...ArgsT>
|
||||
constexpr size_t emplace_right(size_t p, ArgsT&&...args) {
|
||||
return this->_insert_right(p, fennec::forward<ArgsT>(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<value_t>(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<typename...ArgsT>
|
||||
constexpr size_t emplace(size_t parent, bool side, ArgsT&&...args) {
|
||||
return this->_insert(parent, side, fennec::forward<ArgsT>(args)...);
|
||||
@@ -467,6 +597,10 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Clears the tree, destroying all elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
///
|
||||
constexpr void clear() {
|
||||
list<size_t> 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<typename OrderT, typename VisitorT>
|
||||
constexpr void traverse(VisitorT&& visit, size_t i) {
|
||||
OrderT order;
|
||||
i = order(*this, i);
|
||||
while (i != npos) {
|
||||
uint8_t mode = traversal_control_continue;
|
||||
if (_table[i].value) {
|
||||
mode = visit(_table[i].value, i);
|
||||
}
|
||||
if (mode == traversal_control_break) {
|
||||
break;
|
||||
}
|
||||
i = order[*this, i, mode];
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Traverse the tree using a specified order and visiting functor
|
||||
///
|
||||
@@ -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<typename OrderT, typename VisitorT>
|
||||
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<typename...ArgsT>
|
||||
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
|
||||
: value(fennec::forward<ArgsT>(args)...)
|
||||
, parent(p), child{ l, r } {
|
||||
}
|
||||
|
||||
constexpr ~node() {
|
||||
parent = npos;
|
||||
child[0] = npos;
|
||||
child[1] = npos;
|
||||
}
|
||||
|
||||
size_t& operator[](bool d) {
|
||||
return child[d];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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<size_t N>
|
||||
@@ -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<size_t I>
|
||||
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. <br>
|
||||
/// Sets the bits of each index provided in \f$args\ldots\f$.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
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. <br>
|
||||
/// Initializes each bit with the respective boolean in \f$args\ldots\f$. <br>
|
||||
/// Does not necessitate the number of arguments be equal to the number of bits.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
///
|
||||
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
|
||||
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<bytes>{});
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Private Member Variables ============================================================================================
|
||||
private:
|
||||
array<uint8_t, bytes> _bytes;
|
||||
|
||||
|
||||
// Private Helpers =====================================================================================================
|
||||
private:
|
||||
template<size_t...I>
|
||||
void _inv_helper(index_metasequence<I...>) {
|
||||
((_bytes[I] = ~_bytes[I]), ...);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<typename TypeT, typename AllocT = allocator<TypeT>>
|
||||
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<typename...ArgsT>
|
||||
node(node* prev, node* next, ArgsT&&...args)
|
||||
: value(fennec::forward<ArgsT>(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<AllocT>::template rebind<node>; //!< 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<typename...ArgsT>
|
||||
void emplace_front(ArgsT&&...args) {
|
||||
this->_push_front(fennec::forward<ArgsT>(args)...);
|
||||
@@ -235,6 +287,10 @@ public:
|
||||
///
|
||||
/// \brief Push Back Move, moves a value to the back of the deque
|
||||
/// \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<typename...ArgsT>
|
||||
void emplace_back(ArgsT&&...args) {
|
||||
this->_push_back(fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
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<typename...ArgsT>
|
||||
node(node* prev, node* next, ArgsT&&...args)
|
||||
: value(fennec::forward<ArgsT>(args)...)
|
||||
, prev(prev), next(next) {
|
||||
}
|
||||
|
||||
~node() = default;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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<typename...ArgsT>
|
||||
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<size_t N>
|
||||
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<size_t N>
|
||||
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<typename OTypeT, class OAlloc>
|
||||
constexpr dynarray(const dynarray<OTypeT, OAlloc>& 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<value_t> 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<size_t N>
|
||||
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<size_t N>
|
||||
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<typename...ArgsT>
|
||||
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<TypeT>(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<typename...ArgsT>
|
||||
constexpr void emplace_back(ArgsT...args) {
|
||||
dynarray::emplace(_size, fennec::forward<ArgsT>(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<value_t, alloc_t> _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
|
||||
|
||||
@@ -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<typename T>
|
||||
generic(T&& x)
|
||||
: _handle(new T(fennec::forward<T>(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<typename T, typename...ArgsT>
|
||||
generic(type_identity<T>, ArgsT&&...args)
|
||||
: _handle(new T(fennec::forward<ArgsT>(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<fennec::type*>(_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<typename T>
|
||||
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<typename T, typename...ArgsT>
|
||||
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<typename T, typename U = remove_cvref_t<T>>
|
||||
T cast() {
|
||||
return static_cast<T>(*static_cast<U*>(_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<typename T, typename U = remove_cvref_t<T>>
|
||||
T cast() const {
|
||||
return static_cast<T>(*static_cast<U*>(_handle));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
// Members =============================================================================================================
|
||||
|
||||
// Private Member Variables ============================================================================================
|
||||
private:
|
||||
void* _handle;
|
||||
manager_t _manage;
|
||||
|
||||
|
||||
// Helpers =============================================================================================================
|
||||
// Private Helpers =====================================================================================================
|
||||
private:
|
||||
template<typename T>
|
||||
static void* _manage_impl(uint8_t op, void* hnd) {
|
||||
|
||||
@@ -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<vertex_t>; ///< Alias for a pool of vertices
|
||||
using edge_map_t = dynarray<map<size_t, size_t>>; ///< Alias for edge mapping
|
||||
using edge_pool_t = object_pool<edge_t>; ///< Alias for a pool of edges
|
||||
/// \name 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<vertex_t>; //!< Alias for a pool of vertices
|
||||
using edge_map_t = dynarray<map<size_t, size_t>>; //!< Alias for edge mapping
|
||||
using edge_pool_t = object_pool<edge_t>; //!< Alias for a pool of edges
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Constants
|
||||
/// @{
|
||||
|
||||
static constexpr size_t npos = -1; //!< Constant for a non-existent vertex
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
@@ -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<size_t> outgoing(size_t vertex) {
|
||||
list<size_t> 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<size_t> incoming(size_t vertex) {
|
||||
list<size_t> 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<size_t> symmetric(size_t vertex) {
|
||||
list<size_t> 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<size_t> undirected(size_t vertex) {
|
||||
list<size_t> 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_t>(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<typename...ArgsT>
|
||||
constexpr size_t emplace(ArgsT&&...args) {
|
||||
return this->_insert(fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
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<typename...ArgsT>
|
||||
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();
|
||||
|
||||
@@ -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<class TypeT, class Alloc = allocator<TypeT>>
|
||||
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<Alloc>::template rebind<node>;
|
||||
|
||||
using value_t = TypeT; ///< Alias for the value type
|
||||
using value_t = TypeT; //!< Alias for the value type
|
||||
|
||||
static constexpr size_t npos = -1; ///< Constant representing a non-existant position
|
||||
static constexpr size_t npos = -1; //!< Constant representing a non-existant position
|
||||
|
||||
class iterator; ///< Iterator type for forward iteration over the list
|
||||
class const_iterator; ///< Iterator type for forward iteration over a constant list
|
||||
/// @}
|
||||
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
|
||||
private:
|
||||
using table_t = dynarray<node, alloc_t>;
|
||||
@@ -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<value_t>(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<typename...ArgsT>
|
||||
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<typename...ArgsT>
|
||||
constexpr iterator emplace(const iterator& it, ArgsT&&...args) {
|
||||
return this->_insert(it._n, fennec::forward<ArgsT>(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<value_t>(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<typename...ArgsT>
|
||||
constexpr iterator emplace_front(ArgsT&&...args) {
|
||||
return this->_insert(_root, fennec::forward<ArgsT>(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<value_t>(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<typename...ArgsT>
|
||||
constexpr iterator emplace_back(ArgsT&&...args) {
|
||||
return this->_insert(npos, fennec::forward<ArgsT>(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);
|
||||
|
||||
@@ -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<KeyT, ValueT>; ///< then node type
|
||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; ///< Rebinds the allocator type to nodes
|
||||
using hash_t = Hash; ///< The hash type
|
||||
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; ///< The underlying set
|
||||
using iterator = set_t::iterator; ///< Iterator type
|
||||
|
||||
/// \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<KeyT, ValueT>; //!< then node type
|
||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; //!< Rebinds the allocator type to nodes
|
||||
using hash_t = Hash; //!< The hash type
|
||||
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; //!< The underlying set
|
||||
using iterator = set_t::iterator; //!< Iterator type
|
||||
|
||||
///
|
||||
/// \brief key hash helper
|
||||
@@ -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<typename...ArgsT>
|
||||
constexpr value_t* operator[](ArgsT&&...args) {
|
||||
auto it = _set.at(this->_find(fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
constexpr const value_t* operator[](ArgsT&&...args) const {
|
||||
auto it = _set.at(this->_find(fennec::forward<ArgsT>(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<elem_t>(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<typename...ArgsT>
|
||||
constexpr void emplace(const KeyT& key, ArgsT&&...args) {
|
||||
this->_insert(key, fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
this->_insert(fennec::forward<ArgsT>(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<KeyT>(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<typename...ArgsT>
|
||||
constexpr void erase(ArgsT&&...args) {
|
||||
_set.erase(this->_find(fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
set_t::iterator _find(ArgsT&&...args) const {
|
||||
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
|
||||
|
||||
@@ -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<value_t>; //!< The element type
|
||||
using table_t = dynarray<elem_t, AllocT>; //!< The underlying table type
|
||||
using freed_t = list<size_t, AllocT>; //!< 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<value_t>(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<typename...ArgsT>
|
||||
constexpr size_t emplace(ArgsT&&...args) {
|
||||
return this->_insert(fennec::forward<ArgsT>(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);
|
||||
}
|
||||
|
||||
@@ -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<typename T>
|
||||
@@ -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<T>(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<T>
|
||||
: 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<T>
|
||||
: 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<typename...ArgsT>
|
||||
constexpr optional(ArgsT&&...args)
|
||||
: _val(fennec::forward<ArgsT>(args)...)
|
||||
@@ -149,6 +184,10 @@ public:
|
||||
|
||||
///
|
||||
/// \brief destructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
///
|
||||
constexpr ~optional() {
|
||||
if constexpr(is_fundamental_v<T>) {
|
||||
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<T>) {
|
||||
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<T> and is_copy_assignable_v<T> {
|
||||
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<T> and is_move_assignable_v<T> {
|
||||
if (_set) {
|
||||
_val = fennec::forward<T>(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<T> and is_copy_assignable_v<T> {
|
||||
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<T> and is_move_assignable_v<T> {
|
||||
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<T>(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<typename...ArgsT>
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<typename TypeT0, typename TypeT1>
|
||||
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<TypeT0>(x))
|
||||
, second(fennec::forward<TypeT1>(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<typename Arg1T, typename Arg2T>
|
||||
constexpr pair(Arg1T&& arg1, Arg2T&& arg2)
|
||||
: first(fennec::forward<Arg1T>(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);
|
||||
}
|
||||
|
||||
@@ -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<value_t, AllocT>; //!< 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<value_t>(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<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
this->_insert(fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
|
||||
@@ -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<AllocT>::template rebind<node>; //!< the underlying allocator type
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Constants
|
||||
/// @{
|
||||
|
||||
static constexpr size_t root = 0; //!< the id of the root node
|
||||
static constexpr size_t 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<node, alloc_t>;
|
||||
using freed_t = list<size_t>;
|
||||
|
||||
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<typename...ArgsT>
|
||||
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<ArgsT>(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<value_t>(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<pair<size_t, size_t>> 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<typename...ArgsT>
|
||||
constexpr size_t emplace(size_t parent, size_t next, ArgsT&&...args) {
|
||||
return this->_insert(parent, next, fennec::forward<ArgsT>(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<typename OrderT, typename VisitorT>
|
||||
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<typename OrderT, typename VisitorT>
|
||||
constexpr void traverse(VisitorT&& visit, size_t i = root) const {
|
||||
OrderT order;
|
||||
i = order(*this, i);
|
||||
while (i != npos) {
|
||||
uint8_t mode = traversal_control_continue;
|
||||
if (_table[i].value) {
|
||||
mode = visit(_table[i].value, i);
|
||||
}
|
||||
if (mode == traversal_control_break) {
|
||||
break;
|
||||
}
|
||||
i = order[*this, i, mode];
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Traverser pattern for breadth-first traversal
|
||||
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<node, alloc_t> _table;
|
||||
list<size_t> _freed;
|
||||
size_t _size;
|
||||
|
||||
void _expand() {
|
||||
_table.creallocate(_table.capacity() * 2);
|
||||
_table.reallocate(_table.capacity() * 2);
|
||||
}
|
||||
|
||||
size_t _next_free() {
|
||||
|
||||
@@ -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<TypeT, bool>; //!< the node type
|
||||
using alloc_t = allocator_traits<AllocT>::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<value_t>(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<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
node i = _insert_bst(fennec::forward<ArgsT>(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<node> 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<node> _visit;
|
||||
|
||||
constexpr iterator(sequence* seq, node start)
|
||||
: _seq(seq)
|
||||
, _head(start)
|
||||
, _node(seq->leftmost(start)) {
|
||||
}
|
||||
|
||||
constexpr iterator(sequence* seq, node root, node start)
|
||||
: _seq(seq)
|
||||
, _head(root)
|
||||
, _node(start) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
///
|
||||
@@ -466,30 +516,30 @@ public:
|
||||
return lhs._seq != rhs._seq or lhs._node != rhs._node;
|
||||
}
|
||||
|
||||
private:
|
||||
sequence* _seq;
|
||||
node _head;
|
||||
node _node;
|
||||
list<node> _visit;
|
||||
|
||||
constexpr iterator(sequence* seq, node start)
|
||||
: _seq(seq)
|
||||
, _head(start)
|
||||
, _node(seq->leftmost(start)) {
|
||||
}
|
||||
|
||||
constexpr iterator(sequence* seq, node root, node start)
|
||||
: _seq(seq)
|
||||
, _head(root)
|
||||
, _node(start) {
|
||||
}
|
||||
|
||||
friend struct sequence;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
class const_iterator {
|
||||
private:
|
||||
const sequence* _seq;
|
||||
node _head;
|
||||
node _node;
|
||||
list<node> _visit;
|
||||
|
||||
constexpr const_iterator(const sequence* seq, node start)
|
||||
: _seq(seq)
|
||||
, _head(start)
|
||||
, _node(seq->leftmost(start)) {
|
||||
}
|
||||
|
||||
constexpr const_iterator(const sequence* seq, node root, node start)
|
||||
: _seq(seq)
|
||||
, _head(root)
|
||||
, _node(start) {
|
||||
}
|
||||
|
||||
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<node> _visit;
|
||||
|
||||
constexpr const_iterator(const sequence* seq, node start)
|
||||
: _seq(seq)
|
||||
, _head(start)
|
||||
, _node(seq->leftmost(start)) {
|
||||
}
|
||||
|
||||
constexpr const_iterator(const sequence* seq, node root, node start)
|
||||
: _seq(seq)
|
||||
, _head(root)
|
||||
, _node(start) {
|
||||
}
|
||||
|
||||
friend struct sequence;
|
||||
};
|
||||
|
||||
|
||||
// Fields ==============================================================================================================
|
||||
// Private Member Variables ============================================================================================
|
||||
private:
|
||||
alloc_t _alloc;
|
||||
node _root;
|
||||
compare_t _compare;
|
||||
size_t _size;
|
||||
|
||||
// Helpers =============================================================================================================
|
||||
|
||||
// Private Helpers =====================================================================================================
|
||||
private:
|
||||
|
||||
template<typename...ArgsT>
|
||||
|
||||
@@ -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<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
|
||||
struct set {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
private:
|
||||
struct node;
|
||||
|
||||
public:
|
||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>; //!< the allocator type
|
||||
|
||||
/// \name Definitions
|
||||
/// @{
|
||||
|
||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<node>; //!< the allocator type
|
||||
|
||||
using hash_t = Hash; //!< the hash type
|
||||
using 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<elem_t> value;
|
||||
int psl;
|
||||
|
||||
constexpr node() = default;
|
||||
constexpr ~node() = default;
|
||||
};
|
||||
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
using table_t = dynarray<node, alloc_t>;
|
||||
|
||||
|
||||
// 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<elem_t>(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<typename...ArgsT>
|
||||
constexpr iterator emplace(ArgsT&&...args) {
|
||||
return this->_insert(fennec::forward<ArgsT>(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<typename...ArgsT>
|
||||
@@ -488,29 +603,33 @@ private:
|
||||
elem_t value(fennec::forward<ArgsT>(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<node, alloc_t> _alloc;
|
||||
hash_t _hash;
|
||||
equal_t _equal;
|
||||
size_t _size;
|
||||
size_t _sumpsl;
|
||||
float _load;
|
||||
|
||||
// Private Definitions =================================================================================================
|
||||
private:
|
||||
struct node {
|
||||
optional<elem_t> value;
|
||||
int psl;
|
||||
|
||||
constexpr node() = default;
|
||||
constexpr ~node() = default;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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<typename...TypesT> struct tuple;
|
||||
@@ -86,8 +87,14 @@ constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<T
|
||||
|
||||
|
||||
template<typename ...TypesT>
|
||||
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>
|
||||
{
|
||||
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...> {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
|
||||
/// \name Definitions
|
||||
/// @{
|
||||
|
||||
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>; //!< the base type
|
||||
|
||||
template<size_t i>
|
||||
@@ -95,10 +102,20 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
|
||||
|
||||
static constexpr size_t size = sizeof...(TypesT); //!< the number of elements held by the tuple
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Constructors & Destructor ===========================================================================================
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief tuple constructor
|
||||
/// \tparam ArgsT The element types
|
||||
/// \param args The arguments to initialize the tuple with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
tuple(ArgsT&&...args)
|
||||
: base_t(fennec::forward<ArgsT>(args)...) {
|
||||
@@ -107,6 +124,10 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
|
||||
///
|
||||
/// \brief copy constructor
|
||||
/// \param cpy the tuple to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
///
|
||||
tuple(const tuple& cpy)
|
||||
: base_t(cpy) {
|
||||
}
|
||||
@@ -114,8 +135,12 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
|
||||
///
|
||||
/// \brief move constructor
|
||||
/// \param mov the tuple to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
///
|
||||
tuple(tuple&& mov)
|
||||
: base_t(mov) {
|
||||
: base_t(fennec::forward<tuple>(mov)) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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<typename...TypesT>
|
||||
struct variant {
|
||||
// Assertions ==========================================================================================================
|
||||
public:
|
||||
|
||||
static_assert(
|
||||
is_unique_v<TypesT...> and // No two types in TypesT... may be equivalent
|
||||
@@ -69,58 +71,86 @@ struct variant {
|
||||
);
|
||||
|
||||
|
||||
// Typedefs & Constants ================================================================================================
|
||||
// Definitions & Constants =============================================================================================
|
||||
public:
|
||||
|
||||
/// \name Constants
|
||||
/// @{
|
||||
|
||||
static constexpr size_t size = max_element_size_v<TypesT...>; //!< size of the variant in bytes
|
||||
static constexpr size_t 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<is_default_constructible, TypesT...>;
|
||||
fennec::construct<construct_t>(_handle);
|
||||
this->_construct<construct_t>();
|
||||
}
|
||||
|
||||
///
|
||||
/// \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<typename T>
|
||||
variant(T&& t)
|
||||
: _bytes {}
|
||||
, _handle(&_bytes)
|
||||
, _type() {
|
||||
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>;
|
||||
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
|
||||
using construct_t = conditional_t<is_void_v<same_t>, convert_t, convert_t>;
|
||||
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
|
||||
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>::type;
|
||||
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>::type;
|
||||
using construct_t = conditional_t<is_void_v<same_t>, convert_t, same_t>;
|
||||
this->_construct<construct_t>(fennec::forward<T>(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<typename T, typename...ArgsT>
|
||||
variant(type_identity<T>, ArgsT&&...args)
|
||||
: _bytes{}
|
||||
, _handle(&_bytes)
|
||||
, _type(nulltype) {
|
||||
static_assert(contains_element_v<T, TypesT...>, "T must be in TypesT...");
|
||||
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||
this->_construct<T>(fennec::forward<ArgsT>(args)...);
|
||||
_type = find_element_v<T>;
|
||||
}
|
||||
|
||||
///
|
||||
/// \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<TypesT, TypesT...> ?
|
||||
fennec::construct<TypesT>(_handle, v.get<TypesT>()) :
|
||||
(0)
|
||||
this->_construct<TypesT>(v.get<TypesT>()) :
|
||||
((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<TypesT, TypesT...> ?
|
||||
fennec::construct<TypesT>(_handle, fennec::move(v.get<TypesT>())) :
|
||||
(0)
|
||||
this->_construct<TypesT>(fennec::move(v.get<TypesT>())) :
|
||||
((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<typename T>
|
||||
variant& operator=(T&& t) {
|
||||
|
||||
@@ -173,10 +223,10 @@ struct variant {
|
||||
if constexpr((contains_element_v<T, TypesT> or ...)) {
|
||||
using type_t = remove_reference_t<T>;
|
||||
if (_type == find_element_v<type_t, TypesT...>) {
|
||||
*static_cast<type_t*>(_handle) = fennec::forward<T>(t);
|
||||
*_get<type_t>() = fennec::forward<T>(t);
|
||||
} else {
|
||||
_clear();
|
||||
fennec::construct<type_t>(_handle, fennec::forward<T>(t));
|
||||
this->_construct<type_t>(fennec::forward<T>(t));
|
||||
_type = find_element_v<type_t, TypesT...>;
|
||||
}
|
||||
return *this;
|
||||
@@ -186,8 +236,8 @@ struct variant {
|
||||
bool assigned = false;
|
||||
if (_type != nulltype) {
|
||||
((_type == find_element_v<TypesT, TypesT...> ?
|
||||
(*static_cast<TypesT*>(_handle) = fennec::forward<T>(t), assigned = true) :
|
||||
(0)
|
||||
(*_get<TypesT>() = fennec::forward<T>(t), assigned = true) :
|
||||
((void)0)
|
||||
), ...);
|
||||
}
|
||||
|
||||
@@ -198,7 +248,7 @@ struct variant {
|
||||
// Otherwise, destruct, then construct
|
||||
_clear();
|
||||
using construct_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
|
||||
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
|
||||
this->_construct<construct_t>(fennec::forward<T>(t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -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<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
|
||||
void emplace(ArgsT&&...args) {
|
||||
_clear();
|
||||
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||
this->_construct<T>(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief deduced emplace function
|
||||
/// \tparam ArgsT the argument types
|
||||
/// \param args the argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
///
|
||||
template<size_t I, typename...ArgsT>
|
||||
void emplace(ArgsT&&...args) {
|
||||
using type_t = nth_element_t<I, TypesT...>;
|
||||
_clear();
|
||||
fennec::construct<type_t>(fennec::forward<ArgsT>(args)...);
|
||||
this->_construct<type_t>(fennec::forward<ArgsT>(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<typename T> requires(contains_element_v<T, TypesT...>)
|
||||
T& get() {
|
||||
return *static_cast<T*>(_handle);
|
||||
return *_get<T>();
|
||||
}
|
||||
|
||||
///
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
///
|
||||
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||
const T& get() const {
|
||||
return *static_cast<T*>(_handle);
|
||||
return *_get<T>();
|
||||
}
|
||||
|
||||
///
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
///
|
||||
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||
T& get() {
|
||||
return *static_cast<T*>(_handle);
|
||||
return *_get<T>();
|
||||
}
|
||||
|
||||
///
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
///
|
||||
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||
const T& get() const {
|
||||
return *static_cast<T*>(_handle);
|
||||
return *_get<T>();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
// Private Member Variables ============================================================================================
|
||||
private:
|
||||
union {
|
||||
byte_t _bytes[size];
|
||||
void* _handle;
|
||||
};
|
||||
byte_t _bytes[size];
|
||||
void* _handle;
|
||||
size_t _type;
|
||||
|
||||
|
||||
// Private Helpers =====================================================================================================
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
T* _get() const {
|
||||
return static_cast<T*>(_handle);
|
||||
}
|
||||
|
||||
void _clear() {
|
||||
if (_type == nulltype) {
|
||||
return;
|
||||
}
|
||||
|
||||
((_type == find_element_v<TypesT, TypesT...> ?
|
||||
fennec::destruct<TypesT>(_handle) :
|
||||
(0)
|
||||
this->_destruct<TypesT>() :
|
||||
((void)0)
|
||||
), ...);
|
||||
_type = nulltype;
|
||||
}
|
||||
|
||||
template<typename ConstructT, typename...ArgsT>
|
||||
void _construct(ArgsT&&...args) {
|
||||
fennec::construct<ConstructT>(_get<ConstructT>(), fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
template<typename DestructT>
|
||||
void _destruct() {
|
||||
fennec::destruct(_get<DestructT>());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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<typename EventT>
|
||||
@@ -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<typename EventT, typename...ArgsT>
|
||||
static void dispatch(ArgsT&&...args) {
|
||||
event::_dispatch(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...));
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Dispatch an event immediately, on the current thread.
|
||||
///
|
||||
/// \details Blocking
|
||||
/// \tparam EventT The event type
|
||||
/// \tparam ArgsT The argument types
|
||||
/// \param args The arguments to construct the event with
|
||||
template<typename EventT, typename...ArgsT>
|
||||
static void dispatch_immediate(ArgsT&&...args) {
|
||||
event::_dispatch_immediate(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Private Helpers =====================================================================================================
|
||||
private:
|
||||
static void _add_listener(event_listener* listener, uint64_t type);
|
||||
static void _handle_event(unique_ptr<event>& event);
|
||||
|
||||
@@ -42,11 +42,12 @@ namespace fennec
|
||||
///
|
||||
/// \brief logger class
|
||||
class logger : public singleton<logger> {
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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 <fennec/lang/types.h>
|
||||
#include <fennec/string/string.h>
|
||||
|
||||
@@ -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
|
||||
@@ -56,12 +56,12 @@ namespace fennec
|
||||
/// </table>
|
||||
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().
|
||||
/// <br>
|
||||
/// This file paradigm is to subvert time-of-check time-of-use (TOCTOU) attacks. This involves a threat actor
|
||||
/// reading that our application checks if a file exists, and replacing the file with another malicious file
|
||||
/// or symlink between our call to open the file.
|
||||
class file
|
||||
{
|
||||
// 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, <br>
|
||||
/// * Attempts to reopen this file as read-only, <br>
|
||||
/// * Copies the contents of this file to the new stream, <br>
|
||||
/// * Reopen the new stream with the flags of this file.
|
||||
file copy(const cstring& path);
|
||||
|
||||
///
|
||||
/// \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, <br>
|
||||
/// * Attempts to reopen this file as read-only, <br>
|
||||
/// * Copies the contents of this file to the new stream, <br>
|
||||
/// * Reopen the new stream with the flags of this file.
|
||||
file copy(const string& path);
|
||||
|
||||
///
|
||||
/// \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, <br>
|
||||
/// * Attempts to reopen this file as read-only, <br>
|
||||
/// * Copies the contents of this file to the new stream, <br>
|
||||
/// * Reopen the new stream with the flags of this file.
|
||||
file copy(const path& path);
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// File 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<void*>(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<const void*>(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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief C++ 20 format specification
|
||||
/// \tparam ArgsT The argument types
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief helper struct for `fennec::format`
|
||||
struct format_arg {
|
||||
|
||||
@@ -65,12 +65,12 @@ struct tokenizer {
|
||||
using escseq = escape_sequence*;
|
||||
using escmap = map<char, escape_sequence*>;
|
||||
|
||||
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,
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace fennec::detail
|
||||
template<size_t N, typename FindT, typename HeadT>
|
||||
struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {};
|
||||
|
||||
template<size_t N, typename FindT, typename HeadT, typename...RestT> requires(is_same_v<FindT, HeadT>)
|
||||
template<size_t N, typename FindT, typename HeadT, typename...RestT>
|
||||
struct _find_element<N, FindT, HeadT, RestT...>
|
||||
: conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {};
|
||||
|
||||
|
||||
@@ -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<float>(0x800000)
|
||||
/// \brief Largest positive, finite value of \f$float\f$.
|
||||
#define FLT_MAX fennec::bit_cast<float>(0x7f7fffff)
|
||||
/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$.
|
||||
#define FLT_EPSILON fennec::bit_cast<float>(0x34000000)
|
||||
/// \brief A value representing \f$\inf\f$ of type \f$float\f$.
|
||||
#define FLT_INF fennec::bit_cast<float>(0x7f800000)
|
||||
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.
|
||||
#define FLT_QUIET_NAN fennec::bit_cast<float>(0x7fc00000)
|
||||
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps.
|
||||
#define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000)
|
||||
/// \brief Smallest positive, finite, subnormal value of \f$float\f$.
|
||||
#define FLT_DENORM_MIN fennec::bit_cast<float>(0x1)
|
||||
/// \brief Maximum rounding error of type \f$float\f$.
|
||||
#define FLT_ROUND_ERR fennec::bit_cast<float>(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<double>(0x10000000000000ll)
|
||||
/// \brief Largest positive, finite value of \f$double\f$.
|
||||
#define DBL_MAX fennec::bit_cast<double>(0x7fefffffffffffffll)
|
||||
/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$.
|
||||
#define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000ll)
|
||||
/// \brief A value representing \f$\inf\f$ of type \f$double\f$.
|
||||
#define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000ll)
|
||||
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.
|
||||
#define DBL_QUIET_NAN fennec::bit_cast<double>(0x7ff8000000000000ll)
|
||||
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps.
|
||||
#define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000ll)
|
||||
/// \brief Smallest positive, finite, subnormal value of \f$double\f$.
|
||||
#define DBL_DENORM_MIN fennec::bit_cast<double>(0x1ll)
|
||||
/// \brief Maximum rounding error of type \f$double\f$.
|
||||
#define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000ll)
|
||||
|
||||
#endif // FENNEC_LANG_FLOAT_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
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)\f$
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// 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.
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
|
||||
@@ -222,42 +222,42 @@ enum float_round_style
|
||||
/// \tparam TypeT Numeric types, may be overloaded for custom types
|
||||
template<typename TypeT> 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
|
||||
|
||||
@@ -192,6 +192,16 @@
|
||||
/// \copybrief fennec::ptrdiff_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::empty_t "empty_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::empty_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::undefined_t "undefined_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::undefined_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::void_t "void_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \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<typename...> using void_t = void; ///< \brief Void type used for SFINAE
|
||||
class undefined_t; //!< \brief Undefined class for SFINAE.
|
||||
template<typename...> 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
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#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 <fennec/math/detail/_types.h>
|
||||
|
||||
@@ -36,4 +36,4 @@ template<typename ScalarT, size_t ColsV, size_t RowsV> using mat
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_MATH_DETAIL_FWD_H
|
||||
#endif // FENNEC_MATH_DETAIL_FORWARD_H
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef FENNEC_MATH_DETAIL_MATRIX_H
|
||||
#define FENNEC_MATH_DETAIL_MATRIX_H
|
||||
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
|
||||
#define FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
|
||||
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
|
||||
#include <fennec/lang/type_traits.h>
|
||||
#include <fennec/math/swizzle.h>
|
||||
|
||||
@@ -546,81 +546,81 @@ namespace fennec
|
||||
|
||||
// Rational Constants ==================================================================================================
|
||||
|
||||
template<typename genType> constexpr genType zero() { return genType(0); } ///< \returns The value of \f$0\f$
|
||||
template<typename genType> constexpr genType one() { return genType(1); } ///< \returns The value of \f$1\f$
|
||||
template<typename genType> constexpr genType one_half() { return genType(0.5); } ///< \returns The value of \f$\frac{1}{2}\f$
|
||||
template<typename genType> constexpr genType three_over_two() { return genType(1.5); } ///< \returns The value of \f$\frac{3}{2}\f$
|
||||
template<typename genType> constexpr genType zero() { return genType(0); } //!< \returns The value of \f$0\f$
|
||||
template<typename genType> constexpr genType one() { return genType(1); } //!< \returns The value of \f$1\f$
|
||||
template<typename genType> constexpr genType one_half() { return genType(0.5); } //!< \returns The value of \f$\frac{1}{2}\f$
|
||||
template<typename genType> constexpr genType three_over_two() { return genType(1.5); } //!< \returns The value of \f$\frac{3}{2}\f$
|
||||
|
||||
|
||||
|
||||
// Irrational Constants ================================================================================================
|
||||
|
||||
template<typename genType> 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<typename genType> 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<typename genType> constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } ///< \returns The value of \f$\sqrt{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } ///< \returns The value of \f$\sqrt{3}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } ///< \returns The value of \f$\sqrt{5}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } ///< \returns The value of \f$\sqrt{7}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } ///< \returns The value of \f$\sqrt{10}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } //!< \returns The value of \f$\sqrt{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } //!< \returns The value of \f$\sqrt{3}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } //!< \returns The value of \f$\sqrt{5}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } //!< \returns The value of \f$\sqrt{7}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } //!< \returns The value of \f$\sqrt{10}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> constexpr genType pi() { return 3.14159265358979323846264338327950288419716939937510; } ///< \returns The value of \f$\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType tau() { return 6.28318530717958647692528676655900576839433879875021; } ///< \returns The value of \f$\tau\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType pi() { return 3.14159265358979323846264338327950288419716939937510; } //!< \returns The value of \f$\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> 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<typename genType> constexpr genType two_pi() { return 6.28318530717958647692528676655900576839433879875021; } ///< \returns The value of \f$2\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } ///< \returns The value of \f$3\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType four_pi() { return 12.56637061435917295385057353311801153678867759750042; } ///< \returns The value of \f$4\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType two_pi() { return 6.28318530717958647692528676655900576839433879875021; } //!< \returns The value of \f$2\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } //!< \returns The value of \f$3\pi\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> 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<typename genType> constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } ///< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } ///< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } //!< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } //!< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \f$\sqrt{\pi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> 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<typename genType> 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$
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
///
|
||||
///
|
||||
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
#include <fennec/math/detail/_matrix.h>
|
||||
|
||||
#include <fennec/containers/array.h>
|
||||
@@ -78,43 +78,43 @@ constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>&
|
||||
|
||||
|
||||
template<typename ScalarT>
|
||||
using tmat2x2 = mat<ScalarT, 2, 2>; ///< helper for creating 2x2 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; ///< helper for creating 2x3 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; ///< helper for creating 2x4 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; ///< helper for creating 3x2 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat3x3 = mat<ScalarT, 3, 3>; ///< helper for creating 3x3 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat3x4 = mat<ScalarT, 3, 4>; ///< helper for creating 3x4 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat4x2 = mat<ScalarT, 4, 2>; ///< helper for creating 4x2 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat4x3 = mat<ScalarT, 4, 3>; ///< helper for creating 4x3 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat4x4 = mat<ScalarT, 4, 4>; ///< helper for creating 4x4 matrices of the specified type.
|
||||
using tmat2x2 = mat<ScalarT, 2, 2>; //!< helper for creating 2x2 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; //!< helper for creating 2x3 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; //!< helper for creating 2x4 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; //!< helper for creating 3x2 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat3x3 = mat<ScalarT, 3, 3>; //!< helper for creating 3x3 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat3x4 = mat<ScalarT, 3, 4>; //!< helper for creating 3x4 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat4x2 = mat<ScalarT, 4, 2>; //!< helper for creating 4x2 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat4x3 = mat<ScalarT, 4, 3>; //!< helper for creating 4x3 matrices of the specified type.
|
||||
template<typename ScalarT> using tmat4x4 = mat<ScalarT, 4, 4>; //!< helper for creating 4x4 matrices of the specified type.
|
||||
|
||||
using mat2 = tmat2x2<float_t>; ///< Specification for glsl float matrices
|
||||
using mat3 = tmat3x3<float_t>; ///< Specification for glsl float matrices
|
||||
using mat4 = tmat4x4<float_t>; ///< Specification for glsl float matrices
|
||||
using mat2 = tmat2x2<float_t>; //!< Specification for glsl float matrices
|
||||
using mat3 = tmat3x3<float_t>; //!< Specification for glsl float matrices
|
||||
using mat4 = tmat4x4<float_t>; //!< Specification for glsl float matrices
|
||||
|
||||
using mat2x2 = tmat2x2<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat2x3 = tmat2x3<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat2x4 = tmat2x4<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat3x2 = tmat3x2<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat3x3 = tmat3x3<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat3x4 = tmat3x4<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat4x2 = tmat4x2<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat4x3 = tmat4x3<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat4x4 = tmat4x4<float_t>; ///< Specification for sized glsl float matrices
|
||||
using mat2x2 = tmat2x2<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat2x3 = tmat2x3<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat2x4 = tmat2x4<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat3x2 = tmat3x2<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat3x3 = tmat3x3<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat3x4 = tmat3x4<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat4x2 = tmat4x2<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat4x3 = tmat4x3<float_t>; //!< Specification for sized glsl float matrices
|
||||
using mat4x4 = tmat4x4<float_t>; //!< Specification for sized glsl float matrices
|
||||
|
||||
using dmat2 = tmat2x2<double_t>; ///< Specification for glsl double matrices
|
||||
using dmat3 = tmat3x3<double_t>; ///< Specification for glsl double matrices
|
||||
using dmat4 = tmat3x3<double_t>; ///< Specification for glsl double matrices
|
||||
using dmat2 = tmat2x2<double_t>; //!< Specification for glsl double matrices
|
||||
using dmat3 = tmat3x3<double_t>; //!< Specification for glsl double matrices
|
||||
using dmat4 = tmat3x3<double_t>; //!< Specification for glsl double matrices
|
||||
|
||||
using dmat2x2 = tmat2x2<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat2x3 = tmat2x3<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat2x4 = tmat2x4<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat3x2 = tmat3x2<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat3x3 = tmat3x3<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat3x4 = tmat3x4<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat4x2 = tmat4x2<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat4x3 = tmat4x3<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat4x4 = tmat4x4<double_t>; ///< Specification for size glsl double matrices
|
||||
using dmat2x2 = tmat2x2<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat2x3 = tmat2x3<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat2x4 = tmat2x4<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat3x2 = tmat3x2<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat3x3 = tmat3x3<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat3x4 = tmat3x4<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat4x2 = tmat4x2<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat4x3 = tmat4x3<double_t>; //!< Specification for size glsl double matrices
|
||||
using dmat4x4 = tmat4x4<double_t>; //!< Specification for size glsl double matrices
|
||||
|
||||
|
||||
///
|
||||
@@ -676,7 +676,7 @@ struct matrix
|
||||
|
||||
|
||||
|
||||
// Helpers =============================================================================================================
|
||||
// Private Helpers =====================================================================================================
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
#include <fennec/math/detail/_types.h>
|
||||
|
||||
namespace fennec
|
||||
|
||||
@@ -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
|
||||
/// @}
|
||||
|
||||
///
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
///
|
||||
|
||||
#include <fennec/containers/initializer_list.h>
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
|
||||
#include <fennec/math/vector_base.h>
|
||||
#include <fennec/math/vector_traits.h>
|
||||
@@ -146,31 +146,31 @@ template<typename ScalarT>
|
||||
using tvec4 = vec<ScalarT, 4>;
|
||||
|
||||
|
||||
using bvec2 = tvec2<bool_t>; ///< \brief A two-component boolean \ref fennec_math_vector "vector"
|
||||
using bvec3 = tvec3<bool_t>; ///< \brief A three-component boolean \ref fennec_math_vector "vector"
|
||||
using bvec4 = tvec4<bool_t>; ///< \brief A four-component boolean \ref fennec_math_vector "vector"
|
||||
using bvec2 = tvec2<bool_t>; //!< \brief A two-component boolean \ref fennec_math_vector "vector"
|
||||
using bvec3 = tvec3<bool_t>; //!< \brief A three-component boolean \ref fennec_math_vector "vector"
|
||||
using bvec4 = tvec4<bool_t>; //!< \brief A four-component boolean \ref fennec_math_vector "vector"
|
||||
|
||||
using ivec2 = tvec2<int32_t>; ///< \brief A two-component signed integer \ref fennec_math_vector "vector"
|
||||
using ivec3 = tvec3<int32_t>; ///< \brief A three-component signed integer \ref fennec_math_vector "vector"
|
||||
using ivec4 = tvec4<int32_t>; ///< \brief A four-component signed integer \ref fennec_math_vector "vector"
|
||||
using ivec2 = tvec2<int32_t>; //!< \brief A two-component signed integer \ref fennec_math_vector "vector"
|
||||
using ivec3 = tvec3<int32_t>; //!< \brief A three-component signed integer \ref fennec_math_vector "vector"
|
||||
using ivec4 = tvec4<int32_t>; //!< \brief A four-component signed integer \ref fennec_math_vector "vector"
|
||||
|
||||
using uvec2 = tvec2<uint32_t>; ///< \brief A two-component unsigned integer \ref fennec_math_vector "vector"
|
||||
using uvec3 = tvec3<uint32_t>; ///< \brief A three-component unsigned integer \ref fennec_math_vector "vector"
|
||||
using uvec4 = tvec4<uint32_t>; ///< \brief A four-component unsigned integer \ref fennec_math_vector "vector"
|
||||
using uvec2 = tvec2<uint32_t>; //!< \brief A two-component unsigned integer \ref fennec_math_vector "vector"
|
||||
using uvec3 = tvec3<uint32_t>; //!< \brief A three-component unsigned integer \ref fennec_math_vector "vector"
|
||||
using uvec4 = tvec4<uint32_t>; //!< \brief A four-component unsigned integer \ref fennec_math_vector "vector"
|
||||
|
||||
using vec2 = tvec2<float_t>;
|
||||
///< \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<float_t>;
|
||||
///< \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<float_t>;
|
||||
///< \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<double_t>;
|
||||
///< \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<double_t>;
|
||||
///< \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<double_t>;
|
||||
///< \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<ScalarT, sizeof...(IndicesV)>
|
||||
static_assert(is_arithmetic_v<ScalarT>);
|
||||
|
||||
|
||||
// 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<ScalarT, sizeof...(IndicesV)>
|
||||
/// \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<N == 1, scalar_t, vector_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<ScalarT, sizeof...(IndicesV)>
|
||||
/// @}
|
||||
|
||||
|
||||
// Public Member Functions =============================================================================================
|
||||
// Utility Functions ===================================================================================================
|
||||
|
||||
/// \name Public Member Functions
|
||||
/// \name Utility Functions
|
||||
/// @{
|
||||
|
||||
///
|
||||
@@ -1096,7 +1102,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// @}
|
||||
|
||||
|
||||
// Helpers =============================================================================================================
|
||||
// Private Helpers =====================================================================================================
|
||||
|
||||
private:
|
||||
template<size_t IndexV = 0, typename HeadT, typename... TailT>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef FENNEC_MATH_VECTOR_BASE_H
|
||||
#define FENNEC_MATH_VECTOR_BASE_H
|
||||
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
|
||||
#include <fennec/math/swizzle.h>
|
||||
#include <fennec/math/vector_storage.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<typename T, class AllocT = allocator<T>>
|
||||
struct allocation
|
||||
{
|
||||
struct allocation {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
|
||||
/// \name Definitions
|
||||
/// @{
|
||||
|
||||
/// \brief alias for the allocator type
|
||||
using alloc_t = typename allocator_traits<AllocT>::template rebind<T>;
|
||||
|
||||
@@ -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<align_t>()) {
|
||||
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<align_t>()) {
|
||||
callocate(n);
|
||||
allocate(n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -449,7 +460,7 @@ public:
|
||||
, _data(nullptr)
|
||||
, _capacity(0)
|
||||
, _alignment(zero<align_t>()) {
|
||||
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<align_t>()) noexcept {
|
||||
allocate(n, align);
|
||||
fennec::memset(static_cast<void*>(_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<align_t>()) 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<void*>(_data), old, min(_capacity, old_cap) * sizeof(T));
|
||||
|
||||
if (_capacity > old_cap) {
|
||||
fennec::memset(static_cast<void*>(_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<void*>(_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<void*>(_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
|
||||
|
||||
@@ -84,9 +84,14 @@ struct default_delete<TypeT[]>
|
||||
/// \tparam TypeT
|
||||
/// \tparam DeleteT
|
||||
template<typename TypeT, class DeleteT = default_delete<TypeT>>
|
||||
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;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <fennec/containers/bitfield.h>
|
||||
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/forward.h>
|
||||
#include <fennec/platform/interface/window.h>
|
||||
|
||||
#include <fennec/renderers/interface/gfxcontext.h>
|
||||
@@ -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<display_server, platform*> {
|
||||
// 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<feature_count>; //!< 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<gfxcontext> gfx_context; //!< the graphics context of the display server
|
||||
|
||||
private:
|
||||
FENNEC_RTTI_CLASS_ENABLE() {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#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
|
||||
@@ -64,10 +64,25 @@ namespace fennec
|
||||
///
|
||||
/// \brief Main platform class
|
||||
class platform : public singleton<platform*> {
|
||||
|
||||
// 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<window_manager> wmanager; //!< the window manager
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#ifndef FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
||||
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
||||
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/forward.h>
|
||||
|
||||
#include <fennec/math/ext/rect.h>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<wayland_eglcontext>();
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define LATFORM_LINUX_WAYLAND_EGL_SURFACE_H
|
||||
|
||||
#include <fennec/platform/opengl/egl/surface.h>
|
||||
#include <fennec/platform/linux/wayland/fwd.h>
|
||||
#include <fennec/platform/linux/wayland/forward.h>
|
||||
|
||||
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:
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H
|
||||
@@ -31,7 +31,7 @@
|
||||
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
|
||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
|
||||
|
||||
#include <fennec/platform/linux/wayland/fwd.h>
|
||||
#include <fennec/platform/linux/wayland/forward.h>
|
||||
#include <fennec/platform/interface/display_server.h>
|
||||
|
||||
#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<wayland_server, wayland_window> {
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||
|
||||
#include <fennec/platform/linux/wayland/fwd.h>
|
||||
#include <fennec/platform/linux/wayland/forward.h>
|
||||
#include <fennec/platform/interface/window.h>
|
||||
|
||||
#ifndef FENNEC_DOXYGEN
|
||||
@@ -55,21 +55,32 @@ namespace fennec
|
||||
///
|
||||
/// \brief Class for handling a Wayland window
|
||||
class wayland_window : public window_base<wayland_server> {
|
||||
|
||||
// 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*);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H
|
||||
@@ -33,7 +33,7 @@
|
||||
#define FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
||||
|
||||
#include <fennec/platform/opengl/glad/egl.h>
|
||||
#include <fennec/platform/opengl/egl/fwd.h>
|
||||
#include <fennec/platform/opengl/egl/forward.h>
|
||||
|
||||
#include <fennec/renderers/interface/gfxsurface.h>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,10 +32,11 @@
|
||||
#ifndef FENNEC_PLATFORM_WINDOWMANAGER_H
|
||||
#define FENNEC_PLATFORM_WINDOWMANAGER_H
|
||||
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/forward.h>
|
||||
|
||||
#include <fennec/memory/pointers.h>
|
||||
#include <fennec/containers/object_pool.h>
|
||||
#include <fennec/containers/variant.h>
|
||||
#include <fennec/platform/interface/window.h>
|
||||
#include <fennec/threading/lock_guard.h>
|
||||
#include <fennec/threading/mpscq.h>
|
||||
@@ -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<flag_val, ivec2>;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#ifndef FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
|
||||
#define FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
|
||||
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/forward.h>
|
||||
|
||||
#include <fennec/core/version.h>
|
||||
#include <fennec/lang/types.h>
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,11 +16,24 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \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 <fennec/math/common.h>
|
||||
#include <fennec/renderers/opengl/lib/fwd.h>
|
||||
|
||||
#include <fennec/renderers/opengl/lib/forward.h>
|
||||
#include <fennec/renderers/opengl/lib/enum.h>
|
||||
|
||||
namespace fennec
|
||||
@@ -29,27 +42,120 @@ namespace fennec
|
||||
namespace gl
|
||||
{
|
||||
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using vertex_buffer = buffer<VERTEX, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using element_buffer = buffer<ELEMENT, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using uniform_buffer = buffer<UNIFORM, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using shader_storage_buffer = buffer<SHADER_STORAGE, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using query_buffer = buffer<QUERY, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using texture_buffer = buffer<TEXTURE, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using transform_feedback_buffer = buffer<TRANSFORM_FEEDBACK, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using atomic_counter_buffer = buffer<ATOMIC_COUNTER, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using parameter_buffer = buffer<PARAMETER, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using indirect_draw_buffer = buffer<INDIRECT_DRAW, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using indirect_dispatch_buffer = buffer<INDIRECT_DISPATCH, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using copy_read_buffer = buffer<COPY_READ, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using copy_write_buffer = buffer<COPY_WRITE, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using pixel_pack_buffer = buffer<PIXEL_PACK, FlagsV, ImmutableV>;
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV> using pixel_unpack_buffer = buffer<PIXEL_UNPACK, FlagsV, ImmutableV>;
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using vertex_buffer = buffer<VERTEX, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using element_buffer = buffer<ELEMENT, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using uniform_buffer = buffer<UNIFORM, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using shader_storage_buffer = buffer<SHADER_STORAGE, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using query_buffer = buffer<QUERY, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using texture_buffer = buffer<TEXTURE, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using transform_feedback_buffer = buffer<TRANSFORM_FEEDBACK, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using atomic_counter_buffer = buffer<ATOMIC_COUNTER, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using parameter_buffer = buffer<PARAMETER, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using indirect_draw_buffer = buffer<INDIRECT_DRAW, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using indirect_dispatch_buffer = buffer<INDIRECT_DISPATCH, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using copy_read_buffer = buffer<COPY_READ, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using copy_write_buffer = buffer<COPY_WRITE, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using pixel_pack_buffer = buffer<PIXEL_PACK, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \brief Vertex Buffer Alias
|
||||
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
|
||||
/// \tparam ImmutableV Mutability
|
||||
template<GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
using pixel_unpack_buffer = buffer<PIXEL_UNPACK, FlagsV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \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<GLenum TypeV, GLbitfield FlagsV, GLboolean ImmutableV>
|
||||
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<GLenum OTypeV, GLbitfield OFlagsV, GLboolean OImmutableV>
|
||||
constexpr void copy(const buffer<OTypeV, OFlagsV, OImmutableV>& cpy, GLsizeiptr size = -1, GLintptr write_offset = 0, GLintptr read_offset = 0) {
|
||||
void copy(const buffer<OTypeV, OFlagsV, OImmutableV>& 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<typename TypeT>
|
||||
constexpr TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) {
|
||||
TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) {
|
||||
return static_cast<TypeT*>(map(access, n * sizeof(TypeT), offset * sizeof(TypeT)));
|
||||
}
|
||||
|
||||
private:
|
||||
GLuint _handle;
|
||||
GLsizeiptr _size;
|
||||
void* _mapping;
|
||||
void* _data;
|
||||
GLbitfield _mapflags;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,10 +16,22 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \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 <fennec/renderers/opengl/lib/fwd.h>
|
||||
#include <fennec/renderers/opengl/lib/forward.h>
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,20 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#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 <fennec/platform/opengl/glad/gl.h>
|
||||
|
||||
@@ -35,4 +47,4 @@ template<GLenum TypeV, GLint FormatV, GLboolean ImmutableV> class texture;
|
||||
}
|
||||
|
||||
|
||||
#endif // FENNEC_RENDERERS_OPENGL_LIB_FWD_H
|
||||
#endif // FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H
|
||||
@@ -16,6 +16,18 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \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<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEX_1D, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture1d_array = texture<TEX_1D_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEX_2D, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_array = texture<TEX_2D_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEX_RECT, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEX_2D_MS, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms_array = texture<TEX_2D_MS_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<TEX_CUBEMAP, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using cubemap_array = texture<TEX_CUBEMAP_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEX_3D, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<TEX_BUFFER, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEXTURE_1D, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture1d_array = texture<TEXTURE_1D_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEXTURE_2D, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_array = texture<TEXTURE_2D_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEXTURE_RECTANGLE, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEXTURE_2D_MS, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms_array = texture<TEXTURE_2D_MS_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<CUBEMAP, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using cubemap_array = texture<CUBEMAP_ARRAY, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEXTURE_3D, FormatV, ImmutableV>;
|
||||
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<BUFFER_TEXTURE, FormatV, ImmutableV>;
|
||||
|
||||
///
|
||||
/// \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() {
|
||||
|
||||
@@ -16,6 +16,18 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \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);
|
||||
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#ifndef FENNEC_PLATFORM_VULKAN_VKCONTEXT_H
|
||||
#define FENNEC_PLATFORM_VULKAN_VKCONTEXT_H
|
||||
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/forward.h>
|
||||
#include <fennec/renderers/interface/gfxcontext.h>
|
||||
|
||||
namespace fennec
|
||||
|
||||
@@ -18,14 +18,8 @@
|
||||
|
||||
#ifndef FENNEC_RTTI_DETAIL_THIS_T_H
|
||||
#define FENNEC_RTTI_DETAIL_THIS_T_H
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
|
||||
#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 <fennec/lang/type_transforms.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
@@ -36,8 +36,12 @@
|
||||
#include <fennec/rtti/type.h>
|
||||
#include <fennec/rtti/typelist.h>
|
||||
|
||||
#include <fennec/rtti/detail/_this_t.h>
|
||||
#include <fennec/rtti/this_t.h>
|
||||
|
||||
///
|
||||
/// \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: \
|
||||
|
||||
47
include/fennec/rtti/this_t.h
Normal file
47
include/fennec/rtti/this_t.h
Normal file
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \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 <fennec/rtti/detail/_this_t.h>
|
||||
|
||||
///
|
||||
/// \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
|
||||
@@ -31,7 +31,7 @@ namespace fennec
|
||||
class component {
|
||||
public:
|
||||
|
||||
// MEMBERS =============================================================================================================
|
||||
// Public Member Variables =============================================================================================
|
||||
public:
|
||||
///
|
||||
/// \brief reference to the
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace fennec
|
||||
|
||||
struct scene_node {
|
||||
|
||||
// Public Members ======================================================================================================
|
||||
// Public Member Variables =============================================================================================
|
||||
public:
|
||||
scene* const scene;
|
||||
const size_t id;
|
||||
|
||||
@@ -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<size_t n>
|
||||
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
|
||||
|
||||
@@ -42,7 +42,11 @@ using string = _string<>;
|
||||
template<typename AllocT>
|
||||
struct _string
|
||||
{
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
|
||||
|
||||
|
||||
static constexpr size_t npos = -1; //!< null position
|
||||
using char_t = char; //!< the character type
|
||||
using alloc_t = allocation<char, AllocT>; //!< 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>." << 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 <https://www.gnu.org/licenses/>." << '\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 <fennec/lang/bits.h>" << std::endl;
|
||||
out << "#include <fennec/lang/bits.h>" << '\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<float>::has_infinity << std::endl;
|
||||
out << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits<float>::has_quiet_NaN << std::endl;
|
||||
out << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<float>::has_signaling_NaN << std::endl;
|
||||
out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << std::endl;
|
||||
out << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<float>::has_denorm_loss << std::endl;
|
||||
out << "#define FLT_ROUNDS " << std::dec << std::numeric_limits<float>::round_style << std::endl;
|
||||
out << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits<float>::is_iec559 << std::endl;
|
||||
out << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits<float>::digits << std::endl;
|
||||
out << "#define FLT_DIG " << std::dec << std::numeric_limits<float>::digits10 << std::endl;
|
||||
out << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits<float>::max_digits10 << std::endl;
|
||||
out << "#define FLT_RADIX " << std::dec << std::numeric_limits<float>::radix << std::endl;
|
||||
out << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits<float>::min_exponent << std::endl;
|
||||
out << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits<float>::max_exponent << std::endl;
|
||||
out << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits<float>::min_exponent10 << std::endl;
|
||||
out << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits<float>::max_exponent10 << std::endl;
|
||||
out << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::traps << std::endl;
|
||||
out << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits<float>::tinyness_before << std::endl;
|
||||
out << "" << '\n';
|
||||
|
||||
out << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << std::endl;
|
||||
out << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::max() ) << ")" << std::endl;
|
||||
out << "#define FLT_EPSILON " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << std::endl;
|
||||
out << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::infinity() ) << ")" << std::endl;
|
||||
out << "#define FLT_QUIET_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::quiet_NaN() ) << ")" << std::endl;
|
||||
out << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << std::endl;
|
||||
out << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << std::endl;
|
||||
out << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::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<float>::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<float>::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<float>::has_signaling_NaN << '\n';
|
||||
|
||||
out << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits<double>::has_infinity << std::endl;
|
||||
out << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits<double>::has_quiet_NaN << std::endl;
|
||||
out << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<double>::has_signaling_NaN << std::endl;
|
||||
out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::has_denorm << std::endl;
|
||||
out << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<double>::has_denorm_loss << std::endl;
|
||||
out << "#define DBL_ROUNDS " << std::dec << std::numeric_limits<double>::round_style << std::endl;
|
||||
out << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits<double>::is_iec559 << std::endl;
|
||||
out << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits<double>::digits << std::endl;
|
||||
out << "#define DBL_DIG " << std::dec << std::numeric_limits<double>::digits10 << std::endl;
|
||||
out << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits<double>::max_digits10 << std::endl;
|
||||
out << "#define DBL_RADIX " << std::dec << std::numeric_limits<double>::radix << std::endl;
|
||||
out << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits<double>::min_exponent << std::endl;
|
||||
out << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits<double>::max_exponent << std::endl;
|
||||
out << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits<double>::min_exponent10 << std::endl;
|
||||
out << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits<double>::max_exponent10 << std::endl;
|
||||
out << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::traps << std::endl;
|
||||
out << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits<double>::tinyness_before << std::endl;
|
||||
out << R"(/// \brief Does \f$float\f$ use denormalization?)" << '\n';
|
||||
out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << '\n';
|
||||
|
||||
out << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "ll)" << std::endl;
|
||||
out << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::max() ) << "ll)" << std::endl;
|
||||
out << "#define DBL_EPSILON " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::epsilon() ) << "ll)" << std::endl;
|
||||
out << "#define DBL_INF " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::infinity() ) << "ll)" << std::endl;
|
||||
out << "#define DBL_QUIET_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::quiet_NaN() ) << "ll)" << std::endl;
|
||||
out << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::signaling_NaN()) << "ll)" << std::endl;
|
||||
out << "#define DBL_DENORM_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "ll)" << std::endl;
|
||||
out << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::max_exponent10 << '\n';
|
||||
|
||||
out << R"(/// \brief Do arithmetics operations with \f$float\f$ trap?)" << '\n';
|
||||
out << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::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<float>::tinyness_before << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest positive, finite, normal value of \f$float\f$.)" << '\n';
|
||||
out << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << '\n';
|
||||
|
||||
out << R"(/// \brief Largest positive, finite value of \f$float\f$.)" << '\n';
|
||||
out << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::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<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << '\n';
|
||||
|
||||
out << R"(/// \brief A value representing \f$\inf\f$ of type \f$float\f$.)" << '\n';
|
||||
out << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::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<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::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<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << '\n';
|
||||
|
||||
out << R"(/// \brief Smallest positive, finite, subnormal value of \f$float\f$.)" << '\n';
|
||||
out << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << '\n';
|
||||
|
||||
out << R"(/// \brief Maximum rounding error of type \f$float\f$.)" << '\n';
|
||||
out << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::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<double>::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<double>::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<double>::has_signaling_NaN << '\n';
|
||||
|
||||
out << R"(/// \brief Does \f$double\f$ use denormalization?)" << '\n';
|
||||
out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::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<double>::max_exponent10 << '\n';
|
||||
|
||||
out << R"(/// \brief Do arithmetics operations with \f$double\f$ trap?)" << '\n';
|
||||
out << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::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<double>::tinyness_before << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest positive, finite, normal value of \f$double\f$.)" << '\n';
|
||||
out << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "ll)" << '\n';
|
||||
|
||||
out << R"(/// \brief Largest positive, finite value of \f$double\f$.)" << '\n';
|
||||
out << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::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<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::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<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::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<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::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<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::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<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "ll)" << '\n';
|
||||
|
||||
out << R"(/// \brief Maximum rounding error of type \f$double\f$.)" << '\n';
|
||||
out << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::round_error() ) << "ll)" << '\n';
|
||||
|
||||
out << "" << '\n';
|
||||
|
||||
out << "#endif // FENNEC_LANG_FLOAT_H" << '\n';
|
||||
|
||||
out.close();
|
||||
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>." << 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 <https://www.gnu.org/licenses/>." << '\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<char>::is_signed << std::endl;
|
||||
out << R"(/// \brief Is \f$char\f$ signed?)" << '\n';
|
||||
out << "#define CHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<char>::is_signed << '\n';
|
||||
|
||||
out << "#define CHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<char>::round_style << std::endl;
|
||||
out << "#define CHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::digits << std::endl;
|
||||
out << "#define CHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::digits10 << std::endl;
|
||||
out << "#define CHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::max_digits10 << std::endl;
|
||||
out << "#define CHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<char>::radix << std::endl;
|
||||
out << "#define CHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<char>::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<char>::round_style << '\n';
|
||||
|
||||
out << "#define CHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::min()) << std::endl;
|
||||
out << "#define CHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::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<char>::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<char>::digits10 << '\n';
|
||||
|
||||
out << "#define WCHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<wchar_t>::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<char>::max_digits10 << '\n';
|
||||
|
||||
out << "#define WCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits<wchar_t>::round_style << std::endl;
|
||||
out << "#define WCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::digits << std::endl;
|
||||
out << "#define WCHAR_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::digits10 << std::endl;
|
||||
out << "#define WCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::max_digits10 << std::endl;
|
||||
out << "#define WCHAR_RADIX " << "0x" << std::hex << std::numeric_limits<wchar_t>::radix << std::endl;
|
||||
out << "#define WCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<wchar_t>::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<char>::radix << '\n';
|
||||
|
||||
out << "#define WCHAR_MIN " << "0x" << std::hex << +std::numeric_limits<wchar_t>::min() << std::endl;
|
||||
out << "#define WCHAR_MAX " << "0x" << std::hex << +std::numeric_limits<wchar_t>::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<char>::traps << '\n';
|
||||
|
||||
out << "" << std::endl;
|
||||
|
||||
out << "#define SCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<signed char>::round_style << std::endl;
|
||||
out << "#define SCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits << std::endl;
|
||||
out << "#define SCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits10 << std::endl;
|
||||
out << "#define SCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::max_digits10 << std::endl;
|
||||
out << "#define SCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<signed char>::radix << std::endl;
|
||||
out << "#define SCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<signed char>::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<char>::min()) << '\n';
|
||||
|
||||
out << "#define SCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::min()) << std::endl;
|
||||
out << "#define SCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::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<char>::max()) << '\n';
|
||||
|
||||
out << "" << std::endl;
|
||||
|
||||
out << "#define UCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned char>::round_style << std::endl;
|
||||
out << "#define UCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::digits << std::endl;
|
||||
out << "#define UCHAR_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::digits10 << std::endl;
|
||||
out << "#define UCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::max_digits10 << std::endl;
|
||||
out << "#define UCHAR_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned char>::radix << std::endl;
|
||||
out << "#define UCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned char>::traps << std::endl;
|
||||
out << "" << '\n';
|
||||
|
||||
out << "#define UCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::min()) << std::endl;
|
||||
out << "#define UCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::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<wchar_t>::is_signed << '\n';
|
||||
|
||||
out << "#define SHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits<short>::round_style << std::endl;
|
||||
out << "#define SHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<short>::digits << std::endl;
|
||||
out << "#define SHORT_DIG " << "0x" << std::hex << std::numeric_limits<short>::digits10 << std::endl;
|
||||
out << "#define SHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<short>::max_digits10 << std::endl;
|
||||
out << "#define SHORT_RADIX " << "0x" << std::hex << std::numeric_limits<short>::radix << std::endl;
|
||||
out << "#define SHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<short>::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<wchar_t>::round_style << '\n';
|
||||
|
||||
out << "#define SHORT_MIN " << "0x" << std::hex << std::numeric_limits<short>::min() << std::endl;
|
||||
out << "#define SHORT_MAX " << "0x" << std::hex << std::numeric_limits<short>::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<wchar_t>::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<wchar_t>::digits10 << '\n';
|
||||
|
||||
out << "#define USHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned short>::round_style << std::endl;
|
||||
out << "#define USHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::digits << std::endl;
|
||||
out << "#define USHORT_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::digits10 << std::endl;
|
||||
out << "#define USHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::max_digits10 << std::endl;
|
||||
out << "#define USHORT_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned short>::radix << std::endl;
|
||||
out << "#define USHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned short>::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<wchar_t>::max_digits10 << '\n';
|
||||
|
||||
out << "#define USHORT_MIN " << "0x" << std::hex << std::numeric_limits<unsigned short>::min() << std::endl;
|
||||
out << "#define USHORT_MAX " << "0x" << std::hex << std::numeric_limits<unsigned short>::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<wchar_t>::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<wchar_t>::traps << '\n';
|
||||
|
||||
out << "#define INT_ROUNDS " << "0x" << std::hex << std::numeric_limits<int>::round_style << std::endl;
|
||||
out << "#define INT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<int>::digits << std::endl;
|
||||
out << "#define INT_DIG " << "0x" << std::hex << std::numeric_limits<int>::digits10 << std::endl;
|
||||
out << "#define INT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<int>::max_digits10 << std::endl;
|
||||
out << "#define INT_RADIX " << "0x" << std::hex << std::numeric_limits<int>::radix << std::endl;
|
||||
out << "#define INT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<int>::traps << std::endl;
|
||||
|
||||
out << "#define INT_MIN " << "0x" << std::hex << std::numeric_limits<int>::min() << std::endl;
|
||||
out << "#define INT_MAX " << "0x" << std::hex << std::numeric_limits<int>::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<wchar_t>::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<wchar_t>::max() << '\n';
|
||||
|
||||
out << "#define UINT_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned int>::round_style << std::endl;
|
||||
out << "#define UINT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::digits << std::endl;
|
||||
out << "#define UINT_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::digits10 << std::endl;
|
||||
out << "#define UINT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::max_digits10 << std::endl;
|
||||
out << "#define UINT_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned int>::radix << std::endl;
|
||||
out << "#define UINT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned int>::traps << std::endl;
|
||||
|
||||
out << "#define UINT_MIN " << "0x" << std::hex << std::numeric_limits<unsigned int>::min() << std::endl;
|
||||
out << "#define UINT_MAX " << "0x" << std::hex << std::numeric_limits<unsigned int>::max() << std::endl;
|
||||
out << "" << '\n';
|
||||
|
||||
out << "" << std::endl;
|
||||
|
||||
out << "#define LONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<long int>::round_style << std::endl;
|
||||
out << "#define LONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<long int>::digits << std::endl;
|
||||
out << "#define LONG_DIG " << "0x" << std::hex << std::numeric_limits<long int>::digits10 << std::endl;
|
||||
out << "#define LONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long int>::max_digits10 << std::endl;
|
||||
out << "#define LONG_RADIX " << "0x" << std::hex << std::numeric_limits<long int>::radix << std::endl;
|
||||
out << "#define LONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<long int>::traps << std::endl;
|
||||
out << R"(/// \brief Is \f$signed char\f$ signed?)" << '\n';
|
||||
out << "#define SCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<signed char>::round_style << '\n';
|
||||
|
||||
out << "#define LONG_MIN " << "0x" << std::hex << std::numeric_limits<long int>::min() << std::endl;
|
||||
out << "#define LONG_MAX " << "0x" << std::hex << std::numeric_limits<long int>::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<signed char>::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<signed char>::digits10 << '\n';
|
||||
|
||||
out << "#define ULONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned long int>::round_style << std::endl;
|
||||
out << "#define ULONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits << std::endl;
|
||||
out << "#define ULONG_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits10 << std::endl;
|
||||
out << "#define ULONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::max_digits10 << std::endl;
|
||||
out << "#define ULONG_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned long int>::radix << std::endl;
|
||||
out << "#define ULONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned long int>::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<signed char>::max_digits10 << '\n';
|
||||
|
||||
out << "#define ULONG_MIN " << "0x" << std::hex << std::numeric_limits<unsigned long int>::min() << std::endl;
|
||||
out << "#define ULONG_MAX " << "0x" << std::hex << std::numeric_limits<unsigned long int>::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<signed char>::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<signed char>::traps << '\n';
|
||||
|
||||
out << "#define LLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<long long>::round_style << std::endl;
|
||||
out << "#define LLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<long long>::digits << std::endl;
|
||||
out << "#define LLONG_DIG " << "0x" << std::hex << std::numeric_limits<long long>::digits10 << std::endl;
|
||||
out << "#define LLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long long>::max_digits10 << std::endl;
|
||||
out << "#define LLONG_RADIX " << "0x" << std::hex << std::numeric_limits<long long>::radix << std::endl;
|
||||
out << "#define LLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<long long>::traps << std::endl;
|
||||
|
||||
out << "#define LLONG_MIN " << "0x" << std::hex << std::numeric_limits<long long>::min() << std::endl;
|
||||
out << "#define LLONG_MAX " << "0x" << std::hex << std::numeric_limits<long long>::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<signed char>::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<signed char>::max()) << '\n';
|
||||
|
||||
out << "#define ULLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned long long>::round_style << std::endl;
|
||||
out << "#define ULLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits << std::endl;
|
||||
out << "#define ULLONG_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits10 << std::endl;
|
||||
out << "#define ULLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::max_digits10 << std::endl;
|
||||
out << "#define ULLONG_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned long long>::radix << std::endl;
|
||||
out << "#define ULLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned long long>::traps << std::endl;
|
||||
|
||||
out << "#define ULLONG_MIN " << "0x" << std::hex << std::numeric_limits<unsigned long long>::min() << std::endl;
|
||||
out << "#define ULLONG_MAX " << "0x" << std::hex << std::numeric_limits<unsigned long long>::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<unsigned char>::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<unsigned char>::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<unsigned char>::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<unsigned char>::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<unsigned char>::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<unsigned char>::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<unsigned char>::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<unsigned char>::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<short>::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<short>::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<short>::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<short>::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<short>::radix << '\n';
|
||||
|
||||
out << R"(/// \brief Do arithmetics operations with \f$short\f$ trap?)" << '\n';
|
||||
out << "#define SHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<short>::traps << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest finite value of \f$short\f$.)" << '\n';
|
||||
out << "#define SHORT_MIN " << "0x" << std::hex << +std::numeric_limits<short>::min() << '\n';
|
||||
|
||||
out << R"(/// \brief Largest finite value of \f$short\f$.)" << '\n';
|
||||
out << "#define SHORT_MAX " << "0x" << std::hex << +std::numeric_limits<short>::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<unsigned short>::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<unsigned short>::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<unsigned short>::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<unsigned short>::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<unsigned short>::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<unsigned short>::traps << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest finite value of \f$unsigned short\f$.)" << '\n';
|
||||
out << "#define USHORT_MIN " << "0x" << std::hex << +std::numeric_limits<unsigned short>::min() << '\n';
|
||||
|
||||
out << R"(/// \brief Largest finite value of \f$unsigned short\f$.)" << '\n';
|
||||
out << "#define USHORT_MAX " << "0x" << std::hex << +std::numeric_limits<unsigned short>::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<int>::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<int>::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<int>::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<int>::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<int>::radix << '\n';
|
||||
|
||||
out << R"(/// \brief Do arithmetics operations with \f$int\f$ trap?)" << '\n';
|
||||
out << "#define INT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<int>::traps << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest finite value of \f$int\f$.)" << '\n';
|
||||
out << "#define INT_MIN " << "0x" << std::hex << +std::numeric_limits<int>::min() << '\n';
|
||||
|
||||
out << R"(/// \brief Largest finite value of \f$int\f$.)" << '\n';
|
||||
out << "#define INT_MAX " << "0x" << std::hex << +std::numeric_limits<int>::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<unsigned int>::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<unsigned int>::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<unsigned int>::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<unsigned int>::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<unsigned int>::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<unsigned int>::traps << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest finite value of \f$unsigned int\f$.)" << '\n';
|
||||
out << "#define UINT_MIN " << "0x" << std::hex << +std::numeric_limits<unsigned int>::min() << '\n';
|
||||
|
||||
out << R"(/// \brief Largest finite value of \f$unsigned int\f$.)" << '\n';
|
||||
out << "#define UINT_MAX " << "0x" << std::hex << +std::numeric_limits<unsigned int>::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<long int>::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<long int>::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<long int>::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<long int>::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<long int>::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<long int>::traps << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest finite value of \f$long int\f$.)" << '\n';
|
||||
out << "#define LONG_MIN " << "0x" << std::hex << +std::numeric_limits<long int>::min() << '\n';
|
||||
|
||||
out << R"(/// \brief Largest finite value of \f$long int\f$.)" << '\n';
|
||||
out << "#define LONG_MAX " << "0x" << std::hex << +std::numeric_limits<long int>::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<unsigned long int>::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<unsigned long int>::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<unsigned long int>::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<unsigned long int>::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<unsigned long int>::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<unsigned long int>::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<unsigned long int>::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<unsigned long int>::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<long long>::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<long long>::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<long long>::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<long long>::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<long long>::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<long long>::traps << '\n';
|
||||
|
||||
|
||||
out << R"(/// \brief Smallest finite value of \f$long long\f$.)" << '\n';
|
||||
out << "#define LLONG_MIN " << "0x" << std::hex << +std::numeric_limits<long long>::min() << '\n';
|
||||
|
||||
out << R"(/// \brief Largest finite value of \f$long long\f$.)" << '\n';
|
||||
out << "#define LLONG_MAX " << "0x" << std::hex << +std::numeric_limits<long long>::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<unsigned long long>::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<unsigned long long>::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<unsigned long long>::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<unsigned long long>::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<unsigned long long>::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<unsigned long long>::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<unsigned long long>::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<unsigned long long>::max() << '\n';
|
||||
|
||||
|
||||
out << "" << '\n';
|
||||
|
||||
out << "#endif // FENNEC_LANG_INTEGER_H" << '\n';
|
||||
|
||||
out.close();
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ path path::current() {
|
||||
#include <unistd.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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}"
|
||||
|
||||
52
test/tests/core/test_version.h
Normal file
52
test/tests/core/test_version.h
Normal file
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
|
||||
#ifndef FENNEC_TEST_CORE_VERSION_H
|
||||
#define FENNEC_TEST_CORE_VERSION_H
|
||||
|
||||
#include <fennec/core/version.h>
|
||||
|
||||
#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
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef FENNEC_TEST_MATRIX_H
|
||||
#define FENNEC_TEST_MATRIX_H
|
||||
|
||||
#include <fennec/math/detail/_fwd.h>
|
||||
#include <fennec/math/detail/_forward.h>
|
||||
|
||||
#include <fennec/math/matrix.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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user