Added fennec::allocation and all necessary dependencies

This commit is contained in:
Medusa Slockbower 2025-05-30 21:10:52 -04:00
parent 1a27e37f66
commit 67c8ad9a0d
24 changed files with 847 additions and 74 deletions

View File

@ -4,6 +4,7 @@ project(fennec)
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_C_STANDARD 26)
# any necessary include directories
include_directories(include)
add_library(fennec STATIC
@ -22,12 +23,15 @@ add_library(fennec STATIC
include/fennec/lang/conditional_types.h
include/fennec/lang/intrinsics.h
include/fennec/lang/limits.h
include/fennec/lang/numeric_transforms.h
include/fennec/lang/sequences.h
include/fennec/lang/type_traits.h
include/fennec/lang/type_transforms.h
include/fennec/lang/types.h
include/fennec/lang/utility.h
include/fennec/lang/variadics.h
include/fennec/lang/detail/__numeric_transforms.h
include/fennec/lang/detail/__type_traits.h
@ -35,9 +39,11 @@ add_library(fennec STATIC
include/fennec/memory/allocator.h
include/fennec/memory/bits.h
include/fennec/memory/memory.h
include/fennec/memory/new.h
include/fennec/memory/new.h source/memory/new.cpp
include/fennec/memory/pointers.h
include/fennec/memory/ptr_traits.h
source/memory/new.cpp
include/fennec/memory/detail/__ptr_traits.h
# MATH =================================================================================================================
@ -65,21 +71,30 @@ add_library(fennec STATIC
include/fennec/math/detail/__types.h
include/fennec/math/detail/__vector_traits.h
include/fennec/lang/detail/__variadics.h
)
add_subdirectory(metaprogramming)
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled
add_dependencies(fennec fennecdocs metaprogramming)
# Compiler Warning Flags
if(MSVC)
add_compile_options("/W4" "/WX")
add_compile_options("/W4" "/WX") # All MSVC Warnings throw as Errors
else()
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror")
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror") # All gcc/etc. Warnings throw as errors
endif()
target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f")
target_link_options(fennec PRIVATE "-nostdlib" "-nocstdlib")
#target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f") # SIMD Instructions, currently unused
target_link_options(fennec PRIVATE "-nostdlib") # Do not compile base fennec library with c++ stdlib
# fennec does not use the C++ stdlib because it is bloated, difficult to read, and implementation defined.
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
# add the test suite as a sub-project
add_subdirectory(test)
@ -90,20 +105,21 @@ add_subdirectory(test)
find_package(Doxygen)
if(DOXYGEN_FOUND)
get_filename_component(DOXYGEN_PROJECT_NAME ${PROJECT_SOURCE_DIR} NAME)
set(DOXYGEN_CONFIG_IN "${PROJECT_SOURCE_DIR}/doxy/Doxyfile.in")
set(DOXYGEN_CONFIG_OUT "${PROJECT_SOURCE_DIR}/doxy/Doxyfile")
get_filename_component(DOXYGEN_PROJECT_NAME ${PROJECT_SOURCE_DIR} NAME) # Set Doxy Project name to the name of the root dir
set(DOXYGEN_CONFIG_IN "${PROJECT_SOURCE_DIR}/doxy/Doxyfile.in") # Input config file with preprocessor arguments
set(DOXYGEN_CONFIG_OUT "${PROJECT_SOURCE_DIR}/doxy/Doxyfile") # Generated config file from input
configure_file(${DOXYGEN_CONFIG_IN} ${DOXYGEN_CONFIG_OUT} @ONLY)
configure_file(${DOXYGEN_CONFIG_IN} ${DOXYGEN_CONFIG_OUT} @ONLY) # Execute preprocessing step
message("Doxygen Build Started.")
# Target for building docs
add_custom_target(fennecdocs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Generating Doxygen Documentation"
VERBATIM)
# Target for cleaning docs
add_custom_target(fennecdocs-clean ALL
COMMAND rm -r "${PROJECT_SOURCE_DIR}/docs/"
COMMENT "Cleaning Doxygen Documentation"

View File

@ -52,23 +52,58 @@ template<bool_t B, typename T, typename F>
struct conditional;
///
/// \brief Shorthand for ```typename conditional<ConditionV, TrueT, FalseT>::type```
template<bool_t B, typename T, typename F>
using conditional_t
= typename conditional<B, T, F>::type;
// specialization of fennec::conditional for \c true case
// specialization of fennec::conditional for `true` case
template<typename T, typename F>
struct conditional<true, T, F>
: type_transform<T>{};
// specialization of fennec::conditional for \c false case
// specialization of fennec::conditional for `false` case
template<typename T, typename F>
struct conditional<false, T, F>
: type_transform<F>{};
// fennec::detect ======================================================================================================
///
/// \brief Detect whether `DetectT<ArgsT...>` is a valid type
///
/// \details The chosen type is stored in `detect::type` and
/// a boolean value is stored in `detect::is_detected` representing whether `DetectT<ArgsT>`
/// \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;
};
// 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;
};
///
/// \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;
}
#endif //CONDITIONAL_TYPES_H

View File

@ -0,0 +1,64 @@
// =====================================================================================================================
// 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
{
namespace detail
{
template<typename> struct __make_unsigned : undefined_t {};
template<> struct __make_unsigned<char_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<schar_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<short_t> : type_transform<ushort_t> {};
template<> struct __make_unsigned<ushort_t> : type_transform<ushort_t> {};
template<> struct __make_unsigned<uint_t> : type_transform<uint_t> {};
template<> struct __make_unsigned<int_t> : type_transform<uint_t> {};
template<> struct __make_unsigned<long_t> : type_transform<ulong_t> {};
template<> struct __make_unsigned<ulong_t> : type_transform<ulong_t> {};
template<> struct __make_unsigned<llong_t> : type_transform<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_transform<ullong_t> {};
template<typename> struct __make_signed : undefined_t {};
template<> struct __make_signed<char_t> : type_transform<schar_t> {};
template<> struct __make_signed<uchar_t> : type_transform<schar_t> {};
template<> struct __make_signed<schar_t> : type_transform<schar_t> {};
template<> struct __make_signed<short_t> : type_transform<short_t> {};
template<> struct __make_signed<ushort_t> : type_transform<short_t> {};
template<> struct __make_signed<uint_t> : type_transform<int_t> {};
template<> struct __make_signed<int_t> : type_transform<int_t> {};
template<> struct __make_signed<long_t> : type_transform<long_t> {};
template<> struct __make_signed<ulong_t> : type_transform<long_t> {};
template<> struct __make_signed<llong_t> : type_transform<llong_t> {};
template<> struct __make_signed<ullong_t> : type_transform<llong_t> {};
}
}
#endif // FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H

View File

@ -28,36 +28,40 @@ namespace fennec
namespace detail
{
template<typename> struct __is_void_helper : false_type {};
template<> struct __is_void_helper<void> : true_type {};
// Nothing interesting to note here
template<typename> struct __is_bool_helper : false_type {};
template<> struct __is_bool_helper<bool_t> : true_type {};
template<typename> struct __is_void : false_type {};
template<> struct __is_void<void> : true_type {};
template<typename> struct __is_integral_helper : false_type {};
template<> struct __is_integral_helper<bool_t> : true_type {};
template<> struct __is_integral_helper<char_t> : true_type {};
template<> struct __is_integral_helper<char8_t> : true_type {};
template<> struct __is_integral_helper<char16_t> : true_type {};
template<> struct __is_integral_helper<char32_t> : true_type {};
template<> struct __is_integral_helper<schar_t> : true_type {};
template<> struct __is_integral_helper<uchar_t> : true_type {};
template<> struct __is_integral_helper<wchar_t> : true_type {};
template<> struct __is_integral_helper<short_t> : true_type {};
template<> struct __is_integral_helper<ushort_t> : true_type {};
template<> struct __is_integral_helper<int_t> : true_type {};
template<> struct __is_integral_helper<uint_t> : true_type {};
template<> struct __is_integral_helper<long_t> : true_type {};
template<> struct __is_integral_helper<ulong_t> : true_type {};
template<> struct __is_integral_helper<llong_t> : true_type {};
template<> struct __is_integral_helper<ullong_t> : true_type {};
template<typename> struct __is_bool : false_type {};
template<> struct __is_bool<bool_t> : true_type {};
template<typename TypeT> struct __is_signed_helper : bool_constant<TypeT(-1) < TypeT(0)> {};
template<typename TypeT> struct __is_unsigned_helper : bool_constant<TypeT(-1) >= TypeT(0)> {};
// 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 {};
template<typename> struct __is_floating_point_helper : false_type {};
template<> struct __is_floating_point_helper<float_t> : true_type {};
template<> struct __is_floating_point_helper<double_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 {};
}

View File

@ -0,0 +1,36 @@
// =====================================================================================================================
// 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_VARIADICS_H
#define FENNEC_LANG_DETAIL_VARIADICS_H
#include <fennec/lang/type_transforms.h>
namespace fennec
{
namespace detail
{
template<typename FirstT, typename... RestT> struct __first_element : type_transform<FirstT>{};
}
}
#endif // FENNEC_LANG_DETAIL_VARIADICS_H

View File

@ -20,11 +20,83 @@
#ifndef FENNEC_LANG_INTRINSICS_H
#define FENNEC_LANG_INTRINSICS_H
# if defined(__has_builtin)
// Most major compilers support __has_builtin
#if defined(__has_builtin)
// bitcast is slightly more efficient for build times than using memcpy
# define FENNEC_HAS_BUILTIN_BITCAST __has_builtin(__builtin_bit_cast)
#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
# endif
// 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
// Type Traits
// can_convert is also very difficult to implement without intrinsics
#if __has_builtin(__is_convertible)
# define FENNEC_HAS_BUILTIN_CAN_CONVERT 1
# define FENNEC_BUILTIN_CAN_CONVERT(arg0, arg1) __is_convertible(arg0, arg1)
#else
# define FENNEC_HAS_BUILTIN_CAN_CONVERT 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
#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
// 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 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
// 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
#endif
#endif // FENNEC_LANG_INTRINSICS_H

View File

@ -39,6 +39,9 @@ enum float_round_style
, 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;
@ -78,6 +81,7 @@ template<typename TypeT> struct numeric_limits
static constexpr TypeT denorm_min() { return TypeT(); }
};
// Overload for the builtin floating point type
template<> struct numeric_limits<float>
{
static constexpr bool is_specialized = true;
@ -115,6 +119,7 @@ template<> struct numeric_limits<float>
static constexpr double 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;

View File

@ -0,0 +1,46 @@
// =====================================================================================================================
// 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 modify numeric types at compile time
///
///
/// \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
#include <fennec/lang/type_transforms.h>
#include <fennec/lang/detail/__numeric_transforms.h>
// TODO: Document
namespace fennec
{
template<typename TypeT> struct make_signed : detail::__make_signed<remove_cv_t<TypeT>> {};
template<typename TypeT> struct make_unsigned : detail::__make_unsigned<remove_cv_t<TypeT>> {};
}
#endif // FENNEC_LANG_NUMERIC_TRANSFORMS_H

View File

@ -46,7 +46,7 @@ namespace fennec
/// \details
/// \tparam T type to check
template<typename T> struct is_void
: detail::__is_void_helper<remove_cvr_t<T>>{};
: detail::__is_void<remove_cvr_t<T>>{};
///
///
@ -66,7 +66,7 @@ template<typename T> constexpr bool_t is_void_v
/// \details
/// \tparam T type to check
template<typename T> struct is_bool
: detail::__is_bool_helper<remove_cvr_t<T>>{};
: detail::__is_bool<remove_cvr_t<T>>{};
///
///
@ -86,7 +86,7 @@ template<typename T> constexpr bool_t is_bool_v
/// \details
/// \tparam T type to check
template<typename T> struct is_integral
: detail::__is_integral_helper<remove_cvr_t<T>> {};
: detail::__is_integral<remove_cvr_t<T>> {};
///
///
@ -103,7 +103,7 @@ template<typename T> constexpr bool_t is_integral_v
/// \details
/// \tparam T type to check
template<typename T> struct is_signed
: detail::__is_signed_helper<remove_cvr_t<T>> {};
: detail::__is_signed<remove_cvr_t<T>> {};
///
///
@ -120,7 +120,7 @@ template<typename T> constexpr bool_t is_signed_v
/// \details
/// \tparam T type to check
template<typename T> struct is_unsigned
: detail::__is_unsigned_helper<remove_cvr_t<T>> {};
: detail::__is_unsigned<remove_cvr_t<T>> {};
///
///
@ -140,7 +140,7 @@ template<typename T> constexpr bool_t is_unsigned_v
/// \details
/// \tparam T type to check
template<typename T> struct is_floating_point
: detail::__is_floating_point_helper<remove_cvr_t<T>>{};
: detail::__is_floating_point<remove_cvr_t<T>>{};
///
///
@ -173,13 +173,14 @@ template<typename T> constexpr bool_t is_arithmetic_v
///
///
/// \brief check if
/// \brief check if the two types are identical
///
/// \details
/// \tparam T 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 {};
@ -190,6 +191,24 @@ template<typename T> struct is_same<T, T>
template<typename T0, typename T1> constexpr bool_t is_same_v
= is_same<T0, T1> {};
// fennec::can_convert =================================================================================================
///
/// \brief check if type `T0` can be converted `T1`
/// \tparam T0 First type
/// \tparam T1 Second type
template<typename T0, typename T1> struct can_convert
: bool_constant<FENNEC_BUILTIN_CAN_CONVERT(T0, T1)> {};
///
/// \brief shorthand
/// \param T0 First type
/// \param T1 Second type
template<typename T0, typename T1> using can_convert_v = typename can_convert<T0, T1>::type;
//
}
#endif // FENNEC_LANG_TYPE_TRAITS_H

View File

@ -197,6 +197,16 @@ using size_t = __SIZE_TYPE__;
///
/// \brief Signed Integer Type Returned by the Subtraction of two Pointers
using ptrdiff_t = __PTRDIFF_TYPE__;
///
/// \brief undefined class for SFINAE
class undefined_t;
///
/// \brief Void type used for SFINAE
template<typename...>
using void_t = void;
/// @}
}

View File

@ -0,0 +1,66 @@
// =====================================================================================================================
// 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 variadics.h
/// \brief basic types of the c++ language
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_VARIADICS_H
#define FENNEC_LANG_VARIADICS_H
#include <fennec/lang/detail/__variadics.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;
///
///
/// \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

@ -24,11 +24,15 @@
namespace fennec
{
template<typename ScalarT, size_t...IndicesV> struct vector;
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct matrix;
template<typename ScalarT, size_t...IndicesV> struct vector; // Forward def for vectors
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct matrix; // Forward def for matrices
template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{}));
template<typename ScalarT, size_t RowsV, size_t ColsV> using mat = decltype(detail::__gen_matrix<matrix, ScalarT, RowsV>(make_index_sequence<ColsV>{}));
// Simplified interface for creating sized vectors or matrices
template<typename ScalarT, size_t SizeV> using vec
= decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); // Gets the type returned by this function
template<typename ScalarT, size_t RowsV, size_t ColsV> using mat
= decltype(detail::__gen_matrix<matrix, ScalarT, RowsV>(make_index_sequence<ColsV>{})); // Gets the type returned by this function
}

View File

@ -28,11 +28,11 @@ namespace detail
{
template<template<typename, size_t...> typename VectorT, typename ScalarT, size_t...IndicesV>
VectorT<ScalarT, IndicesV...> __gen_vector(index_sequence<IndicesV...>);
VectorT<ScalarT, IndicesV...> __gen_vector(index_sequence<IndicesV...>); // Helper for substituting a size N with sequence of integers
template<template<typename, size_t...> typename MatrixT, typename ScalarT, size_t RowsV, size_t...IndicesV>
MatrixT<ScalarT, RowsV, IndicesV...> __gen_matrix(index_sequence<IndicesV...>);
MatrixT<ScalarT, RowsV, IndicesV...> __gen_matrix(index_sequence<IndicesV...>); // Helper for substituting a size Columns with sequence of integers
}

View File

@ -30,43 +30,47 @@ namespace fennec
namespace detail
{
// Helpers for vector traits
template<typename>
struct __is_vector_helper
: false_type {};
: false_type {}; // Default false case
template<typename ScalarT, size_t...IndicesV>
struct __is_vector_helper<vector<ScalarT, IndicesV...>>
: true_type {};
: true_type {}; // True for vectors
template<typename VectorT, typename DataT, typename ScalarT, size_t...IndicesV>
struct __is_vector_helper<swizzle<VectorT, DataT, ScalarT, IndicesV...>>
: true_type {};
: true_type {}; // True for swizzles
// get number of components of a type
template<typename>
struct __component_count_helper;
// numeric types reduce to 1
template<typename TypeT> requires(is_arithmetic_v<TypeT>)
struct __component_count_helper<TypeT>
: integral_constant<size_t, 1> {};
// Vectors reduce to the number of elements
template<typename ScalarT, size_t...IndicesV>
struct __component_count_helper<vector<ScalarT, IndicesV...>>
: integral_constant<size_t, sizeof...(IndicesV)> {};
// Swizzles reduce to number of elements
template<typename VectorT, typename DataT, typename ScalarT, size_t...IndicesV>
struct __component_count_helper<swizzle<VectorT, DataT, ScalarT, IndicesV...>>
: integral_constant<size_t, sizeof...(IndicesV)> {};
// Matrices reduce to the number of cells
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV>
struct __component_count_helper<matrix<ScalarT, RowsV, ColIndicesV...>>
: integral_constant<size_t, RowsV * sizeof...(ColIndicesV)> {};
// default case reduces to 0
template<typename>
struct __component_count_helper
: integral_constant<size_t, 0> {};

View File

@ -32,6 +32,8 @@
#define FENNEC_MATH_RELATIONAL_H
#include <fennec/lang/types.h>
// TODO: Document
namespace fennec
{

View File

@ -20,13 +20,192 @@
#ifndef FENNEC_MEMORY_ALLOCATOR_H
#define FENNEC_MEMORY_ALLOCATOR_H
#include <cstdlib>
#include <memory>
#include <type_traits>
#include <fennec/memory/ptr_traits.h>
#include <fennec/lang/conditional_types.h>
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
#include <fennec/math/common.h>
namespace fennec
{
std::allocator<char> alloc;
template<class Alloc>
struct allocator_traits
{
private:
// These help with using concepts in `detect_t`
template<typename ClassT> using __pointer = typename ClassT::pointer_t;
template<typename ClassT> using __const_pointer = typename ClassT::const_pointer_t;
template<typename ClassT> using __void_pointer = typename ClassT::void_pointer_t;
template<typename ClassT> using __void_const_pointer = typename ClassT::void_const_pointer_t;
// Propagation Patterns
template<typename ClassT> using __propagate_on_containter_copy_assignment = typename ClassT::propagate_on_containter_copy_assignment;
template<typename ClassT> using __propagate_on_containter_move_assignment = typename ClassT::propagate_on_containter_move_assignment;
template<typename ClassT> using __propagate_on_containter_swap = typename ClassT::propagate_on_containter_swap;
template<typename ClassT> using __is_always_equal = typename ClassT::is_always_equal;
template<typename AllocT, typename TypeT>
struct __rebind : replace_first_element<AllocT, TypeT> {};
template<typename AllocT, typename TypeT>
requires requires { typename AllocT::template rebind<TypeT>::other; }
struct __rebind<AllocT, TypeT> { using type = typename AllocT::template rebind<TypeT>::other; };
// This detects AllocT::diff_t if present, otherwise uses the diff_t associated with PtrT
// It works using SFINAE, 'typename = void' forces the second __diff to be evaluated first when
// __diff is substituted using only two template arguments. That one uses 'type = typename AllocT::diff_t'
// however, if it fails, the compiler moves on to the original definition. __size works in the same manner.
template<typename AllocT, typename PtrT, typename = void>
struct __diff { using type = typename ptr_traits<PtrT>::diff_t; };
template<typename AllocT, typename PtrT>
struct __diff<AllocT, PtrT, void_t<typename AllocT::diff_t>> { using type = typename AllocT::diff_t; };
template<typename AllocT, typename DiffT, typename = void>
struct __size : std::make_unsigned<DiffT> {};
template<typename AllocT, typename DiffT>
struct __size<AllocT, DiffT, void_t<typename AllocT::size_t>> { using type = typename AllocT::size_t; };
public:
/// \brief Alias for the allocator type
using alloc_t = Alloc;
/// \brief Alias for the value type of the allocator
using value_t = typename Alloc::value_t;
/// \brief Alias for a pointer to the value type. Will use `Alloc::pointer_t` if present
using pointer_t = detect_t<value_t*, __pointer, Alloc>;
/// \brief Alias for a const pointer to the value type. Will use `Alloc::const_pointer_t` if present
using const_pointer_t = detect_t<const value_t*, __const_pointer, Alloc>;
/// \brief Alias for a pointer to void. Will use `Alloc::void_pointer_t` if present
using void_pointer_t = detect_t<void*, __void_pointer, Alloc>;
/// \brief Alias for a const pointer to void. Will use `Alloc::const_void_pointer_t` if present
using const_void_pointer_t = detect_t<const void*, __void_const_pointer, Alloc>;
/// \brief Alias for differences between pointers. Will use `Alloc::diff_t` if present
using diff_t = typename __diff<Alloc, pointer_t>::type;
/// \brief Alias for the size of allocations. Will use `Alloc::size_t` if present
using size_t = typename __size<Alloc, pointer_t>::type;
// TODO: Document propagation
using propagate_on_container_copy_assignment = detect_t<false_type, __propagate_on_containter_copy_assignment, Alloc>;
using propagate_on_container_move_assignment = detect_t<false_type, __propagate_on_containter_move_assignment, Alloc>;
using propagate_on_container_swap = detect_t<false_type, __propagate_on_containter_swap, Alloc>;
/// \brief Checks if this allocator type is always equal to another allocator of similar type
using is_always_equal = detect_t<false_type, __is_always_equal, Alloc>;
/// \brief Rebinds the allocator type to produce an element type of type `TypeT`
template<typename TypeT> using rebind = typename __rebind<Alloc, TypeT>::type;
};
///
/// \brief Allocator implementation, uses `new` and `delete` operators.
/// \tparam T The data type to allocate
template<typename T>
class allocator
{
public:
/// \brief Alias for the data type used for metaprogramming
using value_t = T;
/// \brief Metaprogramming utility to rebind an allocator to a different data type
template<typename R> using rebind = allocator<R>;
/// \brief Default Constructor
constexpr allocator() = default;
/// \brief Default Destructor
constexpr ~allocator() = default;
/// \brief Copy Constructor
constexpr allocator(const allocator&) = default;
/// \brief Copy Assignment
constexpr allocator& operator=(const allocator&) = default;
/// \brief Equality operator
constexpr bool_t operator==(const allocator&) { return true; }
/// \brief Inequality operator
constexpr bool_t operator!=(const allocator&) { return false; }
/// \brief Equality operator for allocators of same type but with different data type
template<typename U> constexpr bool_t operator==(const allocator<U>&) { return true; }
/// \brief Inequality operator for allocators of same type but with different data type
template<typename U> constexpr bool_t operator!=(const allocator<U>&) { return true; }
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
constexpr T* allocate(size_t n) { return ::operator new(n * sizeof(T)); }
/// \brief Deallocate a block of memory with type `T`
constexpr void deallocate(T* ptr) { return ::operator delete(ptr); }
};
///
/// \brief Container to hold an allocation
/// \tparam T The data type of the allocation
template<typename T, class AllocT>
class allocation
{
public:
// TODO: Document
using alloc_t = typename allocator_traits<AllocT>::template rebind<T>;
using element_t = T;
using size_t = size_t;
using diff_t = ptrdiff_t;
allocation() : _data(nullptr), _capacity(0) {}
allocation(size_t n) : _data(_alloc.al), _capacity(n) {}
~allocation() { if (_data) _alloc.deallocate(_data); }
void allocate(size_t n)
{
if (_data)
_alloc.deallocate(_data);
_data = alloc_t::allocate(_capacity = n);
}
void release()
{
if (_data)
_alloc.deallocate(_data);
_data = nullptr;
_capacity = 0;
}
void reallocate(size_t n)
{
if (_data == nullptr)
return _alloc.allocate(_capacity = n);
element_t* old = _data;
_data = alloc_t::allocate(n);
fennec::memcpy(_data, old, min(_capacity, n) * sizeof(T));
_alloc.deallocate(old);
_capacity = n;
}
private:
alloc_t _alloc;
element_t* _data;
size_t _capacity;
};
}

View File

@ -36,8 +36,8 @@ namespace fennec
template<typename ToT, typename FromT> requires(sizeof(ToT) == sizeof(FromT))
constexpr ToT bit_cast(const FromT& from)
{
if constexpr(FENNEC_HAS_BUILTIN_BITCAST)
return __builtin_bit_cast(ToT, from);
if constexpr(FENNEC_HAS_BUILTIN_BIT_CAST)
return FENNEC_BUILTIN_BIT_CAST(ToT, from);
else
{
ToT to;

View File

@ -13,12 +13,15 @@ namespace fennec
namespace detail
{
// helper for copying 2 bytes at once
constexpr size_t __memcpy_16(void* dst, const void* src)
{ *static_cast<uint16_t*>(dst) = *static_cast<const uint16_t*>(src); return 2; }
// helper for copying 4 bytes at once
constexpr size_t __memcpy_32(void* dst, const void* src)
{ *static_cast<uint32_t*>(dst) = *static_cast<const uint32_t*>(src); return 4; }
// helper for copying 8 bytes at once
constexpr size_t __memcpy_64(void* dst, const void* src)
{ *static_cast<uint64_t*>(dst) = *static_cast<const uint64_t*>(src); return 8; }

View File

@ -0,0 +1,92 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 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.
//2
// 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_MEMORY_DETAIL_PTR_TRAITS_H
#define FENNEC_MEMORY_DETAIL_PTR_TRAITS_H
#include <fennec/lang/conditional_types.h>
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
#include <fennec/lang/variadics.h>
namespace fennec
{
namespace detail
{
// helper to get the element type of the pointer class
template<typename ClassT, typename = void>
struct __ptr_get_element : first_element<ClassT> { }; // Default case, return the first template parameter
// overload for types that have a member `ClassT::element_t`
template<typename ClassT> requires requires { typename ClassT::element_t; }
struct __ptr_get_element { using type = typename ClassT::element_t; };
// helper for generating `pointer_to`
template<typename PtrT, typename ElemT, bool_t = is_void_v<ElemT>>
struct __ptr_traits_ptr_to
{
using pointer_t = PtrT;
using element_t = ElemT;
static constexpr pointer_t pointer_to(element_t& obj)
{ return pointer_t::pointer_to(obj); }
};
// overload for C style pointers
template<typename ElemT>
struct __ptr_traits_ptr_to<ElemT*, ElemT, false>
{
using pointer_t = ElemT*;
using element_t = ElemT;
static constexpr pointer_t pointer_to(element_t& obj)
{ return addressof(obj); }
};
// underlying implementation for classes that behave like pointers
template<typename ClassT, typename ElemT, bool_t = is_void_v<ElemT>>
struct __ptr_traits_impl : __ptr_traits_ptr_to<ClassT, ElemT>
{
private:
template<typename TypeT>
using __diff_t = typename TypeT::diff_t; // Helper to prevent substitution issues with detecting the difference type
template<typename BaseT, typename OElemT> // Helper to prevent substitution issues with detecting a defined rebind
using __rebind_helper = type_transform<typename BaseT::template rebind<OElemT>>;
public:
using pointer_t = ClassT;
using element_t = __ptr_get_element<ClassT>;
using diff_t = __diff_t<ClassT>;
template<class U> using rebind = detect_t<replace_first_element<ClassT, U>, __rebind_helper, ClassT, ElemT>;
};
// overload for an undefined type
template<typename ClassT> struct __ptr_traits_impl<ClassT, undefined_t> {};
// overload for void element
template<typename PtrT, typename ElemT> struct __ptr_traits_ptr_to<PtrT, ElemT, true> { };
}
}
#endif // FENNEC_MEMORY_DETAIL_PTR_TRAITS_H

View File

@ -25,6 +25,14 @@
namespace fennec
{
///
/// \brief Returns the address of an object regardless of whether the `&` operators is implemented.
/// \tparam TypeT The type of the objects
/// \param obj The object to find the address of
/// \return The true address of the
template<typename TypeT>
constexpr TypeT* addressof(TypeT& obj) { return FENNEC_BUILTIN_ADDRESSOF(obj); }
///
/// \copydetails fennec::memchr(const void*, int, size_t)
constexpr void* memchr(void* arr, int ch, size_t n)
@ -52,7 +60,7 @@ constexpr const void* memchr(const void* arr, int ch, size_t n)
/// \param lhs The first object, interpreted as an array of bytes
/// \param rhs The second object, interpreted as an array of bytes
/// \param n The number of bytes to parse
/// \returns \f$0\f$ if the first \f$n\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise returns \f$1\f$
/// \returns \f$0\f$ if the first \f$n\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise, returns \f$1\f$
/// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$
constexpr int memcmp(const void* lhs, const void* rhs, size_t n)
{
@ -145,6 +153,21 @@ constexpr void* memset(void* dst, int ch, size_t n)
}
template<typename TypeT>
struct default_delete
{
constexpr default_delete() noexcept = default;
template<class U> default_delete(const default_delete<U>&) noexcept;
template<class U> default_delete(const default_delete<U[]>&) noexcept;
};
template<typename TypeT>
struct default_delete<TypeT[]>
{
};
}
#endif // FENNEC_MEMORY_H

View File

@ -25,9 +25,6 @@
#include <fennec/lang/types.h>
// TODO: Document
// TODO: Memory Debugging
namespace fennec
{
@ -39,8 +36,6 @@ enum class align_t : size_t;
/// \brief Type to handle explicit nothrow definitions
struct nothrow_t { explicit nothrow_t() noexcept { } };
//
}
#endif // FENNEC_MEMORY_NEW_H

View File

@ -0,0 +1,46 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 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.
//2
// 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_POINTERS_H
#define FENNEC_LANG_POINTERS_H
template<typename TypeT, class DeleteT = >
class unique_ptr
{
public:
using element_t = TypeT;
using pointer_t = element_t*;
constexpr unique_ptr() : unique_ptr(nullptr) {}
constexpr unique_ptr(pointer_t ptr) : _handle(ptr) {}
constexpr unique_ptr(unique_ptr&& other) : _handle(other._handle) { other._handle = nullptr; }
constexpr ~unique_ptr() { if(_handle) ::operator delete(_handle); }
constexpr unique_ptr& operator=(unique_ptr&& r) noexcept
{ _handle = r._handle; r._handle = nullptr; return *this; }
pointer_t release() { pointer_t retval = _handle; _handle = nullptr; return retval; }
private:
pointer_t _handle;
};
#endif // FENNEC_LANG_POINTERS_H

View File

@ -0,0 +1,48 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 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.
//2
// 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_MEMORY_PTR_TRAITS_H
#define FENNEC_MEMORY_PTR_TRAITS_H
#include <fennec/lang/types.h>
#include <fennec/memory/detail/__ptr_traits.h>
namespace fennec
{
///
/// \brief Class for retrieving the traits of Pointer-like types
/// \tparam ClassT The Pointer class type
template<typename ClassT>
struct ptr_traits
: detail::__ptr_traits_impl<ClassT, detail::__ptr_get_element<ClassT>> {};
// overload for C-Style Pointers
template<typename ElemT>
struct ptr_traits<ElemT*> : detail::__ptr_traits_ptr_to<ElemT*, ElemT>
{
using pointer_t = ElemT*;
using element_t = ElemT;
using diff_t = ptrdiff_t;
template<typename U> using rebind = U*;
};
}
#endif // FENNEC_MEMORY_PTR_TRAITS_H

View File

@ -21,6 +21,10 @@
#ifdef FENNEC_MEMORY_DEBUGGER
// TODO: Memory Debugging
// General concept is to create a table of allocated memory addresses.
#else
// Allocation functions