## 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 0000000..8eeedab
Binary files /dev/null and b/logo/raster.png differ
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