From d3eba6560d4f86fc002b25e7a6bcc1fd691e4e4c Mon Sep 17 00:00:00 2001 From: Medusa Slockbower Date: Mon, 2 Jun 2025 23:35:03 -0400 Subject: [PATCH] Added Logo --- CMakeLists.txt | 4 +- README.md | 47 +++++++++---- build.sh | 7 +- include/fennec/containers/dynarray.h | 3 +- include/fennec/lang/intrinsics.h | 10 ++- include/fennec/lang/type_traits.h | 12 +++- include/fennec/memory/allocator.h | 30 +++++++-- include/fennec/memory/memory.h | 17 +---- include/fennec/memory/pointers.h | 95 ++++++++++++++++++++++++++- logo/raster.png | Bin 0 -> 27827 bytes logo/vector.svg | 70 ++++++++++++++++++++ test.sh | 4 +- 12 files changed, 255 insertions(+), 44 deletions(-) create mode 100644 logo/raster.png create mode 100644 logo/vector.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c9c116..d1ace8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(fennec STATIC include/fennec/lang/detail/__numeric_transforms.h include/fennec/lang/detail/__type_traits.h + include/fennec/lang/detail/__variadics.h # MEMORY =============================================================================================================== @@ -70,9 +71,6 @@ add_library(fennec STATIC include/fennec/math/detail/__fwd.h include/fennec/math/detail/__types.h include/fennec/math/detail/__vector_traits.h - - include/fennec/lang/detail/__variadics.h - ) add_subdirectory(metaprogramming) diff --git a/README.md b/README.md index 69ef250..344ed6a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,21 @@ -# fennec -*a free and open source game engine* +

+ +
+drawing +
+

fennec

+

a free and open source game engine

+
+
+ +

## Table of Contents -1. [Introduction](#introduction) -2. [Building from Source](#building-from-source) - 1. [Building from Terminal](#building-from-terminal) - 2. [Building on Windows](#building-on-windows) -3. [Running the Test Suite](#running-the-test-suite) + 1. [Introduction](#introduction) + 2. [Building from Source](#building-from-source) + 1. [Building from Terminal](#building-from-terminal) + 2. [Building on Windows](#building-on-windows) + 3. [Running the Test Suite](#running-the-test-suite)
@@ -17,14 +26,23 @@ fennec is designed to be a general purpose, educational game engine. Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html). +Some main areas where the engine strays from the GNU standard includes the following: + +- [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html). + fennec provides an implementation for X11, however it does not use the GTK toolkit.
-Some main areas where the engine strays from the GNU standard includes the following: +The C++ stdlib is reimplemented in the fennec engine. +There are a few reasons for this: - - [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html). - fennec provides an implementation for X11, however it does not use the GTK toolkit. - + 1. Standardize implementations across compilers + 2. Set proper naming conventions, i.e. `std::vector`->`fennec::dynarray` + 3. Optimize compilation times, binary size, and performance. + 4. Inject debugging information when necessary. + 5. Expose functionality in a readable manner for those interested in learning the + intricacies of the implementation. +
@@ -107,4 +125,9 @@ cmake -G "Visual Studio 17 2022" -A x64 ## Running the Test Suite -`test.sh` provides profiles for building the test suite and executes them. \ No newline at end of file +`test.sh` provides profiles for building the test suite and executes them. + +By default, it runs in debug mode and the first failed test will throw an assertion. +Any tests that involve running as an application will spawn a subprocess with a window, +and give a short description of the behaviour in the terminal. It will then have you confirm +whether the information displayed is correct. \ No newline at end of file diff --git a/build.sh b/build.sh index 3cc4752..a9652a8 100755 --- a/build.sh +++ b/build.sh @@ -21,7 +21,7 @@ Help() { - echo "Bash script for building fennec from source." + echo "Bash script for building fennec from source. By default, the build script executes in release mode." echo echo "GNU long options:" echo "--help (-h) = Print this help info." @@ -82,6 +82,11 @@ All() # Main Program ========================================================================================================= +if [[ $# -eq 0 ]] ; then + Release + exit 0 +fi + while [ "${1:-}" != '' ]; do case "$1" in '--debug' | '-d') diff --git a/include/fennec/containers/dynarray.h b/include/fennec/containers/dynarray.h index 5acb43d..531f199 100644 --- a/include/fennec/containers/dynarray.h +++ b/include/fennec/containers/dynarray.h @@ -43,7 +43,8 @@ public: using alloc_t = Alloc; dynarray() : _alloc(), _size(0) {} - dynarray() + dynarray(size_t size) : _alloc(size), _size(size) { } + dynarray(const alloc_t& alloc) : _alloc(alloc), _size(0) {} private: allocation _alloc; diff --git a/include/fennec/lang/intrinsics.h b/include/fennec/lang/intrinsics.h index 87ffa30..8cb5f9f 100644 --- a/include/fennec/lang/intrinsics.h +++ b/include/fennec/lang/intrinsics.h @@ -20,7 +20,7 @@ #ifndef FENNEC_LANG_INTRINSICS_H #define FENNEC_LANG_INTRINSICS_H -// Most major compilers support __has_builtin +// Most major compilers support __has_builtin, notably GCC, MINGW, CLANG, and MSVC #if defined(__has_builtin) @@ -91,6 +91,14 @@ # define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 0 #endif +// Difficult and Inconsistent without intrinsics +#if __has_builtin(__is_constructible) +# define FENNEC_BUILTIN_CAN_CONSTRUCT 1 +# define FENNEC_BUILTIN_CAN_CONSTRUCT(type, args...) __is_constructible(type, args) +#else +# define FENNEC_HAS_BUILTIN_CAN_CONSTRUCT 0 +#endif + // For compilers without or differently named builtins #else diff --git a/include/fennec/lang/type_traits.h b/include/fennec/lang/type_traits.h index 6bf6352..cb94f01 100644 --- a/include/fennec/lang/type_traits.h +++ b/include/fennec/lang/type_traits.h @@ -204,8 +204,18 @@ template struct can_convert /// \brief shorthand /// \param T0 First type /// \param T1 Second type -template using can_convert_v = typename can_convert::type; +template using can_convert_v + = typename can_convert::type; + +// fennec::is_constructible ============================================================================================ + + +template struct can_construct + : bool_constant {}; + +template constexpr bool_t can_construct_v + = can_construct{}; // diff --git a/include/fennec/memory/allocator.h b/include/fennec/memory/allocator.h index 0aab02f..8d47db3 100644 --- a/include/fennec/memory/allocator.h +++ b/include/fennec/memory/allocator.h @@ -106,6 +106,8 @@ public: /// \brief Rebinds the allocator type to produce an element type of type `TypeT` template using rebind = typename __rebind::type; + + // TODO: allocator_traits static functions }; @@ -180,19 +182,22 @@ public: /// /// \brief Default Constructor, initializes internal data to `null` and the capacity to `0` - constexpr allocation() noexcept : _data(nullptr), _capacity(0) {} + constexpr allocation() noexcept + : _data(nullptr), _capacity(0) {} /// /// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes /// \param n The number of elements of type `T` to allocate for - constexpr allocation(size_t n) noexcept : _data(_alloc.al), _capacity(n) {} + constexpr allocation(size_t n) noexcept + : _data(_alloc.al), _capacity(n) {} /// /// \brief Allocator Constructor /// \param alloc The allocation object to copy. /// /// \details This constructor should be used when the type `AllocT` needs internal data. - constexpr allocation(const alloc_t& alloc) noexcept : _alloc(alloc), _data(nullptr), _capacity(0) {} + constexpr allocation(const alloc_t& alloc) noexcept + : _alloc(alloc), _data(nullptr), _capacity(0) {} /// /// \brief Sized Allocator Constructor @@ -200,7 +205,24 @@ public: /// \param alloc The allocation object to copy. /// /// \details This constructor should be used when the type `AllocT` needs internal data. - constexpr allocation(size_t n, const alloc_t& alloc) noexcept : _alloc(alloc), _data(nullptr), _capacity(0) {} + constexpr allocation(size_t n, const alloc_t& alloc) noexcept + : _alloc(alloc), _data(nullptr), _capacity(0) {} + + /// + /// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy + /// \param alloc The allocation to copy + constexpr allocation(const allocation& alloc) noexcept + : _alloc(alloc._alloc), _data(_alloc.allocate(alloc._capacity)), _capacity(alloc._capacity) + { fennec::memcpy(_data, alloc._data, alloc._capacity * sizeof(T)); } + + /// + /// \brief Move Constructor, moves the data in `alloc` to the new object and cleans `alloc` so that it + /// can safely destruct + /// \param alloc The allocation to move + constexpr allocation(allocation&& alloc) noexcept + : _alloc(alloc._alloc), _data(alloc._data), _capacity(alloc._capacity) + { alloc._data = nullptr; alloc._capacity = 0; } + /// /// \brief Default Destructor, releases the memory block if still present diff --git a/include/fennec/memory/memory.h b/include/fennec/memory/memory.h index 46fe744..44f3f82 100644 --- a/include/fennec/memory/memory.h +++ b/include/fennec/memory/memory.h @@ -20,6 +20,7 @@ #ifndef FENNEC_MEMORY_H #define FENNEC_MEMORY_H +#include #include namespace fennec @@ -152,22 +153,6 @@ constexpr void* memset(void* dst, int ch, size_t n) return dst; } - -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/pointers.h b/include/fennec/memory/pointers.h index 3d67b7d..50d66e7 100644 --- a/include/fennec/memory/pointers.h +++ b/include/fennec/memory/pointers.h @@ -19,19 +19,105 @@ #ifndef FENNEC_LANG_POINTERS_H #define FENNEC_LANG_POINTERS_H +#include -template +namespace fennec +{ + +template +struct default_delete +{ + /// + /// \brief Default constructor + constexpr default_delete() noexcept = default; + + /// + /// \brief Conversion Constructor + /// \tparam ConvT of other deleter + template requires requires { can_convert{}.value == true; } + constexpr default_delete(const default_delete&) noexcept {} + + /// + /// \brief Function Call Operator, calls `delete` on `ptr` + /// \param ptr Memory resource to delete + constexpr void operator()(TypeT* ptr) const noexcept + { + static_assert(not is_void_v, "cannot delete a pointer to an incomplete type"); + static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type"); + delete ptr; + } +}; + +template +struct default_delete +{ + /// + /// \brief Default constructor + constexpr default_delete() noexcept = default; + + /// + /// \brief Conversion Constructor + /// \tparam ConvT of other deleter + template requires requires { can_convert{}.value == true; } + constexpr default_delete(const default_delete&) noexcept {} + + /// + /// \brief Function Call Operator, calls `delete` on `ptr` + /// \param ptr Memory resource to delete + template requires requires { can_convert{}.value == true; } + constexpr void operator()(TypeT* ptr) const noexcept + { + static_assert(not is_void_v, "cannot delete a pointer to an incomplete type"); + static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type"); + delete[] ptr; + } +}; + +template> class unique_ptr { public: + /// \brief the element type using element_t = TypeT; + + /// \brief pointer to element type using pointer_t = element_t*; + /// \brief the deleter + using delete_t = DeleteT; + + /// + /// \brief Default Constructor, creates a unique_ptr that owns nothing. constexpr unique_ptr() : unique_ptr(nullptr) {} - constexpr unique_ptr(pointer_t ptr) : _handle(ptr) {} + + /// + /// \brief Nullptr Constructor, creates a unique_ptr that owns nothing. + constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr) {} + + /// + /// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del` + /// \param ptr The resource to own + /// \param del The deleter + explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del) : _delete(del), _handle(ptr) {} + + /// + /// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del` + /// \param ptr The resource to own + /// \param del The deleter + explicit constexpr unique_ptr(pointer_t ptr, delete_t&& del) : _delete(del), _handle(ptr) {} + + /// + /// \brief Move Constructor, transfers ownership from `other` + /// \param other The unique_ptr to take ownership from constexpr unique_ptr(unique_ptr&& other) : _handle(other._handle) { other._handle = nullptr; } - constexpr ~unique_ptr() { if(_handle) ::operator delete(_handle); } + // Delete copy constructor + constexpr unique_ptr(const unique_ptr&) = delete; + + /// + /// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t` + constexpr ~unique_ptr() { if(_handle) _delete(_handle); } + constexpr unique_ptr& operator=(unique_ptr&& r) noexcept { _handle = r._handle; r._handle = nullptr; return *this; } @@ -40,7 +126,10 @@ public: private: + delete_t _delete; pointer_t _handle; }; +} + #endif // FENNEC_LANG_POINTERS_H diff --git a/logo/raster.png b/logo/raster.png new file mode 100644 index 0000000000000000000000000000000000000000..8eeedab8fc791ecbec0f0c683d7357988fd54459 GIT binary patch literal 27827 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 P0eGXJBwzHx$nXCE$_RYw literal 0 HcmV?d00001 diff --git a/logo/vector.svg b/logo/vector.svg new file mode 100644 index 0000000..b77523f --- /dev/null +++ b/logo/vector.svg @@ -0,0 +1,70 @@ + + + + diff --git a/test.sh b/test.sh index 2039bdc..423384e 100755 --- a/test.sh +++ b/test.sh @@ -21,7 +21,7 @@ Help() { - echo "Bash script for building fennec from source." + echo "Bash script for running the fennec test suite. By default, the build script executes in debug mode." echo echo "GNU long options:" echo "--help (-h) = Print this help info." @@ -87,7 +87,7 @@ All() # Main Program ========================================================================================================= if [[ $# -eq 0 ]] ; then - All + Debug exit 0 fi