- Basic RTTI type data with inheritance.
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file assert.h
|
||||
/// \brief \ref fennec_lang_assert
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_ASSERT_H
|
||||
#define FENNEC_LANG_ASSERT_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_assert Assertions
|
||||
///
|
||||
/// \code #include <fennec/lang/assert.h> \endcode
|
||||
///
|
||||
/// This header contains macros for making assertions about code behaviour.
|
||||
///
|
||||
/// fennec defines the following assert implementations:
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_bits">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// assert(expr, desc)
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Make an assertion with expression `expr` and provide a description `desc`. Only halts in debug mode.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// assertf(expr, desc)
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Make an assertion with expression `expr` and provide a description `desc`. Always halts.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// assertd(expr, desc)
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Make an assertion, ***only in debug mode***, with expression `expr` and provide a description `desc`.
|
||||
/// This should be used when the branching caused by `assert` would hinder performance in release mode.
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
#define __PRETTY_FUNCTION__ __FUNCSIG__
|
||||
#endif
|
||||
|
||||
using assert_handler = void (*)(const char *, const char *, int , const char *);
|
||||
|
||||
void _assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc, bool halt);
|
||||
|
||||
// flagged unlikely to optimize branch prediction
|
||||
#define assert(expression, description) \
|
||||
if(not(expression)) [[unlikely]] { \
|
||||
_assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, not FENNEC_RELEASE); \
|
||||
}
|
||||
|
||||
#define assertf(expression, description) \
|
||||
if(not(expression)) [[unlikely]] { \
|
||||
_assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, true); \
|
||||
}
|
||||
|
||||
#if FENNEC_RELEASE
|
||||
#define assertd(expression, description)
|
||||
#else
|
||||
#define assertd(expression, description) assert(expression, description)
|
||||
#endif
|
||||
|
||||
#endif // FENNEC_LANG_ASSERT_H
|
||||
@@ -1,232 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file bits.h
|
||||
/// \brief \ref fennec_lang_bit_manipulation
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_BITS_H
|
||||
#define FENNEC_LANG_BITS_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_bit_manipulation Bit Manipulation
|
||||
///
|
||||
/// \code #include <fennec/lang/bits.h> \endcode
|
||||
///
|
||||
/// This header contains definitions for manipulating the bits of a provided object or pointer.
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_bits">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_cast "ToT bit_cast(const FromT& x)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_cast
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_and "void* bit_and(void* arr, const void* mask, size_t n)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_and
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_and_s "void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_and_s
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_or "void* bit_or(void* arr, const void* mask, size_t n)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_or
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_or_s "void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_or_s
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_xor "void* bit_xor(void* arr, const void* mask, size_t n)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_xor
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bit_xor_s "void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1)"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bit_xor_s
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
|
||||
#include <fennec/lang/intrinsics.h>
|
||||
#include <fennec/memory/common.h>
|
||||
#include <fennec/lang/detail/_bits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Perform a bitcast of FromT to ToT
|
||||
///
|
||||
/// \details Perform a bitcast of FromT to ToT
|
||||
/// \tparam ToT Type to cast to
|
||||
/// \tparam FromT Type of the value
|
||||
/// \param from Value to bit cast
|
||||
/// \returns A value containing a bitwise copy of the input
|
||||
template<typename ToT, typename FromT> requires(sizeof(ToT) == sizeof(FromT))
|
||||
constexpr ToT bit_cast(const FromT& from) {
|
||||
if constexpr(FENNEC_HAS_BUILTIN_BIT_CAST) {
|
||||
return FENNEC_BUILTIN_BIT_CAST(ToT, from);
|
||||
} else {
|
||||
ToT to;
|
||||
fennec::memcpy(&to, &from, sizeof(ToT));
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Perform a bit-wise and over an array of bytes
|
||||
///
|
||||
/// \details Perform a bitcast of FromT to ToT
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to and against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer \f$arr\f$
|
||||
constexpr void* bit_and(void* arr, const void* mask, size_t n) {
|
||||
if (arr == mask) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
|
||||
while (n > 0) {
|
||||
const size_t step = detail::_bit_and(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Safe version of fennec::bit_and
|
||||
///
|
||||
/// \details Safe version of fennec::bit_and
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param n0 the size of arr in bytes
|
||||
/// \param mask the mask to and against arr
|
||||
/// \param n1 the size of mask in bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1) {
|
||||
return bit_and(arr, mask, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Perform a bit-wise or over an array of bytes
|
||||
///
|
||||
/// \details Perform a bit-wise or over an array of bytes
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to or against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_or(void* arr, const void* mask, size_t n) {
|
||||
if (arr == mask) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
while (n > 0)
|
||||
{
|
||||
const size_t step = detail::_bit_or(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Safe version of fennec::bit_or
|
||||
///
|
||||
/// \details Safe version of fennec::bit_or
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param n0 the size of arr in bytes
|
||||
/// \param mask the mask to or against arr
|
||||
/// \param n1 the size of mask in bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1) {
|
||||
return bit_or(arr, mask, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Perform a bit-wise or over an array of bytes
|
||||
///
|
||||
/// \details Perform a bit-wise or over an array of bytes
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to or against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_xor(void* arr, const void* mask, size_t n) {
|
||||
if (arr == mask) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
while (n > 0) {
|
||||
const size_t step = detail::_bit_xor(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Safe version of fennec::bit_xor
|
||||
///
|
||||
/// \details Safe version of fennec::bit_xor
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param n0 the size of arr in bytes
|
||||
/// \param mask the mask to or against arr
|
||||
/// \param n1 the size of mask in bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1) {
|
||||
return bit_xor(arr, mask, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_BITS_H
|
||||
@@ -1,123 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_COMPARE_H
|
||||
#define FENNEC_LANG_COMPARE_H
|
||||
|
||||
#include <fennec/lang/type_operators.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// equality ============================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> struct equality;
|
||||
|
||||
template<typename T0, typename T1> requires has_equals_v<T0, T1>
|
||||
struct equality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires(not has_equals_v<T0, T1>
|
||||
and has_less_v<T0, T1> and has_less_v<T1, T0>)
|
||||
struct equality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not(x < y) and not(y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires(not(has_equals_v<T0, T1>)
|
||||
and(not has_less_v<T0, T1> or not has_less_v<T1, T0>)
|
||||
and(has_greater_v<T0, T1> and has_greater_v<T1, T0>))
|
||||
struct equality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not(x > y) and not(y > x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// inequality ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> struct inequality;
|
||||
|
||||
template<typename T0, typename T1> requires has_nequals_v<T0, T1>
|
||||
struct inequality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x != y;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires has_less_v<T0, T1> and has_less_v<T1, T0>
|
||||
struct inequality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return (x < y) or (y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires has_greater_v<T0, T1> and has_greater_v<T1, T0>
|
||||
struct inequality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return (x > y) or (y > x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less ================================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_less_v<T0, T1>
|
||||
struct less {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x < y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less_equal ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_less_equals_v<T0, T1>
|
||||
struct less_equals {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x <= y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less ================================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_greater_v<T0, T1>
|
||||
struct greater {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x < y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less_equal ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_greater_equals_v<T0, T1>
|
||||
struct greater_equals {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x <= y;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_COMPARE_H
|
||||
112
include/fennec/lang/compile/tokenizer.h
Normal file
112
include/fennec/lang/compile/tokenizer.h
Normal file
@@ -0,0 +1,112 @@
|
||||
// =====================================================================================================================
|
||||
// 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 tokenizer.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||
#define FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/map.h>
|
||||
#include <fennec/containers/priority_queue.h>
|
||||
#include <fennec/lang/strings/string.h>
|
||||
|
||||
//
|
||||
// escape sequences are tricky, sometimes they must be separated by white space,
|
||||
// other times they don't. Requiring a list of all possible escape sequences is unrealistic.
|
||||
// We need to allow the user of this struct to specify rules for escape sequences. Here are some basic rules:
|
||||
//
|
||||
// An escape sequence is marked by an escape character, e.g. %, \, {{
|
||||
// Multiple escape characters may be used in a single tokenizer and will have different rules
|
||||
// Escape characters may also be operators, brackets, or quotes
|
||||
// Escape sequences may contain operators, brackets, or quotes
|
||||
//
|
||||
// Here are a few examples of escape sequences from various formats and languages
|
||||
// C: \\, \n, \0, \u200b
|
||||
// PrintF: %s, %2.2f
|
||||
// Python FMT: {{, }}
|
||||
// SPSS: ''
|
||||
//
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
struct escape_sequence {
|
||||
virtual size_t operator[](const string& str, size_t i) = 0;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
enum token_ : uint8_t {
|
||||
token_text = 0,
|
||||
token_integer,
|
||||
token_string,
|
||||
token_newline,
|
||||
token_escaped,
|
||||
token_operator,
|
||||
token_bracket,
|
||||
token_quoted,
|
||||
|
||||
num_token_types
|
||||
};
|
||||
|
||||
using token = pair<string, uint8_t>;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t token_delimiter = num_token_types;
|
||||
|
||||
constexpr list<token> operator()(const string& line) {
|
||||
list<token> res;
|
||||
priority_queue<pair<size_t, uint8_t>> idx;
|
||||
|
||||
for (char c : delimiter) {
|
||||
size_t i = 0;
|
||||
while (i != line.size()) {
|
||||
size_t n = line.find(c, i);
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||
@@ -1,165 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file conditional_types.h
|
||||
/// \brief \ref fennec_lang_conditional_types
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
|
||||
#ifndef FENNEC_LANG_CONDITIONAL_TYPES_H
|
||||
#define FENNEC_LANG_CONDITIONAL_TYPES_H
|
||||
|
||||
#include <fennec/lang/type_identity.h>
|
||||
|
||||
///
|
||||
/// \page fennec_lang_conditional_types Conditional Types
|
||||
///
|
||||
/// \code #include <fennec/lang/conditional_types.h> \endcode
|
||||
///
|
||||
/// This header contains various compile-time functions for conditionally setting types, detecting types, or
|
||||
/// conditionally enabling functions. <br><br>
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_conditional_types">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::conditional "typename conditional<bool B, TrueT, FalseT>::type"<br>
|
||||
/// \ref fennec::conditional_t "conditional_t<bool B, TrueT, FalseT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::conditional
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::detect "typename detect<DefaultT, DetectT<...>, ArgsT...>::type"<br>
|
||||
/// \ref fennec::detect_t "detect_t<DefaultT, DetectT<...>, ArgsT...>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::detect
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::enable_if "typename enable_if<bool B, TypeT>::type"<br>
|
||||
/// \ref fennec::enable_if_t "enable_if_t<bool B, TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::enable_if
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// fennec::conditional =================================================================================================
|
||||
|
||||
///
|
||||
/// \brief select between two types based on a condition
|
||||
///
|
||||
/// \details Selects between \p TrueT and \p FalseT based on the boolean value \p b.
|
||||
/// The chosen type is stored in `conditional::type`.
|
||||
/// \tparam B the value of the condition
|
||||
/// \tparam TrueT type to use when \f$B == true\f$
|
||||
/// \tparam FalseT type to use when \f$B == false\f$
|
||||
template<bool B, typename TrueT, typename FalseT>
|
||||
struct conditional;
|
||||
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```typename conditional<ConditionV, TrueT, FalseT>::type```
|
||||
template<bool B, typename TrueT, typename FalseT>
|
||||
using conditional_t
|
||||
= typename conditional<B, TrueT, FalseT>::type;
|
||||
|
||||
|
||||
// specialization of fennec::conditional for `true` case
|
||||
template<typename T, typename F>
|
||||
struct conditional<true, T, F> : type_identity<T>{};
|
||||
|
||||
|
||||
// specialization of fennec::conditional for `false` case
|
||||
template<typename T, typename F>
|
||||
struct conditional<false, T, F> : type_identity<F>{};
|
||||
|
||||
|
||||
// fennec::detect ======================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Detect whether `DetectT<ArgsT...>` is a valid type
|
||||
///
|
||||
/// \details Selects `DetectT<ArgsT...>` if it exists, otherwise selects `DefaultT` The chosen type is stored in `detect::type` and
|
||||
/// a boolean value is stored in `detect::is_detected` representing whether `DetectT<ArgsT...>` is found.
|
||||
/// \tparam DefaultT Default type
|
||||
/// \tparam DetectT Type to detect
|
||||
/// \tparam ArgsT Any template arguments for `DetectT<ArgsT>`
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
struct detect
|
||||
{
|
||||
using type = DefaultT;
|
||||
static constexpr bool is_detected = false;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type```
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
using detect_t = typename detect<DefaultT, DetectT, ArgsT...>::type;
|
||||
|
||||
|
||||
// true case
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
requires requires { typename DetectT<ArgsT...>; }
|
||||
struct detect<DefaultT, DetectT, ArgsT...>
|
||||
{
|
||||
using type = DetectT<ArgsT...>;
|
||||
static constexpr bool is_detected = true;
|
||||
};
|
||||
|
||||
|
||||
// fennec::enable_if ===================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Leverage SFINAE to conditionally enable a function or class at compile-time
|
||||
///
|
||||
/// \details If `B` is `true`, define a public member type `type`. Otherwise, there is no member. <br>
|
||||
/// **Example Usage**
|
||||
/// \code{.cpp}
|
||||
/// template<typename TypeT,
|
||||
/// enable_if_t<is_integral_v<TypeT>, bool> = true>
|
||||
/// TypeT conditional_func() { return 0; }
|
||||
/// \endcode
|
||||
///
|
||||
/// \tparam B A boolean value
|
||||
/// \tparam T The type to conditionally define
|
||||
template<bool B, typename T = void>
|
||||
struct enable_if {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```typename enable_if<B, T>::type```
|
||||
template<bool B, typename T = void>
|
||||
using enable_if_t = typename enable_if<B, T>::type;
|
||||
|
||||
// true case
|
||||
template<typename T>
|
||||
struct enable_if<true, T> { using type = T; };
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_CONDITIONAL_TYPES_H
|
||||
@@ -1,246 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file sequences.h
|
||||
/// \brief \ref fennec_lang_sequences
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_SEQUENCES_H
|
||||
#define FENNEC_LANG_SEQUENCES_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_sequences Sequences
|
||||
///
|
||||
/// \brief This header is part of the metaprogramming library. It defines structures for sequences of values, used during compile time.
|
||||
///
|
||||
/// \code #include <fennec/lang/sequences.h> \endcode
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_sequences">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::sequence "sequence<ValueT, Values...>"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::sequence
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::integer_sequence "integer_sequence<IntT, Values...>"<br>
|
||||
/// \ref fennec::make_integer_sequence "typename make_integer_sequence<IntT, N>::type"<br>
|
||||
/// \ref fennec::make_integer_sequence_t "make_integer_sequence_t<IntT, N>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::integer_sequence
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::index_sequence "index_sequence<Indices...>"<br>
|
||||
/// \ref fennec::make_index_sequence "typename make_index_sequence<N>::type"<br>
|
||||
/// \ref fennec::make_index_sequence_t "make_index_sequence_t<N>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::index_sequence
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::concat_sequence "typename concat_sequence<SequenceT0, SequenceT1>::type"<br>
|
||||
/// \ref fennec::concat_sequence_t "concat_sequence_t<SequenceT0, SequenceT1>"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::concat_sequence
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// fennec::sequence ====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief metaprogramming sequence
|
||||
///
|
||||
/// \details Stores a sequence of values of type `ValueT` as a template pack.
|
||||
/// You can access the parameter pack in another template function, i.e.
|
||||
/// \code{cpp}
|
||||
/// template<typename TypeT, TypeT...Values>
|
||||
/// constexpr TypeT summation(sequence<TypeT, Values...>)
|
||||
/// {
|
||||
/// return (Values + ...);
|
||||
/// }
|
||||
/// \endcode
|
||||
/// \tparam ValueT type of the values
|
||||
/// \tparam Values sequence values
|
||||
template<typename ValueT, ValueT...Values> struct const_sequence
|
||||
{
|
||||
/// \brief type of the sequence
|
||||
using value_type = ValueT;
|
||||
|
||||
/// \brief self-referential type
|
||||
using type = const_sequence;
|
||||
|
||||
///
|
||||
/// \brief returns the number of elements
|
||||
///
|
||||
/// \return number of elements in the array
|
||||
inline static constexpr size_t size() noexcept {
|
||||
return sizeof...(Values);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// fennec::integer_sequence ============================================================================================
|
||||
|
||||
///
|
||||
/// \brief metaprogramming integral sequence
|
||||
///
|
||||
/// \details A `fennec::sequence` specialized integer types.
|
||||
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
|
||||
/// \tparam Values sequence values
|
||||
template<typename IntT, IntT...Values> requires(is_integral_v<IntT>)
|
||||
struct const_integer_sequence : const_sequence<IntT, Values...>
|
||||
{
|
||||
/// \brief type of the sequence
|
||||
using value_type = IntT;
|
||||
|
||||
/// \brief self-referential type
|
||||
using type = const_integer_sequence;
|
||||
|
||||
///
|
||||
/// \brief returns the number of elements
|
||||
///
|
||||
/// \return number of elements in the array
|
||||
inline static constexpr size_t size() noexcept {
|
||||
return sizeof...(Values);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief generate a fennec::integer_sequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
||||
///
|
||||
/// \details
|
||||
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
|
||||
/// \tparam N size of the sequence to generate
|
||||
template<typename IntT, size_t N> struct make_integer_sequence;
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```typename make_integer_sequence<T, N>::type```
|
||||
template<typename IntT, size_t N> using make_integer_sequence_t = typename make_integer_sequence<IntT, N>::type;
|
||||
|
||||
|
||||
|
||||
// fennec::index_sequence ==============================================================================================
|
||||
|
||||
///
|
||||
/// \brief metaprogramming integral sequence
|
||||
///
|
||||
/// \details A `fennec::integer_sequence` specialized for sequences of `size_t` indices.
|
||||
/// \tparam Indices sequence values
|
||||
template<size_t...Indices> struct const_index_sequence : const_integer_sequence<size_t, Indices...>
|
||||
{
|
||||
/// \brief type of the sequence
|
||||
using value_type = size_t;
|
||||
|
||||
/// \brief self-referential type
|
||||
using type = const_index_sequence;
|
||||
|
||||
///
|
||||
/// \brief returns the number of elements
|
||||
///
|
||||
/// \return number of elements in the array
|
||||
inline static constexpr size_t size() noexcept {
|
||||
return sizeof...(Indices);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief generate a fennec::index_sequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
||||
///
|
||||
/// \details
|
||||
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
|
||||
/// \tparam N size of the sequence to generate
|
||||
template<size_t N> struct make_index_sequence;
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```typename make_index_sequence<N>::type```
|
||||
template<size_t N> using make_index_sequence_t = typename make_index_sequence<N>::type;
|
||||
|
||||
|
||||
|
||||
// fennec::concat_sequence =============================================================================================
|
||||
|
||||
///
|
||||
/// \brief concatenate two sequences
|
||||
///
|
||||
/// \details A tool for concatenating two `fennec::sequence` types.
|
||||
/// \tparam SequenceT0 lhs
|
||||
/// \tparam SequenceT1 rhs
|
||||
template<typename SequenceT0, typename SequenceT1> struct concat_sequence;
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```typename concat_sequence<SequenceT0, SequenceT1>::type```
|
||||
template<typename SequenceT0, typename SequenceT1> using concat_sequence_t
|
||||
= typename concat_sequence<SequenceT0, SequenceT1>::type;
|
||||
|
||||
|
||||
|
||||
// Internal ============================================================================================================
|
||||
|
||||
// Implementation for Generating an integer_sequence
|
||||
template<typename T, size_t N> struct make_integer_sequence : concat_sequence_t<make_integer_sequence_t<T, N / 2>, make_integer_sequence_t<T, N - N / 2>>{};
|
||||
|
||||
// Base Case of N=0
|
||||
template<typename T> struct make_integer_sequence<T, 0> : const_integer_sequence<T> {};
|
||||
|
||||
// Base Case of N=1
|
||||
template<typename T> struct make_integer_sequence<T, 1> : const_integer_sequence<T, 0>{};
|
||||
|
||||
|
||||
// Implementation for Generating an index_sequence
|
||||
template<size_t N> struct make_index_sequence : concat_sequence_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>{};
|
||||
|
||||
// Base Case of N=0
|
||||
template<> struct make_index_sequence<0> : const_index_sequence<> {};
|
||||
|
||||
// Base Case of N=1
|
||||
template<> struct make_index_sequence<1> : const_index_sequence<0>{};
|
||||
|
||||
|
||||
// Specialization for integer sequences
|
||||
template<typename T, T...SequenceV0, T...SequenceV1>
|
||||
struct concat_sequence<const_integer_sequence<T, SequenceV0...>, const_integer_sequence<T, SequenceV1...>>
|
||||
: const_integer_sequence<T, SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
|
||||
|
||||
// Specialization for index sequences
|
||||
template<size_t...SequenceV0, size_t...SequenceV1>
|
||||
struct concat_sequence<const_index_sequence<SequenceV0...>, const_index_sequence<SequenceV1...>>
|
||||
: const_index_sequence<SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_SEQUENCES_H
|
||||
@@ -1,111 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file constants.h
|
||||
/// \brief \ref fennec_lang_constants
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_CONSTANTS_H
|
||||
#define FENNEC_LANG_CONSTANTS_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
|
||||
///
|
||||
///
|
||||
/// \page fennec_lang_constants Constants
|
||||
///
|
||||
/// \brief This header is part of the metaprogramming library. It defines structures for constant values,
|
||||
/// used during compile time.
|
||||
///
|
||||
/// \code #include <fennec/lang/constants.h> \endcode
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_constants">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::integral_constant "integral_constant<IntT, IntT ValueV>::type"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::integral_constant
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bool_constant "bool_constant<bool ValueV>::type"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bool_constant
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::bool_constant "bool_constant<bool ValueV>::type"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::bool_constant
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief metaprogramming integral constant
|
||||
///
|
||||
/// \details A metaprogramming integral constant
|
||||
/// \tparam IntT type of the constant
|
||||
/// \tparam ValueV value of the constant
|
||||
template<typename IntT, IntT ValueV> struct integral_constant
|
||||
{
|
||||
///
|
||||
/// \brief value of the constant
|
||||
inline static constexpr IntT value = ValueV;
|
||||
|
||||
///
|
||||
/// \brief cast operator to allow for braced initialization
|
||||
/// \returns the value of the constant
|
||||
constexpr operator IntT() const noexcept { return value; }
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief metaprogramming boolean constant
|
||||
///
|
||||
/// \details
|
||||
/// \tparam ValueV value of the constant
|
||||
template<bool ValueV>
|
||||
struct bool_constant
|
||||
: integral_constant<bool_t, ValueV> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief metaprogramming true constant
|
||||
struct true_type
|
||||
: bool_constant<true> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief metaprogramming false constant
|
||||
struct false_type
|
||||
: bool_constant<false> {};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_CONSTANTS_H
|
||||
@@ -1,139 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_BITS_H
|
||||
#define FENNEC_LANG_DETAIL_BITS_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
// helper for bitwise and for 1 byte
|
||||
constexpr size_t _bit_and_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise and 2 bytes at once
|
||||
constexpr size_t _bit_and_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise and 4 bytes at once
|
||||
constexpr size_t _bit_and_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise and 8 bytes at once
|
||||
constexpr size_t _bit_and_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t _bit_and(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return _bit_and_8(dst, src);
|
||||
case 2: case 3:
|
||||
return _bit_and_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return _bit_and_32(dst, src);
|
||||
default:
|
||||
return _bit_and_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise or for 1 byte
|
||||
constexpr size_t _bit_or_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise or 2 bytes at once
|
||||
constexpr size_t _bit_or_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise or 4 bytes at once
|
||||
constexpr size_t _bit_or_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise or 8 bytes at once
|
||||
constexpr size_t _bit_or_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t _bit_or(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return _bit_or_8(dst, src);
|
||||
case 2: case 3:
|
||||
return _bit_or_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return _bit_or_32(dst, src);
|
||||
default:
|
||||
return _bit_or_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise and 1 byte
|
||||
constexpr size_t _bit_xor_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 2 bytes at once
|
||||
constexpr size_t _bit_xor_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 4 bytes at once
|
||||
constexpr size_t _bit_xor_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 8 bytes at once
|
||||
constexpr size_t _bit_xor_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t _bit_xor(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return _bit_xor_8(dst, src);
|
||||
case 2: case 3:
|
||||
return _bit_xor_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return _bit_xor_32(dst, src);
|
||||
default:
|
||||
return _bit_xor_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_BITS_H
|
||||
@@ -1,59 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H
|
||||
#define FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
template<typename> struct _make_unsigned : type_identity<undefined_t> {};
|
||||
|
||||
template<> struct _make_unsigned<char_t> : type_identity<uchar_t> {};
|
||||
template<> struct _make_unsigned<uchar_t> : type_identity<uchar_t> {};
|
||||
template<> struct _make_unsigned<schar_t> : type_identity<uchar_t> {};
|
||||
template<> struct _make_unsigned<short_t> : type_identity<ushort_t> {};
|
||||
template<> struct _make_unsigned<ushort_t> : type_identity<ushort_t> {};
|
||||
template<> struct _make_unsigned<uint_t> : type_identity<uint_t> {};
|
||||
template<> struct _make_unsigned<int_t> : type_identity<uint_t> {};
|
||||
template<> struct _make_unsigned<long_t> : type_identity<ulong_t> {};
|
||||
template<> struct _make_unsigned<ulong_t> : type_identity<ulong_t> {};
|
||||
template<> struct _make_unsigned<llong_t> : type_identity<ullong_t> {};
|
||||
template<> struct _make_unsigned<ullong_t> : type_identity<ullong_t> {};
|
||||
|
||||
|
||||
template<typename> struct _make_signed : type_identity<undefined_t> {};
|
||||
|
||||
template<> struct _make_signed<char_t> : type_identity<schar_t> {};
|
||||
template<> struct _make_signed<uchar_t> : type_identity<schar_t> {};
|
||||
template<> struct _make_signed<schar_t> : type_identity<schar_t> {};
|
||||
template<> struct _make_signed<short_t> : type_identity<short_t> {};
|
||||
template<> struct _make_signed<ushort_t> : type_identity<short_t> {};
|
||||
template<> struct _make_signed<uint_t> : type_identity<int_t> {};
|
||||
template<> struct _make_signed<int_t> : type_identity<int_t> {};
|
||||
template<> struct _make_signed<long_t> : type_identity<long_t> {};
|
||||
template<> struct _make_signed<ulong_t> : type_identity<long_t> {};
|
||||
template<> struct _make_signed<llong_t> : type_identity<llong_t> {};
|
||||
template<> struct _make_signed<ullong_t> : type_identity<llong_t> {};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H
|
||||
@@ -1,40 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||
#define FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
template<typename FirstT, typename... RestT> struct _first_element : type_identity<FirstT> {};
|
||||
|
||||
template<size_t n, size_t i, typename...TypesT> struct _nth_element;
|
||||
|
||||
template<size_t n, size_t i> struct _nth_element<n, i> : type_identity<void> {};
|
||||
|
||||
template<size_t n, size_t i, typename HeadT, typename...RestT>
|
||||
struct _nth_element<n, i, HeadT, RestT...> : conditional<
|
||||
n == i, HeadT,
|
||||
typename _nth_element<n, i + 1, RestT...>::type
|
||||
> {};
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||
@@ -1,75 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||
#define FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||
|
||||
#include <fennec/lang/constants.h>
|
||||
#include <fennec/lang/float.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
// Nothing interesting to note here
|
||||
template<typename> struct _is_void : false_type {};
|
||||
template<> struct _is_void<void> : true_type {};
|
||||
|
||||
template<typename> struct _is_bool : false_type {};
|
||||
template<> struct _is_bool<bool_t> : true_type {};
|
||||
|
||||
template<typename> struct _is_null_pointer : false_type {};
|
||||
template<> struct _is_null_pointer<nullptr_t> : true_type {};
|
||||
|
||||
// Provides definitions for all builtin int types
|
||||
template<typename> struct _is_integral : false_type {};
|
||||
template<> struct _is_integral<bool_t> : true_type {};
|
||||
template<> struct _is_integral<char_t> : true_type {};
|
||||
template<> struct _is_integral<char8_t> : true_type {};
|
||||
template<> struct _is_integral<char16_t> : true_type {};
|
||||
template<> struct _is_integral<char32_t> : true_type {};
|
||||
template<> struct _is_integral<schar_t> : true_type {};
|
||||
template<> struct _is_integral<uchar_t> : true_type {};
|
||||
template<> struct _is_integral<wchar_t> : true_type {};
|
||||
template<> struct _is_integral<short_t> : true_type {};
|
||||
template<> struct _is_integral<ushort_t> : true_type {};
|
||||
template<> struct _is_integral<int_t> : true_type {};
|
||||
template<> struct _is_integral<uint_t> : true_type {};
|
||||
template<> struct _is_integral<long_t> : true_type {};
|
||||
template<> struct _is_integral<ulong_t> : true_type {};
|
||||
template<> struct _is_integral<llong_t> : true_type {};
|
||||
template<> struct _is_integral<ullong_t> : true_type {};
|
||||
|
||||
// Most unsigned types will underflow `-1` to the types maximum value
|
||||
template<typename TypeT> struct _is_signed : bool_constant<TypeT(-1) < TypeT(0)> {};
|
||||
template<typename TypeT> struct _is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};
|
||||
|
||||
template<typename> struct _is_floating_point : false_type {};
|
||||
template<> struct _is_floating_point<float_t> : true_type {};
|
||||
template<> struct _is_floating_point<double_t> : true_type {};
|
||||
|
||||
template<typename> struct _is_pointer : false_type {};
|
||||
template<typename T> struct _is_pointer<T*> : true_type {};
|
||||
|
||||
template<typename T, typename U = T&&> U _declval(int);
|
||||
template<typename T> T _declval(long);
|
||||
|
||||
template<typename T> struct _declval_protector : bool_constant<false> {};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||
@@ -1,50 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
|
||||
#define FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
template<typename _Tp, typename = void>
|
||||
struct _add_lvalue_reference {
|
||||
using type = _Tp;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct _add_lvalue_reference<_Tp, void_t<_Tp&>> {
|
||||
using type = _Tp&;
|
||||
};
|
||||
|
||||
|
||||
template<typename _Tp, typename = void>
|
||||
struct _add_rvalue_reference {
|
||||
using type = _Tp;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct _add_rvalue_reference<_Tp, void_t<_Tp&&>> {
|
||||
using type = _Tp&&;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
|
||||
@@ -16,9 +16,9 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_STDLIB_H
|
||||
#define FENNEC_LANG_DETAIL_STDLIB_H
|
||||
#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_STDLIB_H
|
||||
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
322
include/fennec/lang/filesystem/file.h
Normal file
322
include/fennec/lang/filesystem/file.h
Normal file
@@ -0,0 +1,322 @@
|
||||
// =====================================================================================================================
|
||||
// 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_LANGPROC_IO_FILE_H
|
||||
#define FENNEC_LANGPROC_IO_FILE_H
|
||||
|
||||
#include <fennec/lang/filesystem/path.h>
|
||||
|
||||
#include <fennec/lang/strings/cstring.h>
|
||||
#include <fennec/lang/strings/string.h>
|
||||
#include <fennec/lang/strings/wstring.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Mode flags for opening a file
|
||||
///
|
||||
/// fmode_binary and fmode_wide are independent of the other modes
|
||||
///
|
||||
/// \details Valid Flag Combinations
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_LANGPROC_io_fmode">
|
||||
/// <tr><th style="vertical-align: top">Flags
|
||||
/// <th style="vertical-align: top">Description
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">`read`
|
||||
/// <td style="vertical-align: top">Opens file as read-only, reading from start
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">`write`
|
||||
/// <td style="vertical-align: top">Opens file as write-only, writing to end
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">`read | write`
|
||||
/// <td style="vertical-align: top">Opens file as read-write, reading from start
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">`write | trunc`
|
||||
/// <td style="vertical-align: top">Opens file as write-only, destroying contents
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">`read | write | trunc`
|
||||
/// <td style="vertical-align: top">Opens file as read-write, destroying contents
|
||||
/// </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
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Structure for handling streams of data
|
||||
///
|
||||
/// \details operations, when errored, will return a corresponding error.
|
||||
/// 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().
|
||||
class file
|
||||
{
|
||||
public:
|
||||
/// \brief value of an invalid position
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
///
|
||||
/// \brief Check if the provided mode bitflags are a valid combination
|
||||
/// \param mode the bitfield
|
||||
/// \returns true if the combination of flags is valid, false otherwise
|
||||
static constexpr bool is_valid(uint8_t mode) {
|
||||
const bool t = mode & fmode_trunc;
|
||||
const bool x = mode & fmode_exclusive;
|
||||
const bool w = mode & fmode_write;
|
||||
|
||||
// when x is true, t must be true
|
||||
// when t is true, w must be true
|
||||
return (t && x && w)
|
||||
|| (t && w)
|
||||
|| !(t || x);
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the c stdout
|
||||
static file& cout();
|
||||
|
||||
///
|
||||
/// \returns the c stdin
|
||||
static file& cin();
|
||||
|
||||
///
|
||||
/// \returns the c stderr
|
||||
static file& cerr();
|
||||
|
||||
///
|
||||
/// \brief default constructor, initializes an empty stream
|
||||
file();
|
||||
|
||||
///
|
||||
/// \brief default destructor, cleans up an open stream
|
||||
~file();
|
||||
|
||||
///
|
||||
/// \brief move constructor
|
||||
/// \param file the stream to take ownership of
|
||||
file(file&& file) noexcept;
|
||||
|
||||
file& operator=(file&& file) noexcept;
|
||||
|
||||
// don't allow copying streams
|
||||
file(const file&) = delete;
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns the path the stream
|
||||
const path& get_path() const {
|
||||
return _path;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the mode of the stream
|
||||
uint8_t mode() const {
|
||||
return _mode;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns true if there is a valid, open stream.
|
||||
bool is_open() const {
|
||||
return _handle != nullptr;
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
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
|
||||
bool open(const string& 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
|
||||
bool open(const path& path, uint8_t mode);
|
||||
|
||||
///
|
||||
/// \brief close a stream
|
||||
/// \returns false on success, true on error
|
||||
bool close();
|
||||
|
||||
///
|
||||
/// \brief commit the streams buffer to the file
|
||||
/// \returns false on success, true on error
|
||||
bool commit();
|
||||
|
||||
|
||||
// File Operations =====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief closes the stream and erases the file
|
||||
/// \returns false on success, true 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
|
||||
///
|
||||
/// \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.
|
||||
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
|
||||
///
|
||||
/// \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.
|
||||
bool rename(const string& 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
|
||||
///
|
||||
/// \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.
|
||||
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
|
||||
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
|
||||
file copy(const string& 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
|
||||
file copy(const path& path);
|
||||
|
||||
|
||||
// File Positioning ====================================================================================================
|
||||
|
||||
size_t get_pos() const;
|
||||
bool set_pos(size_t i);
|
||||
bool rewind();
|
||||
bool eof() const;
|
||||
|
||||
|
||||
// Binary Read Operations ==============================================================================================
|
||||
|
||||
size_t read(void* data, size_t size, size_t n);
|
||||
|
||||
template<typename T>
|
||||
size_t read(T* data, size_t n) {
|
||||
return read(static_cast<void*>(data), sizeof(T), n);
|
||||
}
|
||||
|
||||
template<typename T, size_t n>
|
||||
size_t read(T (&data)[n]) {
|
||||
return read(static_cast<void*>(data), sizeof(T), n);
|
||||
}
|
||||
|
||||
|
||||
// Binary Write Operations =============================================================================================
|
||||
|
||||
bool putc(char c);
|
||||
bool putwc(wchar_t c);
|
||||
|
||||
size_t write(const void* data, size_t size, size_t n);
|
||||
|
||||
template<size_t n>
|
||||
size_t write(const char (&data)[n]) {
|
||||
return write(data, sizeof(char), n - 1);
|
||||
}
|
||||
|
||||
template<size_t n>
|
||||
size_t write(const wchar_t (&data)[n]) {
|
||||
return write(data, sizeof(wchar_t), n - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t write(const T* data, size_t n) {
|
||||
return write(static_cast<const void*>(data), sizeof(T), n);
|
||||
}
|
||||
|
||||
template<typename T, size_t n>
|
||||
size_t write(const T (&data)[n]) {
|
||||
return write(static_cast<const void*>(data), sizeof(T), n);
|
||||
}
|
||||
|
||||
|
||||
// Read Operations =====================================================================================================
|
||||
|
||||
char getc();
|
||||
wchar_t getwc();
|
||||
|
||||
string getline();
|
||||
wstring getwline();
|
||||
|
||||
|
||||
// Printing Operations =================================================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
// Error Handling ======================================================================================================
|
||||
|
||||
const char* get_error() const { return _error; }
|
||||
void clear_error() { _error = nullptr; }
|
||||
|
||||
private:
|
||||
FILE* _handle;
|
||||
path _path;
|
||||
uint8_t _mode;
|
||||
char* _error;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_IO_FILE_H
|
||||
334
include/fennec/lang/filesystem/path.h
Normal file
334
include/fennec/lang/filesystem/path.h
Normal file
@@ -0,0 +1,334 @@
|
||||
// =====================================================================================================================
|
||||
// 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_LANGPROC_IO_PATH_H
|
||||
#define FENNEC_LANGPROC_IO_PATH_H
|
||||
|
||||
#include <fennec/lang/filesystem/path.h>
|
||||
#include <fennec/lang/strings/string.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief struct for handling file paths
|
||||
///
|
||||
/// \details This structure makes no guarantees about the validity of a path.
|
||||
/// Operations do not examine the system's file structure.
|
||||
struct path
|
||||
{
|
||||
public:
|
||||
// Definitions =========================================================================================================
|
||||
|
||||
class iterator;
|
||||
friend iterator;
|
||||
|
||||
|
||||
// Static Functions ====================================================================================================
|
||||
|
||||
/// \brief Get the current working directory
|
||||
/// \returns a path containing the absolute path to the working directory
|
||||
static path 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);
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, returns the root of the current working directory
|
||||
path() : _str("/") { }
|
||||
|
||||
///
|
||||
/// \brief C-String Conversion Constructor
|
||||
/// \param str the cstring to convert
|
||||
path(const cstring& str)
|
||||
: _str(str) {
|
||||
if (str.size() > 2 && str[str.size() - 1] == '/') {
|
||||
_str = _str.substring(0, str.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Conversion Constructor
|
||||
/// \param str the string to convert
|
||||
path(const string& str)
|
||||
: _str(str) {
|
||||
if (str.size() > 2 && str[str.size() - 1] == '/') {
|
||||
_str = _str.substring(0, str.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Path Copy Constructor
|
||||
/// \param p the path to copy
|
||||
path(const path& p)
|
||||
: _str(p._str) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Path Move Constructor
|
||||
/// \param p the path to take ownership of
|
||||
path(path&& p) noexcept : _str(move(p._str)) { }
|
||||
|
||||
|
||||
// Assignment Operators ================================================================================================
|
||||
|
||||
///
|
||||
/// \brief C-String Assignment Operator
|
||||
/// \param str the cstring to assign
|
||||
/// \returns a reference to `this` after assigning `p`
|
||||
template<size_t n>
|
||||
path& operator=(const char (&str)[n]) {
|
||||
_str = str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C-String Assignment Operator
|
||||
/// \param p the cstring to assign
|
||||
/// \returns a reference to `this` after assigning `p`
|
||||
path& operator=(const cstring& p) {
|
||||
_str = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Assignment Operator
|
||||
/// \param p the cstring to assign
|
||||
/// \returns a reference to `this` after assigning `p`
|
||||
path& operator=(const string& p) {
|
||||
_str = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Path Copy Assignment Operator
|
||||
/// \param p the path to copy
|
||||
/// \returns a reference to `this` after copying `p`
|
||||
path& operator=(const path& p) {
|
||||
_str = p._str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Path Move Assignment Operator
|
||||
/// \param p the path to take ownership of
|
||||
/// \returns a reference to `this` after taking ownership of `p`
|
||||
path& operator=(path&& p) noexcept {
|
||||
_str = move(p._str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Append Operators ====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief
|
||||
/// \param str
|
||||
/// \return
|
||||
path operator/(const cstring& str) const {
|
||||
return path(_str + '/' + str);
|
||||
}
|
||||
|
||||
path operator/(const string& str) const {
|
||||
return path(_str + '/' + str);
|
||||
}
|
||||
|
||||
path operator/(const path& p) const {
|
||||
return path(_str + '/' + p._str);
|
||||
}
|
||||
|
||||
bool operator==(const path& p) const {
|
||||
return _str == p._str;
|
||||
}
|
||||
|
||||
string filename() const {
|
||||
size_t i = _str.rfind('/');
|
||||
return _str.substring(i + 1);
|
||||
}
|
||||
|
||||
const string& str() const { return _str; }
|
||||
const char* cstr() const { return _str.cstr(); }
|
||||
|
||||
bool empty() {
|
||||
size_t size = _str.size();
|
||||
if (size == 0) return true;
|
||||
#if FENNEC_PLATFORM_WINDOWS
|
||||
return (_str[1] == ':' && size == 3);
|
||||
#else
|
||||
return (_str[0] == '/' && size == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
path parent() const {
|
||||
#ifdef FENNEC_PLATFORM_WINDOWS
|
||||
size_t start = _str.size() - 1;
|
||||
start = _str[start] == '/' || _str[start] == '\\' ? start - 1 : start;
|
||||
|
||||
size_t r = _str.rfind('/', start);
|
||||
size_t l = _str.rfind('\\', start);
|
||||
if (r == _str.size()) {
|
||||
start = l;
|
||||
}
|
||||
else if (l == _str.size()) {
|
||||
start = r;
|
||||
}
|
||||
else {
|
||||
start = max(r, l);
|
||||
}
|
||||
return _str.substring(0, start);
|
||||
#else
|
||||
size_t start = _str.size() - 1;
|
||||
start = _str[start] == '/' ? start - 1 : start;
|
||||
return path(_str.substring(0, _str.rfind('/', start)));
|
||||
#endif
|
||||
}
|
||||
|
||||
path absolute() const {
|
||||
path parse = *this;
|
||||
path working; working._str.resize(0);
|
||||
|
||||
// Check if this is a rooted path;
|
||||
#ifdef FENNEC_PLATFORM_WINDOWS
|
||||
if (_str[1] != ':') {
|
||||
#else
|
||||
if (_str[0] != '/') {
|
||||
#endif
|
||||
working = current();
|
||||
}
|
||||
|
||||
while (not parse.empty()) {
|
||||
// Handle dots
|
||||
while (not parse.empty() && parse._str[0] == '.') {
|
||||
// Check for ".."
|
||||
if (parse._str[1] == '.') {
|
||||
// ".."
|
||||
if (parse._str.size() == 2) {
|
||||
parse = path();
|
||||
working = working.parent();
|
||||
}
|
||||
// "../"
|
||||
else if (parse._str[2] == '/') {
|
||||
working = working.parent();
|
||||
parse._str = parse._str.substring(3);
|
||||
}
|
||||
}
|
||||
// "./"
|
||||
else if (parse._str[1] == '/') {
|
||||
parse._str = parse._str.substring(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (parse.empty()) break;
|
||||
|
||||
// Push the path
|
||||
const size_t loc = parse._str.find('/');
|
||||
working._str += '/';
|
||||
working._str += parse._str.substring(0, loc);
|
||||
parse._str = parse._str.substring(loc + 1);
|
||||
}
|
||||
|
||||
return working;
|
||||
}
|
||||
|
||||
|
||||
// Iterator ============================================================================================================
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(this, 0);
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
return iterator(this, _str.size());
|
||||
}
|
||||
|
||||
class iterator {
|
||||
public:
|
||||
constexpr iterator(const path* path, size_t p)
|
||||
: _str(&path->_str)
|
||||
, _pos(p) {
|
||||
|
||||
// Handle end()
|
||||
if (p == _str->size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle rooted paths
|
||||
#ifdef FENNEC_PLATFORM_WINDOWS
|
||||
if ((*_str)[1] == ':') {
|
||||
_pos = max(_pos, size_t(3));
|
||||
}
|
||||
#else
|
||||
if ((*_str)[0] == '/') {
|
||||
_pos = max(_pos, size_t(1));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure we are at the start of a directory/file name
|
||||
if (_pos != 0 && (*_str)[_pos - 1] != '/') {
|
||||
_pos = _str->find('/', _pos) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator(const iterator&) = default;
|
||||
constexpr iterator(iterator&&) noexcept = default;
|
||||
|
||||
constexpr string operator*() const {
|
||||
if ((*_str)[_pos] == '/') {
|
||||
return string("");
|
||||
}
|
||||
|
||||
size_t e = _str->find('/', _pos);
|
||||
return _str->substring(_pos, e - _pos);
|
||||
}
|
||||
|
||||
constexpr iterator& operator++() {
|
||||
_pos = min(_str->find('/', _pos) + 1, _str->size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator operator++(int) {
|
||||
iterator it = *this;
|
||||
this->operator++();
|
||||
return it;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const iterator& rhs) const {
|
||||
return _str == rhs._str and _pos == rhs._pos;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const iterator& rhs) const {
|
||||
return _str != rhs._str or _pos != rhs._pos;
|
||||
}
|
||||
|
||||
private:
|
||||
const string* _str;
|
||||
size_t _pos;
|
||||
};
|
||||
|
||||
private:
|
||||
string _str;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_IO_PATH_H
|
||||
@@ -1,139 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file float.h
|
||||
/// \brief metaprogramming floating point type info
|
||||
///
|
||||
///
|
||||
/// \details this file is automatically generated for the current build environment
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_FLOAT_H
|
||||
#define FENNEC_LANG_FLOAT_H
|
||||
|
||||
#include <fennec/lang/bits.h>
|
||||
|
||||
#undef FLT_HAS_INFINITY
|
||||
#undef FLT_HAS_QUIET_NAN
|
||||
#undef FLT_HAS_SIGNALING_NAN
|
||||
#undef FLT_HAS_DENORM
|
||||
#undef FLT_HAS_DENORM_LOSS
|
||||
#undef FLT_ROUNDS
|
||||
#undef FLT_IS_IEC559
|
||||
#undef FLT_MANT_DIG
|
||||
#undef FLT_DIG
|
||||
#undef FLT_DECIMAL_DIG
|
||||
#undef FLT_RADIX
|
||||
#undef FLT_MIN_EXP
|
||||
#undef FLT_MAX_EXP
|
||||
#undef FLT_MIN_10_EXP
|
||||
#undef FLT_MAX_10_EXP
|
||||
#undef FLT_TRAPS
|
||||
#undef FLT_TINYNESS_BEFORE
|
||||
#undef FLT_MIN
|
||||
#undef FLT_MAX
|
||||
#undef FLT_EPSILON
|
||||
#undef FLT_INF
|
||||
#undef FLT_QUIET_NAN
|
||||
#undef FLT_SIGNALING_NAN
|
||||
#undef FLT_DENORM_MIN
|
||||
#undef FLT_ROUND_ERR
|
||||
|
||||
#define FLT_HAS_INFINITY 1
|
||||
#define FLT_HAS_QUIET_NAN 1
|
||||
#define FLT_HAS_SIGNALING_NAN 1
|
||||
#define FLT_HAS_DENORM 1
|
||||
#define FLT_HAS_DENORM_LOSS 0
|
||||
#define FLT_ROUNDS 1
|
||||
#define FLT_IS_IEC559 1
|
||||
#define FLT_MANT_DIG 24
|
||||
#define FLT_DIG 6
|
||||
#define FLT_DECIMAL_DIG 9
|
||||
#define FLT_RADIX 2
|
||||
#define FLT_MIN_EXP -125
|
||||
#define FLT_MAX_EXP 128
|
||||
#define FLT_MIN_10_EXP -37
|
||||
#define FLT_MAX_10_EXP 38
|
||||
#define FLT_TRAPS 0
|
||||
#define FLT_TINYNESS_BEFORE 0
|
||||
#define FLT_MIN fennec::bit_cast<float>(0x800000)
|
||||
#define FLT_MAX fennec::bit_cast<float>(0x7f7fffff)
|
||||
#define FLT_EPSILON fennec::bit_cast<float>(0x34000000)
|
||||
#define FLT_INF fennec::bit_cast<float>(0x7f800000)
|
||||
#define FLT_QUIET_NAN fennec::bit_cast<float>(0x7fc00000)
|
||||
#define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000)
|
||||
#define FLT_DENORM_MIN fennec::bit_cast<float>(0x1)
|
||||
#define FLT_ROUND_ERR fennec::bit_cast<float>(0x3f000000)
|
||||
|
||||
#undef DBL_HAS_INFINITY
|
||||
#undef DBL_HAS_QUIET_NAN
|
||||
#undef DBL_HAS_SIGNALING_NAN
|
||||
#undef DBL_HAS_DENORM
|
||||
#undef DBL_HAS_DENORM_LOSS
|
||||
#undef DBL_ROUNDS
|
||||
#undef DBL_IS_IEC559
|
||||
#undef DBL_MANT_DIG
|
||||
#undef DBL_DIG
|
||||
#undef DBL_DECIMAL_DIG
|
||||
#undef DBL_RADIX
|
||||
#undef DBL_MIN_EXP
|
||||
#undef DBL_MAX_EXP
|
||||
#undef DBL_MIN_10_EXP
|
||||
#undef DBL_MAX_10_EXP
|
||||
#undef DBL_TRAPS
|
||||
#undef DBL_TINYNESS_BEFORE
|
||||
#undef DBL_MIN
|
||||
#undef DBL_MAX
|
||||
#undef DBL_EPSILON
|
||||
#undef DBL_INF
|
||||
#undef DBL_QUIET_NAN
|
||||
#undef DBL_SIGNALING_NAN
|
||||
#undef DBL_DENORM_MIN
|
||||
#undef DBL_ROUND_ERR
|
||||
|
||||
#define DBL_HAS_INFINITY 1
|
||||
#define DBL_HAS_QUIET_NAN 1
|
||||
#define DBL_HAS_SIGNALING_NAN 1
|
||||
#define DBL_HAS_DENORM 1
|
||||
#define DBL_HAS_DENORM_LOSS 0
|
||||
#define DBL_ROUNDS 1
|
||||
#define DBL_IS_IEC559 1
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_DIG 15
|
||||
#define DBL_DECIMAL_DIG 17
|
||||
#define DBL_RADIX 2
|
||||
#define DBL_MIN_EXP -1021
|
||||
#define DBL_MAX_EXP 1024
|
||||
#define DBL_MIN_10_EXP -307
|
||||
#define DBL_MAX_10_EXP 308
|
||||
#define DBL_TRAPS 0
|
||||
#define DBL_TINYNESS_BEFORE 0
|
||||
#define DBL_MIN fennec::bit_cast<double>(0x10000000000000ll)
|
||||
#define DBL_MAX fennec::bit_cast<double>(0x7fefffffffffffffll)
|
||||
#define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000ll)
|
||||
#define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000ll)
|
||||
#define DBL_QUIET_NAN fennec::bit_cast<double>(0x7ff8000000000000ll)
|
||||
#define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000ll)
|
||||
#define DBL_DENORM_MIN fennec::bit_cast<double>(0x1ll)
|
||||
#define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000ll)
|
||||
|
||||
#endif // FENNEC_LANG_FLOAT_H
|
||||
@@ -1,91 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_HASHING_H
|
||||
#define FENNEC_LANG_HASHING_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Struct for hashing types, there is no default hashing function
|
||||
/// \tparam Key The type to hash
|
||||
template<typename Key> struct hash;
|
||||
|
||||
// Murmur3 Hash for 64-bit ints
|
||||
template<>
|
||||
struct hash<uint64_t> {
|
||||
using type_t = uint64_t;
|
||||
constexpr size_t operator()(uint64_t x) const {
|
||||
// Murmur3
|
||||
x ^= x >> 33U;
|
||||
x *= 0xff51afd7ed558ccd;
|
||||
x ^= x >> 33U;
|
||||
x *= 0xc4ceb9fe1a85ec53;
|
||||
x ^= x >> 33U;
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for casting ints
|
||||
template<typename IntT>
|
||||
requires is_integral_v<IntT>
|
||||
struct hash<IntT> : hash<uint64_t> {
|
||||
using type_t = IntT;
|
||||
};
|
||||
|
||||
// Wrapper for pointers
|
||||
template<typename PtrT>
|
||||
struct hash<PtrT*> : hash<uintptr_t> {
|
||||
constexpr size_t operator()(PtrT* ptr) const {
|
||||
return hash<uintptr_t>::operator()((uintptr_t)(const void*)ptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Float
|
||||
template<>
|
||||
struct hash<float> : hash<uint32_t> {
|
||||
constexpr size_t operator()(float x) const {
|
||||
return hash<uint32_t>::operator()(bit_cast<uint32_t>(x));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<double> : hash<uint64_t> {
|
||||
constexpr size_t operator()(double x) const {
|
||||
return hash<uint64_t>::operator()(bit_cast<uint64_t>(x));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Pairs two hashes
|
||||
/// \param x first hash
|
||||
/// \param y second hash
|
||||
/// \returns a pairing of the two hashes
|
||||
constexpr size_t pair_hash(size_t x, size_t y) {
|
||||
// Szudzik Pairing
|
||||
return (x >= y ? (x * x) + x + y : (y * y) + x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_HASHING_H
|
||||
@@ -1,164 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file integer.h
|
||||
/// \brief metaprogramming integer type info
|
||||
///
|
||||
///
|
||||
/// \details this file is automatically generated for the current build environment
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_INTEGER_H
|
||||
#define FENNEC_LANG_INTEGER_H
|
||||
|
||||
#undef CHAR_MIN
|
||||
#undef CHAR_MAX
|
||||
#undef WCHAR_MIN
|
||||
#undef WCHAR_MAX
|
||||
#undef SCHAR_MIN
|
||||
#undef SCHAR_MAX
|
||||
#undef UCHAR_MIN
|
||||
#undef UCHAR_MAX
|
||||
#undef INT_MIN
|
||||
#undef INT_MAX
|
||||
#undef UINT_MIN
|
||||
#undef UINT_MAX
|
||||
#undef LONG_MIN
|
||||
#undef LONG_MAX
|
||||
#undef ULONG_MIN
|
||||
#undef ULONG_MAX
|
||||
#undef LLONG_MIN
|
||||
#undef LLONG_MAX
|
||||
#undef ULLONG_MIN
|
||||
#undef ULLONG_MAX
|
||||
|
||||
#define CHAR_IS_SIGNED true
|
||||
#define CHAR_ROUNDS 0x0
|
||||
#define CHAR_RADIX_DIG 0x7
|
||||
#define CHAR_DIG 0x2
|
||||
#define CHAR_DECIMAL_DIG 0x0
|
||||
#define CHAR_RADIX 0x2
|
||||
#define CHAR_TRAPS 0xtrue
|
||||
#define CHAR_MIN 0x80
|
||||
#define CHAR_MAX 0x7f
|
||||
|
||||
#define WCHAR_IS_SIGNED true
|
||||
#define WCHAR_ROUNDS 0x0
|
||||
#define WCHAR_RADIX_DIG 0x1f
|
||||
#define WCHAR_DIG 0x9
|
||||
#define WCHAR_DECIMAL_DIG 0x0
|
||||
#define WCHAR_RADIX 0x2
|
||||
#define WCHAR_TRAPS 0xtrue
|
||||
#define WCHAR_MIN 0x80000000
|
||||
#define WCHAR_MAX 0x7fffffff
|
||||
|
||||
#define SCHAR_ROUNDS 0x0
|
||||
#define SCHAR_RADIX_DIG 0x7
|
||||
#define SCHAR_DIG 0x2
|
||||
#define SCHAR_DECIMAL_DIG 0x0
|
||||
#define SCHAR_RADIX 0x2
|
||||
#define SCHAR_TRAPS 0xtrue
|
||||
#define SCHAR_MIN 0x80
|
||||
#define SCHAR_MAX 0x7f
|
||||
|
||||
#define UCHAR_ROUNDS 0x0
|
||||
#define UCHAR_RADIX_DIG 0x8
|
||||
#define UCHAR_DIG 0x2
|
||||
#define UCHAR_DECIMAL_DIG 0x0
|
||||
#define UCHAR_RADIX 0x2
|
||||
#define UCHAR_TRAPS 0xtrue
|
||||
#define UCHAR_MIN 0x0
|
||||
#define UCHAR_MAX 0xff
|
||||
|
||||
#define SHORT_ROUNDS 0x0
|
||||
#define SHORT_RADIX_DIG 0xf
|
||||
#define SHORT_DIG 0x4
|
||||
#define SHORT_DECIMAL_DIG 0x0
|
||||
#define SHORT_RADIX 0x2
|
||||
#define SHORT_TRAPS 0xtrue
|
||||
#define SHORT_MIN 0x8000
|
||||
#define SHORT_MAX 0x7fff
|
||||
|
||||
#define USHORT_ROUNDS 0x0
|
||||
#define USHORT_RADIX_DIG 0x10
|
||||
#define USHORT_DIG 0x4
|
||||
#define USHORT_DECIMAL_DIG 0x0
|
||||
#define USHORT_RADIX 0x2
|
||||
#define USHORT_TRAPS 0xtrue
|
||||
#define USHORT_MIN 0x0
|
||||
#define USHORT_MAX 0xffff
|
||||
|
||||
#define INT_ROUNDS 0x0
|
||||
#define INT_RADIX_DIG 0x1f
|
||||
#define INT_DIG 0x9
|
||||
#define INT_DECIMAL_DIG 0x0
|
||||
#define INT_RADIX 0x2
|
||||
#define INT_TRAPS 0xtrue
|
||||
#define INT_MIN 0x80000000
|
||||
#define INT_MAX 0x7fffffff
|
||||
|
||||
#define UINT_ROUNDS 0x0
|
||||
#define UINT_RADIX_DIG 0x20
|
||||
#define UINT_DIG 0x9
|
||||
#define UINT_DECIMAL_DIG 0x0
|
||||
#define UINT_RADIX 0x2
|
||||
#define UINT_TRAPS 0xtrue
|
||||
#define UINT_MIN 0x0
|
||||
#define UINT_MAX 0xffffffff
|
||||
|
||||
#define LONG_ROUNDS 0x0
|
||||
#define LONG_RADIX_DIG 0x3f
|
||||
#define LONG_DIG 0x12
|
||||
#define LONG_DECIMAL_DIG 0x0
|
||||
#define LONG_RADIX 0x2
|
||||
#define LONG_TRAPS 0xtrue
|
||||
#define LONG_MIN 0x8000000000000000
|
||||
#define LONG_MAX 0x7fffffffffffffff
|
||||
|
||||
#define ULONG_ROUNDS 0x0
|
||||
#define ULONG_RADIX_DIG 0x40
|
||||
#define ULONG_DIG 0x13
|
||||
#define ULONG_DECIMAL_DIG 0x0
|
||||
#define ULONG_RADIX 0x2
|
||||
#define ULONG_TRAPS 0xtrue
|
||||
#define ULONG_MIN 0x0
|
||||
#define ULONG_MAX 0xffffffffffffffff
|
||||
|
||||
#define LLONG_ROUNDS 0x0
|
||||
#define LLONG_RADIX_DIG 0x3f
|
||||
#define LLONG_DIG 0x12
|
||||
#define LLONG_DECIMAL_DIG 0x0
|
||||
#define LLONG_RADIX 0x2
|
||||
#define LLONG_TRAPS 0xtrue
|
||||
#define LLONG_MIN 0x8000000000000000
|
||||
#define LLONG_MAX 0x7fffffffffffffff
|
||||
|
||||
#define ULLONG_ROUNDS 0x0
|
||||
#define ULLONG_RADIX_DIG 0x40
|
||||
#define ULLONG_DIG 0x13
|
||||
#define ULLONG_DECIMAL_DIG 0x0
|
||||
#define ULLONG_RADIX 0x2
|
||||
#define ULLONG_TRAPS 0xtrue
|
||||
#define ULLONG_MIN 0x0
|
||||
#define ULLONG_MAX 0xffffffffffffffff
|
||||
|
||||
#endif // FENNEC_LANG_INTEGER_H
|
||||
@@ -1,284 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file intrinsics.h
|
||||
/// \brief \ref fennec_lang_intrinsics
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_INTRINSICS_H
|
||||
#define FENNEC_LANG_INTRINSICS_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_intrinsics Intrinsics
|
||||
///
|
||||
/// \brief This header contains definitions for compiler intrinsics necessary for implementing functions of the
|
||||
/// C++ stdlib.
|
||||
///
|
||||
/// \code{.cpp}#include <fennec/lang/intrinsics.h>\endcode
|
||||
///
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_intrinsics">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_BIT_CAST` <br>
|
||||
/// `Y FENNEC_BUILTIN_BIT_CAST(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// An intrinsic for doing a bitwise cast without using `reinterpret_cast`.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_ADDRESSOF` <br>
|
||||
/// `Y FENNEC_BUILTIN_ADDRESSOF(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Obtains the true address of an object in circumstances where `operator&` is overloaded.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_CONVERTIBLE` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type `X` can be converted to type `Y`.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_EMPTY` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_EMPTY(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type `X` stores no data.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_POLYMORPHIC` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_POLYMORPHIC(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type `X` is polymorphic, this is for classes only thus checks only for subtyping
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_FINAL` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_FINAL(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type `X` is final, meaning a function or class cannot be derived from.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_ABSTRACT` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_ABSTRACT(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Opposite of `FENNEC_BUILTIN_IS_FINAL`, checks if abstract, meaning `X` has at least one pure virtual function.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if `X` has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class)
|
||||
/// for this trait
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// `FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE` <br>
|
||||
/// `B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)`
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type `X` is constructible with args `...`, such that `X::X(...)` exists.
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
|
||||
|
||||
// Most major compilers support __has_builtin, notably GCC, MINGW, and CLANG
|
||||
#if defined(__has_builtin)
|
||||
|
||||
// addressof is very difficult to implement without intrinsics.
|
||||
#if __has_builtin(__builtin_addressof)
|
||||
# define FENNEC_HAS_BUILTIN_ADDRESSOF 1
|
||||
# define FENNEC_BUILTIN_ADDRESSOF(arg) __builtin_addressof(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_ADDRESSOF 0
|
||||
#endif
|
||||
|
||||
// bitcast is slightly more efficient for build times than using memcpy
|
||||
#if __has_builtin(__builtin_bit_cast)
|
||||
# define FENNEC_HAS_BUILTIN_BIT_CAST 1
|
||||
# define FENNEC_BUILTIN_BIT_CAST(type, arg) __builtin_bit_cast(type, arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_BIT_CAST 0
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_abstract)
|
||||
# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 1
|
||||
# define FENNEC_BUILTIN_IS_ABSTRACT(arg) __is_abstract(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 0
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_array)
|
||||
# define FENNEC_HAS_BUILTIN_IS_ARRAY 1
|
||||
# define FENNEC_BUILTIN_IS_ARRAY(arg) __is_array(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_ARRAY
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_class)
|
||||
# define FENNEC_HAS_BUILTIN_IS_CLASS 1
|
||||
# define FENNEC_BUILTIN_IS_CLASS(arg) __is_class(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_CLASS
|
||||
#endif
|
||||
|
||||
// CONSTRUCTORS ========================================================================================================
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_constructible)
|
||||
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_trivially_constructible)
|
||||
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(type) __is_trivially_constructible(type)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__has_trivial_destructor)
|
||||
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __has_trivial_destructor(type)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
|
||||
// ASSIGNMENTS =========================================================================================================
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_assignable)
|
||||
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 1
|
||||
# define FENNEC_BUILTIN_IS_ASSIGNABLE(a, b) __is_assignable(a, b)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
|
||||
#endif
|
||||
|
||||
|
||||
// Type Traits
|
||||
// can_convert is also very difficult to implement without intrinsics
|
||||
#if __has_builtin(__is_convertible)
|
||||
# define FENNEC_HAS_BUILTIN_IS_CONVERTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_CONVERTIBLE(arg0, arg1) __is_convertible(arg0, arg1)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_CONVERTIBLE 0
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics.
|
||||
#if __has_builtin(__is_empty)
|
||||
# define FENNEC_HAS_BUILTIN_IS_EMPTY 1
|
||||
# define FENNEC_BUILTIN_IS_EMPTY(arg) __is_empty(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_EMPTY 0
|
||||
|
||||
// Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_final)
|
||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
||||
# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics.
|
||||
#if __has_builtin(__is_enum)
|
||||
# define FENNEC_HAS_BUILTIN_IS_ENUM 1
|
||||
# define FENNEC_BUILTIN_IS_ENUM(arg) __is_enum(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_ENUM 0
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_final)
|
||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
||||
# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
||||
#endif
|
||||
|
||||
// Inconsistent with dynamic intrinsics, requires a massive table for static intrinsics
|
||||
#if __has_builtin(__is_fundamental)
|
||||
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 1
|
||||
# define FENNEC_BUILTIN_IS_FUNDAMENTAL(arg) __is_fundamental(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 0
|
||||
#endif
|
||||
|
||||
// Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_polymorphic)
|
||||
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 1
|
||||
# define FENNEC_BUILTIN_IS_POLYMORPHIC(arg) __is_polymorphic(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 0
|
||||
#endif
|
||||
|
||||
// Impossible without instrinsics
|
||||
#if __has_builtin(__is_standard_layout)
|
||||
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 1
|
||||
# define FENNEC_BUILTIN_IS_STANDARD_LAYOUT(arg) __is_standard_layout(arg)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 0
|
||||
#endif
|
||||
|
||||
|
||||
// For compilers without or differently named builtins
|
||||
#else
|
||||
|
||||
// TODO: More compiler support
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_ADDRESS_OF 1
|
||||
# define FENNEC_BUILTIN_ADDRESS_OF(arg) __builtin_addressof(arg)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_BIT_CAST 1
|
||||
# define FENNEC_BUILTIN_BIT_CAST(type, arg) __builtin_bit_cast(type, arg)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_IS_CONVERTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_CONVERTIBLE(arg0, arg1) __is_convertible_to(arg0, arg1)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_IS_EMPTY 1
|
||||
# define FENNEC_BUILTIN_IS_EMPTY(arg) __is_empty(arg)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
||||
# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 1
|
||||
# define FENNEC_BUILTIN_IS_POLYMORPHIC(arg) __is_polymorphic(arg)
|
||||
|
||||
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 1
|
||||
# define FENNEC_BUILTIN_IS_STANDARD_LAYOUT(arg) __is_standard_layout(arg)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // FENNEC_LANG_INTRINSICS_H
|
||||
@@ -1,54 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file lang.h
|
||||
/// \brief \ref fennec_lang
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_H
|
||||
#define FENNEC_LANG_H
|
||||
|
||||
#include <fennec/lang/assert.h>
|
||||
#include <fennec/lang/bits.h>
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/utility.h>
|
||||
|
||||
///
|
||||
/// \page fennec_lang C++ Language Library
|
||||
///
|
||||
/// This library implements the parts of the C++ stdlib that relate to built-in types and metaprogramming.
|
||||
///
|
||||
/// - \subpage fennec_lang_assert
|
||||
/// - \subpage fennec_lang_bit_manipulation
|
||||
/// - \subpage fennec_lang_intrinsics
|
||||
/// - \subpage fennec_lang_limits
|
||||
/// - \subpage fennec_lang_metaprogramming
|
||||
/// - \subpage fennec_lang_types
|
||||
/// - \subpage fennec_lang_utility
|
||||
///
|
||||
///
|
||||
|
||||
#endif // FENNEC_LANG_H
|
||||
@@ -1,761 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file limits.h
|
||||
/// \brief \ref fennec_lang_limits
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
|
||||
#ifndef FENNEC_LANG_LIMITS_H
|
||||
#define FENNEC_LANG_LIMITS_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_limits Limits
|
||||
///
|
||||
/// \brief This header defines fennec::numeric_limits which contains info regarding the limits of numeric types including
|
||||
/// floats and integers. There are overloads for all builtin types, and overloads for other types are included in
|
||||
/// their own header.
|
||||
///
|
||||
/// \code{.cpp}#include <fennec/lang/limits.h>\endcode
|
||||
///
|
||||
/// \section fennec_lang_limits_numeric_limits Numeric Limits
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_limits">
|
||||
/// <tr><th style="vertical-align: top">Member
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><th colspan=2 style="text-align: center;">Traits
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_specialized "is_specialized"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_specialized
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_signed "is_signed"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_signed
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_integer "is_integer"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_integer
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_exact "is_exact"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_exact
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::has_infinity "has_infinity"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::has_infinity
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::has_quiet_nan "has_quiet_nan"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::has_quiet_nan
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::has_signaling_nan "has_signaling_nan"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::has_signaling_nan
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_iec559 "is_iec559"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_iec559
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_bounded "is_bounded"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_bounded
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::is_modulo "is_modulo"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::is_modulo
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::tinyness_before "tinyness_before"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::tinyness_before
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::traps "traps"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::traps
|
||||
///
|
||||
/// <tr><th colspan=2 style="text-align: center;">Binary
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::radix "radix"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::radix
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::digits "digits"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::digits
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::digits10 "digits10"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::digits10
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::max_digits10 "max_digits10"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::max_digits10
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::min_exponent "min_exponent"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::min_exponent
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::min_exponent10 "min_exponent10"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::min_exponent10
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::max_exponent "max_exponent"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::max_exponent
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::max_exponent10 "max_exponent10"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::max_exponent10
|
||||
///
|
||||
/// <tr><th colspan=2 style="text-align: center;">Limits
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::min "min()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::min
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::max "max()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::max
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::lowest "lowest()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::lowest
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::epsilon "epsilon()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::epsilon
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::round_error "round_error()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::round_error
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::infinity "infinity()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::infinity
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::quiet_NaN "quiet_NaN()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::quiet_NaN
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::signaling_NaN "signaling_NaN()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::signaling_NaN
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::numeric_limits::denorm_min "denorm_min()"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::numeric_limits::denorm_min
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
#include <fennec/lang/integer.h>
|
||||
#include <fennec/lang/float.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief enum for determining rounding styles
|
||||
enum float_round_style
|
||||
{
|
||||
round_indeterminate = -1
|
||||
, round_toward_zero = 0
|
||||
, round_to_nearest = 1
|
||||
, round_toward_infinity = 2
|
||||
, round_toward_neg_infinity = 3
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Helper for getting traits of a numeric type
|
||||
/// \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 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
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
// Overload definitions for basic types
|
||||
|
||||
// Overload for the builtin floating point type
|
||||
template<> struct numeric_limits<float>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr bool has_infinity = FLT_HAS_INFINITY;
|
||||
static constexpr bool has_quiet_nan = FLT_HAS_QUIET_NAN;
|
||||
static constexpr bool has_signaling_nan = FLT_HAS_SIGNALING_NAN;
|
||||
static constexpr bool has_denorm = FLT_HAS_DENORM;
|
||||
static constexpr bool has_denorm_loss = FLT_HAS_DENORM_LOSS;
|
||||
static constexpr bool is_iec559 = FLT_IS_IEC559;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = false;
|
||||
static constexpr bool tinyness_before = FLT_TINYNESS_BEFORE;
|
||||
static constexpr bool traps = FLT_TRAPS;
|
||||
|
||||
static constexpr int digits = FLT_MANT_DIG;
|
||||
static constexpr int digits10 = FLT_DIG;
|
||||
static constexpr int max_digits10 = FLT_DECIMAL_DIG;
|
||||
static constexpr int radix = FLT_RADIX;
|
||||
static constexpr int min_exponent = FLT_MIN_EXP;
|
||||
static constexpr int min_exponent10 = FLT_MIN_10_EXP;
|
||||
static constexpr int max_exponent = FLT_MAX_EXP;
|
||||
static constexpr int max_exponent10 = FLT_MAX_10_EXP;
|
||||
|
||||
static constexpr float min() { return -FLT_MAX; }
|
||||
static constexpr float max() { return FLT_MAX; }
|
||||
static constexpr float lowest() { return FLT_MIN; }
|
||||
static constexpr float epsilon() { return FLT_EPSILON; }
|
||||
static constexpr float round_error() { return FLT_ROUND_ERR; }
|
||||
static constexpr float infinity() { return FLT_INF; }
|
||||
static constexpr float quiet_NaN() { return FLT_QUIET_NAN; }
|
||||
static constexpr float signaling_NaN() { return FLT_SIGNALING_NAN; }
|
||||
static constexpr float denorm_min() { return FLT_DENORM_MIN; }
|
||||
};
|
||||
|
||||
// Overload for the bultin double precision floating point type
|
||||
template<> struct numeric_limits<double>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr bool has_infinity = DBL_HAS_INFINITY;
|
||||
static constexpr bool has_quiet_nan = DBL_HAS_QUIET_NAN;
|
||||
static constexpr bool has_signaling_nan = DBL_HAS_SIGNALING_NAN;
|
||||
static constexpr bool has_denorm = DBL_HAS_DENORM;
|
||||
static constexpr bool has_denorm_loss = DBL_HAS_DENORM_LOSS;
|
||||
static constexpr bool is_iec559 = DBL_IS_IEC559;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = false;
|
||||
static constexpr bool tinyness_before = DBL_TINYNESS_BEFORE;
|
||||
static constexpr bool traps = DBL_TRAPS;
|
||||
|
||||
static constexpr int digits = DBL_MANT_DIG;
|
||||
static constexpr int digits10 = DBL_DIG;
|
||||
static constexpr int max_digits10 = DBL_DECIMAL_DIG;
|
||||
static constexpr int radix = DBL_RADIX;
|
||||
static constexpr int min_exponent = DBL_MIN_EXP;
|
||||
static constexpr int min_exponent10 = DBL_MIN_10_EXP;
|
||||
static constexpr int max_exponent = DBL_MAX_EXP;
|
||||
static constexpr int max_exponent10 = DBL_MAX_10_EXP;
|
||||
|
||||
static constexpr double min() { return -DBL_MAX; }
|
||||
static constexpr double max() { return DBL_MAX; }
|
||||
static constexpr double lowest() { return DBL_MIN; }
|
||||
static constexpr double epsilon() { return DBL_EPSILON; }
|
||||
static constexpr double round_error() { return DBL_ROUND_ERR; }
|
||||
static constexpr double infinity() { return DBL_INF; }
|
||||
static constexpr double quiet_NaN() { return DBL_QUIET_NAN; }
|
||||
static constexpr double signaling_NaN() { return DBL_SIGNALING_NAN; }
|
||||
static constexpr double denorm_min() { return DBL_DENORM_MIN; }
|
||||
};
|
||||
|
||||
// Overload for the builtin char type
|
||||
template<> struct numeric_limits<char>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = CHAR_IS_SIGNED;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = CHAR_RADIX_DIG;
|
||||
static constexpr int digits10 = CHAR_DIG;
|
||||
static constexpr int max_digits10 = CHAR_DECIMAL_DIG;
|
||||
static constexpr int radix = CHAR_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr char min() { return static_cast<char>(CHAR_MIN); }
|
||||
static constexpr char max() { return CHAR_MAX; }
|
||||
static constexpr char lowest() { return 1; }
|
||||
static constexpr char epsilon() { return 1; }
|
||||
static constexpr char round_error() { return 0; }
|
||||
static constexpr char infinity() { return 0; }
|
||||
static constexpr char quiet_NaN() { return 0; }
|
||||
static constexpr char signaling_NaN() { return 0; }
|
||||
static constexpr char denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<signed char>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = SCHAR_RADIX_DIG;
|
||||
static constexpr int digits10 = SCHAR_DIG;
|
||||
static constexpr int max_digits10 = SCHAR_DECIMAL_DIG;
|
||||
static constexpr int radix = SCHAR_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr signed char min() { return static_cast<signed char>(SCHAR_MIN); }
|
||||
static constexpr signed char max() { return SCHAR_MAX; }
|
||||
static constexpr signed char lowest() { return 1; }
|
||||
static constexpr signed char epsilon() { return 1; }
|
||||
static constexpr signed char round_error() { return 0; }
|
||||
static constexpr signed char infinity() { return 0; }
|
||||
static constexpr signed char quiet_NaN() { return 0; }
|
||||
static constexpr signed char signaling_NaN() { return 0; }
|
||||
static constexpr signed char denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<unsigned char>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = UCHAR_RADIX_DIG;
|
||||
static constexpr int digits10 = UCHAR_DIG;
|
||||
static constexpr int max_digits10 = UCHAR_DECIMAL_DIG;
|
||||
static constexpr int radix = UCHAR_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr unsigned char min() { return UCHAR_MIN; }
|
||||
static constexpr unsigned char max() { return UCHAR_MAX; }
|
||||
static constexpr unsigned char lowest() { return 1; }
|
||||
static constexpr unsigned char epsilon() { return 1; }
|
||||
static constexpr unsigned char round_error() { return 0; }
|
||||
static constexpr unsigned char infinity() { return 0; }
|
||||
static constexpr unsigned char quiet_NaN() { return 0; }
|
||||
static constexpr unsigned char signaling_NaN() { return 0; }
|
||||
static constexpr unsigned char denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<short>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = SHORT_RADIX_DIG;
|
||||
static constexpr int digits10 = SHORT_DIG;
|
||||
static constexpr int max_digits10 = SHORT_DECIMAL_DIG;
|
||||
static constexpr int radix = SHORT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr short min() { return static_cast<short>(SHORT_MIN); }
|
||||
static constexpr short max() { return SHORT_MAX; }
|
||||
static constexpr short lowest() { return 1; }
|
||||
static constexpr short epsilon() { return 1; }
|
||||
static constexpr short round_error() { return 0; }
|
||||
static constexpr short infinity() { return 0; }
|
||||
static constexpr short quiet_NaN() { return 0; }
|
||||
static constexpr short signaling_NaN() { return 0; }
|
||||
static constexpr short denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<unsigned short>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = USHORT_RADIX_DIG;
|
||||
static constexpr int digits10 = USHORT_DIG;
|
||||
static constexpr int max_digits10 = USHORT_DECIMAL_DIG;
|
||||
static constexpr int radix = USHORT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr unsigned short min() { return USHORT_MIN; }
|
||||
static constexpr unsigned short max() { return USHORT_MAX; }
|
||||
static constexpr unsigned short lowest() { return 1; }
|
||||
static constexpr unsigned short epsilon() { return 1; }
|
||||
static constexpr unsigned short round_error() { return 0; }
|
||||
static constexpr unsigned short infinity() { return 0; }
|
||||
static constexpr unsigned short quiet_NaN() { return 0; }
|
||||
static constexpr unsigned short signaling_NaN() { return 0; }
|
||||
static constexpr unsigned short denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = INT_RADIX_DIG;
|
||||
static constexpr int digits10 = INT_DIG;
|
||||
static constexpr int max_digits10 = INT_DECIMAL_DIG;
|
||||
static constexpr int radix = INT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr int min() { return INT_MIN; }
|
||||
static constexpr int max() { return INT_MAX; }
|
||||
static constexpr int lowest() { return 1; }
|
||||
static constexpr int epsilon() { return 1; }
|
||||
static constexpr int round_error() { return 0; }
|
||||
static constexpr int infinity() { return 0; }
|
||||
static constexpr int quiet_NaN() { return 0; }
|
||||
static constexpr int signaling_NaN() { return 0; }
|
||||
static constexpr int denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<unsigned int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = UINT_RADIX_DIG;
|
||||
static constexpr int digits10 = UINT_DIG;
|
||||
static constexpr int max_digits10 = UINT_DECIMAL_DIG;
|
||||
static constexpr int radix = UINT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr unsigned int min() { return UINT_MIN; }
|
||||
static constexpr unsigned int max() { return UINT_MAX; }
|
||||
static constexpr unsigned int lowest() { return 1; }
|
||||
static constexpr unsigned int epsilon() { return 1; }
|
||||
static constexpr unsigned int round_error() { return 0; }
|
||||
static constexpr unsigned int infinity() { return 0; }
|
||||
static constexpr unsigned int quiet_NaN() { return 0; }
|
||||
static constexpr unsigned int signaling_NaN() { return 0; }
|
||||
static constexpr unsigned int denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<long int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = LONG_RADIX_DIG;
|
||||
static constexpr int digits10 = LONG_DIG;
|
||||
static constexpr int max_digits10 = LONG_DECIMAL_DIG;
|
||||
static constexpr int radix = LONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr long int min() { return LONG_MIN; }
|
||||
static constexpr long int max() { return LONG_MAX; }
|
||||
static constexpr long int lowest() { return 1; }
|
||||
static constexpr long int epsilon() { return 1; }
|
||||
static constexpr long int round_error() { return 0; }
|
||||
static constexpr long int infinity() { return 0; }
|
||||
static constexpr long int quiet_NaN() { return 0; }
|
||||
static constexpr long int signaling_NaN() { return 0; }
|
||||
static constexpr long int denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<unsigned long int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = ULONG_RADIX_DIG;
|
||||
static constexpr int digits10 = ULONG_DIG;
|
||||
static constexpr int max_digits10 = ULONG_DECIMAL_DIG;
|
||||
static constexpr int radix = ULONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr unsigned long min() { return ULONG_MIN; }
|
||||
static constexpr unsigned long max() { return ULONG_MAX; }
|
||||
static constexpr unsigned long lowest() { return 1; }
|
||||
static constexpr unsigned long epsilon() { return 1; }
|
||||
static constexpr unsigned long round_error() { return 0; }
|
||||
static constexpr unsigned long infinity() { return 0; }
|
||||
static constexpr unsigned long quiet_NaN() { return 0; }
|
||||
static constexpr unsigned long signaling_NaN() { return 0; }
|
||||
static constexpr unsigned long denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<long long>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = LLONG_RADIX_DIG;
|
||||
static constexpr int digits10 = LLONG_DIG;
|
||||
static constexpr int max_digits10 = LLONG_DECIMAL_DIG;
|
||||
static constexpr int radix = LLONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr long long min() { return LLONG_MIN; }
|
||||
static constexpr long long max() { return LLONG_MAX; }
|
||||
static constexpr long long lowest() { return 1; }
|
||||
static constexpr long long epsilon() { return 1; }
|
||||
static constexpr long long round_error() { return 0; }
|
||||
static constexpr long long infinity() { return 0; }
|
||||
static constexpr long long quiet_NaN() { return 0; }
|
||||
static constexpr long long signaling_NaN() { return 0; }
|
||||
static constexpr long long denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
template<> struct numeric_limits<unsigned long long>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
|
||||
static constexpr int digits = ULLONG_RADIX_DIG;
|
||||
static constexpr int digits10 = ULLONG_DIG;
|
||||
static constexpr int max_digits10 = ULLONG_DECIMAL_DIG;
|
||||
static constexpr int radix = ULLONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
|
||||
static constexpr unsigned long long min() { return ULLONG_MIN; }
|
||||
static constexpr unsigned long long max() { return ULLONG_MAX; }
|
||||
static constexpr unsigned long long lowest() { return 1; }
|
||||
static constexpr unsigned long long epsilon() { return 1; }
|
||||
static constexpr unsigned long long round_error() { return 0; }
|
||||
static constexpr unsigned long long infinity() { return 0; }
|
||||
static constexpr unsigned long long quiet_NaN() { return 0; }
|
||||
static constexpr unsigned long long signaling_NaN() { return 0; }
|
||||
static constexpr unsigned long long denorm_min() { return 0; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_LIMITS_H
|
||||
@@ -1,52 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file metaprogramming.h
|
||||
/// \brief \ref fennec_lang
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_METAPROGRAMMING_H
|
||||
#define FENNEC_LANG_METAPROGRAMMING_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_metaprogramming Metaprogramming Library
|
||||
///
|
||||
/// This is a sub-library of the fennec \ref fennec_lang. Metaprogramming is a method of obtaining information about the
|
||||
/// structure of the code and changing its behaviour at compile time. This includes getting traits of types, such as with
|
||||
/// \ref fennec::is_signed. You may even \ref fennec_lang_conditional_types "programmatically enable" functions
|
||||
/// based on the info of the types that the function uses.
|
||||
///
|
||||
/// - \subpage fennec_lang_constants
|
||||
/// - \subpage fennec_lang_conditional_types
|
||||
/// - \subpage fennec_lang_numeric_transforms
|
||||
/// - \subpage fennec_lang_sequences
|
||||
/// - \subpage fennec_lang_type_sequences
|
||||
/// - \subpage fennec_lang_type_traits
|
||||
/// - \subpage fennec_lang_type_transforms
|
||||
///
|
||||
///
|
||||
|
||||
#endif // FENNEC_LANG_METAPROGRAMMING_H
|
||||
@@ -1,84 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General 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 License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file numeric_transforms.h
|
||||
/// \brief \ref fennec_lang_numeric_transforms
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_NUMERIC_TRANSFORMS_H
|
||||
#define FENNEC_LANG_NUMERIC_TRANSFORMS_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_numeric_transforms Numeric Transforms
|
||||
///
|
||||
/// \code #include <fennec/lang/numeric_transforms.h> \endcode
|
||||
///
|
||||
/// This header contains various compile-time functions for changing the characteristics of a provided type
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_numeric_transforms">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::make_signed "typename make_signed<TypeT>::type"<br>
|
||||
/// \ref fennec::make_signed_t "make_signed_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::make_signed
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::make_unsigned "typename make_unsigned<TypeT>::type"<br>
|
||||
/// \ref fennec::make_unsigned_t "make_unsigned_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::make_unsigned
|
||||
///
|
||||
/// </table>
|
||||
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
#include <fennec/lang/detail/_numeric_transforms.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Get the corresponding signed integral type of TypeT
|
||||
/// \tparam TypeT the integral type to transform
|
||||
template<typename TypeT> struct make_signed : detail::_make_signed<remove_cv_t<TypeT>> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `typename make_signed<TypeT>::type`
|
||||
template<typename TypeT> using make_signed_t = typename make_signed<TypeT>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief Get the corresponding unsigned integral type of TypeT
|
||||
/// \tparam TypeT the integral type to transform
|
||||
template<typename TypeT> struct make_unsigned : detail::_make_unsigned<remove_cv_t<TypeT>> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `typename make_unsigned<TypeT>::type`
|
||||
template<typename TypeT> using make_unsigned_t = typename make_unsigned<TypeT>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_NUMERIC_TRANSFORMS_H
|
||||
370
include/fennec/lang/strings/cstring.h
Normal file
370
include/fennec/lang/strings/cstring.h
Normal file
@@ -0,0 +1,370 @@
|
||||
// =====================================================================================================================
|
||||
// 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_LANGPROC_STRINGS_CSTRING_H
|
||||
#define FENNEC_LANGPROC_STRINGS_CSTRING_H
|
||||
|
||||
#include <fennec/lang/strings/detail/_ctype.h>
|
||||
#include <fennec/memory/detail/_string.h>
|
||||
|
||||
#include <fennec/langcpp/assert.h>
|
||||
|
||||
#include <fennec/math/common.h>
|
||||
#include <fennec/memory/bytes.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// TODO: Document
|
||||
|
||||
using ::isalnum;
|
||||
using ::isalpha;
|
||||
using ::islower;
|
||||
using ::isupper;
|
||||
using ::isdigit;
|
||||
using ::isxdigit;
|
||||
using ::iscntrl;
|
||||
using ::isgraph;
|
||||
using ::isspace;
|
||||
using ::isblank;
|
||||
using ::isprint;
|
||||
using ::ispunct;
|
||||
|
||||
using ::tolower;
|
||||
using ::toupper;
|
||||
|
||||
|
||||
struct string_view {
|
||||
const char* str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief This struct wraps c-style strings
|
||||
///
|
||||
/// \details Requires that the string is null-terminated.
|
||||
/// Prevents const qualified memory blocks from being manipulated.
|
||||
/// This struct should be used when fennec::string would make unnecessary dynamic buffers.
|
||||
struct cstring
|
||||
{
|
||||
public:
|
||||
static constexpr size_t npos = -1;
|
||||
using char_t = char;
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes with nullptr
|
||||
constexpr cstring()
|
||||
: _str(nullptr), _size(0), _const(true) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes with nullptr
|
||||
constexpr cstring(nullptr_t)
|
||||
: _str(nullptr), _size(0), _const(true) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of characters in the buffer plus the null terminator
|
||||
constexpr cstring(char* str, size_t n)
|
||||
: _str(str)
|
||||
, _size(n - 1)
|
||||
, _const(false) {
|
||||
if constexpr(not is_constant_evaluated()) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of characters in the buffer plus the null terminator
|
||||
template<size_t n>
|
||||
constexpr cstring(char(&str)[n])
|
||||
: _str(str)
|
||||
, _size(n - 1)
|
||||
, _const(false) {
|
||||
if constexpr(not is_constant_evaluated()) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of characters in the buffer plus the null terminator
|
||||
constexpr cstring(const char* str, size_t n)
|
||||
: _cstr(str)
|
||||
, _size(n - 1)
|
||||
, _const(true) {
|
||||
if constexpr(not is_constant_evaluated()) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of characters in the buffer plus the null terminator
|
||||
template<size_t n>
|
||||
constexpr cstring(const char(&str)[n])
|
||||
: _cstr(str)
|
||||
, _size(n - 1)
|
||||
, _const(true) {
|
||||
if constexpr(not is_constant_evaluated()) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Constructor
|
||||
/// \param str object to move
|
||||
constexpr cstring(cstring&& str) noexcept
|
||||
: _cstr(str._cstr)
|
||||
, _size(str._size)
|
||||
, _const(str._const) {
|
||||
str._cstr = nullptr;
|
||||
str._size = 0;
|
||||
str._const = true;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
constexpr cstring(const cstring&) = delete;
|
||||
constexpr ~cstring() = default;
|
||||
|
||||
constexpr cstring& operator=(nullptr_t) {
|
||||
_str = nullptr, _size = 0, _const = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
template<size_t n>
|
||||
constexpr cstring& operator=(char(&str)[n]) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
_str = str, _size = n - 1, _const = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
template<size_t n>
|
||||
constexpr cstring& operator=(const char(&str)[n]) {
|
||||
assert(str[n - 1] == '\0', "Invalid NTBS.");
|
||||
_cstr = str; _size = n - 1; _const = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
constexpr cstring& operator=(cstring&& str) noexcept {
|
||||
_cstr = str._cstr; str._cstr = nullptr;
|
||||
_size = str._size; str._size = 0;
|
||||
_const = str._const; str._const = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the size of the string including its null terminator, i.e. `(*str)[capacity() - 1] == '\0'`
|
||||
constexpr size_t capacity() const {
|
||||
return _size + 1;
|
||||
}
|
||||
|
||||
constexpr bool empty() const {
|
||||
return _cstr == nullptr || _size == 0;
|
||||
}
|
||||
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a reference to the character
|
||||
constexpr char& operator[](size_t i) {
|
||||
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||
assertd(i < size(), "Array Out of Bounds");
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const-Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a copy of the character
|
||||
constexpr char operator[](size_t i) const {
|
||||
assertd(i < size(), "Array Out of Bounds");
|
||||
return _cstr[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Data Access
|
||||
/// \returns A const qualified pointer to the underlying allocation
|
||||
constexpr char* data() {
|
||||
return _str;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Data Access
|
||||
/// \returns A const qualified pointer to the underlying allocation
|
||||
constexpr const char* data() const {
|
||||
return _cstr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Implicit Dereference Cast
|
||||
constexpr operator const char*() const {
|
||||
return _cstr;
|
||||
}
|
||||
|
||||
|
||||
// Examination =========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The length of the string to the first null-terminator
|
||||
constexpr size_t length() const {
|
||||
return find('\0');
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param str the string to compare against
|
||||
/// \param i the index to start at
|
||||
/// \param n the number of characters to compare
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const cstring& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= _size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = min(n, max(_size, str._size) + 1);
|
||||
return ::strncmp(_cstr + i, str, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Equality
|
||||
/// \param str the string to compare against
|
||||
/// \returns True if all characters are equal, false otherwise
|
||||
template<size_t n>
|
||||
constexpr bool operator==(const char (&str)[n]) const {
|
||||
return compare(cstring(str)) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Equality
|
||||
/// \param str the string to compare against
|
||||
/// \returns True if all characters are equal, false otherwise
|
||||
constexpr bool operator==(const cstring& str) const {
|
||||
return compare(str) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||
/// \param c the character to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(char c, size_t i = 0) const {
|
||||
if (i >= _size) { // bounds check
|
||||
return _size;
|
||||
}
|
||||
|
||||
const char* loc = ::strchr(_cstr + i, c); // get location using strchr
|
||||
return loc ? loc - _cstr : _size; // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const cstring& str, size_t i = 0) const {
|
||||
if (i + str._size > _size) { // bounds check
|
||||
return _size;
|
||||
}
|
||||
|
||||
const char* loc = ::strstr(_cstr + i, str); // get location using strstr
|
||||
return loc ? loc - _cstr : _size; // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
||||
/// \param c the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||
if (_size == 0) {
|
||||
return _size;
|
||||
}
|
||||
|
||||
i = min(i, _size - 1); // clamp i to bounds
|
||||
do {
|
||||
if (_cstr[i] == c) return i; // loop backwards looking for c
|
||||
} while (i--);
|
||||
return _size; // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const cstring& str, size_t i = npos) const {
|
||||
if (_size == 0) {
|
||||
return _size;
|
||||
}
|
||||
|
||||
const char first = str[0];
|
||||
i = min(i, _size - str._size);
|
||||
do {
|
||||
if(_cstr[i] == first) {
|
||||
if (compare(str, i, str._size - 1) == 0) {
|
||||
return i;
|
||||
}
|
||||
} // loop backwards looking for str
|
||||
} while (i--);
|
||||
return _size; // base case
|
||||
}
|
||||
|
||||
private:
|
||||
union { // hack to allow both const qualified and non-const strings
|
||||
char* _str;
|
||||
const char* _cstr;
|
||||
};
|
||||
size_t _size;
|
||||
bool _const;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<cstring> : hash<byte_array> {
|
||||
constexpr size_t operator()(const cstring& str) const {
|
||||
return hash<byte_array>::operator()(byte_array(str, str.size()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_STRINGS_CSTRING_H
|
||||
@@ -16,20 +16,10 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_TYPEUUID_H
|
||||
#define FENNEC_LANG_DETAIL_TYPEUUID_H
|
||||
#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
#include <ctype.h>
|
||||
#include <wctype.h>
|
||||
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
template<typename RootT>
|
||||
FENNEC_NO_INLINE uint64_t _typeuuid() {
|
||||
static uint64_t i = 0;
|
||||
return ++i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_TYPEUUID_H
|
||||
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
@@ -16,13 +16,9 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_STARTUP_H
|
||||
#define FENNEC_LANG_STARTUP_H
|
||||
#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
|
||||
// Helper for running a function before main()
|
||||
#define FENNEC_STATIC_CONSTRUCTOR(f) \
|
||||
inline static void f(void); \
|
||||
struct f##_t_ { inline f##_t_(void) { f(); } }; inline static f##_t_ f##_; \
|
||||
inline static void f(void)
|
||||
#include <locale.h>
|
||||
|
||||
#endif // FENNEC_LANG_STARTUP_H
|
||||
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
||||
210
include/fennec/lang/strings/format.h
Normal file
210
include/fennec/lang/strings/format.h
Normal file
@@ -0,0 +1,210 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file format.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANGPROC_STRINGS_FORMAT_H
|
||||
#define FENNEC_LANGPROC_STRINGS_FORMAT_H
|
||||
#include <fennec/containers/pair.h>
|
||||
#include <fennec/lang/strings/cstring.h>
|
||||
#include <fennec/lang/strings/string.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
template<typename TypeT>
|
||||
struct formatter {
|
||||
constexpr string operator()(const string_view&, const TypeT&) {
|
||||
static_assert(false, "Formatter not implemented for the provided type.");
|
||||
return string{""};
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct formatter<cstring> {
|
||||
constexpr string operator()(const string_view&, const cstring& str) {
|
||||
return string(str);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct formatter<const char (&)[N]> {
|
||||
constexpr string operator()(const string_view&, const char (&str)[N]) {
|
||||
return string(str);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t N, typename...ArgsT>
|
||||
struct format_string {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
private:
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
enum token_ : bool {
|
||||
token_text = false,
|
||||
token_param = true,
|
||||
};
|
||||
|
||||
struct token {
|
||||
uint8_t type;
|
||||
string_view view;
|
||||
size_t param;
|
||||
};
|
||||
|
||||
constexpr const char* find(const char* start, char c) {
|
||||
while (*start != c && *start != '\0') {
|
||||
++start;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
constexpr size_t parse_index(const char* start, size_t n) {
|
||||
size_t x = 0;
|
||||
while (n-- > 0) {
|
||||
x *= 10;
|
||||
x += *start - '0';
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
// Constructors & Destructor ===========================================================================================
|
||||
public:
|
||||
format_string() = delete;
|
||||
|
||||
constexpr format_string(const char (&str)[N])
|
||||
: _tokens(), _num_tokens(0) {
|
||||
// TODO: Numbered Parameters
|
||||
|
||||
size_t params = 0;
|
||||
for (size_t i = 0; i < N - 1; ++i) {
|
||||
size_t l = this->find(str + i, '{') - str;
|
||||
|
||||
// Push the current token
|
||||
if (l - i > 0) {
|
||||
_tokens[_num_tokens++] = { token_text, { &str[i], l - i }, npos };
|
||||
}
|
||||
|
||||
// no more braces, break
|
||||
if (l >= N) {
|
||||
break;
|
||||
}
|
||||
|
||||
// escaped brace
|
||||
if (str[l + 1] == '{') {
|
||||
_tokens[_num_tokens++] = { token_text, { &str[l], 1 }, npos };
|
||||
i = l + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t e = this->find(str + l, '}') - str;
|
||||
assertd(e < N, "Malformed format string, mismatched brace");
|
||||
|
||||
// Colon found
|
||||
size_t c = this->find(str + l, ':') - str;
|
||||
if (c < e) {
|
||||
size_t n = c - l;
|
||||
if (n > 1) { // Check if index is provided
|
||||
params = this->parse_index(str + l + 1, n - 1);
|
||||
}
|
||||
l = c;
|
||||
} else if (e - l > 1) { // check if index is provided
|
||||
params = this->parse_index(str + l + 1, e - l - 1);
|
||||
}
|
||||
|
||||
assertd(params < sizeof...(ArgsT), "Malformed format string, parameter count does not match argument count.");
|
||||
_tokens[_num_tokens++] = { token_param, { &str[l + 1], e - l - 1 }, params++ };
|
||||
i = e;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr format_string(const format_string&) = default;
|
||||
constexpr format_string(format_string&&) noexcept = default;
|
||||
|
||||
~format_string() = default;
|
||||
|
||||
string format(ArgsT&&...args) const {
|
||||
string parts[N];
|
||||
|
||||
// Copy raw text tokens
|
||||
size_t i = 0;
|
||||
for (i = 0; i < _num_tokens; ++i) {
|
||||
const token& tok = _tokens[i];
|
||||
if (not tok.type) {
|
||||
parts[i] = tok.view;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy arguments
|
||||
this->_format(0, parts, fennec::forward<ArgsT>(args)...);
|
||||
|
||||
string res;
|
||||
for (i = 0; i < _num_tokens; ++i) {
|
||||
res += parts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
array<token, N> _tokens;
|
||||
size_t _num_tokens;
|
||||
|
||||
void _format(size_t) const {
|
||||
}
|
||||
|
||||
template<typename HeadT, typename...RestT>
|
||||
void _format(size_t p, string (&parts)[N], HeadT&& head, RestT&&...rest) const {
|
||||
size_t i = 0;
|
||||
for (const token& tok : _tokens) {
|
||||
if (i >= _num_tokens) {
|
||||
break;
|
||||
}
|
||||
if (tok.param == p) {
|
||||
formatter<HeadT> fmt;
|
||||
parts[i] = fmt(tok.view, head);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
this->_format(p + 1, fennec::forward<RestT>(rest)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t N, typename...ArgsT>
|
||||
string _format(const format_string<N, ArgsT...>& str, ArgsT&&...args) {
|
||||
return str.format(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
template<size_t N, typename...ArgsT>
|
||||
string format(const char (&str)[N], ArgsT&&...args) {
|
||||
return fennec::_format<N, ArgsT...>(format_string<N, ArgsT...>(str), fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_STRINGS_FORMAT_H
|
||||
@@ -16,19 +16,29 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_DETAIL_INT_H
|
||||
#define FENNEC_LANG_DETAIL_INT_H
|
||||
#ifndef FENNEC_LANGPROC_STRINGS_LOCALE_H
|
||||
#define FENNEC_LANGPROC_STRINGS_LOCALE_H
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4117)
|
||||
#include <fennec/lang/strings/detail/_locale.h>
|
||||
|
||||
#define __PTRDIFF_TYPE__ ptrdiff_t
|
||||
#endif
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// Include math since stdint will define its own versions of isinf and isnan
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
enum locale : int
|
||||
{
|
||||
lc_all = LC_ALL
|
||||
, lc_collate = LC_COLLATE
|
||||
, lc_ctype = LC_CTYPE
|
||||
, lc_monetary = LC_MONETARY
|
||||
, lc_numeric = LC_NUMERIC
|
||||
, lc_time = LC_TIME
|
||||
};
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_INT_H
|
||||
using ::lconv;
|
||||
|
||||
using ::setlocale;
|
||||
using ::localeconv;
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_STRINGS_LOCALE_H
|
||||
480
include/fennec/lang/strings/string.h
Normal file
480
include/fennec/lang/strings/string.h
Normal file
@@ -0,0 +1,480 @@
|
||||
// =====================================================================================================================
|
||||
// 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_LANGPROC_STRINGS_STRING_H
|
||||
#define FENNEC_LANGPROC_STRINGS_STRING_H
|
||||
|
||||
#include <fennec/lang/strings/detail/_ctype.h>
|
||||
#include <fennec/lang/strings/cstring.h>
|
||||
|
||||
#include <fennec/langcpp/assert.h>
|
||||
|
||||
#include <fennec/memory/allocator.h>
|
||||
#include <fennec/memory/common.h>
|
||||
|
||||
#include <fennec/math/common.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// Forward def
|
||||
template<typename AllocT = allocator<char>> struct _string;
|
||||
|
||||
// Alias for default allocator
|
||||
using string = _string<>;
|
||||
|
||||
///
|
||||
/// \brief Struct for wrapping c-style strings
|
||||
///
|
||||
/// \details behaviour guarantees that the underlying string is null-terminated
|
||||
template<typename AllocT>
|
||||
struct _string
|
||||
{
|
||||
public:
|
||||
static constexpr size_t npos = -1;
|
||||
using char_t = char;
|
||||
using alloc_t = allocation<char, AllocT>;
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes empty string
|
||||
constexpr _string()
|
||||
: _str() {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
||||
/// \param n the number of characters
|
||||
/// \param c the character to fill with
|
||||
///
|
||||
/// \details adds additional character for null termination.
|
||||
constexpr _string(size_t n, char c = '\0')
|
||||
: _str(n + 1) {
|
||||
fennec::memset(_str, c, n);
|
||||
}
|
||||
|
||||
constexpr _string(const alloc_t& alloc)
|
||||
: _str(alloc) {
|
||||
}
|
||||
|
||||
constexpr _string(size_t n, char c, const alloc_t& alloc)
|
||||
: _str(n + 1, alloc) {
|
||||
fennec::memset(_str, c, n);
|
||||
}
|
||||
|
||||
constexpr _string(const cstring& cstr)
|
||||
: _str(cstr, cstr.size() + 1) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of characters in the buffer including the null-terminator, if present
|
||||
template<size_t n>
|
||||
explicit constexpr _string(const char (&str)[n])
|
||||
: _str(str[n - 1] != '\0' ? n + 1 : n) {
|
||||
fennec::memcpy(_str, str, n);
|
||||
if (str[n - 1] != '\0') {
|
||||
_str[n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of characters in the buffer including the null-terminator, if present
|
||||
constexpr _string(const char* buf, size_t n)
|
||||
: _str(buf[n - 1] != '\0' ? n + 1 : n) {
|
||||
fennec::memcpy(_str, buf, n);
|
||||
if (buf[n - 1] != '\0') {
|
||||
_str[n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
constexpr _string(const string_view& view)
|
||||
: _string(view.str, view.len) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Copy Constructor
|
||||
/// \param str the string to copy
|
||||
constexpr _string(const _string& str) = default;
|
||||
|
||||
///
|
||||
/// \brief String Move Constructor
|
||||
/// \param str the string to take ownership of
|
||||
constexpr _string(_string&& str) noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief Destructor, cleans up underlying allocation
|
||||
constexpr ~_string() = default;
|
||||
|
||||
// Assignment ==========================================================================================================
|
||||
|
||||
constexpr _string& operator=(const cstring& cstr) {
|
||||
_str.callocate(cstr.capacity());
|
||||
fennec::memcpy(_str, cstr, cstr.capacity());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _string& operator=(const _string& str) {
|
||||
_str = str._str;
|
||||
return *this;
|
||||
}
|
||||
constexpr _string& operator=(_string&& str) noexcept {
|
||||
_str = fennec::move(str._str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The size of the string excluding null terminator
|
||||
constexpr size_t size() const {
|
||||
return _str.capacity() > 0 ? _str.capacity() - 1 : 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The size of the string including null terminator
|
||||
constexpr size_t capacity() const {
|
||||
return _str.capacity();
|
||||
}
|
||||
|
||||
constexpr bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a reference to the character
|
||||
constexpr char& operator[](size_t i) {
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const-Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a copy of the character
|
||||
constexpr const char& operator[](size_t i) const {
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
constexpr char* data() {
|
||||
return _str;
|
||||
}
|
||||
|
||||
constexpr const char* data() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
constexpr const char* cstr() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
// Examination =========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The length of the string to the first null-terminator
|
||||
constexpr size_t length() const {
|
||||
return find('\0');
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param ostr the string to compare against
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const cstring& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return -1;
|
||||
}
|
||||
n = fennec::min(n, fennec::max(size(), str.size()) + 1);
|
||||
|
||||
return ::strncmp(_str + i, str, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param ostr the string to compare against
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const string& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return -1;
|
||||
}
|
||||
n = min(n, max(size(), str.size()) + 1);
|
||||
|
||||
return ::strncmp(_str + i, str.data(), n);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const cstring& str) const {
|
||||
return compare(str) == 0;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const _string& str) const {
|
||||
return compare(str) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Check if the string contains a character
|
||||
/// \param c
|
||||
/// \param i
|
||||
/// \return
|
||||
constexpr bool contains(char c, size_t i = 0) const {
|
||||
return find(c, i) != size();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||
/// \param c the character to find
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(char c, size_t i = 0) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const char* loc = ::strchr(_str + i, c); // get location using strchr
|
||||
return loc ? loc - _str : size(); // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const string& str, size_t i = 0) const { // bounds check
|
||||
if (i >= size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const char* loc = ::strstr(_str, str._str);
|
||||
return loc ? loc - _str : size();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const cstring& str, size_t i = 0) const {
|
||||
if (i + str.size() > size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const char* loc = ::strstr(_str + i, str); // get location using strstr
|
||||
return loc ? loc - _str : size(); // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
||||
/// \param c the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
i = min(i, size() - 1); // clamp i to bounds
|
||||
do {
|
||||
if (_str[i] == c) { // loop backwards looking for c
|
||||
return i;
|
||||
}
|
||||
} while (i--);
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const cstring& str, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
const char first = str[0];
|
||||
i = min(i, size() - str.size());
|
||||
do {
|
||||
if(_str[i] == first) {
|
||||
if (compare(str, i) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} while (i--);
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
const char first = str[0];
|
||||
i = min(i, size() - str.size());
|
||||
do {
|
||||
if(_str[i] == first) {
|
||||
if (compare(str, i) == 0) { // loop backwards looking for str
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} while (i--);
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Retrieve a substring of a string
|
||||
/// \param i the start index
|
||||
/// \param n the number of characters
|
||||
/// \return
|
||||
constexpr _string substring(size_t i, size_t n = npos) const {
|
||||
if (i >= size() || n == 0) {
|
||||
return _string("");
|
||||
}
|
||||
n = fennec::min(n, size() - i);
|
||||
_string res;
|
||||
res._str.callocate(n + 1);
|
||||
fennec::memcpy(res.data(), _str + i, n);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Modifiers ===========================================================================================================
|
||||
|
||||
constexpr void resize(size_t n) {
|
||||
_str.creallocate(n + 1);
|
||||
_str[size()] = '\0';
|
||||
}
|
||||
|
||||
constexpr _string operator+(char c) const {
|
||||
if (_str == nullptr) {
|
||||
return _string(1, c);
|
||||
}
|
||||
_string res;
|
||||
res._str.callocate(capacity() + 1);
|
||||
fennec::memcpy(res.data(), _str, size());
|
||||
res[size()] = c;
|
||||
return res;
|
||||
}
|
||||
|
||||
friend constexpr _string operator+(char c, const _string& str) {
|
||||
_string res(1, c);
|
||||
return res += str;
|
||||
}
|
||||
|
||||
constexpr _string operator+(const cstring& cstr) const {
|
||||
if (_str == nullptr) {
|
||||
return _string(cstr);
|
||||
}
|
||||
_string res;
|
||||
res._str.callocate(size() + cstr.size() + 1);
|
||||
fennec::memcpy(res.data(), _str, size());
|
||||
fennec::memcpy(res.data() + size(), cstr, cstr.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr _string operator+(const _string& str) const {
|
||||
if (_str == nullptr) {
|
||||
return _string(str);
|
||||
}
|
||||
if (str.data() == nullptr) {
|
||||
return _string(*this);
|
||||
}
|
||||
_string res;
|
||||
res._str.callocate(size() + str.size() + 1);
|
||||
fennec::memcpy(res.data(), _str, size());
|
||||
fennec::memcpy(res.data() + size(), str.data(), str.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr _string& operator+=(char c) {
|
||||
if (_str == nullptr) {
|
||||
_str.callocate(2);
|
||||
_str[0] = c;
|
||||
return *this;
|
||||
}
|
||||
_str.creallocate(capacity() + 1);
|
||||
_str[size() - 1] = c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _string& operator+=(const cstring& cstr) {
|
||||
if (_str == nullptr) {
|
||||
return *this = cstr;
|
||||
}
|
||||
size_t middle = size();
|
||||
_str.creallocate(middle + cstr.size() + 1);
|
||||
fennec::memcpy(_str + middle, cstr, cstr.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _string& operator+=(const _string& str) {
|
||||
if (_str == nullptr) {
|
||||
return *this = str;
|
||||
}
|
||||
if (str.data() == nullptr) {
|
||||
return *this;
|
||||
}
|
||||
size_t middle = size();
|
||||
_str.creallocate(middle + str.size() + 1);
|
||||
fennec::memcpy(_str + middle, str.data(), str.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Iteration ===========================================================================================================
|
||||
|
||||
constexpr char* begin() {
|
||||
return _str.data();
|
||||
}
|
||||
|
||||
constexpr const char* begin() const {
|
||||
return _str.data();
|
||||
}
|
||||
|
||||
constexpr char* end() {
|
||||
return _str.data() + _str.capacity();
|
||||
}
|
||||
|
||||
constexpr const char* end() const {
|
||||
return _str.data() + _str.capacity();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
alloc_t _str;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<string> : hash<byte_array> {
|
||||
constexpr size_t operator()(const string& str) const {
|
||||
return hash<byte_array>::operator()(byte_array(str.data(), str.size()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // FENNEC_LANGPROC_STRINGS_STRING_H
|
||||
354
include/fennec/lang/strings/wcstring.h
Normal file
354
include/fennec/lang/strings/wcstring.h
Normal file
@@ -0,0 +1,354 @@
|
||||
// =====================================================================================================================
|
||||
// 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_LANGPROC_STRINGS_wcstring_H
|
||||
#define FENNEC_LANGPROC_STRINGS_wcstring_H
|
||||
|
||||
#include <fennec/lang/strings/detail/_ctype.h>
|
||||
#include <fennec/memory/detail/_string.h>
|
||||
|
||||
#include <fennec/langcpp/assert.h>
|
||||
|
||||
#include <fennec/math/common.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// TODO: Document
|
||||
|
||||
using ::iswalnum;
|
||||
using ::iswalpha;
|
||||
using ::iswlower;
|
||||
using ::iswupper;
|
||||
using ::iswdigit;
|
||||
using ::iswxdigit;
|
||||
using ::iswcntrl;
|
||||
using ::iswgraph;
|
||||
using ::iswspace;
|
||||
using ::iswblank;
|
||||
using ::iswprint;
|
||||
using ::iswpunct;
|
||||
|
||||
using ::towlower;
|
||||
using ::towupper;
|
||||
|
||||
using ::towctrans;
|
||||
using ::wctrans;
|
||||
|
||||
///
|
||||
/// \brief This struct wraps c-style strings
|
||||
///
|
||||
/// \details Requires that the string is null-terminated.
|
||||
/// Prevents const qualified memory blocks from being manipulated.
|
||||
/// This struct should be used when fennec::string would make unnecessary dynamic buffers.
|
||||
struct wcstring
|
||||
{
|
||||
public:
|
||||
static constexpr size_t npos = -1;
|
||||
using char_t = wchar_t;
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes with nullptr
|
||||
constexpr wcstring()
|
||||
: _str(nullptr), _size(0), _const(true) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes with nullptr
|
||||
constexpr wcstring(nullptr_t)
|
||||
: _str(nullptr), _size(0), _const(true) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of characters in the buffer plus the null terminator
|
||||
constexpr wcstring(wchar_t* str, size_t n)
|
||||
: _str(str)
|
||||
, _size(n - 1)
|
||||
, _const(false) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of characters in the buffer plus the null terminator
|
||||
template<size_t n>
|
||||
constexpr wcstring(wchar_t (&str)[n])
|
||||
: _str(str)
|
||||
, _size(n - 1)
|
||||
, _const(false) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of characters in the buffer plus the null terminator
|
||||
constexpr wcstring(const wchar_t* str, size_t n)
|
||||
: _cstr(str)
|
||||
, _size(n - 1)
|
||||
, _const(true) {
|
||||
assert(_cstr[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of characters in the buffer plus the null terminator
|
||||
template<size_t n>
|
||||
constexpr wcstring(const wchar_t (&str)[n])
|
||||
: _cstr(str)
|
||||
, _size(n - 1)
|
||||
, _const(true) {
|
||||
assert(_cstr[n - 1] == '\0', "Invalid NTBS.");
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Constructor
|
||||
/// \param str object to move
|
||||
constexpr wcstring(wcstring&& str) noexcept
|
||||
: _cstr(str._cstr)
|
||||
, _size(str._size)
|
||||
, _const(str._const) {
|
||||
str._cstr = nullptr;
|
||||
str._size = 0;
|
||||
str._const = true;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
constexpr wcstring(const wcstring&) = delete;
|
||||
constexpr ~wcstring() = default;
|
||||
|
||||
constexpr wcstring& operator=(nullptr_t) {
|
||||
_str = nullptr, _size = 0, _const = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
template<size_t n>
|
||||
constexpr wcstring& operator=(wchar_t(&str)[n]) {
|
||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||
_str = str, _size = n - 1, _const = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
template<size_t n>
|
||||
constexpr wcstring& operator=(const wchar_t(&str)[n]) {
|
||||
assert(str[n - 1] == '\0', "Invalid NTBS.");
|
||||
_cstr = str; _size = n - 1; _const = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
constexpr wcstring& operator=(wcstring&& str) noexcept {
|
||||
_cstr = str._cstr; str._cstr = nullptr;
|
||||
_size = str._size; str._size = 0;
|
||||
_const = str._const; str._const = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
|
||||
constexpr size_t size() const { return _size; }
|
||||
|
||||
///
|
||||
/// \returns the size of the string including its null terminator, i.e. `(*str)[capacity() - 1] == '\0'`
|
||||
constexpr size_t capacity() const { return _size + 1; }
|
||||
|
||||
constexpr bool empty() const {
|
||||
return _cstr == nullptr || _size == 0;
|
||||
}
|
||||
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a reference to the character
|
||||
constexpr wchar_t& operator[](size_t i) {
|
||||
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||
assertd(i < size(), "Array Out of Bounds");
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const-Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a copy of the character
|
||||
constexpr const wchar_t& operator[](size_t i) const {
|
||||
assertd(i < size(), "Array Out of Bounds");
|
||||
return _cstr[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Data Access
|
||||
/// \returns A const qualified pointer to the underlying allocation
|
||||
constexpr wchar_t* data() {
|
||||
return _str;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Data Access
|
||||
/// \returns A const qualified pointer to the underlying allocation
|
||||
constexpr const wchar_t* data() const {
|
||||
return _cstr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Implicit Dereference Cast
|
||||
constexpr operator const wchar_t*() const {
|
||||
return _cstr;
|
||||
}
|
||||
|
||||
|
||||
// Examination =========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The length of the string to the first null-terminator
|
||||
constexpr size_t length() const {
|
||||
return find('\0');
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param str the string to compare against
|
||||
/// \param i the index to start at
|
||||
/// \param n the number of characters to compare
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const wcstring& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= _size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = min(n, max(_size, str._size) + 1);
|
||||
return ::wcsncmp(_cstr + i, str, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Equality
|
||||
/// \param str the string to compare against
|
||||
/// \returns True if all characters are equal, false otherwise
|
||||
template<size_t n>
|
||||
constexpr bool operator==(const wchar_t (&str)[n]) const {
|
||||
return compare(wcstring(str)) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Equality
|
||||
/// \param str the string to compare against
|
||||
/// \returns True if all characters are equal, false otherwise
|
||||
constexpr bool operator==(const wcstring& str) const {
|
||||
return compare(str) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||
/// \param c the character to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
||||
if (i >= _size) { // bounds check
|
||||
return _size;
|
||||
}
|
||||
|
||||
const wchar_t* loc = ::wcschr(_cstr + i, c); // get location using strchr
|
||||
return loc ? loc - _cstr : _size; // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const wcstring& str, size_t i = 0) const {
|
||||
if (i + str._size > _size) { // bounds check
|
||||
return _size;
|
||||
}
|
||||
|
||||
const wchar_t* loc = ::wcsstr(_cstr + i, str); // get location using strstr
|
||||
return loc ? loc - _cstr : _size; // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
||||
/// \param c the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||
if (_size == 0) {
|
||||
return _size;
|
||||
}
|
||||
|
||||
i = min(i, _size - 1); // clamp i to bounds
|
||||
do {
|
||||
if (_cstr[i] == c) return i; // loop backwards looking for c
|
||||
} while (i--);
|
||||
return _size; // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
|
||||
if (_size == 0) {
|
||||
return _size;
|
||||
}
|
||||
|
||||
const char first = str[0];
|
||||
i = min(i, _size - str._size);
|
||||
do {
|
||||
if(_cstr[i] == first) {
|
||||
if (compare(str, i, str._size - 1) == 0) {
|
||||
return i;
|
||||
}
|
||||
} // loop backwards looking for str
|
||||
} while (i--);
|
||||
return _size; // base case
|
||||
}
|
||||
|
||||
private:
|
||||
union { // hack to allow both const qualified and non-const strings
|
||||
wchar_t* _str;
|
||||
const wchar_t* _cstr;
|
||||
};
|
||||
size_t _size;
|
||||
bool _const;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<wcstring> : hash<byte_array> {
|
||||
constexpr size_t operator()(const wcstring& str) const {
|
||||
return hash<byte_array>::operator()(byte_array(str, str.size()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANGPROC_STRINGS_wcstring_H
|
||||
451
include/fennec/lang/strings/wstring.h
Normal file
451
include/fennec/lang/strings/wstring.h
Normal file
@@ -0,0 +1,451 @@
|
||||
// =====================================================================================================================
|
||||
// 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_LANGPROC_wstringS_WSTRING_H
|
||||
#define FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||
|
||||
#include <fennec/lang/strings/detail/_ctype.h>
|
||||
#include <fennec/lang/strings/wcstring.h>
|
||||
|
||||
#include <fennec/langcpp/assert.h>
|
||||
|
||||
#include <fennec/memory/allocator.h>
|
||||
#include <fennec/memory/common.h>
|
||||
|
||||
#include <fennec/math/common.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// Forward def
|
||||
template<typename AllocT = allocator<wchar_t>> struct _wstring;
|
||||
|
||||
// Alias for default allocator
|
||||
using wstring = _wstring<>;
|
||||
|
||||
///
|
||||
/// \brief Struct for wrapping c-style strings
|
||||
///
|
||||
/// \details behaviour guarantees that the underlying string is null-terminated
|
||||
template<typename AllocT>
|
||||
struct _wstring
|
||||
{
|
||||
public:
|
||||
static constexpr size_t npos = -1;
|
||||
using char_t = wchar_t;
|
||||
using alloc_t = allocation<wchar_t, AllocT>;
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes empty string
|
||||
constexpr _wstring()
|
||||
: _str() {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
||||
/// \param n the number of wchar_tacters
|
||||
/// \param c the wchar_tacter to fill with
|
||||
///
|
||||
/// \details adds additional wchar_tacter for null termination.
|
||||
constexpr _wstring(size_t n, wchar_t c = '\0')
|
||||
: _str(n + 1) {
|
||||
fennec::wmemset(_str, c, n);
|
||||
}
|
||||
|
||||
constexpr _wstring(const alloc_t& alloc)
|
||||
: _str(alloc) {
|
||||
}
|
||||
|
||||
constexpr _wstring(size_t n, wchar_t c, const alloc_t& alloc)
|
||||
: _str(n + 1, alloc) {
|
||||
fennec::wmemset(_str, c, n);
|
||||
}
|
||||
|
||||
constexpr _wstring(const wcstring& cstr)
|
||||
: _str(cstr, cstr.size() + 1) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of wchar_tacters in the buffer including the null-terminator, if present
|
||||
template<size_t n>
|
||||
explicit constexpr _wstring(const wchar_t (&str)[n])
|
||||
: _str(str[n - 1] != '\0' ? n + 1 : n) {
|
||||
fennec::wmemcpy(_str, str, n);
|
||||
if (str[n - 1] != '\0') {
|
||||
_str[n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of wchar_tacters in the buffer including the null-terminator, if present
|
||||
constexpr _wstring(const wchar_t* buf, size_t n)
|
||||
: _str(buf[n - 1] != '\0' ? n + 1 : n) {
|
||||
fennec::wmemcpy(_str, buf, n);
|
||||
if (buf[n - 1] != '\0') {
|
||||
_str[n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Copy Constructor
|
||||
/// \param str the string to copy
|
||||
constexpr _wstring(const _wstring& str) = default;
|
||||
|
||||
///
|
||||
/// \brief String Move Constructor
|
||||
/// \param str the string to take ownership of
|
||||
constexpr _wstring(_wstring&& str) noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief Destructor, cleans up underlying allocation
|
||||
constexpr ~_wstring() = default;
|
||||
|
||||
// Assignment ==========================================================================================================
|
||||
|
||||
constexpr _wstring& operator=(const wcstring& cstr) {
|
||||
_str.callocate(cstr.capacity());
|
||||
fennec::wmemcpy(_str, cstr, cstr.capacity());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _wstring& operator=(const _wstring& str) = default;
|
||||
constexpr _wstring& operator=(_wstring&& str) noexcept = default;
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The size of the string excluding null terminator
|
||||
constexpr size_t size() const {
|
||||
return _str.capacity() > 0 ? _str.capacity() - 1 : 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The size of the string including null terminator
|
||||
constexpr size_t capacity() const {
|
||||
return _str.capacity();
|
||||
}
|
||||
|
||||
constexpr bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a reference to the wchar_tacter
|
||||
constexpr wchar_t& operator[](size_t i) {
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const-Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a copy of the wchar_tacter
|
||||
constexpr const wchar_t& operator[](size_t i) const {
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
constexpr wchar_t* data() {
|
||||
return _str;
|
||||
}
|
||||
|
||||
constexpr const wchar_t* data() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
constexpr const wchar_t* cstr() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
// Examination =========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The length of the string to the first null-terminator
|
||||
constexpr size_t length() const {
|
||||
return find('\0');
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param ostr the string to compare against
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const wcstring& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return -1;
|
||||
}
|
||||
n = fennec::min(n, fennec::max(_str, str.size()) + 1);
|
||||
|
||||
return ::wcsncmp(_str + i, str, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param ostr the string to compare against
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const _wstring& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return -1;
|
||||
}
|
||||
n = min(n, max(size(), str.size()) + 1);
|
||||
|
||||
return ::wcsncmp(_str + i, str.data(), n);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const wcstring& str) const {
|
||||
return compare(str) == 0;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const _wstring& str) const {
|
||||
return compare(str) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Check if the string contains a character
|
||||
/// \param c
|
||||
/// \param i
|
||||
/// \return
|
||||
constexpr bool contains(char c, size_t i = 0) const {
|
||||
return find(c, i) != size();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||
/// \param c the wchar_tacter to find
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const wchar_t* loc = ::wcschr(_str + i, c); // get location using strchr
|
||||
return loc ? loc - _str : size(); // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const _wstring& str, size_t i = 0) const { // bounds check
|
||||
if (i >= size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const wchar_t* loc = ::wcsstr(_str, str);
|
||||
return loc ? loc - _str : size();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const wcstring& str, size_t i = 0) const {
|
||||
if (i + str.size() > size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const wchar_t* loc = ::wcsstr(_str + i, str); // get location using strstr
|
||||
return loc ? loc - _str : size(); // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
||||
/// \param c the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(wchar_t c, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
i = min(i, size() - 1); // clamp i to bounds
|
||||
do {
|
||||
if (_str[i] == c) { // loop backwards looking for c
|
||||
return i;
|
||||
}
|
||||
} while (i--);
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
const wchar_t first = str[0];
|
||||
i = min(i, size() - str.size());
|
||||
do {
|
||||
if(_str[i] == first) {
|
||||
if (compare(str, i) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} while (i--);
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
const wchar_t first = str[0];
|
||||
i = min(i, size() - str.size());
|
||||
do {
|
||||
if(_str[i] == first) {
|
||||
if (compare(str, i) == 0) { // loop backwards looking for str
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} while (i--);
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Retrieve a substring of a string
|
||||
/// \param i the start index
|
||||
/// \param n the number of wchar_tacters
|
||||
/// \return
|
||||
constexpr _wstring substring(size_t i, size_t n = npos) const {
|
||||
if (i >= size()) {
|
||||
return _wstring("");
|
||||
}
|
||||
n = fennec::min(n, size() - i);
|
||||
_wstring res;
|
||||
res._str.callocate(n + 1);
|
||||
fennec::wmemcpy(res.data(), _str + i, n);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Modifiers ===========================================================================================================
|
||||
|
||||
constexpr void resize(size_t n) {
|
||||
_str.creallocate(n + 1);
|
||||
_str[size()] = '\0';
|
||||
}
|
||||
|
||||
constexpr _wstring operator+(wchar_t c) const {
|
||||
if (_str == nullptr) {
|
||||
return _wstring(1, c);
|
||||
}
|
||||
_wstring res;
|
||||
res._str.callocate(capacity() + 1);
|
||||
fennec::wmemcpy(res.data(), _str, size());
|
||||
res[size()] = c;
|
||||
return res;
|
||||
}
|
||||
|
||||
friend constexpr _wstring operator+(wchar_t c, const _wstring& str) {
|
||||
_wstring res(1, c);
|
||||
return res += str;
|
||||
}
|
||||
|
||||
constexpr _wstring operator+(const wcstring& cstr) const {
|
||||
if (_str == nullptr) {
|
||||
return _wstring(cstr);
|
||||
}
|
||||
_wstring res;
|
||||
res._str.callocate(size() + cstr.size() + 1);
|
||||
fennec::wmemcpy(res.data(), _str, size());
|
||||
fennec::wmemcpy(res.data() + size(), cstr, cstr.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr _wstring operator+(const _wstring& str) const {
|
||||
if (_str == nullptr) {
|
||||
return _wstring(str);
|
||||
}
|
||||
if (str.data() == nullptr) {
|
||||
return _wstring(*this);
|
||||
}
|
||||
_wstring res;
|
||||
res._str.callocate(size() + str.size() + 1);
|
||||
fennec::wmemcpy(res.data(), _str, size());
|
||||
fennec::wmemcpy(res.data() + size(), str.data(), str.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr _wstring& operator+=(wchar_t c) {
|
||||
if (_str == nullptr) {
|
||||
_str.callocate(2);
|
||||
_str[0] = c;
|
||||
return *this;
|
||||
}
|
||||
_str.creallocate(capacity() + 1);
|
||||
_str[size() - 1] = c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _wstring& operator+=(const wcstring& cstr) {
|
||||
if (_str == nullptr) {
|
||||
return *this = cstr;
|
||||
}
|
||||
size_t middle = size();
|
||||
_str.creallocate(middle + cstr.size() + 1);
|
||||
fennec::wmemcpy(_str + middle, cstr, cstr.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _wstring& operator+=(const _wstring& str) {
|
||||
if (_str == nullptr) {
|
||||
return *this = str;
|
||||
}
|
||||
if (str.data() == nullptr) {
|
||||
return *this;
|
||||
}
|
||||
size_t middle = size();
|
||||
_str.creallocate(middle + str.size() + 1);
|
||||
fennec::wmemcpy(_str + middle, str.data(), str.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
alloc_t _str;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<wstring> : hash<byte_array> {
|
||||
constexpr size_t operator()(const string& str) const {
|
||||
return hash<byte_array>::operator()(byte_array(str.data(), str.size()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||
@@ -1,57 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_TYPE_IDENTITY_H
|
||||
#define FENNEC_LANG_TYPE_IDENTITY_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_type_identity Type Identity
|
||||
///
|
||||
/// \brief Part of the fennec metaprogramming library. This header defines structures for copying types with different traits
|
||||
/// or rather, transform them, at compile time.
|
||||
///
|
||||
/// \code #include <fennec/lang/type_identity.h> \endcode
|
||||
///
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_identity">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::type_identity "type_identity<TypeT>::type"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::type_identity
|
||||
/// </table>
|
||||
///
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Base Class for Type Transformations
|
||||
///
|
||||
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct type_identity {
|
||||
|
||||
/// \brief the type to transform into
|
||||
using type = T;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPE_IDENTITY_H
|
||||
@@ -1,112 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_TYPE_OPERATORS_H
|
||||
#define FENNEC_LANG_TYPE_OPERATORS_H
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// https://stackoverflow.com/questions/6534041/how-to-check-whether-operator-exists
|
||||
|
||||
// has_equals ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_equals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() == declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_equals_v = has_equals<T0, T1>::value;
|
||||
|
||||
// has_nequals =========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_nequals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() != declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_nequals_v = has_nequals<T0, T1>::value;
|
||||
|
||||
|
||||
// has_less ============================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_less {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() < declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_less_v = has_less<T0, T1>::value;
|
||||
|
||||
|
||||
// has_less_equals =====================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_less_equals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() <= declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_less_equals_v = has_less_equals<T0, T1>::value;
|
||||
|
||||
|
||||
// has_greater =========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_greater {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() > declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_greater_v = has_greater<T0, T1>::value;
|
||||
|
||||
|
||||
// has_greater_equals ==================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_greater_equals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() >= declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_greater_equals_v = has_greater_equals<T0, T1>::value;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPE_OPERATORS_H
|
||||
@@ -1,90 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file type_sequences.h
|
||||
/// \brief \ref fennec_lang_type_sequences
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_TYPE_SEQUENCES_H
|
||||
#define FENNEC_LANG_TYPE_SEQUENCES_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_type_sequences Type Sequences
|
||||
///
|
||||
/// \brief This header is part of the metaprogramming library. It defines structures for sequences of types, used during compile time.
|
||||
///
|
||||
/// \code #include <fennec/lang/type_sequences.h> \endcode
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_sequences">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::first_element "typename first_element<ValueT, Values...>::type"<br>
|
||||
/// \ref fennec::first_element_t "first_element_t<ValueT, Values...>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydoc fennec::first_element
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydoc fennec::replace_first_element
|
||||
/// </table>
|
||||
///
|
||||
|
||||
#include <fennec/lang/detail/_type_sequences.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Get the first element of a template parameter pack
|
||||
/// \tparam TypesT the Parameter Pack
|
||||
template<typename...TypesT> struct first_element : detail::_first_element<TypesT...> {};
|
||||
|
||||
///
|
||||
/// \brief alias for first_element<TypesT>::type
|
||||
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
|
||||
|
||||
|
||||
template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
||||
template<typename ClassT, typename SubT> struct replace_first_element { };
|
||||
|
||||
// Implementation
|
||||
template<
|
||||
template<typename, typename...> class ClassT // The Base Template
|
||||
, typename SubT, typename OriginT // The Original Type and Type to Substitute
|
||||
, typename... RestT> // The Rest of the Parameter Pack
|
||||
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
|
||||
{ using type = ClassT<SubT, RestT...>; }; // Definition
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // FENNEC_LANG_VARIADICS_H
|
||||
@@ -1,495 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file type_traits.h
|
||||
/// \brief \ref fennec_lang_type_traits
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_TYPE_TRAITS_H
|
||||
#define FENNEC_LANG_TYPE_TRAITS_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_type_traits Type Traits
|
||||
///
|
||||
/// \brief Part of the fennec metaprogramming library. This header defines structures for accessing traits of types
|
||||
/// at compile time.
|
||||
///
|
||||
/// \code #include <fennec/lang/type_traits.h> \endcode
|
||||
///
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_void "is_void<TypeT>::value"<br>
|
||||
/// \ref fennec::is_void_v "is_void_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_void
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_bool "is_bool<TypeT>::value"<br>
|
||||
/// \ref fennec::is_bool_v "is_bool_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_bool
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_integral "is_integral<TypeT>::value"<br>
|
||||
/// \ref fennec::is_integral_v "is_integral_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_integral
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_signed "is_signed<TypeT>::value"<br>
|
||||
/// \ref fennec::is_signed_v "is_signed_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_signed
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_unsigned "is_unsigned<TypeT>::value"<br>
|
||||
/// \ref fennec::is_unsigned_v "is_unsigned_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_unsigned
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_floating_point "is_floating_point<TypeT>::value"<br>
|
||||
/// \ref fennec::is_floating_point_v "is_floating_point_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_floating_point
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_arithmetic "is_arithmetic<TypeT>::value"<br>
|
||||
/// \ref fennec::is_arithmetic_v "is_arithmetic_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_arithmetic
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_same "is_same<TypeT>::value"<br>
|
||||
/// \ref fennec::is_same_v "is_same_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_same
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_convertible "is_convertible<TypeT0, TypeT1>::value"<br>
|
||||
/// \ref fennec::is_convertible_v "is_convertible_v<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::is_convertible
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::is_constructible "is_constructible<ClassT, ArgsT...>::value"<br>
|
||||
/// \ref fennec::is_constructible_v "is_constructible_v<ClassT, ArgsT...>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydoc fennec::is_constructible
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
|
||||
#include <fennec/lang/intrinsics.h>
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
#include <fennec/lang/detail/_type_traits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// fennec::declval =====================================================================================================
|
||||
|
||||
template<typename T> auto declval() noexcept -> decltype(detail::_declval<T>(0)) {
|
||||
static_assert(detail::_declval_protector<T>{}, "declval must not be used");
|
||||
return detail::_declval<T>(0);
|
||||
}
|
||||
|
||||
constexpr inline bool is_constant_evaluated() noexcept {
|
||||
if consteval {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fennec::is_void =====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of type void
|
||||
///
|
||||
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_void
|
||||
: detail::_is_void<remove_cvr_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_void<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
||||
|
||||
|
||||
|
||||
// fennec::is_bool =====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of type bool
|
||||
///
|
||||
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_bool
|
||||
: detail::_is_bool<remove_cvr_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_bool<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
||||
|
||||
|
||||
|
||||
// fennec::is_null_pointer =============================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of type nullptr_t
|
||||
///
|
||||
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_null_pointer
|
||||
: detail::_is_null_pointer<remove_cvr_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_null_pointer<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
|
||||
|
||||
|
||||
|
||||
// fennec::is_array ====================================================================================================
|
||||
|
||||
#ifdef FENNEC_BUILTIN_IS_ARRAY
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of an array type
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_array
|
||||
: bool_constant<FENNEC_BUILTIN_IS_ARRAY(T)> {};
|
||||
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of an array type
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_array
|
||||
: false_type {};
|
||||
|
||||
// overload for a sized array type
|
||||
template<typename T, size_t N> struct is_array<T[N]>
|
||||
: true_type {};
|
||||
|
||||
// overload for a generic array type
|
||||
template<typename T> struct is_array<T[]>
|
||||
: true_type {};
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_array<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
|
||||
|
||||
// fennec::is_class ====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is a class
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_class
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CLASS(T)> {};
|
||||
|
||||
///
|
||||
/// \brief check if \p T is a class
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
||||
|
||||
|
||||
|
||||
// Integral Types ======================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of an integral
|
||||
///
|
||||
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_integral
|
||||
: detail::_is_integral<remove_cvr_t<T>> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_integral<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
||||
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of a signed integral
|
||||
///
|
||||
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_signed
|
||||
: detail::_is_signed<remove_cvr_t<T>> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_signed<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
||||
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of an unsigned integral
|
||||
///
|
||||
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_unsigned
|
||||
: detail::_is_unsigned<remove_cvr_t<T>> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_unsigned<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
||||
|
||||
|
||||
|
||||
// Floating Point Types ================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of a floating point type
|
||||
///
|
||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_floating_point
|
||||
: detail::_is_floating_point<remove_cvr_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_floating_point<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
|
||||
|
||||
|
||||
// Pointer Types =======================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is of a floating point type
|
||||
///
|
||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_pointer
|
||||
: detail::_is_pointer<remove_cvr_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_floating_point<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
||||
|
||||
|
||||
|
||||
// Arithmetic Types ====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is an arithmetic type
|
||||
///
|
||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_arithmetic
|
||||
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_arithmetic<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
||||
|
||||
|
||||
// fennec::is_fundamental ==============================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_fundamental
|
||||
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_fundamental<T>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
||||
|
||||
|
||||
// fennec::is_same =====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if the two types are identical
|
||||
///
|
||||
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
|
||||
/// \tparam T0 first type to check
|
||||
/// \tparam T1 second type to check
|
||||
template<typename T0, typename T1> struct is_same : false_type {};
|
||||
|
||||
// true case
|
||||
template<typename T> struct is_same<T, T> : true_type {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_same<T0, T1>::value```
|
||||
/// \tparam T type to check
|
||||
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
||||
|
||||
// fennec::is_convertible ==============================================================================================
|
||||
|
||||
///
|
||||
/// \brief check if type `T0` can be converted `T1`
|
||||
///
|
||||
/// \details Checks if `TypeT0`
|
||||
/// \tparam FromT First type
|
||||
/// \tparam ToT Second type
|
||||
template<typename FromT, typename ToT> struct is_convertible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONVERTIBLE(FromT, ToT)> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `can_convert<TypeT0, TypeT1>::value`
|
||||
/// \param FromT First type
|
||||
/// \param ToT Second type
|
||||
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
|
||||
|
||||
|
||||
// fennec::is_constructible ============================================================================================
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
|
||||
/// This may be read as "is `ClassT` constructible with `ArgsT`"
|
||||
/// \tparam ClassT The class type to test
|
||||
/// \tparam ArgsT The arguments for the specific constructor
|
||||
template<typename ClassT, typename...ArgsT> struct is_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, ArgsT...)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
|
||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is default constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_default_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT,)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
|
||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is copy constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_copy_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
|
||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructible_v = is_copy_constructible<ClassT>{};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is copy constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_move_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
|
||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is trivially constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_trivially_constructible<ClassT, ArgsT...>::value`
|
||||
template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_trivially_constructible<ClassT>{};
|
||||
|
||||
|
||||
// fennec::is_trivially_destructible ===================================================================================
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is trivially destructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_destructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
|
||||
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
|
||||
|
||||
|
||||
// fennec::is_assignable ===============================================================================================
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
|
||||
/// This may be read as "is `ClassT` constructible with `ArgsT`"
|
||||
/// \tparam ClassAT The class type to test
|
||||
/// \tparam ClassBT The arguments for the specific constructor
|
||||
template<typename ClassAT, typename ClassBT> struct is_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(ClassAT, ClassBT)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
|
||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_assignable_v = is_assignable<ClassT, ArgsT...>{};
|
||||
|
||||
|
||||
// fennec::is_copy_assignable ==========================================================================================
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is copy assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_copy_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_copy_assignable<ClassT>::value`
|
||||
template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assignable<ClassT>{};
|
||||
|
||||
|
||||
// fennec::is_move_assignable ==========================================================================================
|
||||
|
||||
///
|
||||
/// \brief Check if `ClassT` is move assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_move_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_move_assignable<ClassT>::value`
|
||||
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
|
||||
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPE_TRAITS_H
|
||||
@@ -1,352 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General 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 License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file type_transforms.h
|
||||
/// \brief \ref fennec_lang_type_transforms
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_TYPE_TRANSFORMS_H
|
||||
#define FENNEC_LANG_TYPE_TRANSFORMS_H
|
||||
|
||||
#include <fennec/lang/type_identity.h>
|
||||
#include <fennec/lang/detail/_type_transforms.h>
|
||||
|
||||
///
|
||||
/// \page fennec_lang_type_transforms Type Transforms
|
||||
///
|
||||
/// \brief Part of the fennec metaprogramming library. This header defines structures for copying types with different traits
|
||||
/// or rather, transform them, at compile time.
|
||||
///
|
||||
/// \code #include <fennec/lang/type_transforms.h> \endcode
|
||||
///
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_transforms">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::add_pointer "add_pointer<TypeT>::type"<br>
|
||||
/// \ref fennec::add_pointer_t "add_pointer_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::add_pointer
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::remove_pointer "remove_pointer<TypeT>::type"<br>
|
||||
/// \ref fennec::remove_pointer_t "remove_pointer_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::remove_pointer
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::add_reference "add_reference<TypeT>::type"<br>
|
||||
/// \ref fennec::add_reference_t "add_reference_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::add_reference
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::remove_reference "remove_reference<TypeT>::type"<br>
|
||||
/// \ref fennec::remove_reference_t "remove_reference_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::remove_reference
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::add_const "add_const<TypeT>::type"<br>
|
||||
/// \ref fennec::add_const_t "add_const_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::add_const
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::remove_const "remove_const<TypeT>::type"<br>
|
||||
/// \ref fennec::remove_const_t "remove_const_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::remove_const
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::add_volatile "add_volatile<TypeT>::type"<br>
|
||||
/// \ref fennec::add_volatile_t "add_volatile_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::add_volatile
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::remove_volatile "remove_volatile<TypeT>::type"<br>
|
||||
/// \ref fennec::remove_volatile_t "remove_volatile_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::remove_volatile
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::add_cv "add_cv<TypeT>::type"<br>
|
||||
/// \ref fennec::add_cv_t "add_cv_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::add_cv
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::remove_cv "remove_cv<TypeT>::type"<br>
|
||||
/// \ref fennec::remove_cv_t "remove_cv_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::remove_cv
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::add_cvr "add_cvr<TypeT>::type"<br>
|
||||
/// \ref fennec::add_cvr_t "add_cvr_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::add_cvr
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::remove_cvr "remove_cvr<TypeT>::type"<br>
|
||||
/// \ref fennec::remove_cvr_t "remove_cvr_t<TypeT>"
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::remove_cvr
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// Pointer Conversions =================================================================================================
|
||||
|
||||
///
|
||||
/// \brief adds a pointer level to \p T
|
||||
///
|
||||
/// \details adds a pointer to the provided type such that `T` becomes `T*`
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct add_pointer : type_identity<T*>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename add_pointer<T>::type`
|
||||
template<typename T> using add_pointer_t = typename add_pointer<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief removes a pointer level from \p T
|
||||
///
|
||||
/// \details removes a pointer from the provided type such that `T*` becomes `T`
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct remove_pointer : type_identity<T> {};
|
||||
|
||||
// specialization for T*
|
||||
template<typename T> struct remove_pointer<T*> : type_identity<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_pointer<T>::type`
|
||||
template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
|
||||
|
||||
|
||||
// Reference Conversions ===============================================================================================
|
||||
|
||||
///
|
||||
/// \brief add a reference to \p T
|
||||
///
|
||||
/// \details adds a pointer to the provided type such that `T` becomes `T&`
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct add_reference : type_identity<T&> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename add_reference<T>::type`
|
||||
template<typename T> using add_reference_t = typename add_reference<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove a reference from \p T
|
||||
///
|
||||
/// \details removes references from the provided type such that `T&` and `T&&` become `T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_reference : type_identity<T> {};
|
||||
|
||||
// specialization for `T&`
|
||||
template<typename T> struct remove_reference<T&> : type_identity<T> {};
|
||||
|
||||
// specialization for `T&&`
|
||||
template<typename T> struct remove_reference<T&&> : type_identity<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_reference<T>::type`
|
||||
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief add a lvalue reference to \p T
|
||||
///
|
||||
/// \details adds a lvalue reference to the provided type such that 'T' becomes 'T&'
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_lvalue_reference : detail::_add_lvalue_reference<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_reference<T>::type`
|
||||
template<typename T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief add a rvalue reference to \p T
|
||||
///
|
||||
/// \details adds a rvalue reference to the provided type such that 'T' becomes 'T&&'
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_rvalue_reference : detail::_add_rvalue_reference<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_reference<T>::type`
|
||||
template<typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
|
||||
|
||||
|
||||
|
||||
// Const & Volatile Conversions ========================================================================================
|
||||
|
||||
///
|
||||
/// \brief add the const qualifier to the provided type \p T
|
||||
///
|
||||
/// \details adds const qualification to the provided type such that `T` becomes `const T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_const : type_identity<const T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename add_const<T>::type`
|
||||
template<typename T> using add_const_t = typename add_const<T>::type;
|
||||
|
||||
// specialization for const types
|
||||
template<typename T> struct add_const<const T> : type_identity<const T> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the const qualifier from the provided type \p T
|
||||
///
|
||||
/// \details removes const qualification from the provided type such that `const T` becomes `T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_const : type_identity<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_const<T>::type`
|
||||
template<typename T> using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
// specialization for const types
|
||||
template<typename T> struct remove_const<const T> : type_identity<T> {};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief add the volatile qualifier to the provided type \p T
|
||||
///
|
||||
/// \details removes references from the provided type such that `T` becomes `volatile T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_volatile : type_identity<volatile T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename add_volatile<T>::type`
|
||||
template<typename T> using add_volatile_t = typename add_volatile<T>::type;
|
||||
|
||||
// specialization for volatile types
|
||||
template<typename T> struct add_volatile<volatile T> : type_identity<volatile T> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the volatile qualifier from the provided type \p T
|
||||
///
|
||||
/// \details removes references from the provided type such that `volatile T` becomes `T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_volatile : type_identity<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_volatile<T>::type`
|
||||
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
|
||||
|
||||
// specialization for volatile types
|
||||
template<typename T> struct remove_volatile<volatile T> : type_identity<T> {};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the volatile qualifier from the provided type \p T
|
||||
///
|
||||
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
|
||||
/// `const volatile T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_cv : type_identity<const volatile T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename add_cv<T>::type`
|
||||
template<typename T> using add_cv_t = typename add_cv<T>::type;
|
||||
|
||||
// specialization for const types
|
||||
template<typename T> struct add_cv<const T> : type_identity<const volatile T> {};
|
||||
|
||||
// specialization for volatile types
|
||||
template<typename T> struct add_cv<volatile T> : type_identity<const volatile T> {};
|
||||
|
||||
// specialization for const volatile types
|
||||
template<typename T> struct add_cv<const volatile T> : type_identity<const volatile T> {};
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the const and volatile qualifiers from the provided type \p T
|
||||
///
|
||||
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
|
||||
/// `const volatile T` become `T`
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_cv : type_identity<T> {};
|
||||
|
||||
// specialization for const types
|
||||
template<typename T> struct remove_cv<const T> : type_identity<T> {};
|
||||
|
||||
// specialization for volatile types
|
||||
template<typename T> struct remove_cv<volatile T> : type_identity<T> {};
|
||||
|
||||
// specialization for const volatile types
|
||||
template<typename T> struct remove_cv<const volatile T> : type_identity<T> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_cv<T>::type`
|
||||
template<typename T> using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief add a reference and the const volatile qualifiers from the provided type \p T
|
||||
///
|
||||
/// \details adds references and const volatile qualifiers to the provided type.
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_cvr : type_identity<add_reference_t<add_cv_t<T>>> {};
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename add_cvr<T>::type`
|
||||
template<typename T> using add_cvr_t = typename add_cvr<T>::type;
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief removes references as well as the const and volatile qualifiers from the provided type \p T
|
||||
///
|
||||
/// \details removes const and volatile from the provided type such that
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_cvr : type_identity<remove_cv_t<remove_reference_t<T>>> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief shorthand for `typename remove_cvr<T>::type`
|
||||
template<typename T> using remove_cvr_t = typename remove_cvr<T>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPE_TRANSFORMS_H
|
||||
@@ -1,66 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANG_TYPEUUID_H
|
||||
#define FENNEC_LANG_TYPEUUID_H
|
||||
|
||||
#include <fennec/lang/assert.h>
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
#include <fennec/lang/detail/_typeuuid.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
constexpr uint64_t nullid = 0;
|
||||
|
||||
template<typename TypeT, typename RootT = void>
|
||||
FENNEC_NO_INLINE uint64_t typeuuid() {
|
||||
static bool init = false;
|
||||
static uint64_t id = nullid;
|
||||
|
||||
if (init) return id;
|
||||
init = true;
|
||||
return id = detail::_typeuuid<RootT>();
|
||||
}
|
||||
|
||||
template<typename RootT = void>
|
||||
struct typed {
|
||||
public:
|
||||
const uint64_t type;
|
||||
|
||||
template<typename TypeT>
|
||||
bool is_type() const {
|
||||
return type == typeuuid<TypeT, RootT>();
|
||||
}
|
||||
|
||||
template<typename TypeT>
|
||||
typed(TypeT*)
|
||||
: type(typeuuid<TypeT, RootT>()) {
|
||||
}
|
||||
|
||||
template<typename TypeT>
|
||||
static uint64_t id() {
|
||||
return typeuuid<TypeT, RootT>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPEUUID_H
|
||||
@@ -1,293 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file types.h
|
||||
/// \brief \ref fennec_lang_types
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_TYPES_H
|
||||
#define FENNEC_LANG_TYPES_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_types Types
|
||||
///
|
||||
/// \code #include <fennec/lang/types.h> \endcode
|
||||
///
|
||||
/// \brief This header contains definitions for the built-in types of the C++ language.
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_types">
|
||||
/// <tr><th style="vertical-align: top">Type
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><th colspan=2 style="text-align: center;">Basic Types
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::bool_t "bool_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::bool_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::char_t "char_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::char_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::schar_t "schar_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::schar_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uchar_t "uchar_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uchar_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::short_t "short_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::short_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::ushort_t "ushort_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::ushort_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::int_t "int_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::int_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uint_t "uint_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uint_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::long_t "long_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::long_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::ulong_t "ulong_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::ulong_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::llong_t "llong_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::llong_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::ullong_t "ullong_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::ullong_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::float_t "float_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::float_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::double_t "double_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::double_t
|
||||
///
|
||||
/// <tr><th colspan=2 style="text-align: center;">Sized Arithmetic Types
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::int8_t "int8_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::int8_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::int16_t "int16_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::int16_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::int32_t "int32_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::int32_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::int64_t "int64_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::int64_t
|
||||
///
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uint8_t "uint8_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uint8_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uint16_t "uint16_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uint16_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uint32_t "uint32_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uint32_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uint64_t "uint64_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::int64_t
|
||||
///
|
||||
///
|
||||
/// <tr><th colspan=2 style="text-align: center;">Special Types
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::nullptr_t "nullptr_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::nullptr_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::intptr_t "intptr_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::intptr_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uintptr_t "uintptr_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uintptr_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::intmax_t "intmax_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::intmax_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::uintmax_t "uintmax_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::uintmax_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::size_t "size_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::size_t
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// <tt>\ref fennec::ptrdiff_t "ptrdiff_t"</tt>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copybrief fennec::ptrdiff_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
|
||||
///
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
|
||||
#include <fennec/lang/detail/_int.h>
|
||||
|
||||
#include <fennec/lang/conditional_types.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
// Basic Types =========================================================================================================
|
||||
|
||||
///
|
||||
/// \name Basic Types
|
||||
/// @{
|
||||
|
||||
using bool_t = bool; ///< \brief A conditional type
|
||||
|
||||
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 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 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
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \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 `sizeof`, `sizeof...`, and `alignof`
|
||||
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
|
||||
struct empty_t {};
|
||||
|
||||
|
||||
class undefined_t; ///< \brief undefined class for SFINAE
|
||||
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Sized Arithmetic Types ==============================================================================================
|
||||
|
||||
///
|
||||
/// \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 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
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \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
|
||||
|
||||
/// @}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPES_H
|
||||
@@ -1,133 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file utility.h
|
||||
/// \brief \ref fennec_lang_utility
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_LANG_UTILITY_H
|
||||
#define FENNEC_LANG_UTILITY_H
|
||||
|
||||
///
|
||||
/// \page fennec_lang_utility Utility
|
||||
///
|
||||
/// \brief This header contains common utility functions related to the C++ language.
|
||||
///
|
||||
/// \code #include <fennec/lang/utility.h> \endcode
|
||||
///
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_utility">
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::forward "T&& forward(x)"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::forward
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::move "T&& move(x)"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::move
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \ref fennec::copy "const T& copy(x)"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \copydetails fennec::copy
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief forwards reference types to extend their lifetime
|
||||
///
|
||||
/// \details forwards reference types to extend their lifetime
|
||||
/// \tparam T base type of the object
|
||||
/// \param x reference to the object
|
||||
/// \returns
|
||||
template<typename T> constexpr T&& forward(remove_reference_t<T>& x) noexcept {
|
||||
return static_cast<T&&>(x);
|
||||
}
|
||||
|
||||
// specialization for T&&
|
||||
template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept {
|
||||
return static_cast<T&&>(x);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// \brief produces an x-value type to indicate \p x may be "moved"
|
||||
///
|
||||
/// \details produces an x-value type to indicate \p x may be "moved"
|
||||
/// \tparam T base type of the object
|
||||
/// \param x object to be moved
|
||||
/// \returns `static_cast<remove_reference_t<T>&&>(x)`
|
||||
template<typename T> constexpr remove_reference_t<T>&& move(T&& x) noexcept {
|
||||
return static_cast<remove_reference_t<T>&&>(x);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// \brief produces an r-value type to indicate \p x may be "copied"
|
||||
///
|
||||
/// \details produces an r-value type to indicate \p x may be "copied"
|
||||
/// \tparam T base type of the object
|
||||
/// \param x object to be copied
|
||||
/// \returns const r-value
|
||||
template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept {
|
||||
return x;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Swaps x and y
|
||||
/// \tparam T the fundamental type
|
||||
/// \param x first value
|
||||
/// \param y second value
|
||||
template<typename T> requires is_fundamental_v<T>
|
||||
constexpr void swap(T& x, T& y) noexcept {
|
||||
T a = x;
|
||||
x = y;
|
||||
y = a;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Swaps x and y without invoking destructor
|
||||
/// \tparam T the type
|
||||
/// \param x first value
|
||||
/// \param y second value
|
||||
template<typename T> constexpr void swap(T& x, T& y) noexcept {
|
||||
T a = fennec::move(x);
|
||||
x = fennec::move(y);
|
||||
y = fennec::move(a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_UTILITY_H
|
||||
Reference in New Issue
Block a user