From 67c8ad9a0de0d7aca5c91a616a841d7cce888770 Mon Sep 17 00:00:00 2001 From: Medusa Slockbower Date: Fri, 30 May 2025 21:10:52 -0400 Subject: [PATCH] Added fennec::allocation and all necessary dependencies --- CMakeLists.txt | 38 ++-- include/fennec/lang/conditional_types.h | 39 +++- .../fennec/lang/detail/__numeric_transforms.h | 64 ++++++ include/fennec/lang/detail/__type_traits.h | 56 +++--- include/fennec/lang/detail/__variadics.h | 36 ++++ include/fennec/lang/intrinsics.h | 78 +++++++- include/fennec/lang/limits.h | 5 + include/fennec/lang/numeric_transforms.h | 46 +++++ include/fennec/lang/type_traits.h | 33 +++- include/fennec/lang/types.h | 10 + include/fennec/lang/variadics.h | 66 +++++++ include/fennec/math/detail/__fwd.h | 12 +- include/fennec/math/detail/__types.h | 4 +- include/fennec/math/detail/__vector_traits.h | 18 +- include/fennec/math/relational.h | 2 + include/fennec/memory/allocator.h | 185 +++++++++++++++++- include/fennec/memory/bits.h | 4 +- include/fennec/memory/detail/__memory.h | 3 + include/fennec/memory/detail/__ptr_traits.h | 92 +++++++++ include/fennec/memory/memory.h | 27 ++- include/fennec/memory/new.h | 5 - include/fennec/memory/pointers.h | 46 +++++ include/fennec/memory/ptr_traits.h | 48 +++++ source/memory/new.cpp | 4 + 24 files changed, 847 insertions(+), 74 deletions(-) create mode 100644 include/fennec/lang/detail/__numeric_transforms.h create mode 100644 include/fennec/lang/detail/__variadics.h create mode 100644 include/fennec/lang/numeric_transforms.h create mode 100644 include/fennec/lang/variadics.h create mode 100644 include/fennec/memory/detail/__ptr_traits.h create mode 100644 include/fennec/memory/pointers.h create mode 100644 include/fennec/memory/ptr_traits.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f5dde45..7c9c116 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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" diff --git a/include/fennec/lang/conditional_types.h b/include/fennec/lang/conditional_types.h index 7ae8726..11323eb 100644 --- a/include/fennec/lang/conditional_types.h +++ b/include/fennec/lang/conditional_types.h @@ -52,23 +52,58 @@ template struct conditional; +/// /// \brief Shorthand for ```typename conditional::type``` template using conditional_t = typename conditional::type; -// specialization of fennec::conditional for \c true case +// specialization of fennec::conditional for `true` case template struct conditional : type_transform{}; -// specialization of fennec::conditional for \c false case +// specialization of fennec::conditional for `false` case template struct conditional : type_transform{}; + +// fennec::detect ====================================================================================================== + +/// +/// \brief Detect whether `DetectT` 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` +/// \tparam DefaultT Default type +/// \tparam DetectT Type to detect +/// \tparam ArgsT Any template arguments for `DetectT` +template typename DetectT, typename...ArgsT> +struct detect +{ + using type = DefaultT; + static constexpr bool is_detected = false; +}; + +// true case +template typename DetectT, typename...ArgsT> + requires requires { typename DetectT; } +struct detect +{ + using type = DetectT; + static constexpr bool is_detected = true; +}; + + +/// +/// \brief Shorthand for ```typename detect::type``` +template typename DetectT, typename...ArgsT> +using detect_t + = typename detect::type; + } #endif //CONDITIONAL_TYPES_H diff --git a/include/fennec/lang/detail/__numeric_transforms.h b/include/fennec/lang/detail/__numeric_transforms.h new file mode 100644 index 0000000..5e7e743 --- /dev/null +++ b/include/fennec/lang/detail/__numeric_transforms.h @@ -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 . +// ===================================================================================================================== + +#ifndef FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H +#define FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H + +#include +#include + +namespace fennec +{ + +namespace detail +{ + +template struct __make_unsigned : undefined_t {}; + +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; +template<> struct __make_unsigned : type_transform {}; + + +template struct __make_signed : undefined_t {}; + +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; +template<> struct __make_signed : type_transform {}; + +} + +} + +#endif // FENNEC_LANG_DETAIL_NUMERIC_TRANSFORMS_H diff --git a/include/fennec/lang/detail/__type_traits.h b/include/fennec/lang/detail/__type_traits.h index 0ec5528..4c335e5 100644 --- a/include/fennec/lang/detail/__type_traits.h +++ b/include/fennec/lang/detail/__type_traits.h @@ -28,36 +28,40 @@ namespace fennec namespace detail { -template struct __is_void_helper : false_type {}; -template<> struct __is_void_helper : true_type {}; +// Nothing interesting to note here -template struct __is_bool_helper : false_type {}; -template<> struct __is_bool_helper : true_type {}; +template struct __is_void : false_type {}; +template<> struct __is_void : true_type {}; -template struct __is_integral_helper : false_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; -template<> struct __is_integral_helper : true_type {}; +template struct __is_bool : false_type {}; +template<> struct __is_bool : true_type {}; -template struct __is_signed_helper : bool_constant {}; -template struct __is_unsigned_helper : bool_constant= TypeT(0)> {}; +// Provides definitions for all builtin int types +template struct __is_integral : false_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; +template<> struct __is_integral : true_type {}; -template struct __is_floating_point_helper : false_type {}; -template<> struct __is_floating_point_helper : true_type {}; -template<> struct __is_floating_point_helper : true_type {}; +// Most unsigned types will underflow `-1` to the types maximum value +template struct __is_signed : bool_constant {}; +template struct __is_unsigned : bool_constant= TypeT(0)> {}; + +template struct __is_floating_point : false_type {}; +template<> struct __is_floating_point : true_type {}; +template<> struct __is_floating_point : true_type {}; } diff --git a/include/fennec/lang/detail/__variadics.h b/include/fennec/lang/detail/__variadics.h new file mode 100644 index 0000000..0459983 --- /dev/null +++ b/include/fennec/lang/detail/__variadics.h @@ -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 . +// ===================================================================================================================== + +#ifndef FENNEC_LANG_DETAIL_VARIADICS_H +#define FENNEC_LANG_DETAIL_VARIADICS_H + +#include + +namespace fennec +{ + +namespace detail +{ + +template struct __first_element : type_transform{}; + +} + +} + +#endif // FENNEC_LANG_DETAIL_VARIADICS_H diff --git a/include/fennec/lang/intrinsics.h b/include/fennec/lang/intrinsics.h index 780bded..87ffa30 100644 --- a/include/fennec/lang/intrinsics.h +++ b/include/fennec/lang/intrinsics.h @@ -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 diff --git a/include/fennec/lang/limits.h b/include/fennec/lang/limits.h index 458a064..60bdbd8 100644 --- a/include/fennec/lang/limits.h +++ b/include/fennec/lang/limits.h @@ -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 struct numeric_limits { static constexpr bool is_specialized = false; @@ -78,6 +81,7 @@ template struct numeric_limits static constexpr TypeT denorm_min() { return TypeT(); } }; +// Overload for the builtin floating point type template<> struct numeric_limits { static constexpr bool is_specialized = true; @@ -115,6 +119,7 @@ template<> struct numeric_limits static constexpr double denorm_min() { return FLT_DENORM_MIN; } }; +// Overload for the bultin double precision floating point type template<> struct numeric_limits { static constexpr bool is_specialized = true; diff --git a/include/fennec/lang/numeric_transforms.h b/include/fennec/lang/numeric_transforms.h new file mode 100644 index 0000000..dda33be --- /dev/null +++ b/include/fennec/lang/numeric_transforms.h @@ -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 . +// ===================================================================================================================== + +/// +/// \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 +#include + +// TODO: Document + +namespace fennec +{ + +template struct make_signed : detail::__make_signed> {}; +template struct make_unsigned : detail::__make_unsigned> {}; + +} + +#endif // FENNEC_LANG_NUMERIC_TRANSFORMS_H diff --git a/include/fennec/lang/type_traits.h b/include/fennec/lang/type_traits.h index ea2a5c3..6bf6352 100644 --- a/include/fennec/lang/type_traits.h +++ b/include/fennec/lang/type_traits.h @@ -46,7 +46,7 @@ namespace fennec /// \details /// \tparam T type to check template struct is_void - : detail::__is_void_helper>{}; + : detail::__is_void>{}; /// /// @@ -66,7 +66,7 @@ template constexpr bool_t is_void_v /// \details /// \tparam T type to check template struct is_bool - : detail::__is_bool_helper>{}; + : detail::__is_bool>{}; /// /// @@ -86,7 +86,7 @@ template constexpr bool_t is_bool_v /// \details /// \tparam T type to check template struct is_integral - : detail::__is_integral_helper> {}; + : detail::__is_integral> {}; /// /// @@ -103,7 +103,7 @@ template constexpr bool_t is_integral_v /// \details /// \tparam T type to check template struct is_signed - : detail::__is_signed_helper> {}; + : detail::__is_signed> {}; /// /// @@ -120,7 +120,7 @@ template constexpr bool_t is_signed_v /// \details /// \tparam T type to check template struct is_unsigned - : detail::__is_unsigned_helper> {}; + : detail::__is_unsigned> {}; /// /// @@ -140,7 +140,7 @@ template constexpr bool_t is_unsigned_v /// \details /// \tparam T type to check template struct is_floating_point - : detail::__is_floating_point_helper>{}; + : detail::__is_floating_point>{}; /// /// @@ -173,13 +173,14 @@ template constexpr bool_t is_arithmetic_v /// /// -/// \brief check if +/// \brief check if the two types are identical /// /// \details /// \tparam T type to check template struct is_same : false_type {}; +// true case template struct is_same : true_type {}; @@ -190,6 +191,24 @@ template struct is_same template constexpr bool_t is_same_v = is_same {}; +// fennec::can_convert ================================================================================================= + +/// +/// \brief check if type `T0` can be converted `T1` +/// \tparam T0 First type +/// \tparam T1 Second type +template struct can_convert + : bool_constant {}; + +/// +/// \brief shorthand +/// \param T0 First type +/// \param T1 Second type +template using can_convert_v = typename can_convert::type; + + +// + } #endif // FENNEC_LANG_TYPE_TRAITS_H diff --git a/include/fennec/lang/types.h b/include/fennec/lang/types.h index 2941911..c78d8a1 100644 --- a/include/fennec/lang/types.h +++ b/include/fennec/lang/types.h @@ -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 +using void_t = void; + /// @} } diff --git a/include/fennec/lang/variadics.h b/include/fennec/lang/variadics.h new file mode 100644 index 0000000..b590953 --- /dev/null +++ b/include/fennec/lang/variadics.h @@ -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 . +// ===================================================================================================================== + +/// +/// \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 + +namespace fennec +{ + +/// +/// \brief Get the first element of a template parameter pack +/// \tparam TypesT the Parameter Pack +template struct first_element : detail::__first_element {}; + +/// +/// \brief alias for first_element::type +template using first_element_t = typename first_element::type; + + + +/// +/// +/// \brief Take a Template with a Pack `ClassT` and replace the first `ArgT` of `ArgsT...` with `SubT` +template struct replace_first_element { }; + +// Implementation +template< + template 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, SubT> // Specialization + { using type = ClassT; }; // Definition + +} + + +#endif // FENNEC_LANG_VARIADICS_H diff --git a/include/fennec/math/detail/__fwd.h b/include/fennec/math/detail/__fwd.h index b641263..d8406a7 100644 --- a/include/fennec/math/detail/__fwd.h +++ b/include/fennec/math/detail/__fwd.h @@ -24,11 +24,15 @@ namespace fennec { -template struct vector; -template struct matrix; +template struct vector; // Forward def for vectors +template struct matrix; // Forward def for matrices -template using vec = decltype(detail::__gen_vector(make_index_sequence{})); -template using mat = decltype(detail::__gen_matrix(make_index_sequence{})); +// Simplified interface for creating sized vectors or matrices +template using vec + = decltype(detail::__gen_vector(make_index_sequence{})); // Gets the type returned by this function + +template using mat + = decltype(detail::__gen_matrix(make_index_sequence{})); // Gets the type returned by this function } diff --git a/include/fennec/math/detail/__types.h b/include/fennec/math/detail/__types.h index 86705af..3da7c8d 100644 --- a/include/fennec/math/detail/__types.h +++ b/include/fennec/math/detail/__types.h @@ -28,11 +28,11 @@ namespace detail { template typename VectorT, typename ScalarT, size_t...IndicesV> -VectorT __gen_vector(index_sequence); +VectorT __gen_vector(index_sequence); // Helper for substituting a size N with sequence of integers template typename MatrixT, typename ScalarT, size_t RowsV, size_t...IndicesV> -MatrixT __gen_matrix(index_sequence); +MatrixT __gen_matrix(index_sequence); // Helper for substituting a size Columns with sequence of integers } diff --git a/include/fennec/math/detail/__vector_traits.h b/include/fennec/math/detail/__vector_traits.h index ffa5979..b4490ee 100644 --- a/include/fennec/math/detail/__vector_traits.h +++ b/include/fennec/math/detail/__vector_traits.h @@ -30,43 +30,47 @@ namespace fennec namespace detail { +// Helpers for vector traits + template struct __is_vector_helper - : false_type {}; + : false_type {}; // Default false case template struct __is_vector_helper> - : true_type {}; + : true_type {}; // True for vectors template struct __is_vector_helper> - : true_type {}; + : true_type {}; // True for swizzles +// get number of components of a type template struct __component_count_helper; - +// numeric types reduce to 1 template requires(is_arithmetic_v) struct __component_count_helper : integral_constant {}; - +// Vectors reduce to the number of elements template struct __component_count_helper> : integral_constant {}; - +// Swizzles reduce to number of elements template struct __component_count_helper> : integral_constant {}; - +// Matrices reduce to the number of cells template struct __component_count_helper> : integral_constant {}; +// default case reduces to 0 template struct __component_count_helper : integral_constant {}; diff --git a/include/fennec/math/relational.h b/include/fennec/math/relational.h index 5132bd7..3b5fdd0 100644 --- a/include/fennec/math/relational.h +++ b/include/fennec/math/relational.h @@ -32,6 +32,8 @@ #define FENNEC_MATH_RELATIONAL_H #include +// TODO: Document + namespace fennec { diff --git a/include/fennec/memory/allocator.h b/include/fennec/memory/allocator.h index e1dbf56..12291dc 100644 --- a/include/fennec/memory/allocator.h +++ b/include/fennec/memory/allocator.h @@ -20,13 +20,192 @@ #ifndef FENNEC_MEMORY_ALLOCATOR_H #define FENNEC_MEMORY_ALLOCATOR_H -#include -#include +#include +#include +#include +#include +#include +#include namespace fennec { -std::allocator alloc; +template +struct allocator_traits +{ +private: + // These help with using concepts in `detect_t` + template using __pointer = typename ClassT::pointer_t; + template using __const_pointer = typename ClassT::const_pointer_t; + template using __void_pointer = typename ClassT::void_pointer_t; + template using __void_const_pointer = typename ClassT::void_const_pointer_t; + + // Propagation Patterns + template using __propagate_on_containter_copy_assignment = typename ClassT::propagate_on_containter_copy_assignment; + template using __propagate_on_containter_move_assignment = typename ClassT::propagate_on_containter_move_assignment; + template using __propagate_on_containter_swap = typename ClassT::propagate_on_containter_swap; + + template using __is_always_equal = typename ClassT::is_always_equal; + + template + struct __rebind : replace_first_element {}; + + template + requires requires { typename AllocT::template rebind::other; } + struct __rebind { using type = typename AllocT::template rebind::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 + struct __diff { using type = typename ptr_traits::diff_t; }; + + template + struct __diff> { using type = typename AllocT::diff_t; }; + + template + struct __size : std::make_unsigned {}; + + template + struct __size> { 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; + + /// \brief Alias for a const pointer to the value type. Will use `Alloc::const_pointer_t` if present + using const_pointer_t = detect_t; + + /// \brief Alias for a pointer to void. Will use `Alloc::void_pointer_t` if present + using void_pointer_t = detect_t; + + /// \brief Alias for a const pointer to void. Will use `Alloc::const_void_pointer_t` if present + using const_void_pointer_t = detect_t; + + /// \brief Alias for differences between pointers. Will use `Alloc::diff_t` if present + using diff_t = typename __diff::type; + + /// \brief Alias for the size of allocations. Will use `Alloc::size_t` if present + using size_t = typename __size::type; + + // TODO: Document propagation + using propagate_on_container_copy_assignment = detect_t; + using propagate_on_container_move_assignment = detect_t; + using propagate_on_container_swap = detect_t; + + /// \brief Checks if this allocator type is always equal to another allocator of similar type + using is_always_equal = detect_t; + + /// \brief Rebinds the allocator type to produce an element type of type `TypeT` + template using rebind = typename __rebind::type; +}; + + +/// +/// \brief Allocator implementation, uses `new` and `delete` operators. +/// \tparam T The data type to allocate +template +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 using rebind = allocator; + + /// \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 constexpr bool_t operator==(const allocator&) { return true; } + + /// \brief Inequality operator for allocators of same type but with different data type + template constexpr bool_t operator!=(const allocator&) { 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 +class allocation +{ +public: + // TODO: Document + + using alloc_t = typename allocator_traits::template rebind; + 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; +}; } diff --git a/include/fennec/memory/bits.h b/include/fennec/memory/bits.h index 522ec68..db1881e 100644 --- a/include/fennec/memory/bits.h +++ b/include/fennec/memory/bits.h @@ -36,8 +36,8 @@ namespace fennec template 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; diff --git a/include/fennec/memory/detail/__memory.h b/include/fennec/memory/detail/__memory.h index 412aa6e..4ef098c 100644 --- a/include/fennec/memory/detail/__memory.h +++ b/include/fennec/memory/detail/__memory.h @@ -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(dst) = *static_cast(src); return 2; } +// helper for copying 4 bytes at once constexpr size_t __memcpy_32(void* dst, const void* src) { *static_cast(dst) = *static_cast(src); return 4; } +// helper for copying 8 bytes at once constexpr size_t __memcpy_64(void* dst, const void* src) { *static_cast(dst) = *static_cast(src); return 8; } diff --git a/include/fennec/memory/detail/__ptr_traits.h b/include/fennec/memory/detail/__ptr_traits.h new file mode 100644 index 0000000..5a1324f --- /dev/null +++ b/include/fennec/memory/detail/__ptr_traits.h @@ -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 . +// ===================================================================================================================== + +#ifndef FENNEC_MEMORY_DETAIL_PTR_TRAITS_H +#define FENNEC_MEMORY_DETAIL_PTR_TRAITS_H + +#include +#include +#include +#include + +namespace fennec +{ + +namespace detail +{ + +// helper to get the element type of the pointer class +template +struct __ptr_get_element : first_element { }; // Default case, return the first template parameter + +// overload for types that have a member `ClassT::element_t` +template requires requires { typename ClassT::element_t; } +struct __ptr_get_element { using type = typename ClassT::element_t; }; + +// helper for generating `pointer_to` +template> +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 +struct __ptr_traits_ptr_to +{ + 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> +struct __ptr_traits_impl : __ptr_traits_ptr_to +{ +private: + template + using __diff_t = typename TypeT::diff_t; // Helper to prevent substitution issues with detecting the difference type + + template // Helper to prevent substitution issues with detecting a defined rebind + using __rebind_helper = type_transform>; + +public: + using pointer_t = ClassT; + using element_t = __ptr_get_element; + using diff_t = __diff_t; + + template using rebind = detect_t, __rebind_helper, ClassT, ElemT>; +}; + +// overload for an undefined type +template struct __ptr_traits_impl {}; + +// overload for void element +template struct __ptr_traits_ptr_to { }; + +} + +} + +#endif // FENNEC_MEMORY_DETAIL_PTR_TRAITS_H diff --git a/include/fennec/memory/memory.h b/include/fennec/memory/memory.h index 6c38581..46fe744 100644 --- a/include/fennec/memory/memory.h +++ b/include/fennec/memory/memory.h @@ -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 +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) { @@ -132,7 +140,7 @@ constexpr void* memset(void* dst, int ch, size_t n) { uint8_t* d = static_cast(dst); uint8_t val8 = ch; - uint16_t val16 = (static_cast(val8) << 8) | static_cast(val8); + uint16_t val16 = (static_cast(val8) << 8) | static_cast(val8); uint32_t val32 = (static_cast(val16) << 16) | static_cast(val16); uint64_t val64 = (static_cast(val32) << 32) | static_cast(val32); @@ -145,6 +153,21 @@ constexpr void* memset(void* dst, int ch, size_t n) } +template +struct default_delete +{ + constexpr default_delete() noexcept = default; + + template default_delete(const default_delete&) noexcept; + template default_delete(const default_delete&) noexcept; +}; + +template +struct default_delete +{ + +}; + } #endif // FENNEC_MEMORY_H diff --git a/include/fennec/memory/new.h b/include/fennec/memory/new.h index 7fc2447..7bd7c78 100644 --- a/include/fennec/memory/new.h +++ b/include/fennec/memory/new.h @@ -25,9 +25,6 @@ #include -// 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 diff --git a/include/fennec/memory/pointers.h b/include/fennec/memory/pointers.h new file mode 100644 index 0000000..3d67b7d --- /dev/null +++ b/include/fennec/memory/pointers.h @@ -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 . +// ===================================================================================================================== + +#ifndef FENNEC_LANG_POINTERS_H +#define FENNEC_LANG_POINTERS_H + + +template +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 diff --git a/include/fennec/memory/ptr_traits.h b/include/fennec/memory/ptr_traits.h new file mode 100644 index 0000000..d756d85 --- /dev/null +++ b/include/fennec/memory/ptr_traits.h @@ -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 . +// ===================================================================================================================== + +#ifndef FENNEC_MEMORY_PTR_TRAITS_H +#define FENNEC_MEMORY_PTR_TRAITS_H + +#include +#include + +namespace fennec +{ + +/// +/// \brief Class for retrieving the traits of Pointer-like types +/// \tparam ClassT The Pointer class type +template +struct ptr_traits + : detail::__ptr_traits_impl> {}; + +// overload for C-Style Pointers +template +struct ptr_traits : detail::__ptr_traits_ptr_to +{ + using pointer_t = ElemT*; + using element_t = ElemT; + using diff_t = ptrdiff_t; + + template using rebind = U*; +}; + +} + +#endif // FENNEC_MEMORY_PTR_TRAITS_H diff --git a/source/memory/new.cpp b/source/memory/new.cpp index 9ac8280..f3ce24a 100644 --- a/source/memory/new.cpp +++ b/source/memory/new.cpp @@ -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