- Basic RTTI type data with inheritance.

This commit is contained in:
2025-11-28 12:58:23 -05:00
parent b9026ec8da
commit fe8c3a4602
126 changed files with 2158 additions and 979 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,210 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file 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

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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