- Separated Platform and Compiler Dependent Behaviour into CMake scripts

- Implemented Basic Platform Interfaces
 - Implemented partial Linux platform and Wayland Display.
 - Implemented Dependencies for the above
   - map
     - set
       - optional
     - pair

TODO: threading
This commit is contained in:
2025-07-22 00:59:41 -04:00
parent ab1c7d94be
commit 73333b4c67
86 changed files with 3257 additions and 203 deletions

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "external/sdl"]
path = external/sdl
url = https://github.com/libsdl-org/SDL.git
[submodule "external/cpptrace"] [submodule "external/cpptrace"]
path = external/cpptrace path = external/cpptrace
url = https://github.com/jeremy-rifkin/cpptrace.git url = https://github.com/jeremy-rifkin/cpptrace.git

View File

@@ -1,34 +1,51 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
cmake_minimum_required(VERSION 3.30) cmake_minimum_required(VERSION 3.30)
project(fennec) project(fennec)
# External dependencies should be loaded here # External dependencies should be loaded here
# SDL is a dependency of the project, added as a git submodule
add_subdirectory(external/sdl)
# CppTrace is a dependency of the project, added as a git submodule # CppTrace is a dependency of the project, added as a git submodule
add_subdirectory(external/cpptrace) add_subdirectory(external/cpptrace)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD 23) set(CMAKE_C_STANDARD 23)
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
# include scripts
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
include("${FENNEC_SOURCE_DIR}/cmake/build.cmake")
# find dependencies # find dependencies
find_package(Doxygen) find_package(Doxygen)
fennec_check_platform()
# any necessary include directories # any necessary include directories
include_directories(${PROJECT_SOURCE_DIR}/include) include_directories(${FENNEC_SOURCE_DIR}/include)
# Metaprogramming is a dependency for generating various type info before compilation of the engine. # Metaprogramming is a dependency for generating various type info before compilation of the engine.
add_subdirectory(metaprogramming) add_subdirectory(metaprogramming)
string(TOLOWER ${CMAKE_BUILD_TYPE} FENNEC_BUILD_NAME)
message(STATUS "OS: ${CMAKE_SYSTEM_NAME}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
message(STATUS "Build: ${FENNEC_BUILD_NAME}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
# add the test suite as a sub-project # add the test suite as a sub-project
add_subdirectory(test) add_subdirectory(test)
@@ -42,6 +59,10 @@ add_library(fennec STATIC
# CONTAINERS =========================================================================================================== # CONTAINERS ===========================================================================================================
include/fennec/containers/array.h include/fennec/containers/array.h
include/fennec/containers/dynarray.h include/fennec/containers/dynarray.h
include/fennec/containers/map.h
include/fennec/containers/optional.h
include/fennec/containers/pair.h
include/fennec/containers/set.h
# LANG ================================================================================================================= # LANG =================================================================================================================
@@ -51,15 +72,17 @@ add_library(fennec STATIC
include/fennec/lang/bits.h include/fennec/lang/bits.h
include/fennec/lang/constants.h include/fennec/lang/constants.h
include/fennec/lang/conditional_types.h include/fennec/lang/conditional_types.h
include/fennec/lang/hashing.h
include/fennec/lang/intrinsics.h include/fennec/lang/intrinsics.h
include/fennec/lang/limits.h include/fennec/lang/limits.h
include/fennec/lang/numeric_transforms.h include/fennec/lang/numeric_transforms.h
include/fennec/lang/sequences.h include/fennec/lang/sequences.h
include/fennec/lang/type_identity.h
include/fennec/lang/type_sequences.h
include/fennec/lang/type_traits.h include/fennec/lang/type_traits.h
include/fennec/lang/type_transforms.h include/fennec/lang/type_transforms.h
include/fennec/lang/types.h include/fennec/lang/types.h
include/fennec/lang/utility.h include/fennec/lang/utility.h
include/fennec/lang/type_sequences.h
include/fennec/lang/integer.h include/fennec/lang/integer.h
include/fennec/lang/detail/__bits.h include/fennec/lang/detail/__bits.h
@@ -67,6 +90,7 @@ add_library(fennec STATIC
include/fennec/lang/detail/__numeric_transforms.h include/fennec/lang/detail/__numeric_transforms.h
include/fennec/lang/detail/__stdlib.h include/fennec/lang/detail/__stdlib.h
include/fennec/lang/detail/__type_traits.h include/fennec/lang/detail/__type_traits.h
include/fennec/lang/detail/__type_transforms.h
include/fennec/lang/detail/__type_sequences.h include/fennec/lang/detail/__type_sequences.h
include/fennec/lang/assert.h source/lang/assert.cpp include/fennec/lang/assert.h source/lang/assert.cpp
@@ -75,8 +99,9 @@ add_library(fennec STATIC
# MEMORY =============================================================================================================== # MEMORY ===============================================================================================================
include/fennec/memory/new.h source/memory/new.cpp include/fennec/memory/new.h source/memory/new.cpp
include/fennec/memory/common.h
include/fennec/memory/allocator.h include/fennec/memory/allocator.h
include/fennec/memory/bytes.h
include/fennec/memory/common.h
include/fennec/memory/memory.h include/fennec/memory/memory.h
include/fennec/memory/pointers.h include/fennec/memory/pointers.h
include/fennec/memory/ptr_traits.h include/fennec/memory/ptr_traits.h
@@ -110,10 +135,12 @@ add_library(fennec STATIC
include/fennec/math/ext/common.h include/fennec/math/ext/common.h
include/fennec/math/ext/constants.h include/fennec/math/ext/constants.h
include/fennec/math/ext/primes.h
include/fennec/math/ext/quaternion.h include/fennec/math/ext/quaternion.h
include/fennec/math/ext/transform.h include/fennec/math/ext/transform.h
include/fennec/math/ext/trigonometric.h include/fennec/math/ext/trigonometric.h
include/fennec/math/detail/__fwd.h include/fennec/math/detail/__fwd.h
include/fennec/math/detail/__math.h include/fennec/math/detail/__math.h
include/fennec/math/detail/__matrix.h include/fennec/math/detail/__matrix.h
@@ -132,32 +159,34 @@ add_library(fennec STATIC
# Filesystem # Filesystem
include/fennec/fproc/filesystem/file.h source/fproc/filesystem/file.cpp include/fennec/fproc/filesystem/file.h source/fproc/filesystem/file.cpp
include/fennec/fproc/filesystem/path.h source/fproc/filesystem/path.cpp include/fennec/fproc/filesystem/path.h source/fproc/filesystem/path.cpp
# PLATFORM =============================================================================================================
include/fennec/platform/interface/fwd.h
include/fennec/platform/interface/dialog.h
include/fennec/platform/interface/display.h
include/fennec/platform/interface/window.h source/platform/interface/window.cpp
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
${FENNEC_EXTRA_SOURCES}
) )
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled add_dependencies(fennec metaprogramming)
if(DOXYGEN_FOUND)
add_dependencies(fennec fennecdocs metaprogramming) # SDL3-shared cpptrace::cpptrace)
else()
add_dependencies(fennec metaprogramming) # SDL3-shared cpptrace::cpptrace)
endif()
# Compiler Warning Flags target_compile_definitions(fennec PUBLIC
if(MSVC) ${FENNEC_COMPILE_DEFINITIONS}
add_compile_options("/W4" "/WX") # All MSVC Warnings throw as Errors )
else()
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror") # All gcc/etc. Warnings throw as errors
target_compile_definitions(fennec PRIVATE _GLIBCXX_INCLUDE_NEXT_C_HEADERS __USE_FILE_OFFSET64)
endif()
target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f") # SIMD Instructions, automatic vectorization will occur
target_link_options(fennec PRIVATE "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates") # Do not compile base fennec library with c++ stdlib target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # 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. # 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 # This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
target_link_libraries(fennec PRIVATE SDL3-shared cpptrace::cpptrace) target_link_libraries(fennec PRIVATE
cpptrace::cpptrace
${FENNEC_LINK_LIBRARIES}
)
@@ -167,10 +196,11 @@ target_link_libraries(fennec PRIVATE SDL3-shared cpptrace::cpptrace)
file(COPY logo DESTINATION docs/logo) file(COPY logo DESTINATION docs/logo)
if(DOXYGEN_FOUND) if(DOXYGEN_FOUND)
set(DOXY_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/docs") add_dependencies(fennec fennecdocs)
get_filename_component(DOXYGEN_PROJECT_NAME ${PROJECT_SOURCE_DIR} NAME) # Set Doxy Project name to the name of the root dir set(DOXY_OUTPUT_DIR "${FENNEC_SOURCE_DIR}/docs")
set(DOXYGEN_CONFIG_IN "${PROJECT_SOURCE_DIR}/doxy/Doxyfile.in") # Input config file with preprocessor arguments get_filename_component(DOXYGEN_PROJECT_NAME ${FENNEC_SOURCE_DIR} NAME) # Set Doxy Project name to the name of the root dir
set(DOXYGEN_CONFIG_OUT "${PROJECT_SOURCE_DIR}/doxy/Doxyfile") # Generated config file from input set(DOXYGEN_CONFIG_IN "${FENNEC_SOURCE_DIR}/doxy/Doxyfile.in") # Input config file with preprocessor arguments
set(DOXYGEN_CONFIG_OUT "${FENNEC_SOURCE_DIR}/doxy/Doxyfile") # Generated config file from input
configure_file(${DOXYGEN_CONFIG_IN} ${DOXYGEN_CONFIG_OUT} @ONLY) # Execute preprocessing step configure_file(${DOXYGEN_CONFIG_IN} ${DOXYGEN_CONFIG_OUT} @ONLY) # Execute preprocessing step
message("Doxygen Build Started.") message("Doxygen Build Started.")
@@ -179,8 +209,8 @@ if(DOXYGEN_FOUND)
# Target for building docs # Target for building docs
add_custom_target(fennecdocs ALL add_custom_target(fennecdocs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT} COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${FENNEC_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/logo/raster.png COMMAND ${CMAKE_COMMAND} -E copy ${FENNEC_SOURCE_DIR}/logo/raster.png
${DOXY_OUTPUT_DIR}/logo/raster.png ${DOXY_OUTPUT_DIR}/logo/raster.png
COMMENT "Generating Doxygen Documentation" COMMENT "Generating Doxygen Documentation"
VERBATIM) VERBATIM)
@@ -189,7 +219,7 @@ if(DOXYGEN_FOUND)
# Target for cleaning docs # Target for cleaning docs
add_custom_target(fennecdocs-clean ALL add_custom_target(fennecdocs-clean ALL
COMMAND ${CMAKE_COMMAND} -E remove -f "${PROJECT_SOURCE_DIR}/docs" COMMAND ${CMAKE_COMMAND} -E remove -f "${FENNEC_SOURCE_DIR}/docs"
COMMENT "Cleaning Doxygen Documentation" COMMENT "Cleaning Doxygen Documentation"
VERBATIM) VERBATIM)
else() else()

View File

@@ -7,6 +7,7 @@
1. [Introduction](#introduction) 1. [Introduction](#introduction)
2. [TODO](#todo) 2. [TODO](#todo)
1. [Security Ramblings](#file-security-ramblings) 1. [Security Ramblings](#file-security-ramblings)
2. [Platform Support](#platform--api-support)
3. [C++ Language](#c-language-library-lang) 3. [C++ Language](#c-language-library-lang)
4. [Math Library](#math-library-math) 4. [Math Library](#math-library-math)
5. [Memory Library](#memory-library-memory) 5. [Memory Library](#memory-library-memory)
@@ -15,7 +16,7 @@
8. [Core](#core-core) 8. [Core](#core-core)
1. [Tick](#tick) 1. [Tick](#tick)
2. [Frame](#frame) 2. [Frame](#frame)
9. [Application Layer](#application-layer-app) 9. [Platform Support Layer](#platform-support-layer-platform)
10. [Scene](#scene-scene) 10. [Scene](#scene-scene)
11. [2D Graphics](#2d-graphics-gfx2d) 11. [2D Graphics](#2d-graphics-gfx2d)
12. [3D Graphics](#3d-graphics-gfx3d) 12. [3D Graphics](#3d-graphics-gfx3d)
@@ -152,6 +153,38 @@ Directories remain an issue, with `dirent.h` being the only sensible option at t
for MSVC. for MSVC.
### Platform & API Support
I have decided to forgo SDL, this is so the engine can provide specific support for specific platforms.
Also, SDL implements a lot of things that will need to be implemented specifically for the engine, so only the window
management would be used.
Platform support will be implemented in the following order:
- Linux/BSD
- Wayland
- XKB
- OpenGL (EGL)
- PulseAudio
- Vulkan
- X11
- OpenGL (EGL)
- ALSA
- Vulkan
- Microsoft Windows
- XInput
- OpenGL
- DirectSound
- Vulkan
- Android
- OpenGL ES
- macOS
- iOS
Most consoles will never get official platform support due to NDAs which conflict with the principles of this engine.
fennec will avoid using proprietary libraries except when strictly necessary, such as support for Windows and MacOS.
fennec will interact with any drivers required for the listed operating systems above, even if proprietary.
## C++ Language Library (`lang`) ## C++ Language Library (`lang`)
Implement header files for standard functions relating to the C++ Language. Implement header files for standard functions relating to the C++ Language.
@@ -320,14 +353,12 @@ in their operation order:
## Application Layer (`app`) ## Platform Support Layer (`platform`)
This is the core windowing system of fennec. The implementation will initially be an SDL3 wrapper.
Custom implementation may be further down the roadmap, however this is extremely complicated and there are better
implementations than I could write alone.
This is the core part of platform support for fennec. All necessary drivers
and OS specific functionality will be wrapped up nicely into these interfaces.
See implementation order [here](#platform--api-support)
## Scene (`scene`) ## Scene (`scene`)

View File

@@ -142,9 +142,9 @@ for more info.
build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
&ensp; I will at no point provide official cross-compilation toolchains for fennec, if you wish to compile your project for &ensp; I will at no point provide official cross-compilation toolchains for fennec. However, I will provide tools for
both Windows and Linux, working on Windows with WSL is likely your best option besides dual-booting. For Android and using specific toolchains for specific platforms that necessitate this. The primary examples would be Android and iOS.
iOS, using the GCC and Clang cross-compilation toolchains, respectively, will suffice. If you wish to build for Windows *and* Linux, your options are WSL or Dual Boot. I recommend Dual Boot over WSL.
<br> <br>
@@ -223,14 +223,17 @@ licensing that mesh under another license.
Any code that is linked against fennec or uses any part is by definition a covered work must be licensed under GPLv3. Any code that is linked against fennec or uses any part is by definition a covered work must be licensed under GPLv3.
&ensp; Later down the line, I plan on implementing scripts in a manner that allows the script itself to remain proprietary.
The scripts will likely be trans-compiled to another language before being compiled to binary, but this is only an
intermediate step and will be erased when no longer needed.
&ensp; As long as you use the official editor, it will properly include licenses in project content when provided a license &ensp; As long as you use the official editor, it will properly include licenses in project content when provided a license
and the name of the license holder. Archive packs will include the license holders non-GPLv3 license in them and any and the name of the license holder. Archive packs will include the license holders non-GPLv3 license in them and any
linked code will be covered by GPLv3 under the name of the license holder. Be aware that the parts of your project linked code will be covered by GPLv3 under the name of the license holder. Be aware that the parts of your project
licensed under GPLv3 must be available upon request. licensed under GPLv3 must be available upon request.
&ensp; A release project will consist of an executable, a shared library for your code, an archive pak, and streamable assets. &ensp; A release project will consist of an executable, a shared library for your code, an archive pak, and streamable assets.
The executable and shared library are protected under the GPLv3 license, while the archive pak and streamable assets are The executable and shared library are under the GPLv3 license, while the archive pak and streamable assets are under your license.
protected under your license.
It is to my discretion whether I enforce the terms of the license on a party. It is to my discretion whether I enforce the terms of the license on a party.

26
cmake/build.cmake Normal file
View File

@@ -0,0 +1,26 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
string(TOLOWER ${CMAKE_BUILD_TYPE} FENNEC_BUILD_NAME)
message(STATUS "Build: ${FENNEC_BUILD_NAME}")
if(${FENNEC_BUILD_NAME} MATCHES "debug")
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_RELEASE=false)
else()
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_RELEASE=true)
endif()

24
cmake/compiler.cmake Normal file
View File

@@ -0,0 +1,24 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=0)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set(FENNEC_COMPILER "GCC")
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")
endif()

23
cmake/gcc.cmake Normal file
View File

@@ -0,0 +1,23 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER=FENNEC_COMPILER_GCC)

63
cmake/libwayland.cmake Normal file
View File

@@ -0,0 +1,63 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
# https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a
macro(fennec_check_libwayland)
set(WAYLAND_CLIENT_FOUND 0)
find_path(
WAYLAND_CLIENT_INCLUDE_DIR
NAMES wayland-client.h
)
find_library(
WAYLAND_CLIENT_LIBRARY
NAMES wayland-client libwayland-client
)
get_filename_component(
WAYLAND_CLIENT_LIBRARY
${WAYLAND_CLIENT_LIBRARY}
NAME
)
if(WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY)
set(WAYLAND_CLIENT_FOUND 1)
add_library(wayland::client UNKNOWN IMPORTED)
set_target_properties(
wayland::client PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_CLIENT_INCLUDE_DIR}"
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${WAYLAND_CLIENT_LIBRARY}"
)
list(APPEND FENNEC_EXTRA_SOURCES
# Dynamic Library Files
include/fennec/platform/linux/wayland/lib/fwd.h
include/fennec/platform/linux/wayland/lib/sym.h
include/fennec/platform/linux/wayland/lib/sym_def.h
include/fennec/platform/linux/wayland/lib/dyn.h source/platform/linux/wayland/lib/dyn.cpp
# Fennec Files
include/fennec/platform/linux/wayland/display.h source/platform/linux/wayland/display.cpp
)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}")
endif()
endmacro()

37
cmake/linux.cmake Normal file
View File

@@ -0,0 +1,37 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
macro(fennec_check_platform)
# compile definitions
list(APPEND FENNEC_COMPILE_DEFINITIONS
FENNEC_PLATFORM_NAME="Linux"
FENNEC_PLATFORM_LINUX=1
)
# extra source files
list(APPEND FENNEC_EXTRA_SOURCES
include/fennec/platform/linux/platform.h source/platform/linux/platform.cpp
)
# includes
include("${FENNEC_SOURCE_DIR}/cmake/libwayland.cmake")
# tests
fennec_check_libwayland()
endmacro()

25
cmake/platform.cmake Normal file
View File

@@ -0,0 +1,25 @@
# ======================================================================================================================
# 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/>.
# ======================================================================================================================
message(STATUS "OS: ${CMAKE_SYSTEM_NAME}")
# Check for Linux
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(FENNEC_PLATFORM "Linux")
include("${FENNEC_SOURCE_DIR}/cmake/linux.cmake")
endif ()

1
external/sdl vendored

Submodule external/sdl deleted from d7939abf42

View File

@@ -38,7 +38,7 @@
namespace fennec namespace fennec
{ {
template<class TypeT, class Alloc> template<class TypeT, class Alloc = allocator<TypeT>>
class dynarray class dynarray
{ {
public: public:
@@ -129,7 +129,9 @@ public:
void insert(size_t i, const TypeT& val) { void insert(size_t i, const TypeT& val) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow(); if(_size == capacity()) {
_grow();
}
// Move the data if we are not inserting at the end of the array // Move the data if we are not inserting at the end of the array
if((i = min(i, _size)) < _size) { if((i = min(i, _size)) < _size) {
@@ -141,30 +143,36 @@ public:
// Insert the element // Insert the element
fennec::construct(_alloc.data() + i, val); fennec::construct(_alloc.data() + i, val);
++_size;
} }
void insert(size_t i, TypeT&& val) { void insert(size_t i, TypeT&& val) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow(); if(_size == capacity()) {
_grow();
}
// Move the data if we are not inserting at the end of the array // Move the data if we are not inserting at the end of the array
if((i = min(i, _size)) < _size) { if((i = min(i, _size)) < _size) {
fennec::memmove( fennec::memmove(
_alloc.data() + i _alloc.data() + i + 1
, _alloc.data() + i + 1 , _alloc.data() + i
, (_size - i) * sizeof(TypeT)); , (_size - i) * sizeof(TypeT));
} }
// Insert the element // Insert the element
fennec::construct(_alloc.data() + i, fennec::forward<TypeT>(val)); fennec::construct(_alloc.data() + i, fennec::forward<TypeT>(val));
++_size;
} }
template<typename...ArgsT> template<typename...ArgsT>
void emplace(size_t i, ArgsT&&...args) { void emplace(size_t i, ArgsT&&...args) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow(); if(_size == capacity()) {
_grow();
}
// Move the data if we are not inserting at the end of the array // Move the data if we are not inserting at the end of the array
if((i = min(i, _size)) < _size) { if((i = min(i, _size)) < _size) {
@@ -176,6 +184,7 @@ public:
// Insert the element // Insert the element
fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...); fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...);
++_size;
} }
void push_back(const TypeT& val) { void push_back(const TypeT& val) {
@@ -190,8 +199,14 @@ public:
dynarray::emplace(_size, fennec::forward<ArgsT>(args)...); dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
} }
void resize(size_t n) {
_alloc.reallocate(n);
}
private: private:
void _grow() const { _alloc.reallocate(_alloc.capacity() * 2); } void _grow() {
_alloc.reallocate(_alloc.capacity() * 2);
}
allocation<element_t, alloc_t> _alloc; allocation<element_t, alloc_t> _alloc;
size_t _size; size_t _size;

View File

@@ -0,0 +1,50 @@
// =====================================================================================================================
// 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_CONTAINERS_MAP_H
#define FENNEC_CONTAINERS_MAP_H
#include <fennec/containers/pair.h>
#include <fennec/containers/set.h>
namespace fennec
{
// TODO: Document
template<typename KeyT, typename ValueT, typename Hash = hash<KeyT>, typename Alloc = allocator<pair<KeyT, ValueT>>>
struct map {
public:
using key_t = KeyT;
using value_t = ValueT;
using elem_t = pair<KeyT, ValueT>;
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>;
using hash_t = Hash;
map() = default;
~map() = default;
private:
set<elem_t, hash_t, alloc_t> _set;
};
}
#endif // FENNEC_CONTAINERS_MAP_H

View File

@@ -0,0 +1,247 @@
// =====================================================================================================================
// 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_CONTAINERS_OPTIONAL_H
#define FENNEC_CONTAINERS_OPTIONAL_H
#include <fennec/lang/utility.h>
#include <fennec/memory/new.h>
#include <fennec/lang/assert.h>
namespace fennec
{
struct nullopt_t {};
constexpr nullopt_t nullopt_v = {};
#define nullopt nullopt_v
///
/// \brief Structure to hold an optional value.
/// \tparam T
template<typename T>
struct optional {
public:
// Constructors ========================================================================================================
///
/// \brief Default Constructor
constexpr optional()
: _root(0)
, _set(false) {
}
///
/// \brief Default Constructor
constexpr optional(nullopt_t)
: _root(0)
, _set(false) {
}
///
/// \brief Fundamental Type Constructor
/// \param val the value to initialize the underlying object with
constexpr optional(T val) requires is_fundamental_v<T>
: _val(val)
, _set(true) {
}
///
/// \brief Type Copy Constructor
/// \param val the value to initialize the underlying object with
constexpr optional(const T& val)
: _val(val)
, _set(true) {
}
///
/// \brief Copy Constructor
/// \param opt the optional to copy
constexpr optional(const optional& opt) requires is_copy_assignable_v<T>
: optional() {
_set = opt._set;
if (_set) {
_val = opt._val;
}
}
///
/// \brief Move Constructor
/// \param opt the optional to move
constexpr optional(optional&& opt) noexcept requires is_move_assignable_v<T>
: optional() {
_set = opt._set;
if (_set) {
_val = fennec::move(opt._val);
}
opt = nullopt;
}
constexpr ~optional() {
if constexpr(is_fundamental_v<T>) {
return;
}
if (_set) {
_val.~T();
}
}
// Assignment Operators ================================================================================================
///
/// \brief Fundamental Type Assignment
/// \val The value to set with
constexpr optional& operator=(nullopt_t) {
if constexpr(not is_fundamental_v<T>) {
if (_set) {
_val.~T();
}
}
_root = '\0';
_set = false;
return *this;
}
///
/// \brief Type Copy Assignment
/// \val The value to set with
constexpr optional& operator=(const T& val) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set) {
_val = val;
} else {
fennec::construct(&_val, val);
_set = true;
}
return *this;
}
///
/// \brief Type Move Assignment
/// \val The value to set with
constexpr optional& operator=(T&& val) requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set) {
_val = fennec::move(val);
} else {
fennec::construct(&_val, fennec::move(val));
_set = true;
}
return *this;
}
///
/// \brief Copy Assignment
/// \val The optional to copy
constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set != opt._set) {
_set = opt._set;
if (_set) { // Construct
fennec::construct(&_val, opt._val);
} else { // Destruct
_val.~T();
_root = 0;
}
} else if (_set) { // Copy Assignment
_val = opt._val;
}
return *this;
}
///
/// \brief Move Assignment
/// \val The optional to move
constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set != opt._set) {
_set = opt._set;
if (_set) { // Construct
fennec::construct(&_val, fennec::move(opt._val));
} else { // Destruct
_val.~T();
_root = 0;
}
} else if (_set) { // Copy Assignment
_val = fennec::move(opt._val);
}
return *this;
}
template<typename...ArgsT>
constexpr T& emplace(ArgsT&&...args) {
if (_set) {
_val = T(fennec::forward<ArgsT>(args)...);
} else {
fennec::construct(&_val, fennec::forward<ArgsT>(args)...);
_set = true;
}
return _val;
}
void reset() {
this->operator=(nullopt);
}
// Operators ===========================================================================================================
constexpr operator bool() const {
return _set;
}
constexpr T* operator->() noexcept {
return _set ? &_val : nullptr;
}
constexpr const T* operator->() const noexcept {
return _set ? &_val : nullptr;
}
constexpr T& operator*() & noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
constexpr const T& operator*() const& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
constexpr T&& operator*() && noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
constexpr const T&& operator*() const&& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
private:
union {
char _root;
T _val;
};
bool _set;
};
}
#endif // FENNEC_CONTAINERS_OPTIONAL_H

View File

@@ -0,0 +1,91 @@
// =====================================================================================================================
// 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_CONTAINERS_PAIR_H
#define FENNEC_CONTAINERS_PAIR_H
#include <fennec/lang/hashing.h>
#include <fennec/lang/utility.h>
namespace fennec
{
// TODO: Document
template<typename T0, typename T1>
struct pair {
constexpr pair() = default;
constexpr ~pair() = default;
constexpr pair(const T0& x, const T1& y)
: first(x)
, second(y) {
}
constexpr pair(T0&& x, T1&& y) noexcept
: first(fennec::forward<T0>(x))
, second(fennec::forward<T1>(y)) {
}
constexpr pair(const pair&) = default;
constexpr pair(pair&&) noexcept = default;
pair& operator=(const pair&) = default;
pair& operator=(pair&&) noexcept = default;
bool operator==(const pair& p) const {
return first == p.first and second == p.second;
}
bool operator!=(const pair& p) const {
return first != p.first or second != p.second;
}
bool operator<(const pair& p) const {
return first < p.first or (first == p.first and second < p.second);
}
bool operator<=(const pair& p) const {
return first < p.first or (first == p.first and second <= p.second);
}
bool operator>(const pair& p) const {
return first > p.first or (first == p.first and second > p.second);
}
bool operator>=(const pair& p) const {
return first > p.first or (first == p.first and second >= p.second);
}
T0 first;
T1 second;
};
template<typename T0, typename T1>
struct hash<pair<T0, T1>> : hash<T0>, hash<T1> {
constexpr size_t operator()(const pair<T0, T1>& p) const {
return fennec::pair_hash( // pair the hashes of both elements
hash<T0>::operator()(p.first),
hash<T1>::operator()(p.second)
);
}
};
}
#endif // FENNEC_CONTAINERS_PAIR_H

View File

@@ -0,0 +1,297 @@
// =====================================================================================================================
// 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_CONTAINERS_SET_H
#define FENNEC_CONTAINERS_SET_H
// https://programming.guide/robin-hood-hashing.html
#include <fennec/containers/optional.h>
#include <fennec/math/ext/primes.h>
#include <fennec/memory/allocator.h>
#include <fennec/lang/hashing.h>
namespace fennec
{
// TODO: Document
template<typename T, class Hash = hash<T>, class Alloc = allocator<T>>
struct set {
public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<T>;
using hash_t = Hash;
using elem_t = T;
class iterator;
static constexpr size_t npos = -1;
private:
struct node {
optional<elem_t> value;
int psl;
constexpr node() = default;
constexpr ~node() = default;
};
public:
constexpr set()
: _alloc()
, _hash()
, _size(0) {
};
constexpr set(const hash_t& hash)
: _alloc()
, _hash(hash)
, _size(0) {
}
constexpr set(hash_t&& hash) noexcept
: _alloc()
, _hash(hash)
, _size(0) {
}
constexpr set(const alloc_t& alloc)
: _alloc(alloc)
, _hash()
, _size(0) {
}
constexpr set(alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash()
, _size(0) {
}
constexpr set(const hash_t& hash, const alloc_t& alloc)
: _alloc(alloc)
, _hash(hash)
, _size(0) {
}
constexpr set(const hash_t& hash, alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
, _size(0) {
}
constexpr set(hash_t&& hash, alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
, _size(0) {
}
constexpr set(hash_t&& hash, const alloc_t& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
, _size(0) {}
constexpr set(const set& set)
: _alloc(set._alloc)
, _hash(set._hash)
, _size(set._size) {
}
constexpr set(set&& set) noexcept
: _alloc(fennec::move(set._alloc))
, _hash(fennec::move(set._hash))
, _size(fennec::move(set._size)) {
}
constexpr ~set() = default;
constexpr size_t size() const {
return _size;
}
constexpr size_t capacity() const {
return _alloc.capacity();
}
constexpr void insert(elem_t&& val) {
if (_size >= capacity()) { // expand when full
_expand();
}
elem_t value = fennec::forward<elem_t>(val);
size_t i = _hash(value) % capacity(); // Initial search index
int psl = 0;
while (_alloc[i].value) { // Search for empty cell
if (*_alloc[i].value == val) { // Check to see if this element is already inserted
return;
}
if (psl >= _alloc[i].psl) { // When psl is higher, swap
fennec::swap(*_alloc[i].value, value);
fennec::swap(_alloc[i].psl, psl);
}
i = (i + 1) % capacity(); ++psl;
}
_alloc[i].value = fennec::move(value);
_alloc[i].psl = psl;
++_size;
}
constexpr void insert(const elem_t& val) {
elem_t value = val; // Copy Constructor invoked here
this->insert(fennec::move(value)); // Only invokes moves
}
template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) {
elem_t value = elem_t(fennec::forward<ArgsT>(args)...); // Constructor invoked here
this->insert(fennec::move(value)); // Only invokes moves
}
constexpr iterator find(const elem_t& val) const {
size_t i = _hash(val) % capacity(); // Initial search index
int psl = 0;
// Loop while there is a value and its psl is greater than our probe
while (_alloc[i].value && _alloc[i].psl > psl) {
if (*_alloc[i].value == val) {
return iterator(this, i);
}
i = (i + 1) % capacity(); ++psl;
}
return iterator(this, npos);
}
constexpr bool contains(const elem_t& val) const {
return this->find(val) != end();
}
constexpr void erase(iterator it) {
size_t i = it._i;
if (i >= capacity()) {
return;
} // These are separated due to compilers being inconsistent
if (not _alloc[i].value) {
return;
}
_alloc[i].value = nullopt;
--_size;
size_t p = i;
while (_alloc[i = (i + 1) % capacity()].value) {
size_t psl = _alloc[i].psl;
if (psl == 0) break;
fennec::swap(_alloc[i - 1].value, _alloc[i].value);
_alloc[p].psl = psl - 1;
p = i;
}
}
constexpr void erase(const elem_t& val) {
this->erase(this->find(val));
}
// ITERATOR ============================================================================================================
class iterator {
public:
constexpr iterator(const set* set, size_t i)
: _set(set)
, _i(i) {
}
constexpr ~iterator() {
_set = nullptr;
}
// prefix operator
constexpr friend iterator& operator++(iterator& rhs) {
while (++rhs._i < capacity()) {
if (rhs._set->_alloc[rhs._i]) {
return rhs;
}
}
rhs._i = npos;
return rhs;
}
constexpr friend iterator operator++(iterator& lhs, int) {
iterator prev = lhs;
++lhs;
return prev;
}
constexpr const elem_t& operator*() const {
return *_set->_alloc[_i].value;
}
constexpr bool operator==(const iterator& it) {
return _set == it._set and _i == it._i;
}
constexpr bool operator!=(const iterator& it) {
return _set != it._set or _i != it._i;
}
private:
const set* _set;
size_t _i;
};
constexpr iterator begin() const {
iterator it(this, 0);
if (not _alloc[it._i].value) {
++it;
}
return it;
}
constexpr iterator end() const {
return iterator(this, npos);
}
// PRIVATE =============================================================================================================
private:
constexpr void _expand() {
set cpy; // Create a new set
cpy._alloc.allocate(
fennec::next_prime2(_alloc.capacity())
);
fennec::memset(cpy._alloc.data(), 0, cpy._alloc.size());
// rehash
for (size_t i = 0; i < capacity(); ++i) {
if (_alloc[i].value) {
cpy.insert(fennec::move(*_alloc[i].value));
}
}
// Swap buffers
fennec::swap(_alloc, cpy._alloc);
}
allocation<node, alloc_t> _alloc;
hash_t _hash;
size_t _size;
};
}
#endif // FENNEC_CONTAINERS_SET_H

View File

@@ -99,7 +99,8 @@ public:
/// \details adds additional character for null termination. Ignores whether str is null-terminated. /// \details adds additional character for null termination. Ignores whether str is null-terminated.
/// This constructor makes the assumption that `n` is the intended number of characters. /// This constructor makes the assumption that `n` is the intended number of characters.
constexpr _string(const char* str, size_t n) constexpr _string(const char* str, size_t n)
: _str(str, n + 1) { : _str(n + 1) {
fennec::memcpy(_str.data(), str, n);
_str[n] = '\0'; _str[n] = '\0';
} }
@@ -318,7 +319,7 @@ public:
constexpr void resize(size_t n) { constexpr void resize(size_t n) {
size_t i = size(); size_t i = size();
_str.reallocate(n + 1); _str.reallocate(n + 1);
if (n > i) fennec::memset(_str.data() + i, '\0', n - i); if (n > i) fennec::memset(_str.data() + i, '\0', n + 1 - i);
} }
/// ///
@@ -387,6 +388,10 @@ public:
return res; return res;
} }
friend constexpr _string operator+(char c, _string& str) {
return _string(c, 1) + str;
}
constexpr _string operator+(const cstring& str) const { constexpr _string operator+(const cstring& str) const {
_string res(size() + str.size()); // Make a new string with the size of this + str _string res(size() + str.size()); // Make a new string with the size of this + str
fennec::memcpy(&res[0], _str.data(), size()); // Copy the contents of this fennec::memcpy(&res[0], _str.data(), size()); // Copy the contents of this

View File

@@ -46,7 +46,12 @@
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// assert(expr, desc) /// assert(expr, desc)
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// Make an assertion with expression `expr` and provide a description `desc`. /// Make an assertion with expression `expr` and provide a description `desc`. Only halts in debug mode.
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assertf(expr, desc)
/// <td width="50%" style="vertical-align: top">
/// Make an assertion with expression `expr` and provide a description `desc`. Always halts.
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// assertd(expr, desc) /// assertd(expr, desc)
@@ -65,15 +70,20 @@
using assert_handler = void (*)(const char *, const char *, int , const char *); using assert_handler = void (*)(const char *, const char *, int , const char *);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc); void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc, bool halt);
// flagged unlikely to optimize branch prediction // flagged unlikely to optimize branch prediction
#define assert(expression, description) \ #define assert(expression, description) \
if(not(expression)) [[unlikely]] { \ if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); \ __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, not FENNEC_RELEASE); \
} }
#ifdef NDEBUG #define assertf(expression, description) \
if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, true); \
}
#if FENNEC_RELEASE
#define assertd(expression, description) (0) #define assertd(expression, description) (0)
#else #else
#define assertd(expression, description) assert(expression, description) #define assertd(expression, description) assert(expression, description)

View File

@@ -32,6 +32,8 @@
#ifndef FENNEC_LANG_CONDITIONAL_TYPES_H #ifndef FENNEC_LANG_CONDITIONAL_TYPES_H
#define FENNEC_LANG_CONDITIONAL_TYPES_H #define FENNEC_LANG_CONDITIONAL_TYPES_H
#include <fennec/lang/type_identity.h>
/// ///
/// \page fennec_lang_conditional_types Conditional Types /// \page fennec_lang_conditional_types Conditional Types
/// ///
@@ -64,8 +66,6 @@
/// ///
/// ///
#include <fennec/lang/type_transforms.h>
namespace fennec namespace fennec
{ {
@@ -92,12 +92,12 @@ using conditional_t
// specialization of fennec::conditional for `true` case // specialization of fennec::conditional for `true` case
template<typename T, typename F> template<typename T, typename F>
struct conditional<true, T, F> : type_transform<T>{}; struct conditional<true, T, F> : type_identity<T>{};
// specialization of fennec::conditional for `false` case // specialization of fennec::conditional for `false` case
template<typename T, typename F> template<typename T, typename F>
struct conditional<false, T, F> : type_transform<F>{}; struct conditional<false, T, F> : type_identity<F>{};
// fennec::detect ====================================================================================================== // fennec::detect ======================================================================================================

View File

@@ -28,34 +28,34 @@ namespace fennec
namespace detail namespace detail
{ {
template<typename> struct __make_unsigned : type_transform<undefined_t> {}; template<typename> struct __make_unsigned : type_identity<undefined_t> {};
template<> struct __make_unsigned<char_t> : type_transform<uchar_t> {}; template<> struct __make_unsigned<char_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_transform<uchar_t> {}; template<> struct __make_unsigned<uchar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<schar_t> : type_transform<uchar_t> {}; template<> struct __make_unsigned<schar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<short_t> : type_transform<ushort_t> {}; template<> struct __make_unsigned<short_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<ushort_t> : type_transform<ushort_t> {}; template<> struct __make_unsigned<ushort_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<uint_t> : type_transform<uint_t> {}; template<> struct __make_unsigned<uint_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<int_t> : type_transform<uint_t> {}; template<> struct __make_unsigned<int_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<long_t> : type_transform<ulong_t> {}; template<> struct __make_unsigned<long_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<ulong_t> : type_transform<ulong_t> {}; template<> struct __make_unsigned<ulong_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<llong_t> : type_transform<ullong_t> {}; template<> struct __make_unsigned<llong_t> : type_identity<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_transform<ullong_t> {}; template<> struct __make_unsigned<ullong_t> : type_identity<ullong_t> {};
template<typename> struct __make_signed : type_transform<undefined_t> {}; template<typename> struct __make_signed : type_identity<undefined_t> {};
template<> struct __make_signed<char_t> : type_transform<schar_t> {}; template<> struct __make_signed<char_t> : type_identity<schar_t> {};
template<> struct __make_signed<uchar_t> : type_transform<schar_t> {}; template<> struct __make_signed<uchar_t> : type_identity<schar_t> {};
template<> struct __make_signed<schar_t> : type_transform<schar_t> {}; template<> struct __make_signed<schar_t> : type_identity<schar_t> {};
template<> struct __make_signed<short_t> : type_transform<short_t> {}; template<> struct __make_signed<short_t> : type_identity<short_t> {};
template<> struct __make_signed<ushort_t> : type_transform<short_t> {}; template<> struct __make_signed<ushort_t> : type_identity<short_t> {};
template<> struct __make_signed<uint_t> : type_transform<int_t> {}; template<> struct __make_signed<uint_t> : type_identity<int_t> {};
template<> struct __make_signed<int_t> : type_transform<int_t> {}; template<> struct __make_signed<int_t> : type_identity<int_t> {};
template<> struct __make_signed<long_t> : type_transform<long_t> {}; template<> struct __make_signed<long_t> : type_identity<long_t> {};
template<> struct __make_signed<ulong_t> : type_transform<long_t> {}; template<> struct __make_signed<ulong_t> : type_identity<long_t> {};
template<> struct __make_signed<llong_t> : type_transform<llong_t> {}; template<> struct __make_signed<llong_t> : type_identity<llong_t> {};
template<> struct __make_signed<ullong_t> : type_transform<llong_t> {}; template<> struct __make_signed<ullong_t> : type_identity<llong_t> {};
} }

View File

@@ -27,7 +27,7 @@ namespace fennec
namespace detail namespace detail
{ {
template<typename FirstT, typename... RestT> struct __first_element : type_transform<FirstT>{}; template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT>{};
} }

View File

@@ -65,6 +65,9 @@ template<typename> struct __is_floating_point : false_type {};
template<> struct __is_floating_point<float_t> : true_type {}; template<> struct __is_floating_point<float_t> : true_type {};
template<> struct __is_floating_point<double_t> : true_type {}; template<> struct __is_floating_point<double_t> : true_type {};
template<typename> struct __is_pointer : false_type {};
template<typename T> struct __is_pointer<T*> : true_type {};
} }
} }

View File

@@ -0,0 +1,55 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
#define FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
#include <fennec/lang/types.h>
namespace fennec
{
namespace detail
{
template<typename _Tp, typename = void>
struct __add_lvalue_reference {
using type = _Tp;
};
template<typename _Tp>
struct __add_lvalue_reference<_Tp, void_t<_Tp&>> {
using type = _Tp&;
};
template<typename _Tp, typename = void>
struct __add_rvalue_reference {
using type = _Tp;
};
template<typename _Tp>
struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> {
using type = _Tp&&;
};
}
}
#endif // FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H

View File

@@ -0,0 +1,89 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_HASHING_H
#define FENNEC_LANG_HASHING_H
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
namespace fennec
{
///
/// \brief Struct for hashing types, there is no default hashing function
/// \tparam Key The type to hash
template<typename Key> struct hash;
// Murmur3 Hash for 64-bit ints
template<>
struct hash<uint64_t> {
using type_t = uint64_t;
constexpr size_t operator()(uint64_t x) const {
// Murmur3
x ^= x >> 33U;
x *= 0xff51afd7ed558ccd;
x ^= x >> 33U;
x *= 0xc4ceb9fe1a85ec53;
x ^= x >> 33U;
return x;
}
};
// Wrapper for casting ints
template<typename IntT>
requires is_integral_v<IntT>
struct hash<IntT> : hash<uint64_t> {
using type_t = IntT;
};
// Wrapper for pointers
template<typename PtrT>
requires is_pointer_v<PtrT>
struct hash<PtrT> : hash<uintptr_t> {
};
// Float
template<>
struct hash<float> : hash<uint32_t> {
constexpr size_t operator()(float x) const {
return hash<uint32_t>::operator()(bit_cast<uint32_t>(x));
}
};
template<>
struct hash<double> : hash<uint64_t> {
constexpr size_t operator()(double x) const {
return hash<uint64_t>::operator()(bit_cast<uint64_t>(x));
}
};
///
/// \brief Pairs two hashes
/// \param x first hash
/// \param y second hash
/// \returns a pairing of the two hashes
constexpr size_t pair_hash(size_t x, size_t y) {
// Szudzik Pairing
return (x >= y ? (x * x) + x + y : (y * y) + x);
}
}
#endif // FENNEC_LANG_HASHING_H

View File

@@ -142,14 +142,44 @@
# define FENNEC_HAS_BUILTIN_IS_CLASS # define FENNEC_HAS_BUILTIN_IS_CLASS
#endif #endif
// CONSTRUCTORS ========================================================================================================
// Difficult and Inconsistent without intrinsics // Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_constructible) #if __has_builtin(__is_constructible)
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1 # define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type, __VA_ARGS__) # define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type __VA_OPT__(,) __VA_ARGS__)
#else #else
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0 # define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
#endif #endif
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_trivially_constructible)
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(type) __is_trivially_constructible(type)
#else
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0
#endif
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__has_trivial_destructor)
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __has_trivial_destructor(type)
#else
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
#endif
// ASSIGNMENTS =========================================================================================================
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_assignable)
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 1
# define FENNEC_BUILTIN_IS_ASSIGNABLE(a, b) __is_assignable(a, b)
#else
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
#endif
// Type Traits // Type Traits
// can_convert is also very difficult to implement without intrinsics // can_convert is also very difficult to implement without intrinsics
#if __has_builtin(__is_convertible) #if __has_builtin(__is_convertible)

View File

@@ -0,0 +1,57 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_TYPE_IDENTITY_H
#define FENNEC_LANG_TYPE_IDENTITY_H
///
/// \page fennec_lang_type_identity Type Identity
///
/// \brief Part of the fennec metaprogramming library. This header defines structures for copying types with different traits
/// or rather, transform them, at compile time.
///
/// \code #include <fennec/lang/type_identity.h> \endcode
///
///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_identity">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::type_identity "type_identity<TypeT>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::type_identity
/// </table>
///
namespace fennec
{
///
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_identity {
/// \brief the type to transform into
using type = T;
};
}
#endif // FENNEC_LANG_TYPE_IDENTITY_H

View File

@@ -272,6 +272,22 @@ template<typename T> struct is_floating_point
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {}; template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
// Pointer Types =======================================================================================================
///
/// \brief check if \p T is of a floating point type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \tparam T type to check
template<typename T> struct is_pointer
: detail::__is_pointer<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
// Arithmetic Types ==================================================================================================== // Arithmetic Types ====================================================================================================
@@ -339,7 +355,7 @@ template<typename FromT, typename ToT> struct is_convertible
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{}; template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
// fennec::is_constructible =============================================================================================== // fennec::is_constructible ============================================================================================
/// ///
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`. /// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
@@ -354,7 +370,106 @@ template<typename ClassT, typename...ArgsT> struct is_constructible
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{}; template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{};
// fennec::
///
/// \brief Check if `ClassT` is default constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_default_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT,)> {};
///
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is copy constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_copy_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
///
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructible_v = is_copy_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is copy constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_move_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
///
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is trivially constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_trivially_constructible
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
///
/// \brief Shorthand for `is_trivially_constructible<ClassT, ArgsT...>::value`
template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_trivially_constructible<ClassT>{};
// fennec::is_trivially_destructible ===================================================================================
///
/// \brief Check if `ClassT` is trivially destructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_trivially_destructible
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
///
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
// fennec::is_assignable ===============================================================================================
///
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
/// This may be read as "is `ClassT` constructible with `ArgsT`"
/// \tparam ClassAT The class type to test
/// \tparam ClassBT The arguments for the specific constructor
template<typename ClassAT, typename ClassBT> struct is_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(ClassAT, ClassBT)> {};
///
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_assignable_v = is_assignable<ClassT, ArgsT...>{};
// fennec::is_copy_assignable ==========================================================================================
///
/// \brief Check if `ClassT` is copy assignable
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_copy_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
///
/// \brief Shorthand for `is_copy_assignable<ClassT>::value`
template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assignable<ClassT>{};
// fennec::is_move_assignable ==========================================================================================
///
/// \brief Check if `ClassT` is move assignable
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_move_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
///
/// \brief Shorthand for `is_move_assignable<ClassT>::value`
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
// //

View File

@@ -31,6 +31,9 @@
#ifndef FENNEC_LANG_TYPE_TRANSFORMS_H #ifndef FENNEC_LANG_TYPE_TRANSFORMS_H
#define FENNEC_LANG_TYPE_TRANSFORMS_H #define FENNEC_LANG_TYPE_TRANSFORMS_H
#include <fennec/lang/type_identity.h>
#include <fennec/lang/detail/__type_transforms.h>
/// ///
/// \page fennec_lang_type_transforms Type Transforms /// \page fennec_lang_type_transforms Type Transforms
/// ///
@@ -44,11 +47,6 @@
/// <tr><th style="vertical-align: top">Syntax /// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::type_transform "type_transform<TypeT>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::type_transform
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_pointer "add_pointer<TypeT>::type"<br> /// \ref fennec::add_pointer "add_pointer<TypeT>::type"<br>
/// \ref fennec::add_pointer_t "add_pointer_t<TypeT>" /// \ref fennec::add_pointer_t "add_pointer_t<TypeT>"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
@@ -127,22 +125,6 @@
namespace fennec namespace fennec
{ {
// fennec::type_transform ==============================================================================================
///
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_transform {
///
/// \brief the type to transform into
using type = T;
};
// Pointer Conversions ================================================================================================= // Pointer Conversions =================================================================================================
/// ///
@@ -150,7 +132,7 @@ template<typename T> struct type_transform {
/// ///
/// \details adds a pointer to the provided type such that `T` becomes `T*` /// \details adds a pointer to the provided type such that `T` becomes `T*`
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct add_pointer : type_transform<T*>{}; template<typename T> struct add_pointer : type_identity<T*>{};
/// ///
/// \brief shorthand for `typename add_pointer<T>::type` /// \brief shorthand for `typename add_pointer<T>::type`
@@ -162,10 +144,10 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
/// ///
/// \details removes a pointer from the provided type such that `T*` becomes `T` /// \details removes a pointer from the provided type such that `T*` becomes `T`
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct remove_pointer : type_transform<T> {}; template<typename T> struct remove_pointer : type_identity<T> {};
// specialization for T* // specialization for T*
template<typename T> struct remove_pointer<T*> : type_transform<T> {}; template<typename T> struct remove_pointer<T*> : type_identity<T> {};
/// ///
/// \brief shorthand for `typename remove_pointer<T>::type` /// \brief shorthand for `typename remove_pointer<T>::type`
@@ -180,7 +162,7 @@ template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
/// ///
/// \details adds a pointer to the provided type such that `T` becomes `T&` /// \details adds a pointer to the provided type such that `T` becomes `T&`
/// \tparam T Resultant Type /// \tparam T Resultant Type
template<typename T> struct add_reference : type_transform<T&> {}; template<typename T> struct add_reference : type_identity<T&> {};
/// ///
/// \brief shorthand for `typename add_reference<T>::type` /// \brief shorthand for `typename add_reference<T>::type`
@@ -192,19 +174,43 @@ template<typename T> using add_reference_t = typename add_reference<T>::type;
/// ///
/// \details removes references from the provided type such that `T&` and `T&&` become `T` /// \details removes references from the provided type such that `T&` and `T&&` become `T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_reference : type_transform<T> {}; template<typename T> struct remove_reference : type_identity<T> {};
// specialization for `T&` // specialization for `T&`
template<typename T> struct remove_reference<T&> : type_transform<T> {}; template<typename T> struct remove_reference<T&> : type_identity<T> {};
// specialization for `T&&` // specialization for `T&&`
template<typename T> struct remove_reference<T&&> : type_transform<T> {}; template<typename T> struct remove_reference<T&&> : type_identity<T> {};
/// ///
/// \brief shorthand for `typename remove_reference<T>::type` /// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using remove_reference_t = typename remove_reference<T>::type; template<typename T> using remove_reference_t = typename remove_reference<T>::type;
///
/// \brief add a lvalue reference to \p T
///
/// \details adds a lvalue reference to the provided type such that 'T' becomes 'T&'
/// \tparam T Reference Type
template<typename T> struct add_lvalue_reference : detail::__add_lvalue_reference<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
///
/// \brief add a rvalue reference to \p T
///
/// \details adds a rvalue reference to the provided type such that 'T' becomes 'T&&'
/// \tparam T Reference Type
template<typename T> struct add_rvalue_reference : detail::__add_rvalue_reference<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
// Const & Volatile Conversions ======================================================================================== // Const & Volatile Conversions ========================================================================================
@@ -213,14 +219,14 @@ template<typename T> using remove_reference_t = typename remove_reference<T>::t
/// ///
/// \details adds const qualification to the provided type such that `T` becomes `const T` /// \details adds const qualification to the provided type such that `T` becomes `const T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_const : type_transform<const T> {}; template<typename T> struct add_const : type_identity<const T> {};
/// ///
/// \brief shorthand for `typename add_const<T>::type` /// \brief shorthand for `typename add_const<T>::type`
template<typename T> using add_const_t = typename add_const<T>::type; template<typename T> using add_const_t = typename add_const<T>::type;
// specialization for const types // specialization for const types
template<typename T> struct add_const<const T> : type_transform<const T> {}; template<typename T> struct add_const<const T> : type_identity<const T> {};
/// ///
@@ -228,14 +234,14 @@ template<typename T> struct add_const<const T> : type_transform<const T> {};
/// ///
/// \details removes const qualification from the provided type such that `const T` becomes `T` /// \details removes const qualification from the provided type such that `const T` becomes `T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_const : type_transform<T> {}; template<typename T> struct remove_const : type_identity<T> {};
/// ///
/// \brief shorthand for `typename remove_const<T>::type` /// \brief shorthand for `typename remove_const<T>::type`
template<typename T> using remove_const_t = typename remove_const<T>::type; template<typename T> using remove_const_t = typename remove_const<T>::type;
// specialization for const types // specialization for const types
template<typename T> struct remove_const<const T> : type_transform<T> {}; template<typename T> struct remove_const<const T> : type_identity<T> {};
@@ -244,14 +250,14 @@ template<typename T> struct remove_const<const T> : type_transform<T> {};
/// ///
/// \details removes references from the provided type such that `T` becomes `volatile T` /// \details removes references from the provided type such that `T` becomes `volatile T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_volatile : type_transform<volatile T> {}; template<typename T> struct add_volatile : type_identity<volatile T> {};
/// ///
/// \brief shorthand for `typename add_volatile<T>::type` /// \brief shorthand for `typename add_volatile<T>::type`
template<typename T> using add_volatile_t = typename add_volatile<T>::type; template<typename T> using add_volatile_t = typename add_volatile<T>::type;
// specialization for volatile types // specialization for volatile types
template<typename T> struct add_volatile<volatile T> : type_transform<volatile T> {}; template<typename T> struct add_volatile<volatile T> : type_identity<volatile T> {};
/// ///
@@ -259,14 +265,14 @@ template<typename T> struct add_volatile<volatile T> : type_transform<volatile T
/// ///
/// \details removes references from the provided type such that `volatile T` becomes `T` /// \details removes references from the provided type such that `volatile T` becomes `T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_volatile : type_transform<T> {}; template<typename T> struct remove_volatile : type_identity<T> {};
/// ///
/// \brief shorthand for `typename remove_volatile<T>::type` /// \brief shorthand for `typename remove_volatile<T>::type`
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type; template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
// specialization for volatile types // specialization for volatile types
template<typename T> struct remove_volatile<volatile T> : type_transform<T> {}; template<typename T> struct remove_volatile<volatile T> : type_identity<T> {};
@@ -276,20 +282,20 @@ template<typename T> struct remove_volatile<volatile T> : type_transform<T> {};
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become /// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
/// `const volatile T` /// `const volatile T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_cv : type_transform<const volatile T> {}; template<typename T> struct add_cv : type_identity<const volatile T> {};
/// ///
/// \brief shorthand for `typename add_cv<T>::type` /// \brief shorthand for `typename add_cv<T>::type`
template<typename T> using add_cv_t = typename add_cv<T>::type; template<typename T> using add_cv_t = typename add_cv<T>::type;
// specialization for const types // specialization for const types
template<typename T> struct add_cv<const T> : type_transform<const volatile T> {}; template<typename T> struct add_cv<const T> : type_identity<const volatile T> {};
// specialization for volatile types // specialization for volatile types
template<typename T> struct add_cv<volatile T> : type_transform<const volatile T> {}; template<typename T> struct add_cv<volatile T> : type_identity<const volatile T> {};
// specialization for const volatile types // specialization for const volatile types
template<typename T> struct add_cv<const volatile T> : type_transform<const volatile T> {}; template<typename T> struct add_cv<const volatile T> : type_identity<const volatile T> {};
@@ -299,16 +305,16 @@ template<typename T> struct add_cv<const volatile T> : type_transform<const vola
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and /// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
/// `const volatile T` become `T` /// `const volatile T` become `T`
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_cv : type_transform<T> {}; template<typename T> struct remove_cv : type_identity<T> {};
// specialization for const types // specialization for const types
template<typename T> struct remove_cv<const T> : type_transform<T> {}; template<typename T> struct remove_cv<const T> : type_identity<T> {};
// specialization for volatile types // specialization for volatile types
template<typename T> struct remove_cv<volatile T> : type_transform<T> {}; template<typename T> struct remove_cv<volatile T> : type_identity<T> {};
// specialization for const volatile types // specialization for const volatile types
template<typename T> struct remove_cv<const volatile T> : type_transform<T> {}; template<typename T> struct remove_cv<const volatile T> : type_identity<T> {};
/// ///
/// \brief shorthand for `typename remove_cv<T>::type` /// \brief shorthand for `typename remove_cv<T>::type`
@@ -321,7 +327,7 @@ template<typename T> using remove_cv_t = typename remove_cv<T>::type;
/// ///
/// \details adds references and const volatile qualifiers to the provided type. /// \details adds references and const volatile qualifiers to the provided type.
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct add_cvr : type_transform<add_reference_t<add_cv_t<T>>> {}; template<typename T> struct add_cvr : type_identity<add_reference_t<add_cv_t<T>>> {};
/// ///
/// \brief shorthand for `typename add_cvr<T>::type` /// \brief shorthand for `typename add_cvr<T>::type`
@@ -334,7 +340,7 @@ template<typename T> using add_cvr_t = typename add_cvr<T>::type;
/// ///
/// \details removes const and volatile from the provided type such that /// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type /// \tparam T Reference Type
template<typename T> struct remove_cvr : type_transform<remove_cv_t<remove_reference_t<T>>> {}; template<typename T> struct remove_cvr : type_identity<remove_cv_t<remove_reference_t<T>>> {};
/// ///

View File

@@ -242,7 +242,6 @@ namespace fennec
/// \name Special Types /// \name Special Types
/// @{ /// @{
using nullptr_t = decltype(nullptr); ///< \brief Null Pointer Type using nullptr_t = decltype(nullptr); ///< \brief Null Pointer Type
using intptr_t = intptr_t; ///< \brief Signed Integer Capable of Holding a Pointer to void using intptr_t = intptr_t; ///< \brief Signed Integer Capable of Holding a Pointer to void
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void
@@ -251,6 +250,7 @@ namespace fennec
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof` using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
class undefined_t; ///< \brief undefined class for SFINAE class undefined_t; ///< \brief undefined class for SFINAE
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE template<typename...> using void_t = void; ///< \brief Void type used for SFINAE
@@ -263,15 +263,15 @@ namespace fennec
/// \name Sized Integer Types /// \name Sized Integer Types
/// @{ /// @{
using int8_t = schar_t; ///< \brief Signed 8-bit integer using int8_t = schar_t; ///< \brief Signed 8-bit integer
using int16_t = short_t; ///< \brief Signed 16-bit integer using int16_t = short_t; ///< \brief Signed 16-bit integer
using int32_t = conditional_t<sizeof(int_t) == 4, int_t, long_t>; ///< \brief Signed 32-bit integer using int32_t = conditional_t<sizeof(int_t) == 4, int_t, long_t>; ///< \brief Signed 32-bit integer
using int64_t = llong_t; ///< \brief Signed 64-bit integer using int64_t = conditional_t<sizeof(long_t) == 8, long_t, llong_t>; ///< \brief Signed 64-bit integer
using uint8_t = uchar_t; ///< \brief Unsigned 8-bit integer using uint8_t = uchar_t; ///< \brief Unsigned 8-bit integer
using uint16_t = ushort_t; ///< \brief Unsigned 16-bit integer using uint16_t = ushort_t; ///< \brief Unsigned 16-bit integer
using uint32_t = conditional_t<sizeof(uint_t) == 4, uint_t, ulong_t>; ///< \brief Unsigned 32-bit integer using uint32_t = conditional_t<sizeof(uint_t) == 4, uint_t, ulong_t>; ///< \brief Unsigned 32-bit integer
using uint64_t = ullong_t; ///< \brief Unsigned 64-bit integer using uint64_t = conditional_t<sizeof(ulong_t) == 8, ulong_t, ullong_t>; ///< \brief Unsigned 64-bit integer
/// @} /// @}

View File

@@ -60,6 +60,7 @@
/// ///
#include <fennec/lang/type_transforms.h> #include <fennec/lang/type_transforms.h>
#include <fennec/lang/type_traits.h>
namespace fennec namespace fennec
{ {
@@ -104,6 +105,29 @@ template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept
return x; return x;
} }
///
/// \brief Swaps x and y
/// \tparam T the fundamental type
/// \param x first value
/// \param y second value
template<typename T> requires is_fundamental_v<T>
constexpr void swap(T& x, T& y) noexcept {
T a = x;
x = y;
y = a;
}
///
/// \brief Swaps x and y without invoking destructor
/// \tparam T the type
/// \param x first value
/// \param y second value
template<typename T> constexpr void swap(T& x, T& y) noexcept {
T a = fennec::move(x);
x = fennec::move(y);
y = fennec::move(a);
}
} }
#endif // FENNEC_LANG_UTILITY_H #endif // FENNEC_LANG_UTILITY_H

View File

@@ -88,6 +88,7 @@
/// ///
#include <fennec/math/detail/__math.h> #include <fennec/math/detail/__math.h>
#include <fennec/math/vector.h>
namespace fennec namespace fennec
{ {

View File

@@ -0,0 +1,107 @@
// =====================================================================================================================
// 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_MATH_EXT_PRIMES_H
#define FENNEC_MATH_EXT_PRIMES_H
#include <fennec/math/exponential.h>
namespace fennec
{
template<typename genType>
constexpr bool is_prime(genType x) {
// Base Cases Covers
if (x <= 1) return false; // Eliminates 0 and 1
if (x <= 3) return true; // Eliminates 2 and 3
if (x % 2 == 0 or x % 3 == 0) return false; // Eliminates even numbers and numbers divisible by 3
// 4, 6, 8, 9, 10, 12, 14, 15
if (x < 15) return true; // Covers 5, 7, 11, 13
// Due to the property of 15 being divisible by 5 and the nature of primes
// All prime numbers must end in 1, 3, 7, 9
// when x/15 is even, x%15 must be odd
// and when x/15 is odd, x%15 must be even
// To explain, when x/15 is even, 15*x/15 ends in 0, and when odd, ends in 5
// Thus when x/15 is even, 15*x/15 ends in 0, and the results are 1, 3, 7, 11, 13
// And when x/15 is even, 15*x/15 ends in 5, and the results are 2, 4, 8, 14
genType mod15 = x % 15;
genType mod15e = mod15 % 2;
genType div15e = (x / 15) % 2;
if (mod15e == div15e) return false;
// Iterate
genType limit = sqrt(x);
for (genType i = 5; i <= limit; i += 6) {
if (x % i == 0 || x % (i + 2) == 0) {
return false;
}
}
return true;
}
template<typename genType>
constexpr genType next_prime(genType x) {
genType n = (x + 1) / 6 + 1;
while (true) {
x = (n++ * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
template<typename genType>
constexpr genType next_prime2(genType x) {
genType n = (x + 1) / 6;
n *= 2;
while (true) {
x = (n++ * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
template<typename genType>
constexpr genType prev_prime(genType x) {
genType n = (x + 1) / 6 - 1;
while (true) {
x = (n-- * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
template<typename genType>
constexpr genType prev_prime2(genType x) {
genType n = (x + 1) / 6;
n /= 2;
while (true) {
x = (n-- * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
}
#endif // FENNEC_MATH_EXT_PRIMES_H

View File

@@ -105,7 +105,7 @@ public:
/// ///
/// \brief Component Constructor /// \brief Component Constructor
/// \param w The real component /// \param w The scalar component
/// \param x The coefficient of the `i` component /// \param x The coefficient of the `i` component
/// \param y The coefficient of the `j` component /// \param y The coefficient of the `j` component
/// \param z The coefficient of the `k` component /// \param z The coefficient of the `k` component
@@ -113,10 +113,18 @@ public:
data = { x, y, z, w }; data = { x, y, z, w };
} }
///
/// \brief Component Constructor
/// \param s The scalar component
/// \param v The vector component
constexpr quaternion(scalar_t s, vec3_t v) {
data = { v.x, v.y, v.z, s };
}
/// ///
/// \brief Vector Constructor /// \brief Vector Constructor
/// \param v A 4d vector /// \param v A 4d vector
constexpr quaternion(const vec<scalar_t, 4>& v) { constexpr quaternion(const vec4_t& v) {
data = v.data; data = v.data;
} }

View File

@@ -131,7 +131,7 @@ constexpr qua<genType> rotation(const vec<genType, 3>& axis, genType angle) {
vec<genType, 3> a = fennec::normalize(axis); vec<genType, 3> a = fennec::normalize(axis);
const genType s = fennec::sin(angle); const genType s = fennec::sin(angle);
return qua<genType>(fennec::cos(angle * genType(0.5)), s * a.x, s * a.y, s * a.z); return qua<genType>(fennec::cos(angle * genType(0.5)), s * a);
} }
/// \brief enum to denote the unit-axis of rotation /// \brief enum to denote the unit-axis of rotation

View File

@@ -457,14 +457,11 @@ public:
/// \param alloc the allocation to copy /// \param alloc the allocation to copy
/// \returns a reference to `this` /// \returns a reference to `this`
constexpr allocation& operator=(allocation&& alloc) noexcept { constexpr allocation& operator=(allocation&& alloc) noexcept {
// Copy contents
_alloc = alloc._alloc;
_data = alloc._data;
_capacity = alloc._capacity;
// Cleanup alloc // Copy contents
alloc._data = nullptr; fennec::swap(_alloc, alloc._alloc);
alloc._capacity = 0; fennec::swap(_data, alloc._data);
fennec::swap(_capacity, alloc._capacity);
return *this; return *this;
} }
@@ -525,6 +522,11 @@ public:
return _data[i]; return _data[i];
} }
constexpr value_t operator[](size_t i) const requires is_fundamental_v<value_t> {
assertd(i < size(), "Array Out of Bounds");
return _data[i];
}
constexpr const value_t& operator[](size_t i) const { constexpr const value_t& operator[](size_t i) const {
assertd(i < size(), "Array Out of Bounds"); assertd(i < size(), "Array Out of Bounds");
return _data[i]; return _data[i];

View File

@@ -0,0 +1,188 @@
// =====================================================================================================================
// 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_BYTES_H
#define FENNEC_LANG_BYTES_H
#include <fennec/lang/assert.h>
#include <fennec/lang/types.h>
#include <fennec/lang/hashing.h>
namespace fennec
{
/// \brief byte type
using byte_t = uint8_t;
///
/// \brief container for handling byte arrays
struct byte_array {
public:
///
/// \brief Default Constructor
constexpr byte_array()
: _carr(nullptr)
, _size(0)
, _const(true) {
}
///
/// \brief Buffer Constructor
/// \param arr the buffer to wrap
/// \param n the size of the buffer in bytes
constexpr byte_array(void* arr, size_t n)
: _arr(static_cast<byte_t*>(arr))
, _size(n)
, _const(false) {
}
///
/// \brief Const Buffer Constructor
/// \param arr the buffer to wrap
/// \param n the size of the buffer in bytes
constexpr byte_array(const void* arr, size_t n)
: _carr(static_cast<const byte_t*>(arr))
, _size(n)
, _const(true) {
}
///
/// \brief Buffer Constructor
/// \param arr the buffer to wrap
/// \tparam n the size of the buffer in elements
template<typename T, size_t n>
constexpr byte_array(T arr[n])
: byte_array(arr, n * sizeof(T)) {
}
///
/// \brief Const Buffer Constructor
/// \param arr the buffer to wrap
/// \tparam n the size of the buffer in elements
template<typename T, size_t n>
constexpr byte_array(const T arr[n])
: byte_array(arr, n * sizeof(T)) {
}
///
/// \returns The size of the array in bytes
constexpr size_t size() const {
return _size;
}
///
/// \brief Array Access Operator
/// \param i the index to access
/// \returns a reference to the byte at `i`
constexpr byte_t& operator[](int i) {
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < _size, "Array Out of Bounds");
return _arr[i];
}
///
/// \brief Const Array Access Operator
/// \param i the index to access
/// \returns a copy of the byte at `i`
constexpr byte_t operator[](int i) const {
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < _size, "Array Out of Bounds");
return _carr[i];
}
///
/// \brief Cast Function
/// \tparam T type to cast to
/// \returns a pointer to the underlying buffer interpreted as an array of `T`
template<typename T>
constexpr T* cast() {
void* temp = _arr;
return static_cast<T*>(temp);
}
///
/// \brief Const Cast Function
/// \tparam T type to cast to
/// \returns a pointer to the underlying buffer interpreted as an array of `T`
template<typename T>
constexpr const T* cast() const {
const void* temp = _carr;
return static_cast<T*>(temp);
}
private:
union { // hack to allow both const qualified and non-const strings
byte_t* _arr;
const byte_t* _carr;
};
size_t _size;
bool _const;
};
///
/// \brief Byte Array Hash Function
template<>
struct hash<byte_array> {
size_t operator()(const byte_array& bytes) {
// Murmur2
static constexpr uint64_t m = 0xc6a4a7935bd1e995;
static constexpr uint64_t s = 0xff51afd7ed558ccd;
static constexpr uint64_t r = 47;
const uint64_t n = bytes.size();
uint64_t h = s ^ (n * m);
const uint64_t* x = bytes.cast<>();
const uint64_t* y = x + (n / sizeof(uint64_t));
while (x != y) {
uint64_t k = *x++;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const uint8_t* b = (const uint8_t*)x;
switch (n & 7) {
case 7: h ^= uint64_t(b[6]) << 48;
case 6: h ^= uint64_t(b[5]) << 40;
case 5: h ^= uint64_t(b[4]) << 32;
case 4: h ^= uint64_t(b[3]) << 24;
case 3: h ^= uint64_t(b[2]) << 16;
case 2: h ^= uint64_t(b[1]) << 8;
case 1: h ^= uint64_t(b[0]);
h *= m;
default:
}
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
};
}
#endif // FENNEC_LANG_BYTES_H

View File

@@ -71,7 +71,7 @@ private:
using __diff_t = typename TypeT::diff_t; // Helper to prevent substitution issues with detecting the difference type 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 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>>; using __rebind_helper = type_identity<typename BaseT::template rebind<OElemT>>;
public: public:
using pointer_t = ClassT; using pointer_t = ClassT;

View File

@@ -54,19 +54,19 @@ struct nothrow_t
size_t pagesize(); size_t pagesize();
template<typename TypeT> void construct(TypeT* ptr) { template<typename TypeT> void construct(TypeT* ptr) {
ptr->TypeT(); new(ptr) TypeT();
} }
template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) { template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) {
ptr->TypeT(val); new(ptr) TypeT(val);
} }
template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) { template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) {
ptr->TypeT(fennec::forward<TypeT>(val)); new(ptr) TypeT(fennec::forward<TypeT>(val));
} }
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args) { template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT&&...args) {
ptr->TypeT(fennec::forward<TypeT>(args)...); new(ptr) TypeT(fennec::forward<ArgsT>(args)...);
} }
template<typename TypeT> void destruct(TypeT* ptr) { template<typename TypeT> void destruct(TypeT* ptr) {

View File

@@ -0,0 +1,22 @@
// =====================================================================================================================
// 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_PLATFORM_INTERFACE_DIALOG_H
#define FENNEC_PLATFORM_INTERFACE_DIALOG_H
#endif // FENNEC_PLATFORM_INTERFACE_DIALOG_H

View File

@@ -0,0 +1,47 @@
// =====================================================================================================================
// 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_PLATFORM_INTERFACE_DISPLAY_H
#define FENNEC_PLATFORM_INTERFACE_DISPLAY_H
#include <fennec/platform/interface/fwd.h>
namespace fennec
{
///
/// \brief Interface for display management
class display
{
public:
struct config {
};
virtual bool connected() const = 0;
protected:
virtual ~display() = default;
private:
config _config;
};
}
#endif // FENNEC_PLATFORM_INTERFACE_DISPLAY_H

View File

@@ -0,0 +1,30 @@
// =====================================================================================================================
// 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_PLATFORM_INTERFACE_FORWARD_H
#define FENNEC_PLATFORM_INTERFACE_FORWARD_H
namespace fennec
{
class window;
class display;
}
#endif // FENNEC_PLATFORM_INTERFACE_FORWARD_H

View File

@@ -0,0 +1,74 @@
// =====================================================================================================================
// 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_PLATFORM_INTERFACE_PLATFORM_H
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
#include <fennec/fproc/strings/string.h>
#include <fennec/platform/interface/fwd.h>
namespace fennec
{
class platform {
public:
using shared_object = struct shared_object;
using function_pointer = void (*)(void);
struct shared_lib {
shared_object* _lib;
const cstring _name;
};
enum class user {
client,
server
};
struct config {
user type;
};
// Functions with default implementations
virtual string get_environment_variable(const cstring& var);
// Pure Virtual Functions
virtual display* get_display() = 0;
virtual shared_object* load_object(const cstring& file) = 0;
virtual void unload_object(shared_object* obj) = 0;
virtual function_pointer find_symbol(shared_object* hndl, const cstring& name) = 0;
protected:
platform(user t);
virtual ~platform() = default;
private:
config _config;
};
}
#endif // FENNEC_PLATFORM_INTERFACE_PLATFORM_H

View File

@@ -0,0 +1,137 @@
// =====================================================================================================================
// 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_PLATFORM_INTERFACE_WINDOW_H
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
#include <fennec/fproc/strings/string.h>
#include <fennec/platform/interface/fwd.h>
namespace fennec
{
///
/// \brief interface for handling windows
/// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation.
class window {
public:
enum class fullscreen_mode {
windowed = 0,
borderless,
fullscreen
};
enum flags_ : uint32_t {
flags_none = 0,
flags_child = 0x1 << 0,
flags_modal = 0x1 << 1,
flags_grab_mouse = 0x1 << 2,
flags_grab_keyboard = 0x1 << 3,
flags_block_screensaver = 0x1 << 4,
};
union bits {
uint32_t depth;
uint8_t r, g, b, a;
};
struct config {
string title;
uint32_t flags;
size_t width, height;
fullscreen_mode fullscreen;
bits bit_depth;
};
virtual bool set_title(const cstring& title) = 0;
virtual bool set_title(const string& title) = 0;
virtual bool set_width(size_t w) = 0;
virtual bool set_height(size_t h) = 0;
virtual bool set_size(size_t w, size_t h) = 0;
virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0;
virtual bool set_resizable(bool e) = 0;
virtual bool grab_keyboard(bool e) = 0;
virtual bool grab_mouse(bool e) = 0;
virtual bool block_screensaver(bool e) = 0;
bool is_child() const {
return _config.flags & flags_child;
}
bool is_modal() const {
return _config.flags & flags_modal;
}
display* get_display() {
return _display;
}
const display* get_display() const {
return _display;
}
const string& get_title() const {
return _config.title;
}
size_t get_width() const {
return _config.width;
}
size_t get_height() const {
return _config.height;
}
fullscreen_mode get_fullscreen_mode() const {
return _config.fullscreen;
}
bool is_keyboard_grabbed() const {
return _config.flags & flags_grab_keyboard;
}
bool is_mouse_grabbed() const {
return _config.flags & flags_grab_mouse;
}
bool is_screensaver_blocked() const {
return _config.flags & flags_block_screensaver;
}
protected:
virtual ~window() = default;
window(display* display, window* parent, bool modal);
display* _display;
window* _parent;
config _config;
private:
};
}
#endif // FENNEC_PLATFORM_INTERFACE_WINDOW_H

View File

@@ -0,0 +1,59 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_PLATFORM_H
#define FENNEC_PLATFORM_LINUX_PLATFORM_H
#include <fennec/containers/set.h>
#include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/platform.h>
namespace fennec
{
class linux_platform : public platform {
public:
enum display_ : int_t {
display_none = -1,
display_x11 = 0,
display_wayland,
};
linux_platform(user type);
~linux_platform() override;
shared_object* load_object(const cstring& file) override;
void unload_object(shared_object* obj) override;
function_pointer find_symbol(shared_object* hndl, const cstring& name) override;
display* get_display() override;
private:
display* _display;
int_t _display_driver;
void _runtime_client_checks();
void _find_display_driver();
void _runtime_server_checks();
};
}
#endif // FENNEC_PLATFORM_LINUX_PLATFORM_H

View File

@@ -0,0 +1,51 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_DISPLAY_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H
#include <fennec/fproc/strings/cstring.h>
#include <fennec/platform/interface/display.h>
#include <fennec/platform/linux/platform.h>
#include <fennec/platform/linux/wayland/lib/fwd.h>
namespace fennec
{
namespace wayland
{
class wayland_display : public display {
public:
wayland_display(linux_platform* platform);
wayland_display(linux_platform* platform, const cstring& drv);
~wayland_display() override;
bool connected() const override;
private:
struct wl_display* _handle;
linux_platform* _platform;
};
}
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H

View File

@@ -0,0 +1,37 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_DYN_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_DYN_H
#include <fennec/platform/linux/platform.h>
namespace fennec
{
namespace wayland
{
bool load_symbols(linux_platform* platform);
void unload_symbols(linux_platform* platform);
}
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DYN_H

View File

@@ -0,0 +1,24 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_FWD_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
struct wl_display;
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H

View File

@@ -0,0 +1,37 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/linux/wayland/lib/fwd.h>
#ifndef FENNEC_LIB
#define FENNEC_LIB(...)
#endif
#ifndef FENNEC_SYMBOL
#define FENNEC_SYMBOL(...)
#endif
FENNEC_LIB(WAYLAND);
FENNEC_SYMBOL(struct wl_display*, wl_display_connect, const char* name);
FENNEC_SYMBOL(void, wl_display_disconnect, wl_display* name);
#undef FENNEC_LIB
#undef FENNEC_SYMBOL

View File

@@ -0,0 +1,27 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_SYM_DEF_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_SYM_DEF_H
#define FENNEC_LIB(name) inline bool FENNEC_HAS_LIB_##name = false;
#define FENNEC_SYMBOL(ret, fn, ...) using sym_##fn = ret(*)(__VA_ARGS__); \
inline sym_##fn fn = nullptr;
#include <fennec/platform/linux/wayland/lib/sym.h>
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_SYM_DEF_H

View File

@@ -17,7 +17,7 @@
// ===================================================================================================================== // =====================================================================================================================
#include <stdio.h> #include <stdio.h>
//#include <cpptrace/cpptrace.hpp> #include <cpptrace/cpptrace.hpp>
void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description) void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description)
{ {
@@ -28,5 +28,5 @@ void __assert_callback(const char* expression, const char* file, int line, const
"At %s:%d in %s \n" "At %s:%d in %s \n"
"Description: %s \n", "Description: %s \n",
expression, file, line, function, description); expression, file, line, function, description);
// cpptrace::generate_trace(2).print(); cpptrace::generate_trace(2).print();
} }

View File

@@ -22,12 +22,11 @@ using assert_handler = void (*)(const char *, const char *, int , const char *);
void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description); void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* description) void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* description, bool halt)
{ {
__assert_callback(expression, file, line, function, description); __assert_callback(expression, file, line, function, description);
#ifndef NDEBUG if (halt) {
::abort();
::abort(); }
#endif
} }

View File

@@ -0,0 +1,34 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <cstdlib>
#include <fennec/platform/interface/platform.h>
namespace fennec
{
string platform::get_environment_variable(const cstring& var) {
const char* val = getenv(var);
return string(val, strlen(val));
}
platform::platform(user t) {
_config.type = t;
}
}

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/>.
// =====================================================================================================================
#include <fennec/platform/interface/window.h>
namespace fennec
{
window::window(display* display, window* parent, bool modal)
: _display(display)
, _parent(parent)
, _config() {
bool child = parent != nullptr;
assert(!modal || child, "Attempted to create non-child modal window.");
_config.flags |= child ? flags_child : flags_none;
_config.flags |= modal ? flags_modal : flags_none;
}
}

View File

@@ -0,0 +1,98 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/linux/platform.h>
#include <dlfcn.h>
#ifdef FENNEC_LIB_WAYLAND
#include <fennec/platform/linux/wayland/lib/dyn.h>
#include <fennec/platform/linux/wayland/display.h>
#endif
namespace fennec
{
using namespace wayland;
linux_platform::linux_platform(user _type)
: platform(_type)
, _display_driver(display_none) {
switch (_type) {
case user::client: {
_runtime_client_checks();
return;
}
case user::server: {
_runtime_server_checks();
}
}
}
linux_platform::~linux_platform() {
}
shared_object* linux_platform::load_object(const cstring& file) {
void* handle = dlopen(file, RTLD_NOW | RTLD_LOCAL);
const char* load_error = dlerror();
assert(handle != nullptr, load_error);
return static_cast<shared_object*>(handle);
}
void linux_platform::unload_object(shared_object* obj) {
if (obj) {
dlclose(obj);
}
}
platform::function_pointer linux_platform::find_symbol(shared_object* hndl, const cstring& name) {
string _name = name;
void* symbol = dlsym(hndl, _name);
if (symbol == nullptr) {
_name = '_' + _name;
symbol = dlsym(hndl, _name);
}
return (function_pointer)symbol;
}
display* linux_platform::get_display() {
return _display;
}
void linux_platform::_runtime_client_checks() {
#ifdef FENNEC_LIB_WAYLAND
if (wayland::load_symbols(this)) {
_display_driver = display_wayland;
_display = new wayland_display(this);
wayland::unload_symbols(this); // Doesn't actually unload symbols, just resets ref counter to only consider
// the created display
}
#endif
assertf(_display != nullptr, "failed to find suitable display driver");
}
void linux_platform::_find_display_driver() {
}
void linux_platform::_runtime_server_checks() {
}
}

View File

@@ -0,0 +1,58 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/linux/wayland/display.h>
#include <fennec/platform/linux/wayland/lib/sym_def.h>
#include <fennec/platform/linux/wayland/lib/dyn.h>
namespace fennec
{
namespace wayland
{
wayland_display::wayland_display(linux_platform* platform)
: display()
, _handle()
, _platform(platform) {
load_symbols(_platform);
_handle = wl_display_connect(nullptr);
}
wayland_display::wayland_display(linux_platform* platform, const cstring& drv)
: display()
, _handle()
, _platform(platform) {
load_symbols(_platform);
_handle = wl_display_connect(nullptr);
}
wayland_display::~wayland_display() {
wl_display_disconnect(_handle);
unload_symbols(_platform);
_handle = nullptr;
_platform = nullptr;
}
bool wayland_display::connected() const {
return _handle != nullptr;
}
}
}

View File

@@ -0,0 +1,69 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/linux/wayland/lib/sym_def.h>
#include <fennec/platform/linux/wayland/lib/dyn.h>
namespace fennec
{
namespace wayland
{
using shared_lib = platform::shared_lib;
static int _load_count = 0;
// Create private variables
#define FENNEC_LIB(lib) static shared_lib _FENNEC_LIB_##lib = { nullptr, FENNEC_LIB_##lib };
#define FENNEC_SYMBOL(...)
#include <fennec/platform/linux/wayland/lib/sym.h>
bool load_symbols(linux_platform* platform) {
if (_load_count++ != 0) {
return true;
}
#define FENNEC_LIB(lib) _FENNEC_LIB_##lib._lib = platform->load_object(_FENNEC_LIB_##lib._name); \
FENNEC_HAS_LIB_##lib = _FENNEC_LIB_##lib._lib != nullptr; \
if(not FENNEC_HAS_LIB_##lib) { \
unload_symbols(platform); \
return false; \
} \
shared_lib& current_lib = _FENNEC_LIB_##lib;
#define FENNEC_SYMBOL(ret, fn, ...) fn = (sym_##fn)(platform->find_symbol(current_lib._lib, #fn));
#include <fennec/platform/linux/wayland/lib/sym.h>
return true;
}
void unload_symbols(linux_platform* platform) {
if (--_load_count != 0) {
return;
}
#define FENNEC_LIB(lib) platform->unload_object(_FENNEC_LIB_##lib._lib); \
_FENNEC_LIB_##lib._lib = nullptr;
#define FENNEC_SYMBOL(ret, fn, ...) fn = nullptr;
#include <fennec/platform/linux/wayland/lib/sym.h>
}
}
}

View File

@@ -27,6 +27,12 @@ add_executable(fennec-test main.cpp
printing.h printing.h
tests/math/test_ext.h tests/math/test_ext.h
tests/math/ext/test_quaternion.h tests/math/ext/test_quaternion.h
tests/platform/linux/test_wayland.h
tests/platform/test_linux.h
tests/test_platform.h
tests/lang/test_hashing.h
tests/containers/test_array.h
tests/containers/test_set.h
) )
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}" target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"

View File

@@ -23,7 +23,9 @@
#include "tests/test_memory.h" #include "tests/test_memory.h"
#include "test.h" #include "test.h"
#include "tests/test_containers.h"
#include "tests/test_fproc.h" #include "tests/test_fproc.h"
#include "tests/test_platform.h"
int main(int, char **) int main(int, char **)
@@ -37,6 +39,11 @@ int main(int, char **)
fennec::test::fennec_test_lang(); fennec::test::fennec_test_lang();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_header("containers library");
fennec_test_spacer(2);
fennec::test::fennec_test_containers();
fennec_test_spacer(3);
fennec_test_header("math library"); fennec_test_header("math library");
fennec_test_spacer(2); fennec_test_spacer(2);
fennec::test::fennec_test_math(); fennec::test::fennec_test_math();
@@ -47,5 +54,10 @@ int main(int, char **)
fennec::test::fennec_test_fproc(); fennec::test::fennec_test_fproc();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_header("platform library");
fennec_test_spacer(2);
fennec::test::fennec_test_platform();
fennec_test_spacer(3);
return 0; return 0;
} }

View File

@@ -73,7 +73,7 @@ inline void __fennec_test_run(const std::string& expression, const ResultT& resu
std::cout << std::endl; std::cout << std::endl;
// Assert to halt and get some debug info // Assert to halt and get some debug info
assert(passed, "Test Failed"); assertf(passed, "Test Failed");
} }
} }

View File

@@ -0,0 +1,49 @@
// =====================================================================================================================
// 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_TEST_CONTAINERS_ARRAY_H
#define FENNEC_TEST_CONTAINERS_ARRAY_H
#include "../../test.h"
#include <fennec/containers/array.h>
namespace fennec
{
namespace test
{
inline void fennec_test_containers_array() {
const char string[] = "Hello World!";
array<char, sizeof(string)> arr1;
array<char, sizeof(string)> arr2;
strcpy(&arr1[0], string);
strcpy(&arr2[0], string);
fennec_test_run(strcmp(&arr1[0], string), 0);
fennec_test_run(strcmp(&arr2[0], string), 0);
fennec_test_run(arr1 == arr2, true);
}
}
}
#endif // FENNEC_TEST_CONTAINERS_ARRAY_H

View File

@@ -0,0 +1,55 @@
// =====================================================================================================================
// 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_TEST_CONTAINERS_DYNARRAY_H
#define FENNEC_TEST_CONTAINERS_DYNARRAY_H
#include "../../test.h"
#include <fennec/containers/dynarray.h>
namespace fennec
{
namespace test
{
inline void fennec_test_containers_dynarray() {
dynarray<int> test1;
dynarray<int> test2;
int n = 10000;
test1.resize(n); test2.resize(n);
for (int i = 0; i < n; ++i) {
test1.push_back(i);
test2.push_back(n - i - 1);
}
for (int i = 0; i < n; ++i) {
assertf(test1[i] == test2[n - i - 1], "Failed dynarray::push_back");
}
std::cout << "passed" << std::endl;
}
}
}
#endif // FENNEC_TEST_CONTAINERS_DYNARRAY_H

View File

@@ -0,0 +1,124 @@
// =====================================================================================================================
// 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_TEST_CONTAINERS_OPTIONAL_H
#define FENNEC_TEST_CONTAINERS_OPTIONAL_H
#include "../../test.h"
#include <fennec/containers/optional.h>
namespace fennec
{
namespace test
{
enum opt_test_ : uint8_t {
opt_test_none = 0x1 << 0,
opt_test_default_constructor = 0x1 << 1,
opt_test_destructor = 0x1 << 2,
opt_test_copy_constructor = 0x1 << 3,
opt_test_move_constructor = 0x1 << 4,
opt_test_copy_assignment = 0x1 << 5,
opt_test_move_assignment = 0x1 << 6,
};
struct optional_helper {
inline static uint8_t test = opt_test_none;
optional_helper() : i(0) {
fennec_test_run(bool(test & opt_test_default_constructor), true);
}
~optional_helper() {
fennec_test_run(bool(test & opt_test_destructor), true);
}
optional_helper(const optional_helper&) : i(0) {
fennec_test_run(bool(test & opt_test_copy_constructor), true);
}
optional_helper(optional_helper&&) noexcept : i(0) {
fennec_test_run(bool(test & opt_test_move_constructor), true);
}
optional_helper& operator=(const optional_helper&) {
fennec_test_run(bool(test & opt_test_copy_assignment), true);
return *this;
}
optional_helper& operator=(optional_helper&&) noexcept {
fennec_test_run(bool(test & opt_test_move_assignment), true);
return *this;
}
int i;
};
inline void fennec_test_containers_optional() {
static_assert(
is_default_constructible_v<optional_helper>
and is_copy_constructible_v<optional_helper>
and is_move_constructible_v<optional_helper>
and is_copy_assignable_v<optional_helper>
and is_move_assignable_v<optional_helper>
);
optional<optional_helper> opt = optional<optional_helper>();
optional_helper::test = opt_test_default_constructor;
opt.emplace();
optional_helper::test = opt_test_destructor;
opt.reset();
optional_helper::test = opt_test_default_constructor | opt_test_copy_constructor | opt_test_destructor;
opt = copy(optional_helper());
optional_helper::test = opt_test_destructor;
opt.reset();
optional_helper::test = opt_test_default_constructor | opt_test_move_constructor | opt_test_destructor;
opt = optional_helper();
optional_helper::test = opt_test_destructor;
opt.reset();
optional_helper::test = opt_test_default_constructor;
opt.emplace();
optional_helper::test = opt_test_default_constructor | opt_test_copy_assignment | opt_test_destructor;
opt = copy(optional_helper());
optional_helper::test = opt_test_default_constructor | opt_test_move_assignment | opt_test_destructor;
opt = optional_helper();
optional_helper::test = opt_test_destructor;
opt.reset();
std::cout << opt << std::endl;
std::cout << "passed" << std::endl;
}
}
}
#endif // FENNEC_TEST_CONTAINERS_OPTIONAL_H

View File

@@ -0,0 +1,58 @@
// =====================================================================================================================
// 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_TEST_CONTAINERS_SET_H
#define FENNEC_TEST_CONTAINERS_SET_H
#include "../../test.h"
#include <cstdlib>
#include <unordered_set>
#include <fennec/containers/set.h>
namespace fennec
{
namespace test
{
inline void fennec_test_containers_set() {
using type_t = decltype(rand());
std::unordered_set<type_t> ref;
set<type_t> test;
srand(0);
for (int i = 0; i < 10000; ++i) {
type_t v = rand();
ref.insert(v);
test.insert(v);
}
for (int i = 0; i < 10000; ++i) {
assertf(ref.contains(i) == test.contains(i), "set test failed");
}
std::cout << "passed" << std::endl;
}
}
}
#endif // FENNEC_TEST_CONTAINERS_SET_H

View File

@@ -47,8 +47,6 @@ inline void fennec_test_fproc_strings_cstring()
fennec_test_run(str.rfind('o'), static_cast<size_t>(7)); fennec_test_run(str.rfind('o'), static_cast<size_t>(7));
fennec_test_run(str.rfind("World"), static_cast<size_t>(6)); fennec_test_run(str.rfind("World"), static_cast<size_t>(6));
fennec_test_spacer(2);
} }
} }

View File

@@ -88,8 +88,6 @@ inline void fennec_test_fproc_io() {
fennec_test_run(file::cout().write("Hello World!"), sizeof("Hello World!")); fennec_test_run(file::cout().write("Hello World!"), sizeof("Hello World!"));
fennec_test_run(file::cerr().write("Hello World!"), sizeof("Hello World!")); fennec_test_run(file::cerr().write("Hello World!"), sizeof("Hello World!"));
fennec_test_spacer(2);
} }
} }

View File

@@ -35,6 +35,7 @@ inline void fennec_test_fproc_strings()
fennec_test_fproc_strings_cstring(); fennec_test_fproc_strings_cstring();
fennec_test_spacer(3); fennec_test_spacer(3);
// TODO
} }
} }

View File

@@ -30,7 +30,7 @@ namespace fennec
namespace test namespace test
{ {
void fennec_test_lang_bits() inline void fennec_test_lang_bits()
{ {
int a = 0x48ef13ad; int a = 0x48ef13ad;
int b = 0x23e5ab9c; int b = 0x23e5ab9c;

View File

@@ -0,0 +1,57 @@
// =====================================================================================================================
// 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_TEST_LANG_HASHING_H
#define FENNEC_TEST_LANG_HASHING_H
#include <fennec/lang/hashing.h>
#include "../../test.h"
namespace fennec
{
namespace test
{
inline void fennec_test_lang_hashing() {
size_t num = 61;
float_t numf = bit_cast<float>((uint32_t)num);
double_t numd = bit_cast<double>(num);
size_t exp = hash<size_t>()(num);
fennec_test_run(hash<int8_t>()(num), exp);
fennec_test_run(hash<uint8_t>()(num), exp);
fennec_test_run(hash<int16_t>()(num), exp);
fennec_test_run(hash<uint16_t>()(num), exp);
fennec_test_run(hash<int32_t>()(num), exp);
fennec_test_run(hash<uint32_t>()(num), exp);
fennec_test_run(hash<int64_t>()(num), exp);
fennec_test_run(hash<uint64_t>()(num), exp);
fennec_test_spacer(1);
fennec_test_run(hash<float_t>()(numf), exp);
fennec_test_run(hash<double_t>()(numd), exp);
}
}
}
#endif // FENNEC_TEST_LANG_HASHING_H

View File

@@ -32,6 +32,8 @@ inline void test_sequences()
static_assert(fennec::is_same_v<make_index_sequence_t<2>, index_sequence<0, 1>>); static_assert(fennec::is_same_v<make_index_sequence_t<2>, index_sequence<0, 1>>);
static_assert(fennec::is_same_v<make_index_sequence_t<3>, index_sequence<0, 1, 2>>); static_assert(fennec::is_same_v<make_index_sequence_t<3>, index_sequence<0, 1, 2>>);
static_assert(fennec::is_same_v<make_index_sequence_t<4>, index_sequence<0, 1, 2, 3>>); static_assert(fennec::is_same_v<make_index_sequence_t<4>, index_sequence<0, 1, 2, 3>>);
// TODO
} }
} }

View File

@@ -38,6 +38,8 @@ inline void fennec_test_math_quaternion() {
fennec_test_run(quat(), quat(1, 0, 0, 0)); fennec_test_run(quat(), quat(1, 0, 0, 0));
fennec_test_spacer(2); fennec_test_spacer(2);
// TODO
} }
} }

View File

@@ -208,9 +208,6 @@ inline void fennec_test_math_common()
fennec_test_run(mix(0.0f, 1.0f, false), 0.0f); fennec_test_run(mix(0.0f, 1.0f, false), 0.0f);
fennec_test_run(mix(0.0f, 1.0f, true), 1.0f); fennec_test_run(mix(0.0f, 1.0f, true), 1.0f);
fennec_test_spacer(2);
} }
} }

View File

@@ -75,9 +75,6 @@ inline void fennec_test_math_exponential()
fennec_test_run(fennec::inversesqrt(1.0f), 1.0f / 1.0f); fennec_test_run(fennec::inversesqrt(1.0f), 1.0f / 1.0f);
fennec_test_run(fennec::inversesqrt(4.0f), 1.0f / 2.0f); fennec_test_run(fennec::inversesqrt(4.0f), 1.0f / 2.0f);
fennec_test_run(fennec::inversesqrt(9.0f), 1.0f / 3.0f); fennec_test_run(fennec::inversesqrt(9.0f), 1.0f / 3.0f);
fennec_test_spacer(2);
} }
} }

View File

@@ -36,6 +36,7 @@ inline void fennec_test_math_ext() {
fennec_test_math_quaternion(); fennec_test_math_quaternion();
fennec_test_spacer(3); fennec_test_spacer(3);
// TODO
} }
} }

View File

@@ -77,9 +77,6 @@ inline void fennec_test_math_geometric()
fennec_test_run(fennec::reflect(vec2(1, -1), vec2(0, 1)), vec2(1, 1)); fennec_test_run(fennec::reflect(vec2(1, -1), vec2(0, 1)), vec2(1, 1));
fennec_test_run(fennec::refract(vec2(1, -1), vec2(0, 1), 1/1.33f), vec2(0.7518797, -1)); fennec_test_run(fennec::refract(vec2(1, -1), vec2(0, 1), 1/1.33f), vec2(0.7518797, -1));
fennec_test_spacer(2);
} }
} }

View File

@@ -320,8 +320,6 @@ inline void fennec_test_math_matrix()
fennec_test_run(fennec::inverse(mat2(1, 2, 3, 4)), mat2(-2, 1, 1.5, -0.5)); fennec_test_run(fennec::inverse(mat2(1, 2, 3, 4)), mat2(-2, 1, 1.5, -0.5));
fennec_test_run(fennec::inverse(mat3(1, 2, 3, 0, 1, 4, 5, 6, 0)), mat3(-24, 18, 5, 20, -15, -4, -5, 4, 1)); fennec_test_run(fennec::inverse(mat3(1, 2, 3, 0, 1, 4, 5, 6, 0)), mat3(-24, 18, 5, 20, -15, -4, -5, 4, 1));
fennec_test_run(fennec::inverse(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), (1.0f / 414.0f) * mat4(36, -39, 33, 51, -18, 31, 133, -83, -72, 55, 49, 13, 36, 53, -13, 5)); fennec_test_run(fennec::inverse(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), (1.0f / 414.0f) * mat4(36, -39, 33, 51, -18, 31, 133, -83, -72, 55, 49, 13, 36, 53, -13, 5));
fennec_test_spacer(2);
} }
} }

View File

@@ -45,8 +45,6 @@ inline void fennec_test_math_relational()
fennec_test_run(not(bvec3(true, false, true)), bvec3(false, true, false)); fennec_test_run(not(bvec3(true, false, true)), bvec3(false, true, false));
fennec_test_run(fennec::all(bvec3(true, true, true)), true); fennec_test_run(fennec::all(bvec3(true, true, true)), true);
fennec_test_spacer(2);
} }
} }

View File

@@ -112,11 +112,6 @@ inline void fennec_test_math_trigonometric()
fennec_test_run(fennec::asinh((fennec::e<float>() - fennec::one_over_e<float>()) / 2.0f), 1.0f); fennec_test_run(fennec::asinh((fennec::e<float>() - fennec::one_over_e<float>()) / 2.0f), 1.0f);
fennec_test_run(fennec::acosh((fennec::e<float>() + fennec::one_over_e<float>()) / 2.0f), 1.0f); fennec_test_run(fennec::acosh((fennec::e<float>() + fennec::one_over_e<float>()) / 2.0f), 1.0f);
fennec_test_run(fennec::atanh(((fennec::e_raised_two<float>() - 1) / (fennec::e_raised_two<float>() + 1))), 1.0f); fennec_test_run(fennec::atanh(((fennec::e_raised_two<float>() - 1) / (fennec::e_raised_two<float>() + 1))), 1.0f);
fennec_test_spacer(2);
} }
} }

View File

@@ -594,8 +594,6 @@ inline void fennec_test_math_vector()
fennec_test_run(([]() -> ivec2 { ivec2 v(0x2A1E, 0x7BF3); return v >>= ivec2(4, 8); }()), ivec2(0x2A1, 0x7B)); fennec_test_run(([]() -> ivec2 { ivec2 v(0x2A1E, 0x7BF3); return v >>= ivec2(4, 8); }()), ivec2(0x2A1, 0x7B));
fennec_test_run(([]() -> ivec3 { ivec3 v(0x2A1E, 0x7BF3, 0x3927); return v >>= ivec3(4, 8, 12); }()), ivec3(0x2A1, 0x7B, 0x3)); fennec_test_run(([]() -> ivec3 { ivec3 v(0x2A1E, 0x7BF3, 0x3927); return v >>= ivec3(4, 8, 12); }()), ivec3(0x2A1, 0x7B, 0x3));
fennec_test_run(([]() -> ivec4 { ivec4 v(0x2A1E, 0x7BF3, 0x3927, 0x237C); return v >>= ivec4(4, 8, 12, 16); }()), ivec4(0x2A1, 0x7B, 0x3, 0x0)); fennec_test_run(([]() -> ivec4 { ivec4 v(0x2A1E, 0x7BF3, 0x3927, 0x237C); return v >>= ivec4(4, 8, 12, 16); }()), ivec4(0x2A1, 0x7B, 0x3, 0x0));
} }
} }

View File

@@ -0,0 +1,43 @@
// =====================================================================================================================
// 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_TEST_PLATFORM_LINUX_WAYLAND_H
#define FENNEC_TEST_PLATFORM_LINUX_WAYLAND_H
#include "../../../test.h"
#include <fennec/platform/linux/wayland/display.h>
namespace fennec
{
namespace test
{
using namespace wayland;
inline void fennec_test_platform_linux_wayland(linux_platform& platform) {
wayland_display* display = static_cast<wayland_display*>(platform.get_display());
fennec_test_run(display != nullptr, true);
}
}
}
#endif // FENNEC_TEST_PLATFORM_LINUX_WAYLAND_H

View File

@@ -0,0 +1,51 @@
// =====================================================================================================================
// 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_TEST_PLATFORM_LINUX_H
#define FENNEC_TEST_PLATFORM_LINUX_H
#include "../../test.h"
#ifdef FENNEC_LIB_WAYLAND
#include "linux/test_wayland.h"
#endif
namespace fennec
{
namespace test
{
inline void fennec_test_platform_linux() {
linux_platform platform(platform::user::client);
#ifdef FENNEC_LIB_WAYLAND
fennec_test_section("wayland tests");
fennec_test_spacer(2);
fennec_test_platform_linux_wayland(platform);
fennec_test_spacer(3);
#endif
// TODO
}
}
}
#endif // FENNEC_TEST_PLATFORM_LINUX_H

View File

@@ -0,0 +1,61 @@
// =====================================================================================================================
// fennec-test, a program to execute unit tests for fennec
// 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_TEST_CONTAINERS_H
#define FENNEC_TEST_CONTAINERS_H
#include "containers/test_array.h"
#include "containers/test_dynarray.h"
#include "containers/test_optional.h"
#include "containers/test_set.h"
namespace fennec
{
namespace test
{
inline void fennec_test_containers()
{
fennec_test_subheader("optional tests");
fennec_test_spacer(2);
fennec_test_containers_optional();
fennec_test_spacer(3);
fennec_test_subheader("array tests");
fennec_test_spacer(2);
fennec_test_containers_array();
fennec_test_spacer(3);
fennec_test_subheader("dynarray tests");
fennec_test_spacer(2);
fennec_test_containers_dynarray();
fennec_test_spacer(3);
fennec_test_subheader("set tests");
fennec_test_spacer(2);
fennec_test_containers_set();
// TODO
}
}
}
#endif // FENNEC_TEST_CONTAINERS_H

View File

@@ -40,6 +40,8 @@ inline void fennec_test_fproc() {
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_fproc_io(); fennec_test_fproc_io();
fennec_test_spacer(3); fennec_test_spacer(3);
// TODO
} }
} }

View File

@@ -21,6 +21,7 @@
#include "lang/test_bits.h" #include "lang/test_bits.h"
#include "lang/test_conditional_types.h" #include "lang/test_conditional_types.h"
#include "lang/test_hashing.h"
namespace fennec namespace fennec
{ {
@@ -34,6 +35,12 @@ inline void fennec_test_lang()
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_lang_bits(); fennec_test_lang_bits();
fennec_test_spacer(3); fennec_test_spacer(3);
fennec_test_subheader("hashing tests");
fennec_test_spacer(2);
fennec_test_lang_hashing();
// TODO
} }
} }

View File

@@ -83,6 +83,8 @@ inline void fennec_test_math()
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_math_ext(); fennec_test_math_ext();
fennec_test_spacer(3); fennec_test_spacer(3);
// TODO
} }
} }

View File

@@ -19,4 +19,6 @@
#ifndef FENNEC_TEST_MEMORY_H #ifndef FENNEC_TEST_MEMORY_H
#define FENNEC_TEST_MEMORY_H #define FENNEC_TEST_MEMORY_H
// TODO
#endif // FENNEC_TEST_MEMORY_H #endif // FENNEC_TEST_MEMORY_H

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 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_TEST_PLATFORM_H
#define FENNEC_TEST_PLATFORM_H
#include "../test.h"
#if FENNEC_PLATFORM_LINUX
#include "./platform/test_linux.h"
#endif
namespace fennec
{
namespace test
{
inline void fennec_test_platform() {
#if FENNEC_PLATFORM_LINUX
fennec_test_subheader("linux");
fennec_test_spacer(2);
fennec_test_platform_linux();
fennec_test_spacer(3);
#endif
}
}
}
#endif // FENNEC_TEST_PLATFORM_H