Compare commits
35 Commits
custom_pla
...
520a0e1363
| Author | SHA1 | Date | |
|---|---|---|---|
| 520a0e1363 | |||
| 97f5bbfe00 | |||
| b64ce44d4e | |||
| 1acf00138a | |||
| 5dcb58f53c | |||
| a1bdc077b1 | |||
| 9553f9b662 | |||
| 9645856554 | |||
| a2abb58705 | |||
| 7f1dd245dc | |||
| 6d58105734 | |||
| d928d86014 | |||
| 0b76b06a1b | |||
| 6f09c3f7fe | |||
| fe8c3a4602 | |||
| b9026ec8da | |||
| 7b87828f06 | |||
| 8925b3f2f0 | |||
| f636feb4f1 | |||
| 1a9a80e37f | |||
| 18c8171847 | |||
| d546519180 | |||
| f208141b5b | |||
| 52d6c62f76 | |||
| 037e2554a1 | |||
| 8867576a2e | |||
| 788f63d092 | |||
| a35f2a699d | |||
| 80925965d4 | |||
| f2a45aa913 | |||
| 3565bbbc52 | |||
| 375492ef7b | |||
| dbcb50349d | |||
| 992a02db3e | |||
| e1eaf97961 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@
|
|||||||
/bin/
|
/bin/
|
||||||
/lib/
|
/lib/
|
||||||
/doxy/README.md
|
/doxy/README.md
|
||||||
|
/doxy/Doxyfile.out
|
||||||
|
|||||||
144
CMakeLists.txt
144
CMakeLists.txt
@@ -16,21 +16,11 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
# ======================================================================================================================
|
# ======================================================================================================================
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.30)
|
cmake_minimum_required(VERSION 3.28)
|
||||||
|
|
||||||
project(fennec)
|
project(fennec)
|
||||||
|
|
||||||
# External dependencies should be loaded here
|
|
||||||
add_subdirectory(external/cpptrace)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
|
||||||
set(CMAKE_C_STANDARD 23)
|
|
||||||
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
add_custom_target(fennec-dependencies
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "Running dependencies."
|
|
||||||
COMMENT "Running dependencies."
|
|
||||||
)
|
|
||||||
|
|
||||||
macro(fennec_add_sources)
|
macro(fennec_add_sources)
|
||||||
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
|
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
@@ -43,6 +33,25 @@ macro(fennec_add_link_libraries)
|
|||||||
list(APPEND FENNEC_LINK_LIBRARIES ${ARGN})
|
list(APPEND FENNEC_LINK_LIBRARIES ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(fennec_add_shared_libraries)
|
||||||
|
list(APPEND FENNEC_SHARED_LIBRARIES ${ARGN})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(fennec_add_link_options)
|
||||||
|
list(APPEND FENNEC_PRIVATE_LINK_OPTIONS ${ARGN})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# External dependencies should be loaded here
|
||||||
|
add_subdirectory(external/cpptrace)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_C_STANDARD 23)
|
||||||
|
|
||||||
|
add_custom_target(fennec-dependencies
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "Running dependencies."
|
||||||
|
COMMENT "Running dependencies."
|
||||||
|
)
|
||||||
|
|
||||||
# include scripts
|
# include scripts
|
||||||
include("${FENNEC_SOURCE_DIR}/cmake/version.cmake")
|
include("${FENNEC_SOURCE_DIR}/cmake/version.cmake")
|
||||||
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
|
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
|
||||||
@@ -62,7 +71,7 @@ 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)
|
||||||
|
|
||||||
|
# Specify where to send libraries and executables
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${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_RUNTIME_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
|
||||||
@@ -75,28 +84,48 @@ add_library(fennec STATIC
|
|||||||
# CORE =================================================================================================================
|
# CORE =================================================================================================================
|
||||||
include/fennec/core/engine.h source/core/engine.cpp
|
include/fennec/core/engine.h source/core/engine.cpp
|
||||||
include/fennec/core/event.h source/core/event.cpp
|
include/fennec/core/event.h source/core/event.cpp
|
||||||
|
include/fennec/core/logger.h source/core/logger.cpp
|
||||||
|
|
||||||
|
include/fennec/core/version.h
|
||||||
include/fennec/core/system.h
|
include/fennec/core/system.h
|
||||||
|
|
||||||
|
|
||||||
# SCENE ================================================================================================================
|
# SCENE ================================================================================================================
|
||||||
include/fennec/scene/scene.h
|
include/fennec/scene/scene.h source/scene/scene.cpp
|
||||||
include/fennec/scene/component.h
|
include/fennec/scene/component.h
|
||||||
|
include/fennec/scene/scene_node.h
|
||||||
|
include/fennec/scene/node2d.h
|
||||||
|
include/fennec/scene/forward.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# RENDERERS ============================================================================================================
|
||||||
|
include/fennec/renderers/interface/forward.h
|
||||||
|
|
||||||
|
include/fennec/renderers/interface/gfxcontext.h
|
||||||
|
include/fennec/renderers/interface/gfxsubpass.h
|
||||||
|
include/fennec/renderers/interface/gfxresourcepool.h
|
||||||
|
|
||||||
|
|
||||||
# CONTAINERS ===========================================================================================================
|
# CONTAINERS ===========================================================================================================
|
||||||
include/fennec/containers/containers.h
|
include/fennec/containers/containers.h
|
||||||
|
|
||||||
include/fennec/containers/array.h
|
include/fennec/containers/array.h
|
||||||
|
include/fennec/containers/bintree.h
|
||||||
|
include/fennec/containers/bitfield.h
|
||||||
include/fennec/containers/deque.h
|
include/fennec/containers/deque.h
|
||||||
include/fennec/containers/dynarray.h
|
include/fennec/containers/dynarray.h
|
||||||
|
include/fennec/containers/generic.h
|
||||||
include/fennec/containers/graph.h
|
include/fennec/containers/graph.h
|
||||||
|
include/fennec/containers/initializer_list.h
|
||||||
include/fennec/containers/list.h
|
include/fennec/containers/list.h
|
||||||
include/fennec/containers/map.h
|
include/fennec/containers/map.h
|
||||||
include/fennec/containers/object_pool.h
|
include/fennec/containers/object_pool.h
|
||||||
include/fennec/containers/optional.h
|
include/fennec/containers/optional.h
|
||||||
include/fennec/containers/pair.h
|
include/fennec/containers/pair.h
|
||||||
|
include/fennec/containers/priority_queue.h
|
||||||
include/fennec/containers/rdtree.h
|
include/fennec/containers/rdtree.h
|
||||||
|
include/fennec/containers/sequence.h
|
||||||
include/fennec/containers/set.h
|
include/fennec/containers/set.h
|
||||||
include/fennec/containers/traversal.h
|
include/fennec/containers/traversal.h
|
||||||
include/fennec/containers/tuple.h
|
include/fennec/containers/tuple.h
|
||||||
@@ -106,40 +135,58 @@ add_library(fennec STATIC
|
|||||||
include/fennec/containers/detail/_tuple.h
|
include/fennec/containers/detail/_tuple.h
|
||||||
|
|
||||||
|
|
||||||
# LANG =================================================================================================================
|
# lang =================================================================================================================
|
||||||
include/fennec/lang/lang.h
|
include/fennec/lang/lang.h
|
||||||
include/fennec/lang/metaprogramming.h
|
include/fennec/lang/metaprogramming.h
|
||||||
|
|
||||||
|
|
||||||
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/declval.h
|
||||||
include/fennec/lang/hashing.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/const_sequences.h
|
include/fennec/lang/metasequences.h
|
||||||
include/fennec/lang/startup.h
|
include/fennec/lang/ranges.h
|
||||||
|
include/fennec/lang/static_constructor.h
|
||||||
include/fennec/lang/type_identity.h
|
include/fennec/lang/type_identity.h
|
||||||
include/fennec/lang/type_operators.h
|
include/fennec/lang/type_operators.h
|
||||||
include/fennec/lang/type_sequences.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/typeuuid.h
|
|
||||||
include/fennec/lang/types.h
|
include/fennec/lang/types.h
|
||||||
include/fennec/lang/utility.h
|
include/fennec/lang/utility.h
|
||||||
include/fennec/lang/integer.h
|
include/fennec/lang/integer.h
|
||||||
|
|
||||||
include/fennec/lang/assert.h source/lang/assert.cpp
|
include/fennec/lang/assert.h source/lang/assert.cpp
|
||||||
|
|
||||||
|
|
||||||
include/fennec/lang/detail/_bits.h
|
include/fennec/lang/detail/_bits.h
|
||||||
|
include/fennec/lang/detail/_declval.h
|
||||||
include/fennec/lang/detail/_int.h
|
include/fennec/lang/detail/_int.h
|
||||||
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_transforms.h
|
||||||
include/fennec/lang/detail/_type_sequences.h
|
include/fennec/lang/detail/_type_sequences.h
|
||||||
include/fennec/lang/detail/_typeuuid.h
|
|
||||||
|
|
||||||
|
# RTTI =================================================================================================================
|
||||||
|
include/fennec/rtti/typeid.h
|
||||||
|
include/fennec/rtti/type_data.h
|
||||||
|
include/fennec/rtti/type.h
|
||||||
|
include/fennec/rtti/enable.h
|
||||||
|
include/fennec/rtti/forward.h
|
||||||
|
include/fennec/rtti/typelist.h
|
||||||
|
include/fennec/rtti/type_registry.h
|
||||||
|
include/fennec/rtti/singleton.h
|
||||||
|
|
||||||
|
|
||||||
|
include/fennec/rtti/detail/_constants.h
|
||||||
|
include/fennec/rtti/detail/_this_t.h
|
||||||
|
include/fennec/rtti/detail/_typeid.h
|
||||||
|
include/fennec/rtti/detail/_type_name.h
|
||||||
|
|
||||||
|
|
||||||
# MEMORY ===============================================================================================================
|
# MEMORY ===============================================================================================================
|
||||||
@@ -184,7 +231,6 @@ add_library(fennec STATIC
|
|||||||
include/fennec/math/ext/primes.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/detail/_fwd.h
|
include/fennec/math/detail/_fwd.h
|
||||||
@@ -194,32 +240,56 @@ add_library(fennec STATIC
|
|||||||
include/fennec/math/detail/_vector_traits.h
|
include/fennec/math/detail/_vector_traits.h
|
||||||
|
|
||||||
|
|
||||||
# langproc ================================================================================================================
|
|
||||||
|
|
||||||
# Strings
|
# string ===============================================================================================================
|
||||||
include/fennec/langproc/strings/cstring.h
|
include/fennec/string/locale.h
|
||||||
include/fennec/langproc/strings/locale.h
|
include/fennec/string/cstring.h
|
||||||
include/fennec/langproc/strings/string.h
|
include/fennec/string/string.h
|
||||||
|
|
||||||
include/fennec/langproc/strings/detail/_ctype.h
|
include/fennec/string/detail/_ctype.h
|
||||||
|
|
||||||
# Filesystem
|
|
||||||
include/fennec/langproc/filesystem/file.h source/langproc/filesystem/file.cpp
|
|
||||||
include/fennec/langproc/filesystem/path.h source/langproc/filesystem/path.cpp
|
# format ===============================================================================================================
|
||||||
|
include/fennec/format/format.h
|
||||||
|
include/fennec/format/format_arg.h
|
||||||
|
include/fennec/format/formatter.h
|
||||||
|
include/fennec/format/charconv.h
|
||||||
|
|
||||||
|
include/fennec/format/detail/_format.h
|
||||||
|
|
||||||
|
source/format/charconv.cpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# filesystem ===========================================================================================================
|
||||||
|
include/fennec/filesystem/file.h source/filesystem/file.cpp
|
||||||
|
include/fennec/filesystem/path.h source/filesystem/path.cpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# interpret ============================================================================================================
|
||||||
|
include/fennec/interpret/tokenizer.h
|
||||||
|
|
||||||
|
|
||||||
# PLATFORM =============================================================================================================
|
# PLATFORM =============================================================================================================
|
||||||
|
|
||||||
include/fennec/platform/interface/fwd.h
|
include/fennec/platform/interface/fwd.h
|
||||||
|
include/fennec/platform/interface/display_server.h
|
||||||
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
|
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
|
||||||
include/fennec/platform/interface/display.h source/platform/interface/display.cpp
|
include/fennec/platform/interface/window.h source/platform/interface/window.cpp
|
||||||
include/fennec/platform/interface/gfxcontext.h
|
|
||||||
include/fennec/platform/interface/gfxsurface.h
|
|
||||||
|
|
||||||
|
# GRAPHICS =============================================================================================================
|
||||||
|
|
||||||
|
include/fennec/gfx3d/mesh_instance.h
|
||||||
|
|
||||||
# EXTRA SOURCES ========================================================================================================
|
# EXTRA SOURCES ========================================================================================================
|
||||||
|
|
||||||
${FENNEC_EXTRA_SOURCES}
|
${FENNEC_EXTRA_SOURCES}
|
||||||
|
include/fennec/math/ext/rect.h
|
||||||
|
include/fennec/platform/opengl/egl/error.h
|
||||||
|
include/fennec/platform/window_manager.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||||
@@ -235,10 +305,16 @@ target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not comp
|
|||||||
|
|
||||||
target_link_libraries(fennec PRIVATE
|
target_link_libraries(fennec PRIVATE
|
||||||
${FENNEC_LINK_LIBRARIES}
|
${FENNEC_LINK_LIBRARIES}
|
||||||
|
${FENNEC_SHARED_LIBRARIES}
|
||||||
|
|
||||||
cpptrace::cpptrace
|
cpptrace::cpptrace
|
||||||
)
|
)
|
||||||
|
|
||||||
|
foreach (_LIB IN ITEMS ${FENNEC_SHARED_LIBRARIES})
|
||||||
|
add_custom_command(TARGET fennec POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_LINKER_FILE:${_LIB}> ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||||
|
)
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
|
||||||
# DOXYGEN ==============================================================================================================
|
# DOXYGEN ==============================================================================================================
|
||||||
@@ -252,7 +328,7 @@ if(DOXYGEN_FOUND)
|
|||||||
set(DOXY_EXAMPLES_DIR "${FENNEC_SOURCE_DIR}/examples")
|
set(DOXY_EXAMPLES_DIR "${FENNEC_SOURCE_DIR}/examples")
|
||||||
get_filename_component(DOXYGEN_PROJECT_NAME ${FENNEC_SOURCE_DIR} NAME) # Set Doxy Project name to the name of the root dir
|
get_filename_component(DOXYGEN_PROJECT_NAME ${FENNEC_SOURCE_DIR} NAME) # Set Doxy Project name to the name of the root dir
|
||||||
set(DOXYGEN_CONFIG_IN "${FENNEC_SOURCE_DIR}/doxy/Doxyfile.in") # Input config file with preprocessor arguments
|
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
|
set(DOXYGEN_CONFIG_OUT "${FENNEC_SOURCE_DIR}/doxy/Doxyfile.out") # 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.")
|
||||||
|
|||||||
@@ -49,9 +49,11 @@ Some main areas where the engine strays from the GNU standard includes the follo
|
|||||||
|
|
||||||
* [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html).
|
* [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html).
|
||||||
fennec provides an implementation for X11, however it does not use the GTK toolkit.
|
fennec provides an implementation for X11, however it does not use the GTK toolkit.
|
||||||
- [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html)
|
- [Section 5.1, Formatting Your Source Code](https://www.gnu.org/prep/standards/html_node/index.html).
|
||||||
|
fennec uses Allman (BSD) for namespaces, otherwise K&R.
|
||||||
|
* [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html)
|
||||||
fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section.
|
fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section.
|
||||||
* [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html)
|
- [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html)
|
||||||
fennec follows most of the conventions in this section, however the build system used is CMake and not
|
fennec follows most of the conventions in this section, however the build system used is CMake and not
|
||||||
Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time.
|
Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time.
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
# this script finds the compiler being used
|
# this script finds the compiler being used
|
||||||
|
|
||||||
|
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
|
||||||
|
|
||||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||||
set(FENNEC_COMPILER "GCC")
|
set(FENNEC_COMPILER "GCC")
|
||||||
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")
|
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")
|
||||||
|
|||||||
@@ -18,8 +18,13 @@
|
|||||||
|
|
||||||
# this script sets flags and variables for gnu and gnu-like compilers
|
# this script sets flags and variables for gnu and gnu-like compilers
|
||||||
|
|
||||||
add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
|
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror" "-fms-extensions")
|
||||||
|
|
||||||
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
||||||
|
|
||||||
list(APPEND FENNEC_COMPILE_DEFINITIONS _GLIBCXX_INCLUDE_NEXT_C_HEADERS=1 FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]])
|
fennec_add_definitions(
|
||||||
|
_GLIBCXX_INCLUDE_NEXT_C_HEADERS=1
|
||||||
|
FENNEC_COMPILER_GCC=1
|
||||||
|
FENNEC_NO_INLINE=[[gnu::noinline]]
|
||||||
|
FENNEC_FUNCTION_NAME=__PRETTY_FUNCTION__
|
||||||
|
)
|
||||||
|
|||||||
@@ -16,42 +16,31 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
# ======================================================================================================================
|
# ======================================================================================================================
|
||||||
|
|
||||||
|
find_package(OpenGL)
|
||||||
|
|
||||||
if(FENNEC_GRAPHICS_WANT_EGL)
|
if(FENNEC_GRAPHICS_WANT_EGL)
|
||||||
find_package(OpenGL REQUIRED COMPONENTS EGL)
|
find_package(OpenGL REQUIRED COMPONENTS EGL)
|
||||||
find_package(GLEW REQUIRED)
|
|
||||||
message(STATUS "EGL Requested")
|
message(STATUS "EGL Requested")
|
||||||
else()
|
|
||||||
find_package(OpenGL)
|
|
||||||
find_package(GLEW REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TARGET OpenGL::GL AND TARGET GLEW::GLEW)
|
|
||||||
message(STATUS "Found OpenGL: ${OPENGL_gl_LIBRARY}")
|
|
||||||
fennec_add_link_libraries(OpenGL::GL GLEW::GLEW)
|
|
||||||
fennec_add_definitions(FENNEC_GRAPHICS_OPENGL=1)
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(FENNEC_GRAPHICS_WANT_EGL)
|
|
||||||
if(NOT TARGET OpenGL::EGL)
|
|
||||||
message(FATAL_ERROR "EGL Library not found.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Found EGL: ${OPENGL_egl_LIBRARY}")
|
|
||||||
|
|
||||||
fennec_add_link_libraries(OpenGL::EGL)
|
fennec_add_link_libraries(OpenGL::EGL)
|
||||||
fennec_add_definitions(FENNEC_GRAPHICS_EGL=1)
|
|
||||||
|
|
||||||
fennec_add_sources(
|
fennec_add_sources(
|
||||||
include/fennec/platform/opengl/lib/fwd.h
|
|
||||||
include/fennec/platform/opengl/lib/enum.h
|
|
||||||
include/fennec/platform/opengl/lib/buffer.h
|
|
||||||
include/fennec/platform/opengl/lib/texture.h
|
|
||||||
include/fennec/platform/opengl/lib/vertex_array.h
|
|
||||||
|
|
||||||
include/fennec/platform/opengl/egl/fwd.h
|
include/fennec/platform/opengl/egl/fwd.h
|
||||||
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
|
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
|
||||||
include/fennec/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
|
include/fennec/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(GLEW REQUIRED)
|
||||||
|
|
||||||
|
if(TARGET OpenGL::GL AND TARGET GLEW::GLEW)
|
||||||
|
message(STATUS "Found OpenGL: ${OPENGL_LIBRARIES}")
|
||||||
|
fennec_add_link_libraries(OpenGL::GL GLEW::GLEW)
|
||||||
|
fennec_add_definitions(FENNEC_GRAPHICS_OPENGL=1)
|
||||||
|
|
||||||
|
fennec_add_sources(
|
||||||
|
include/fennec/renderers/opengl/glcontext.h source/renderers/opengl/glcontext.cpp
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
|
||||||
|
endif()
|
||||||
@@ -21,6 +21,17 @@
|
|||||||
|
|
||||||
# some of this code is based on SDL3's use of wayland-scanner
|
# some of this code is based on SDL3's use of wayland-scanner
|
||||||
|
|
||||||
|
function(fennec_wayland_get_protocol)
|
||||||
|
set( _OPTIONS_ARGS )
|
||||||
|
set( _ONE_VALUE_ARGS )
|
||||||
|
set( _MULTI_VALUE_ARGS NAMES PATHS )
|
||||||
|
|
||||||
|
cmake_parse_arguments(_FINDPROTOCOLS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} )
|
||||||
|
|
||||||
|
find_file(_FINDPROTOCOLS_TEMP NAMES ${_FINDPROTOCOLS_NAMES} PATHS ${_FINDPROTOCOLS_PATHS})
|
||||||
|
file(COPY ${_FINDPROTOCOLS_TEMP} DESTINATION ${WAYLAND_PROTOCOLS_DIR})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
macro(fennec_wayland_get_header _SCANNER _XML _FILE)
|
macro(fennec_wayland_get_header _SCANNER _XML _FILE)
|
||||||
set(_WAYLAND_PROT_H_CODE "${WAYLAND_HEADERS_DIR}/${_FILE}-client-protocols.h")
|
set(_WAYLAND_PROT_H_CODE "${WAYLAND_HEADERS_DIR}/${_FILE}-client-protocols.h")
|
||||||
set(_WAYLAND_PROT_C_CODE "${WAYLAND_SOURCES_DIR}/${_FILE}-client.c")
|
set(_WAYLAND_PROT_C_CODE "${WAYLAND_SOURCES_DIR}/${_FILE}-client.c")
|
||||||
@@ -59,21 +70,18 @@ macro(fennec_check_wayland)
|
|||||||
NAMES wayland-egl libwayland-egl
|
NAMES wayland-egl libwayland-egl
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY AND WAYLAND_SCANNER)
|
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY AND WAYLAND_SCANNER)
|
||||||
AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARY))
|
AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARY))
|
||||||
message(STATUS "Found Wayland: ${WAYLAND_CLIENT_LIBRARY}")
|
message(STATUS "Found Wayland: ${WAYLAND_CLIENT_LIBRARY}")
|
||||||
|
|
||||||
set(WAYLAND_PROTOCOLS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/protocols)
|
set(WAYLAND_PROTOCOLS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/protocols)
|
||||||
set(WAYLAND_HEADERS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/headers)
|
set(WAYLAND_HEADERS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/headers)
|
||||||
set(WAYLAND_SOURCES_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/sources)
|
set(WAYLAND_SOURCES_DIR ${FENNEC_SOURCE_DIR}/source/platform/linux/wayland/lib/sources)
|
||||||
|
|
||||||
# Search for base protocol xml
|
# Search for base protocol xml
|
||||||
find_file(WAYLAND_PROTOCOL NAMES wayland.xml PATHS /usr/share/wayland /usr/share/wayland-protocols)
|
fennec_wayland_get_protocol(NAMES "wayland.xml" PATHS "/usr/share/wayland" "/usr/share/wayland-protocols")
|
||||||
file(COPY ${WAYLAND_PROTOCOL} DESTINATION ${WAYLAND_PROTOCOLS_DIR})
|
fennec_wayland_get_protocol(NAMES "xdg-shell.xml" PATHS "/usr/share/wayland/stable/xdg-shell" "/usr/share/wayland-protocols/stable/xdg-shell")
|
||||||
|
|
||||||
# search for xdg protocols
|
|
||||||
find_file(XDG_SHELL_PROTOCOL NAMES xdg-shell.xml PATHS /usr/share/wayland-protocols/stable/xdg-shell)
|
|
||||||
file(COPY ${XDG_SHELL_PROTOCOL} DESTINATION ${WAYLAND_PROTOCOLS_DIR})
|
|
||||||
|
|
||||||
# include sub-dependencies
|
# include sub-dependencies
|
||||||
include("${FENNEC_SOURCE_DIR}/cmake/xkb.cmake")
|
include("${FENNEC_SOURCE_DIR}/cmake/xkb.cmake")
|
||||||
@@ -109,8 +117,13 @@ macro(fennec_check_wayland)
|
|||||||
include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp
|
include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp
|
||||||
|
|
||||||
# Fennec Files
|
# Fennec Files
|
||||||
include/fennec/platform/linux/wayland/display.h source/platform/linux/wayland/display.cpp
|
include/fennec/platform/linux/wayland/fwd.h
|
||||||
|
include/fennec/platform/linux/wayland/server.h source/platform/linux/wayland/server.cpp
|
||||||
include/fennec/platform/linux/wayland/window.h source/platform/linux/wayland/window.cpp
|
include/fennec/platform/linux/wayland/window.h source/platform/linux/wayland/window.cpp
|
||||||
|
|
||||||
|
# EGL
|
||||||
|
include/fennec/platform/linux/wayland/egl/context.h source/platform/linux/wayland/egl/context.cpp
|
||||||
|
include/fennec/platform/linux/wayland/egl/surface.h source/platform/linux/wayland/egl/surface.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
fennec_add_definitions(
|
fennec_add_definitions(
|
||||||
@@ -118,5 +131,38 @@ macro(fennec_check_wayland)
|
|||||||
FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}"
|
FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}"
|
||||||
FENNEC_LIB_WAYLAND_EGL="${WAYLAND_EGL_LIBRARY}"
|
FENNEC_LIB_WAYLAND_EGL="${WAYLAND_EGL_LIBRARY}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# find libdecor
|
||||||
|
find_path(
|
||||||
|
LIBDECOR_INCLUDE_DIR
|
||||||
|
PATH_SUFFIXES libdecor libdecor-0
|
||||||
|
NAMES libdecor.h libdecor.h
|
||||||
|
)
|
||||||
|
find_library(
|
||||||
|
LIBDECOR_LIBRARY
|
||||||
|
PATH_SUFFIXES libdecor libdecor-0
|
||||||
|
NAMES libdecor.so libdecor-0.so
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LIBDECOR_INCLUDE_DIR AND LIBDECOR_LIBRARY)
|
||||||
|
message(STATUS "Found libdecor: ${LIBDECOR_LIBRARY}")
|
||||||
|
|
||||||
|
fennec_add_definitions(
|
||||||
|
FENNEC_HAS_LIBDECOR=1
|
||||||
|
FENNEC_LIB_LIBDECOR="${LIBDECOR_LIBRARY}"
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${LIBDECOR_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
fennec_add_sources(
|
||||||
|
include/fennec/platform/linux/wayland/libdecor/sym.h
|
||||||
|
include/fennec/platform/linux/wayland/libdecor/libdecor.h
|
||||||
|
include/fennec/platform/linux/wayland/libdecor/loader.h source/platform/linux/wayland/libdecor/loader.cpp
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
2869
doxy/Doxyfile
2869
doxy/Doxyfile
File diff suppressed because it is too large
Load Diff
@@ -1049,7 +1049,8 @@ RECURSIVE = YES
|
|||||||
# Note that relative paths are relative to the directory from which doxygen is
|
# Note that relative paths are relative to the directory from which doxygen is
|
||||||
# run.
|
# run.
|
||||||
|
|
||||||
EXCLUDE =
|
EXCLUDE = "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/lib" \
|
||||||
|
"@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/xkb/lib"
|
||||||
|
|
||||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||||
@@ -2435,8 +2436,7 @@ INCLUDE_FILE_PATTERNS =
|
|||||||
# recursively expanded use the := operator instead of the = operator.
|
# recursively expanded use the := operator instead of the = operator.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
|
||||||
PREDEFINED = "FENNEC_SCALAR_TEMPLATE=" \
|
PREDEFINED = "FENNEC_DOXYGEN="
|
||||||
"FENNEC_VECTOR_TEMPLATE="
|
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||||
# tag can be used to specify a list of macro names that should be expanded. The
|
# tag can be used to specify a list of macro names that should be expanded. The
|
||||||
|
|||||||
67
examples/assert.cpp
Normal file
67
examples/assert.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// I release this example code into the public domain
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
// This file contains code that tests the efficiency of the assert macro scheme in
|
||||||
|
// fennec engine. This is purely looking at the branching aspect and not the private
|
||||||
|
// assert definition. The code only uses passing values to see any performance overhead
|
||||||
|
// from the conditional
|
||||||
|
|
||||||
|
// This code is based on the example code that cppreference provides at
|
||||||
|
// https://en.cppreference.com/w/cpp/language/attributes/likely
|
||||||
|
|
||||||
|
// To my surprise, the difference between them is negligible.
|
||||||
|
// Even when n is a crazy number like one billion, there isn't a conclusive difference.
|
||||||
|
// I checked that it isn't the lambdas, they are optimized out.
|
||||||
|
|
||||||
|
// In debug mode, the results are to be expected; release < experimental < control
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define assert_c(expression) \
|
||||||
|
if(not(expression)) { \
|
||||||
|
std::abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define assert_e(expression) \
|
||||||
|
if(not(expression)) [[unlikely]] { \
|
||||||
|
std::abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define assert_r(expression) (static_cast<void> (0))
|
||||||
|
|
||||||
|
volatile int sink{}; // ensures a side effect
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto benchmark = [](auto fun, auto rem) {
|
||||||
|
srand(0);
|
||||||
|
|
||||||
|
const auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
for (auto size{1ULL}; size != 10'000'000ULL; ++size)
|
||||||
|
sink = fun(rand());
|
||||||
|
const std::chrono::duration<double> diff =
|
||||||
|
std::chrono::high_resolution_clock::now() - start;
|
||||||
|
|
||||||
|
std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count()
|
||||||
|
<< " sec " << rem << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
benchmark([](int x) {
|
||||||
|
assert_c(0 <= x && x <= RAND_MAX);
|
||||||
|
return x;
|
||||||
|
}, "control");
|
||||||
|
|
||||||
|
benchmark([](int x) {
|
||||||
|
assert_r(0 <= x && x <= RAND_MAX);
|
||||||
|
return x;
|
||||||
|
}, "release");
|
||||||
|
|
||||||
|
benchmark([](int x) {
|
||||||
|
assert_e(0 <= x && x <= RAND_MAX);
|
||||||
|
return x;
|
||||||
|
}, "experimental");
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
# GDB CODE =============================================================================================================
|
# GDB CODE =============================================================================================================
|
||||||
|
|
||||||
import gdb
|
import gdb
|
||||||
|
import gdb.printing
|
||||||
|
|
||||||
from . import containers
|
from . import containers
|
||||||
from . import strings
|
from . import strings
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ class RDTreePrinter:
|
|||||||
index += '└'
|
index += '└'
|
||||||
|
|
||||||
index += '─'
|
index += '─'
|
||||||
index += '[{}, {}]'.format(node, i)
|
index += '[{}]'.format(node)
|
||||||
return index, value
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
@@ -389,6 +389,200 @@ class RDTreePrinter:
|
|||||||
return self.Iterator(self.tree, 0, self.capacity)
|
return self.Iterator(self.tree, 0, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
# PRIORITY QUEUE =======================================================================================================
|
||||||
|
|
||||||
|
class PriorityQueuePrinter:
|
||||||
|
"""Print a fennec::rdtree"""
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
def __init__(self, tree, node, capacity):
|
||||||
|
self.tree = tree
|
||||||
|
self.capacity = capacity
|
||||||
|
self.visit = deque()
|
||||||
|
self.skip = True
|
||||||
|
|
||||||
|
self.visit.append((node, 0, 0, node))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if len(self.visit) == 0:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
node = self.visit[0][0]
|
||||||
|
i = self.visit[0][1]
|
||||||
|
depth = self.visit[0][2]
|
||||||
|
start = self.visit[0][3]
|
||||||
|
self.visit.popleft()
|
||||||
|
|
||||||
|
if node == start and not self.skip:
|
||||||
|
return self.__next__()
|
||||||
|
|
||||||
|
self.skip = False
|
||||||
|
|
||||||
|
value = self.tree[node]['_val']['key']
|
||||||
|
|
||||||
|
nnext = self.tree[node]['_val']['next']
|
||||||
|
child = self.tree[node]['_val']['child']
|
||||||
|
|
||||||
|
index = '⠀' * depth * 2 # Uses Braille Space, otherwise it would get eaten as whitespace by parsers
|
||||||
|
|
||||||
|
if nnext < self.capacity:
|
||||||
|
self.visit.appendleft((nnext, i + 1, depth, start))
|
||||||
|
|
||||||
|
if child < self.capacity:
|
||||||
|
self.visit.appendleft((child, 0, depth + 1, child))
|
||||||
|
self.skip = True
|
||||||
|
|
||||||
|
# ┌ ─ ├ └
|
||||||
|
|
||||||
|
if nnext != 18446744073709551615:
|
||||||
|
index += '├'
|
||||||
|
else:
|
||||||
|
index += '└'
|
||||||
|
|
||||||
|
index += '─'
|
||||||
|
index += '[{}]'.format(node)
|
||||||
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.tree = val['_table']['_table']['_alloc']['_data']
|
||||||
|
self.size = val['_table']['_size']
|
||||||
|
self.capacity = val['_table']['_table']['_alloc']['_capacity']
|
||||||
|
self.min = val['_min']
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
if self.size == 0:
|
||||||
|
return "{ empty }"
|
||||||
|
return "{ size = " + str(self.size) + " }"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self.Iterator(self.tree, self.min, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
# BINTREE ==============================================================================================================
|
||||||
|
|
||||||
|
class BinTreePrinter:
|
||||||
|
"""Print a fennec::bintree"""
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
def __init__(self, tree, node, capacity):
|
||||||
|
self.tree = tree
|
||||||
|
self.capacity = capacity
|
||||||
|
self.visit = deque()
|
||||||
|
|
||||||
|
if capacity > 0:
|
||||||
|
self.visit.append((node, 0, 0))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if len(self.visit) == 0:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
node = self.visit[0][0]
|
||||||
|
i = self.visit[0][1]
|
||||||
|
depth = self.visit[0][2]
|
||||||
|
parent = self.tree[node]['parent']
|
||||||
|
self.visit.popleft()
|
||||||
|
|
||||||
|
value = self.tree[node]['value']
|
||||||
|
left = self.tree[node]['child'][0]
|
||||||
|
right = self.tree[node]['child'][1]
|
||||||
|
|
||||||
|
if right < self.capacity:
|
||||||
|
self.visit.appendleft((right, 1, depth + 1))
|
||||||
|
if left < self.capacity:
|
||||||
|
self.visit.appendleft((left, 0, depth + 1))
|
||||||
|
|
||||||
|
index = '⠀' * depth * 2 # Uses Braille Space, otherwise it would get eaten as whitespace by parsers
|
||||||
|
if i == 0 and parent != 18446744073709551615 and self.tree[parent]['right'] != 18446744073709551615:
|
||||||
|
index += '├'
|
||||||
|
else:
|
||||||
|
index += '└'
|
||||||
|
|
||||||
|
index += '─'
|
||||||
|
index += '[{}]'.format(node)
|
||||||
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.tree = val['_table']['_data']
|
||||||
|
self.size = val['_size']
|
||||||
|
self.root = val['_root']
|
||||||
|
self.capacity = val['_table']['_capacity']
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
if self.size == 0:
|
||||||
|
return "{ empty }"
|
||||||
|
return "{ size = " + str(self.size) + " }"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self.Iterator(self.tree, self.root, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
# SEQUENCE =============================================================================================================
|
||||||
|
|
||||||
|
class SequencePrinter:
|
||||||
|
"""Print a fennec::sequence"""
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
def __init__(self, node):
|
||||||
|
self.visit = deque()
|
||||||
|
|
||||||
|
if node is not None:
|
||||||
|
self.visit.append((node, 0, 0))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if len(self.visit) == 0:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
node = self.visit[0][0]
|
||||||
|
i = self.visit[0][1]
|
||||||
|
depth = self.visit[0][2]
|
||||||
|
self.visit.popleft()
|
||||||
|
|
||||||
|
value = node['key']
|
||||||
|
left = node['child'][0]
|
||||||
|
right = node['child'][1]
|
||||||
|
print("it: ", node, " ", left, " ", right);
|
||||||
|
|
||||||
|
if right != 0:
|
||||||
|
self.visit.appendleft((right, 1, depth + 1))
|
||||||
|
if left != 0:
|
||||||
|
self.visit.appendleft((left, 0, depth + 1))
|
||||||
|
|
||||||
|
index = '⠀' * depth * 2 # Uses Braille Space, otherwise it would get eaten as whitespace by parsers
|
||||||
|
if i == 0:
|
||||||
|
index += '├'
|
||||||
|
else:
|
||||||
|
index += '└'
|
||||||
|
|
||||||
|
index += '─'
|
||||||
|
index += '[{}]'.format(node)
|
||||||
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.size = val['_size']
|
||||||
|
self.root = val['_root']
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
if self.size == 0:
|
||||||
|
return "{ empty }"
|
||||||
|
return "{ size = " + str(self.size) + " }"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
print("root: ", self.root)
|
||||||
|
return self.Iterator(self.root)
|
||||||
|
|
||||||
|
|
||||||
# Graph ================================================================================================================
|
# Graph ================================================================================================================
|
||||||
|
|
||||||
class GraphPrinter:
|
class GraphPrinter:
|
||||||
@@ -475,6 +669,9 @@ def register_printers():
|
|||||||
pp.add_printer('fennec::pair', '^fennec::pair<.*>$', PairPrinter)
|
pp.add_printer('fennec::pair', '^fennec::pair<.*>$', PairPrinter)
|
||||||
pp.add_printer('fennec::set', '^fennec::set<.*>$', SetPrinter)
|
pp.add_printer('fennec::set', '^fennec::set<.*>$', SetPrinter)
|
||||||
pp.add_printer('fennec::rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
|
pp.add_printer('fennec::rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
|
||||||
|
pp.add_printer('fennec::bintree', '^fennec::bintree<.*>$', BinTreePrinter)
|
||||||
|
pp.add_printer('fennec::sequence', '^fennec::sequence<.*>$', SequencePrinter)
|
||||||
|
pp.add_printer('fennec::priority_queue', '^fennec::priority_queue<.*>$', PriorityQueuePrinter)
|
||||||
pp.add_printer('fennec::tuple', '^fennec::tuple<.*>$', TuplePrinter)
|
pp.add_printer('fennec::tuple', '^fennec::tuple<.*>$', TuplePrinter)
|
||||||
return pp
|
return pp
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from . import utility
|
|||||||
class VectorPrinter:
|
class VectorPrinter:
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.val = val
|
self.val = val
|
||||||
self.base = val['data']['elements']
|
self.base = val['data']['data']
|
||||||
self.len = self.base.type.range()[1] + 1
|
self.len = self.base.type.range()[1] + 1
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
@@ -51,7 +51,7 @@ class VectorPrinter:
|
|||||||
class QuaternionPrinter:
|
class QuaternionPrinter:
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.val = val
|
self.val = val
|
||||||
self.base = val['data']['elements']
|
self.base = val['data']['data']
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
res = ("< "
|
res = ("< "
|
||||||
@@ -72,7 +72,7 @@ class QuaternionPrinter:
|
|||||||
# VECTOR =================================================================================================================
|
# VECTOR =================================================================================================================
|
||||||
class MatrixPrinter:
|
class MatrixPrinter:
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.columns = val['data']['elements']
|
self.columns = val['data']['data']
|
||||||
self.num_columns = self.columns.type.range()[1] + 1
|
self.num_columns = self.columns.type.range()[1] + 1
|
||||||
self.num_rows = val.type.template_argument(1)
|
self.num_rows = val.type.template_argument(1)
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
#include <fennec/lang/assert.h>
|
#include <fennec/lang/assert.h>
|
||||||
|
#include <fennec/lang/metasequences.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -166,13 +167,13 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Checks if all elements in the arrays are equal
|
/// \brief Checks if all elements in the arrays are equal
|
||||||
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
|
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
|
||||||
return array::_compare(lhs, rhs, make_index_sequence<ElemV>{});
|
return array::_compare(lhs, rhs, make_index_metasequence<ElemV>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Checks if any element in the arrays is not equal
|
/// \brief Checks if any element in the arrays is not equal
|
||||||
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
|
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
|
||||||
return not array::_compare(lhs, rhs, make_index_sequence<ElemV>{});
|
return not array::_compare(lhs, rhs, make_index_metasequence<ElemV>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -217,7 +218,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
template<size_t...i>
|
template<size_t...i>
|
||||||
static bool _compare(const array& lhs, const array& rhs, const_index_sequence<i...>) {
|
static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) {
|
||||||
return ((lhs[i] == rhs[i]) && ...);
|
return ((lhs[i] == rhs[i]) && ...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
831
include/fennec/containers/bintree.h
Normal file
831
include/fennec/containers/bintree.h
Normal file
@@ -0,0 +1,831 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file bintree.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_BINTREE_H
|
||||||
|
#define FENNEC_CONTAINERS_BINTREE_H
|
||||||
|
|
||||||
|
#include <fennec/containers/dynarray.h>
|
||||||
|
#include <fennec/containers/list.h>
|
||||||
|
#include <fennec/containers/optional.h>
|
||||||
|
#include <fennec/containers/traversal.h>
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Structure defining a binary tree
|
||||||
|
/// \tparam TypeT The data type
|
||||||
|
/// \tparam AllocT An allocator class
|
||||||
|
template<typename TypeT, class AllocT = allocator<TypeT>>
|
||||||
|
struct bintree {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
protected:
|
||||||
|
struct node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_t = TypeT;
|
||||||
|
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
||||||
|
static constexpr size_t npos = -1;
|
||||||
|
|
||||||
|
friend class iterator;
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct node {
|
||||||
|
value_t value;
|
||||||
|
size_t parent;
|
||||||
|
size_t child[2];
|
||||||
|
|
||||||
|
constexpr node()
|
||||||
|
: value()
|
||||||
|
, parent(npos), child{ npos, npos } {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
|
||||||
|
: value(fennec::forward<ArgsT>(args)...)
|
||||||
|
, parent(p), child{ l, r } {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ~node() {
|
||||||
|
parent = npos;
|
||||||
|
child[0] = npos;
|
||||||
|
child[1] = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t& operator[](bool d) {
|
||||||
|
return child[d];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using table_t = allocation<node, alloc_t>;
|
||||||
|
using freed_t = list<size_t, alloc_t>;
|
||||||
|
|
||||||
|
// Constructors & Destructor ===========================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, initializes an empty tree
|
||||||
|
constexpr bintree()
|
||||||
|
: _table()
|
||||||
|
, _freed()
|
||||||
|
, _root(npos)
|
||||||
|
, _size(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor, takes ownership of a tree
|
||||||
|
/// \param tree The tree to take ownership of
|
||||||
|
constexpr bintree(bintree&& tree) noexcept
|
||||||
|
: _table(fennec::move(tree._table))
|
||||||
|
, _freed(fennec::move(tree._freed))
|
||||||
|
, _root(tree._root)
|
||||||
|
, _size(tree._size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor, copies a tree
|
||||||
|
/// \param tree The tree to copy
|
||||||
|
constexpr bintree(const bintree& tree)
|
||||||
|
: _table(tree._table)
|
||||||
|
, _freed(tree._freed)
|
||||||
|
, _root(tree._root)
|
||||||
|
, _size(tree._size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor, clears the tree
|
||||||
|
constexpr ~bintree() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The number of elements in the tree
|
||||||
|
constexpr size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no elements in the tree, `false` otherwise.
|
||||||
|
constexpr bool empty() const {
|
||||||
|
return _size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The capacity of the underlying allocation
|
||||||
|
constexpr size_t capacity() const {
|
||||||
|
return _table.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The next id to be returned by `insert` or `emplace`.
|
||||||
|
constexpr size_t next_id() const {
|
||||||
|
size_t i = _size;
|
||||||
|
if (not _freed.empty()) {
|
||||||
|
i = _freed.front();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The next id to be returned by `insert` or `emplace`.
|
||||||
|
constexpr size_t root() const {
|
||||||
|
return _root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Navigation ==========================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Navigation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The parent of node `i`
|
||||||
|
constexpr size_t parent(size_t i) const {
|
||||||
|
return i == npos ? npos : _table[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The grandparent of node `i`
|
||||||
|
constexpr size_t grandparent(size_t i) const {
|
||||||
|
return parent(parent(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The left child of node `i`
|
||||||
|
constexpr size_t left(size_t i) const {
|
||||||
|
return i == npos ? npos : _table[i].child[false];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The right child of node `i`
|
||||||
|
constexpr size_t right(size_t i) const {
|
||||||
|
return i == npos ? npos : _table[i].child[true];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \param dir The direction to go `true` for right, `false` for left
|
||||||
|
/// \returns The child in the direction specified by `dir`
|
||||||
|
constexpr size_t child(size_t i, bool dir) const {
|
||||||
|
return i == npos ? npos : _table[i].child[dir];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns `true` if `i` is the right node of `parent(i)`, `false` otherwise
|
||||||
|
constexpr bool direction(size_t i) const {
|
||||||
|
return i == npos ? false : i == right(_parent(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief \f$O(1)\f$
|
||||||
|
/// \param i The id of the node
|
||||||
|
/// \returns The id of the sibling of `i`
|
||||||
|
constexpr size_t sibling(size_t i) const {
|
||||||
|
if (i == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
if (i == _root) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
size_t p = _parent(i);
|
||||||
|
bool d = i == _right(p);
|
||||||
|
return _child(p, !d);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(\log n)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The depth of node `i`
|
||||||
|
constexpr size_t depth(size_t i) const {
|
||||||
|
size_t d = 0;
|
||||||
|
while (i != npos) {
|
||||||
|
i = _parent(i);
|
||||||
|
++d;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief \f$O(\log n)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The id of the left-most node of `i`
|
||||||
|
constexpr size_t left_most(size_t i) const {
|
||||||
|
if (i >= _table.size()) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
while (_table[i].child[false] != npos) {
|
||||||
|
i = _table[i].child[false];
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief \f$O(\log n)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The id of the right-most node of `i`
|
||||||
|
constexpr size_t right_most(size_t i) const {
|
||||||
|
if (i >= _table.size()) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
while (_table[i].right[false] != npos) {
|
||||||
|
i = _table[i].right[false];
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Access ==============================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Access
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
|
||||||
|
constexpr value_t& operator[](size_t i) {
|
||||||
|
assertd(i < _table.size(), "Index out of bounds.");
|
||||||
|
return _table[i].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Const Access, \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
|
||||||
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
|
assertd(i < _table.size(), "Index out of bounds.");
|
||||||
|
return _table[i].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
/// \name Modifiers
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Left Insertion, constructs a new node as the left child of `p`
|
||||||
|
/// \details If the left node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to move into the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_left(size_t p, value_t&& val) {
|
||||||
|
return this->_insert_left(p, fennec::forward<value_t>(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Left Insertion, constructs a new node as the left child of `p`
|
||||||
|
/// \details If the left node of `p` already exists, the copy assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to copy to the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_left(size_t p, const value_t& val) {
|
||||||
|
return this->_insert_left(p, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Left Insertion, constructs a new node as the left child of `p`
|
||||||
|
/// \details If the left node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param args The arguments to construct the new node with
|
||||||
|
/// \returns The id of the new node
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t emplace_left(size_t p, ArgsT&&...args) {
|
||||||
|
return this->_insert_left(p, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Right Insertion, constructs a new node as the right child of `p`
|
||||||
|
/// \details If the right node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to move into the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_right(size_t p, value_t&& val) {
|
||||||
|
return this->_insert_right(p, fennec::forward<value_t>(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Right Insertion, constructs a new node as the right child of `p`
|
||||||
|
/// \details If the right node of `p` already exists, the copy assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to copy to the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_right(size_t p, const value_t& val) {
|
||||||
|
return this->_insert_right(p, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Right Insertion, constructs a new node as the right child of `p`
|
||||||
|
/// \details If the right node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param args The arguments to construct the new node with
|
||||||
|
/// \returns The id of the new node
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t emplace_right(size_t p, ArgsT&&...args) {
|
||||||
|
return this->_insert_right(p, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Perform a Tree Rotation at `i` in the specified direction
|
||||||
|
/// \param i The root node for the rotation
|
||||||
|
/// \param dir The direction to rotate, `true` for right, `false` for left
|
||||||
|
constexpr size_t rotate(size_t sub, bool dir) {
|
||||||
|
if (sub == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
size_t sub_parent = _parent(sub);
|
||||||
|
size_t new_root = _child(sub, not dir);
|
||||||
|
size_t new_child = _child(new_root, dir);
|
||||||
|
|
||||||
|
_child(sub, not dir) = new_child;
|
||||||
|
if (new_child != npos) {
|
||||||
|
_parent(new_child) = sub;
|
||||||
|
}
|
||||||
|
_child(new_root, dir) = sub;
|
||||||
|
|
||||||
|
_parent(new_root) = sub_parent;
|
||||||
|
_parent(sub) = new_root;
|
||||||
|
if (sub_parent != npos) {
|
||||||
|
_child(sub_parent, sub == _right(sub_parent)) = new_root;
|
||||||
|
} else {
|
||||||
|
_root = new_root;
|
||||||
|
}
|
||||||
|
return new_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Insertion, bool d, constructs a new node as the child of `p`
|
||||||
|
/// \details If the child of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param d The direction to insert
|
||||||
|
/// \param val The object to move into the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert(size_t p, bool d, value_t&& val) {
|
||||||
|
return this->_insert(p, d, fennec::forward<value_t>(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Insertion, bool d, constructs a new node as the child of `p`
|
||||||
|
/// \details If the child of `p` already exists, the copy assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param d The direction to insert
|
||||||
|
/// \param val The object to copy to the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert(size_t p, bool d, const value_t& val) {
|
||||||
|
return this->_insert(p, d, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Insertion, constructs a new node as the child of `p`
|
||||||
|
/// \details If the child of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param d The direction to insert
|
||||||
|
/// \param args The arguments to construct the new node with
|
||||||
|
/// \returns The id of the new node
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t emplace(size_t p, bool d, ArgsT&&...args) {
|
||||||
|
return this->_insert(p, d, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clears the tree, destroying all elements
|
||||||
|
constexpr void clear() {
|
||||||
|
list<size_t> queue;
|
||||||
|
|
||||||
|
if (_root != npos) {
|
||||||
|
queue.push_back(_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (not queue.empty()) {
|
||||||
|
size_t i = queue.front();
|
||||||
|
queue.pop_front();
|
||||||
|
|
||||||
|
if (_right(i) != npos) {
|
||||||
|
queue.push_front(_right(i));
|
||||||
|
}
|
||||||
|
if (_left(i) != npos) {
|
||||||
|
queue.push_front(_left(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
fennec::destruct(&_table[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_size = 0;
|
||||||
|
_root = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Traversal ===========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverse the tree using a specified order and visiting functor
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// The visitor should accept a reference to a value of type `TypeT` and a `size_t` which contains the node's id.
|
||||||
|
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||||
|
///
|
||||||
|
/// \tparam OrderT The order with which to traverse the tree.
|
||||||
|
/// \tparam VisitorT The visitor, should fulfill the signature `uint8_t visit(TypeT&, size_t)`
|
||||||
|
/// \param visit The visiting object
|
||||||
|
/// \param i The node to start at
|
||||||
|
template<typename OrderT, typename VisitorT>
|
||||||
|
constexpr void traverse(VisitorT&& visit, size_t i) {
|
||||||
|
OrderT order;
|
||||||
|
i = order(*this, i);
|
||||||
|
while (i != npos) {
|
||||||
|
uint8_t mode = traversal_control_continue;
|
||||||
|
if (_table[i].value) {
|
||||||
|
mode = visit(_table[i].value, i);
|
||||||
|
}
|
||||||
|
if (mode == traversal_control_break) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = order[*this, i, mode];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct breadth_first {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
size_t operator()(const bintree&, size_t start) {
|
||||||
|
return head = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t lft = tree.left(tree.parent(node));
|
||||||
|
size_t nxt = lft == node ? tree.right(tree.parent(node)) : npos;
|
||||||
|
size_t chd = tree.left(node);
|
||||||
|
|
||||||
|
if (nxt != npos && node != head) {
|
||||||
|
visit.push_front(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chd != npos && mode != traversal_control_jump_over) {
|
||||||
|
visit.push_back(chd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pre_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const bintree&, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nxt = tree.right(tree.parent(node));
|
||||||
|
size_t chd = tree.left(node);
|
||||||
|
nxt = node == nxt ? npos : nxt;
|
||||||
|
|
||||||
|
if (nxt != npos && node != head) {
|
||||||
|
visit.push_front(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chd != npos && mode != traversal_control_jump_over) {
|
||||||
|
visit.push_front(chd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct in_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const bintree& tree, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return tree.left_most(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t parent = tree.parent(node);
|
||||||
|
size_t pright = tree.right(parent);
|
||||||
|
size_t next = tree.left_most(tree.right(node));
|
||||||
|
|
||||||
|
if (node != pright && parent != npos) {
|
||||||
|
visit.push_front(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next != npos) {
|
||||||
|
visit.push_front(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct post_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t successor(const bintree& tree, size_t n) {
|
||||||
|
size_t s = tree.left_most(n);
|
||||||
|
while (n == s) {
|
||||||
|
size_t r = tree.right(n);
|
||||||
|
if (r != npos) {
|
||||||
|
n = r;
|
||||||
|
s = tree.left_most(n);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s == npos ? n : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator()(const bintree& tree, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return this->successor(tree, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t parent = tree.parent(node);
|
||||||
|
size_t pright = tree.right(parent);
|
||||||
|
|
||||||
|
if (node == pright) {
|
||||||
|
if (parent != npos) {
|
||||||
|
visit.push_front(parent);
|
||||||
|
}
|
||||||
|
} else if (pright != npos) {
|
||||||
|
visit.push_front(this->successor(tree, pright));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
protected:
|
||||||
|
bintree* _tree;
|
||||||
|
in_order _order;
|
||||||
|
size_t _n;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr iterator(bintree* tree, size_t root)
|
||||||
|
: _tree(tree)
|
||||||
|
, _order()
|
||||||
|
, _n(_order(*tree, root)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator(bintree* tree, size_t root, size_t node)
|
||||||
|
: _tree(tree)
|
||||||
|
, _order()
|
||||||
|
, _n(node) {
|
||||||
|
_order.head = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t index() const {
|
||||||
|
return _n;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator& operator++() {
|
||||||
|
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& operator*() {
|
||||||
|
return (*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t* operator->() {
|
||||||
|
return &(*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return (*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return &(*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const iterator& it) {
|
||||||
|
return _tree == it._tree and _n == it._n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const iterator& it) {
|
||||||
|
return _tree != it._tree or _n != it._n;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fields ==============================================================================================================
|
||||||
|
protected:
|
||||||
|
table_t _table;
|
||||||
|
freed_t _freed;
|
||||||
|
size_t _root, _size;
|
||||||
|
|
||||||
|
// Helpers =============================================================================================================
|
||||||
|
|
||||||
|
constexpr size_t _next_free() {
|
||||||
|
size_t i = _size;
|
||||||
|
if (not _freed.empty()) {
|
||||||
|
i = _freed.front();
|
||||||
|
_freed.pop_front();
|
||||||
|
}
|
||||||
|
if (i >= _table.capacity()) {
|
||||||
|
_table.creallocate(2 * fennec::max(_table.capacity(), size_t(4)));
|
||||||
|
}
|
||||||
|
++_size;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t _insert_left(size_t p, ArgsT&&...args) {
|
||||||
|
size_t i = p >= capacity() ? npos : p;
|
||||||
|
i = i == npos ? _root : _left(i);
|
||||||
|
if (i != npos) {
|
||||||
|
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||||
|
} else {
|
||||||
|
i = _next_free();
|
||||||
|
if (p != npos) {
|
||||||
|
_left(p) = i;
|
||||||
|
}
|
||||||
|
if (_root == npos) {
|
||||||
|
_root = i;
|
||||||
|
}
|
||||||
|
fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t _insert_right(size_t p, ArgsT&&...args) {
|
||||||
|
size_t i = p == npos ? _root : _right(p);
|
||||||
|
if (i != npos) {
|
||||||
|
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||||
|
} else {
|
||||||
|
i = _next_free();
|
||||||
|
if (p != npos) {
|
||||||
|
_right(p) = i;
|
||||||
|
}
|
||||||
|
if (_root == npos) {
|
||||||
|
_root = i;
|
||||||
|
}
|
||||||
|
fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t _insert(size_t p, bool d, ArgsT&&...args) {
|
||||||
|
size_t i = p == npos ? _root : _child(p, d);
|
||||||
|
if (i != npos) {
|
||||||
|
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = _next_free();
|
||||||
|
if (p != npos) {
|
||||||
|
_child(p, d) = i;
|
||||||
|
}
|
||||||
|
if (_root == npos) {
|
||||||
|
_root = i;
|
||||||
|
}
|
||||||
|
fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr size_t& _parent(size_t i) {
|
||||||
|
return _table[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& _grandparent(size_t i) {
|
||||||
|
return _parent(_parent(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& _left(size_t i) {
|
||||||
|
return _table[i].child[false];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& _right(size_t i) {
|
||||||
|
return _table[i].child[true];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& _child(size_t i, bool dir) {
|
||||||
|
return _table[i].child[dir];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& _sibling(size_t i) {
|
||||||
|
size_t p = _parent(i);
|
||||||
|
bool d = i == _right(p);
|
||||||
|
return _child(p, !d);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_BINTREE_H
|
||||||
148
include/fennec/containers/bitfield.h
Normal file
148
include/fennec/containers/bitfield.h
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file bitfield.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_BITFIELD_H
|
||||||
|
#define FENNEC_CONTAINERS_BITFIELD_H
|
||||||
|
|
||||||
|
#include <fennec/containers/array.h>
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/lang/utility.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Bitfield Container with basic Bit Ops
|
||||||
|
/// \tparam N The number of bits in the bitfield
|
||||||
|
template<size_t N>
|
||||||
|
struct bitfield {
|
||||||
|
static constexpr size_t bits = N;
|
||||||
|
static constexpr size_t bytes = (N + 7) / 8;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr bitfield()
|
||||||
|
: _bytes() {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit constexpr bitfield(const bool (&arr)[N])
|
||||||
|
: _bytes() {
|
||||||
|
for (size_t i = 0; i < arr; ++i) {
|
||||||
|
this->store(i, arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I>
|
||||||
|
explicit constexpr bitfield(const size_t (&arr)[I])
|
||||||
|
: _bytes() {
|
||||||
|
for (size_t i : arr) {
|
||||||
|
this->set(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr bitfield(ArgsT&&...args)
|
||||||
|
: _bytes() {
|
||||||
|
(this->store(fennec::forward<ArgsT>(args), true), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
|
||||||
|
constexpr bitfield(ArgsT&&...args)
|
||||||
|
: _bytes() {
|
||||||
|
size_t i = 0;
|
||||||
|
(this->store(i++, fennec::forward<ArgsT>(args)), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitfield(const bitfield& bf)
|
||||||
|
: _bytes(bf._bytes) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bitfield(bitfield&& bf) noexcept
|
||||||
|
: _bytes(bf._bytes) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ~bitfield() = default;
|
||||||
|
|
||||||
|
bitfield& operator=(const bitfield& bf) = default;
|
||||||
|
bitfield& operator=(bitfield&& bf) noexcept = default;
|
||||||
|
|
||||||
|
bool test(size_t i) const {
|
||||||
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
|
size_t b = i / 8;
|
||||||
|
size_t o = i % 8;
|
||||||
|
return _bytes[b] & (1 << o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(size_t i) {
|
||||||
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
|
size_t b = i / 8;
|
||||||
|
size_t o = i % 8;
|
||||||
|
_bytes[b] |= (1 << o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(size_t i) {
|
||||||
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
|
size_t b = i / 8;
|
||||||
|
size_t o = i % 8;
|
||||||
|
_bytes[b] &= ~(1 << o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle(size_t i) {
|
||||||
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
|
size_t b = i / 8;
|
||||||
|
size_t o = i % 8;
|
||||||
|
_bytes[b] ^= (1 << o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void store(size_t i, bool v) {
|
||||||
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
|
size_t b = i / 8;
|
||||||
|
size_t o = i % 8;
|
||||||
|
(_bytes[b] &= ~((1 << o))) |= ((v << o));
|
||||||
|
}
|
||||||
|
|
||||||
|
bitfield operator~() const {
|
||||||
|
bitfield res = *this;
|
||||||
|
res._inv_helper(make_index_metasequence_t<bytes>{});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
array<uint8_t, bytes> _bytes;
|
||||||
|
|
||||||
|
template<size_t...I>
|
||||||
|
void _inv_helper(index_metasequence<I...>) {
|
||||||
|
((_bytes[I] = ~_bytes[I]), ...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_BITFIELD_H
|
||||||
@@ -18,14 +18,14 @@
|
|||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_DETAIL_TUPLE_H
|
#ifndef FENNEC_CONTAINERS_DETAIL_TUPLE_H
|
||||||
#define FENNEC_CONTAINERS_DETAIL_TUPLE_H
|
#define FENNEC_CONTAINERS_DETAIL_TUPLE_H
|
||||||
#include <fennec/lang/const_sequences.h>
|
#include <fennec/lang/metasequences.h>
|
||||||
#include <fennec/lang/utility.h>
|
#include <fennec/lang/utility.h>
|
||||||
|
|
||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
template <std::size_t I, typename T>
|
template <size_t I, typename T>
|
||||||
struct _tuple_leaf
|
struct _tuple_leaf
|
||||||
{
|
{
|
||||||
template <typename ArgT>
|
template <typename ArgT>
|
||||||
@@ -43,7 +43,7 @@ template <typename, typename...>
|
|||||||
struct _tuple;
|
struct _tuple;
|
||||||
|
|
||||||
template <size_t...IndicesV, typename...TypesT>
|
template <size_t...IndicesV, typename...TypesT>
|
||||||
struct _tuple<const_index_sequence<IndicesV...>, TypesT...> : _tuple_leaf<IndicesV, TypesT>...
|
struct _tuple<index_metasequence<IndicesV...>, TypesT...> : _tuple_leaf<IndicesV, TypesT>...
|
||||||
{
|
{
|
||||||
template <typename...ArgsT>
|
template <typename...ArgsT>
|
||||||
constexpr _tuple(ArgsT&&... args)
|
constexpr _tuple(ArgsT&&... args)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#ifndef FENNEC_CONTAINERS_DYNARRAY_H
|
#ifndef FENNEC_CONTAINERS_DYNARRAY_H
|
||||||
#define FENNEC_CONTAINERS_DYNARRAY_H
|
#define FENNEC_CONTAINERS_DYNARRAY_H
|
||||||
|
|
||||||
|
#include <fennec/containers/initializer_list.h>
|
||||||
#include <fennec/lang/utility.h>
|
#include <fennec/lang/utility.h>
|
||||||
#include <fennec/memory/allocator.h>
|
#include <fennec/memory/allocator.h>
|
||||||
#include <fennec/memory/new.h>
|
#include <fennec/memory/new.h>
|
||||||
@@ -60,7 +61,7 @@ namespace fennec
|
|||||||
///
|
///
|
||||||
/// \tparam TypeT value type
|
/// \tparam TypeT value type
|
||||||
template<class TypeT, class Alloc = allocator<TypeT>>
|
template<class TypeT, class Alloc = allocator<TypeT>>
|
||||||
class dynarray {
|
struct dynarray {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
@@ -156,7 +157,7 @@ public:
|
|||||||
|
|
||||||
// This constructor should not be invokable since moving is a single object operation and will cause undefined
|
// This constructor should not be invokable since moving is a single object operation and will cause undefined
|
||||||
// behaviour when moving to multiple elements
|
// behaviour when moving to multiple elements
|
||||||
constexpr dynarray(size_t n, TypeT&&) = delete;
|
constexpr dynarray(size_t n, TypeT&& val) = delete;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Emplace Constructor
|
/// \brief Emplace Constructor
|
||||||
@@ -172,6 +173,60 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Array Copy Constructor
|
||||||
|
/// \tparam N The length of the array, automatically deduced
|
||||||
|
/// \param arr The array to copy
|
||||||
|
template<size_t N>
|
||||||
|
constexpr dynarray(const TypeT (&arr)[N])
|
||||||
|
: _alloc(N)
|
||||||
|
, _size(N) {
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
_alloc[i] = arr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Array Move Constructor
|
||||||
|
/// \tparam N The length of the array, automatically deduced
|
||||||
|
/// \param arr The array to move
|
||||||
|
template<size_t N>
|
||||||
|
constexpr dynarray(TypeT (&&arr)[N])
|
||||||
|
: _alloc(N)
|
||||||
|
, _size(N) {
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
_alloc[i] = fennec::move(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Conversion Constructor, copies elements of conv as this `value_t`
|
||||||
|
/// \tparam OTypeT The other value type
|
||||||
|
/// \tparam OAlloc The other allocator type
|
||||||
|
/// \param conv The dynarray to convert
|
||||||
|
template<typename OTypeT, class OAlloc>
|
||||||
|
constexpr dynarray(const dynarray<OTypeT, OAlloc>& conv)
|
||||||
|
: _alloc(conv.size())
|
||||||
|
, _size(conv.size()) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto& it : conv) {
|
||||||
|
fennec::construct(&_alloc[i++], it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Initializer List Constructor
|
||||||
|
/// \param l List of elements to initialize with
|
||||||
|
/// \param alloc An allocator object to copy
|
||||||
|
constexpr dynarray(initializer_list<value_t> l, const alloc_t& alloc = alloc_t())
|
||||||
|
: _alloc(l.size(), alloc)
|
||||||
|
, _size(l.size()) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (auto& it : l) {
|
||||||
|
fennec::construct(&_alloc[i++], fennec::move(it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Constructor, uses the copy constructor to copy each element
|
/// \brief Copy Constructor, uses the copy constructor to copy each element
|
||||||
/// \param arr the dynarray to copy
|
/// \param arr the dynarray to copy
|
||||||
@@ -234,6 +289,36 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Array Copy Assignment Operator
|
||||||
|
/// \tparam N the length of the array
|
||||||
|
/// \param arr the array to copy
|
||||||
|
/// \returns A dynarray after having copied each element of `arr`
|
||||||
|
template<size_t N>
|
||||||
|
constexpr dynarray& operator=(const TypeT (&arr)[N]) {
|
||||||
|
this->clear();
|
||||||
|
_alloc.creallocate(_size = N);
|
||||||
|
for (size_t i = 0; i < _size; ++i) {
|
||||||
|
fennec::construct(&_alloc[i], fennec::copy(arr[i]));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Array Copy Assignment Operator
|
||||||
|
/// \tparam N the length of the array
|
||||||
|
/// \param arr the array to copy
|
||||||
|
/// \returns A dynarray after having moved each element of `arr`
|
||||||
|
template<size_t N>
|
||||||
|
constexpr dynarray& operator=(TypeT (&&arr)[N]) {
|
||||||
|
this->clear();
|
||||||
|
_alloc.creallocate(_size = N);
|
||||||
|
for (size_t i = 0; i < _size; ++i) {
|
||||||
|
fennec::construct(&_alloc[i], fennec::move(arr[i]));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
@@ -432,6 +517,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Resize the dynarray, invoking the copy constructor for all new elements
|
||||||
|
/// \param n The new size in elements
|
||||||
|
/// \param val The value to fill with
|
||||||
|
constexpr void resize(size_t n, const TypeT& val) {
|
||||||
|
_alloc.creallocate(n);
|
||||||
|
|
||||||
|
while (_size < n) {
|
||||||
|
emplace_back(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation.
|
/// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation.
|
||||||
constexpr void clear() {
|
constexpr void clear() {
|
||||||
|
|||||||
210
include/fennec/containers/generic.h
Normal file
210
include/fennec/containers/generic.h
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file universal.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_GENERIC_H
|
||||||
|
#define FENNEC_CONTAINERS_GENERIC_H
|
||||||
|
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
#include <fennec/rtti/type.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief A struct capable of holding a single object of any type
|
||||||
|
struct generic {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
private:
|
||||||
|
|
||||||
|
// based on GCC
|
||||||
|
enum op_ : uint8_t {
|
||||||
|
op_clone,
|
||||||
|
op_destroy,
|
||||||
|
op_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
using manager_t = void* (*)(uint8_t, void*);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ========================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor
|
||||||
|
generic()
|
||||||
|
: _handle(nullptr)
|
||||||
|
, _manage(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor
|
||||||
|
/// \param gen The generic object to copy
|
||||||
|
generic(const generic& gen)
|
||||||
|
: _handle(nullptr)
|
||||||
|
, _manage(gen._manage) {
|
||||||
|
if (_manage) {
|
||||||
|
_handle = _manage(op_clone, gen._handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor
|
||||||
|
/// \param gen The generic object to move
|
||||||
|
generic(generic&& gen)
|
||||||
|
: _handle(gen._handle)
|
||||||
|
, _manage(gen._manage) {
|
||||||
|
gen._handle = nullptr;
|
||||||
|
gen._manage = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Constructor
|
||||||
|
/// \tparam T The type of the value
|
||||||
|
/// \param x The value
|
||||||
|
template<typename T>
|
||||||
|
generic(T&& x)
|
||||||
|
: _handle(new T(fennec::forward<T>(x)))
|
||||||
|
, _manage(_manage_impl<T>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Constructor
|
||||||
|
/// \tparam T The type to construct
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param args The argument values
|
||||||
|
template<typename T, typename...ArgsT>
|
||||||
|
generic(type_identity<T>, ArgsT&&...args)
|
||||||
|
: _handle(new T(fennec::forward<ArgsT>(args)...))
|
||||||
|
, _manage(_manage_impl<T>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor
|
||||||
|
~generic() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
type type() const {
|
||||||
|
return *static_cast<fennec::type*>(_manage(op_type, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_value() const {
|
||||||
|
return _handle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
generic& operator=(const generic& gen) {
|
||||||
|
if (this == &gen) { // self-assignment case
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
_manage = gen._manage;
|
||||||
|
_handle = _manage(op_clone, gen._handle);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
generic& operator=(generic&& gen) noexcept {
|
||||||
|
swap(gen);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Utility =============================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
generic& operator=(T&& x) {
|
||||||
|
reset();
|
||||||
|
_handle = new T(fennec::forward<T>(x));
|
||||||
|
_manage = _manage_impl<T>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename...ArgsT>
|
||||||
|
void emplace(ArgsT&&...args) {
|
||||||
|
reset();
|
||||||
|
_handle = new T(fennec::forward<ArgsT>(args)...);
|
||||||
|
_manage = _manage_impl<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if (_manage) {
|
||||||
|
_handle = _manage(op_destroy, _handle);
|
||||||
|
_manage = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(generic& gen) noexcept {
|
||||||
|
fennec::swap(_handle, gen._handle);
|
||||||
|
fennec::swap(_manage, gen._manage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& cast() {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& cast() const {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* _handle;
|
||||||
|
manager_t _manage;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void* _manage_impl(uint8_t op, void* hnd) {
|
||||||
|
static fennec::type t = type::get<T>();
|
||||||
|
T* ptr = hnd;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case op_clone:
|
||||||
|
return new T(*ptr);
|
||||||
|
case op_destroy:
|
||||||
|
delete ptr;
|
||||||
|
return nullptr;
|
||||||
|
case op_type:
|
||||||
|
return &t;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_GENERIC_H
|
||||||
57
include/fennec/containers/initializer_list.h
Normal file
57
include/fennec/containers/initializer_list.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file initializer_list.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_INITIALIZER_LIST_H
|
||||||
|
#define FENNEC_CONTAINERS_INITIALIZER_LIST_H
|
||||||
|
|
||||||
|
// Since initializer lists are completely intertwined with the compiler, and this is part of the c++ standard
|
||||||
|
// (specifically standard, and not the standard template library) we need to use std::initializer_list.
|
||||||
|
// We can at least alias it for proper naming conventions.
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
using std::initializer_list;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr const T* begin(initializer_list<T> inls) noexcept {
|
||||||
|
return inls.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr const T* end(initializer_list<T> inls) noexcept {
|
||||||
|
return inls.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_INITIALIZER_LIST_H
|
||||||
@@ -140,6 +140,7 @@ public:
|
|||||||
for (const value_t& it : l) {
|
for (const value_t& it : l) {
|
||||||
this->push_back(it);
|
this->push_back(it);
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -152,6 +153,7 @@ public:
|
|||||||
_freed = fennec::move(l._freed);
|
_freed = fennec::move(l._freed);
|
||||||
_root = l._root; _last = l._last;
|
_root = l._root; _last = l._last;
|
||||||
_size = l._size;
|
_size = l._size;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -164,15 +166,21 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The size of the list in elements.
|
/// \returns The size of the list in elements.
|
||||||
constexpr size_t size() const { return _size; }
|
constexpr size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The capacity of the list in elements.
|
/// \returns The capacity of the list in elements.
|
||||||
constexpr size_t capacity() const { return _table.capacity(); }
|
constexpr size_t capacity() const {
|
||||||
|
return _table.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when the list is empty, `false` otherwise.
|
/// \returns `true` when the list is empty, `false` otherwise.
|
||||||
constexpr bool empty() const { return _root == npos; }
|
constexpr bool empty() const {
|
||||||
|
return _root == npos;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
@@ -437,10 +445,7 @@ public:
|
|||||||
|
|
||||||
// prefix operator
|
// prefix operator
|
||||||
constexpr friend iterator& operator++(iterator& rhs) {
|
constexpr friend iterator& operator++(iterator& rhs) {
|
||||||
if (rhs._list->_next(rhs._n) < rhs._list->capacity()) {
|
rhs._n = rhs._list->_next(rhs._n);
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
rhs._n = npos;
|
|
||||||
return rhs;
|
return rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -291,7 +291,9 @@ private:
|
|||||||
~U() {
|
~U() {
|
||||||
fennec::destruct(&root);
|
fennec::destruct(&root);
|
||||||
}
|
}
|
||||||
} trick = { .root = { KeyT(fennec::forward<ArgsT>(args)...), 0 } };
|
} trick = {
|
||||||
|
.root = { KeyT(fennec::forward<ArgsT>(args)...), 0 }
|
||||||
|
};
|
||||||
return _set.find(trick.val);
|
return _set.find(trick.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,586 +0,0 @@
|
|||||||
// =====================================================================================================================
|
|
||||||
// fennec, a free and open source game engine
|
|
||||||
// Copyright © 2025 Medusa Slockbower
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \file multiset.h
|
|
||||||
/// \brief A header containing the definition for a set of repeating values
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// \details
|
|
||||||
/// \author Medusa Slockbower
|
|
||||||
///
|
|
||||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
|
||||||
///
|
|
||||||
///
|
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_MULTISET_H
|
|
||||||
#define FENNEC_CONTAINERS_MULTISET_H
|
|
||||||
|
|
||||||
// https://programming.guide/robin-hood-hashing.html
|
|
||||||
|
|
||||||
#include <fennec/containers/optional.h>
|
|
||||||
#include <fennec/containers/multiset.h>
|
|
||||||
#include <fennec/lang/compare.h>
|
|
||||||
#include <fennec/math/ext/primes.h>
|
|
||||||
#include <fennec/memory/allocator.h>
|
|
||||||
#include <fennec/lang/hashing.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// \brief A Data Structure that defines a set of elements that may repeat
|
|
||||||
/// \details
|
|
||||||
/// | Property | Value |
|
|
||||||
/// |:----------:|:----------:|
|
|
||||||
/// | stable | ⛔ |
|
|
||||||
/// | dynamic | ✅ |
|
|
||||||
/// | homogenous | ✅ |
|
|
||||||
/// | distinct | ⛔ |
|
|
||||||
/// | ordered | ⛔ |
|
|
||||||
/// | space | \f$O(N)\f$ |
|
|
||||||
/// | linear | ✅ |
|
|
||||||
/// | access | \f$O(1)\f$ |
|
|
||||||
/// | find | \f$O(1)\f$ |
|
|
||||||
/// | insertion | \f$O(1)\f$ |
|
|
||||||
/// | deletion | \f$O(1)\f$ |
|
|
||||||
///
|
|
||||||
/// \tparam TypeT The type to contain
|
|
||||||
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
|
|
||||||
struct multiset {
|
|
||||||
|
|
||||||
// Definitions =========================================================================================================
|
|
||||||
public:
|
|
||||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>;
|
|
||||||
using hash_t = Hash;
|
|
||||||
using equal_t = Equals;
|
|
||||||
using elem_t = TypeT;
|
|
||||||
|
|
||||||
class iterator;
|
|
||||||
class value_iterator;
|
|
||||||
static constexpr size_t npos = -1;
|
|
||||||
static constexpr double default_load = 0.8;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct node {
|
|
||||||
optional<elem_t> value;
|
|
||||||
int psl;
|
|
||||||
|
|
||||||
constexpr node() = default;
|
|
||||||
constexpr ~node() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// \name Constructors & Destructor
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Default Constructor, initializes empty multiset
|
|
||||||
constexpr multiset()
|
|
||||||
: _alloc()
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Copy Constructor, initializes empty multiset with a hash
|
|
||||||
constexpr multiset(const hash_t& hash)
|
|
||||||
: _alloc()
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Constructor, initializes empty multiset with a hash
|
|
||||||
constexpr multiset(hash_t&& hash) noexcept
|
|
||||||
: _alloc()
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Alloc Copy Constructor, initializes empty multiset with an allocator
|
|
||||||
constexpr multiset(const alloc_t& alloc)
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Alloc Move Constructor, initializes empty multiset with an allocator
|
|
||||||
constexpr multiset(alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Alloc Copy Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(const hash_t& hash, const alloc_t& alloc)
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Copy Alloc Move Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(const hash_t& hash, alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Alloc Move Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(hash_t&& hash, alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Alloc Copy Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(hash_t&& hash, const alloc_t& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Set Copy Constructor
|
|
||||||
/// \param multiset Set to copy
|
|
||||||
constexpr multiset(const multiset& multiset)
|
|
||||||
: _alloc( multiset._alloc)
|
|
||||||
, _hash( multiset._hash)
|
|
||||||
, _size( multiset._size)
|
|
||||||
, _sumpsl( multiset._sumpsl)
|
|
||||||
, _load( multiset._load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Set Move Constructor
|
|
||||||
/// \param multiset Set to move
|
|
||||||
constexpr multiset(multiset&& multiset) noexcept
|
|
||||||
: _alloc(fennec::move( multiset._alloc))
|
|
||||||
, _hash(fennec::move( multiset._hash))
|
|
||||||
, _size(fennec::move( multiset._size))
|
|
||||||
, _sumpsl( multiset._sumpsl)
|
|
||||||
, _load( multiset._load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Destructor, destructs all elements and releases the allocation
|
|
||||||
constexpr ~multiset() {
|
|
||||||
for (size_t i = 0; i < capacity(); ++i) {
|
|
||||||
_alloc[i].value = nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
|
||||||
|
|
||||||
/// \name Properties
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns Size of the multiset in elements
|
|
||||||
constexpr size_t size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns `true` when the set is empty, `false` otherwise
|
|
||||||
constexpr bool empty() const {
|
|
||||||
return _size == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns Capacity of the multiset in elements
|
|
||||||
constexpr size_t capacity() const {
|
|
||||||
return _alloc.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// Access ==============================================================================================================
|
|
||||||
|
|
||||||
/// \name Access
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Find an Element
|
|
||||||
/// \param val Value to find
|
|
||||||
/// \returns An iterator at the location of the first instance of `value`
|
|
||||||
constexpr iterator find(const elem_t& val, size_t c = 0) const {
|
|
||||||
if (capacity() == 0) {
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
size_t s = _hash(val) % capacity(); // Initial search index
|
|
||||||
int psl = (_size != 0) ? _sumpsl / _size : 0; // Initial psl
|
|
||||||
size_t i = (s + psl) % capacity(); // Median search
|
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
// Check the first element;
|
|
||||||
if (_alloc[i].psl >= psl && _alloc[i].value) {
|
|
||||||
if (*_alloc[i].value == val) {
|
|
||||||
return iterator(this, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop while there is a value and its psl is greater than our probe
|
|
||||||
while (c > 0) {
|
|
||||||
++n;
|
|
||||||
size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow
|
|
||||||
size_t i1 = (i + n) % capacity();
|
|
||||||
int p0 = psl - n, p1 = psl + n;
|
|
||||||
bool c0 = p0 >= 0 && _alloc[i0].psl >= p0, c1 = _alloc[i1].psl >= p1; // Check that we are in range
|
|
||||||
|
|
||||||
if (c0 && _alloc[i0].value) {
|
|
||||||
if (*_alloc[i0].value == val) {
|
|
||||||
if (c-- == 0) {
|
|
||||||
return iterator(this, i0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c1 && _alloc[i1].value) {
|
|
||||||
if (*_alloc[i1].value == val) {
|
|
||||||
if (c-- == 0) {
|
|
||||||
return iterator(this, i1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not(c0 or c1)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if a multiset contains a value
|
|
||||||
/// \param val Value to check
|
|
||||||
/// \returns `true` if `val` can be found, `false` otherwise
|
|
||||||
constexpr bool contains(const elem_t& val) const {
|
|
||||||
return this->find(val) != end();
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Iterator Access
|
|
||||||
/// \param it Location to access
|
|
||||||
/// \returns A pointer to the element, `nullptr` if not found.
|
|
||||||
/// The value should not be changed in a manner that will change the hash of the element.
|
|
||||||
constexpr elem_t* at(const iterator& it) {
|
|
||||||
if (it == end()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (not _alloc[it._i].value) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return &*_alloc[it._i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Iterator Const Access
|
|
||||||
/// \param it Location to access
|
|
||||||
/// \returns A const-qualified pointer to the element, `nullptr` if not found.
|
|
||||||
constexpr const elem_t* at(const iterator& it) const {
|
|
||||||
if (not _alloc[it._i].value) return nullptr;
|
|
||||||
return &*_alloc[it._i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
// Modifiers ===========================================================================================================
|
|
||||||
|
|
||||||
/// \name Modifiers
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Move Insertion
|
|
||||||
/// \param val Value to insert
|
|
||||||
constexpr void insert(elem_t&& val) {
|
|
||||||
this->_insert(fennec::forward<elem_t>(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Copy Insertion
|
|
||||||
/// \param val Value to insert
|
|
||||||
constexpr void insert(const elem_t& val) {
|
|
||||||
this->_insert(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Emplace Insertion
|
|
||||||
/// \tparam ArgsT Argument types
|
|
||||||
/// \param args Arguments to construct with
|
|
||||||
template<typename...ArgsT>
|
|
||||||
constexpr void emplace(ArgsT&&...args) {
|
|
||||||
this->_insert(fennec::forward<ArgsT>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Element Erase
|
|
||||||
/// \param it Location to erase
|
|
||||||
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;
|
|
||||||
_sumpsl -= _alloc[i].psl;
|
|
||||||
--_size;
|
|
||||||
size_t p = i;
|
|
||||||
while (_alloc[i = (i + 1) % capacity()].value) {
|
|
||||||
if (_alloc[i].psl == 0) break;
|
|
||||||
|
|
||||||
fennec::swap(_alloc[i - 1].value, _alloc[i].value);
|
|
||||||
--_alloc[p].psl, --_sumpsl;
|
|
||||||
p = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Element Erase
|
|
||||||
/// \param val Value to erase
|
|
||||||
constexpr void erase(const elem_t& val) {
|
|
||||||
this->erase(this->find(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// ITERATOR ============================================================================================================
|
|
||||||
|
|
||||||
/// \name Iteration
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief C++ Iterator Specification `begin()`
|
|
||||||
/// \returns An iterator for all elements of the set in no particular order
|
|
||||||
constexpr iterator begin() const {
|
|
||||||
iterator it(this, 0);
|
|
||||||
if (not _alloc[it._i].value) {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief C++ Iterator Specification `end()`
|
|
||||||
/// \returns An iterator representing the end of the set
|
|
||||||
constexpr iterator end() const {
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Class for Iterating the Set
|
|
||||||
class iterator {
|
|
||||||
public:
|
|
||||||
constexpr ~iterator() {
|
|
||||||
_set = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefix operator
|
|
||||||
constexpr iterator& operator++() {
|
|
||||||
while (++_i < _set->capacity()) {
|
|
||||||
if (_set->_alloc[_i].value) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_i = npos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr iterator operator++(int) {
|
|
||||||
iterator prev = *this;
|
|
||||||
this->operator++();
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t& operator*() const {
|
|
||||||
return *_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t* operator->() const {
|
|
||||||
if (not _set->_alloc[_i].value) return nullptr;
|
|
||||||
return &*_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const iterator& it) const {
|
|
||||||
return _set == it._set and _i == it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator!=(const iterator& it) const {
|
|
||||||
return _set != it._set or _i != it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const multiset* _set;
|
|
||||||
size_t _i;
|
|
||||||
friend multiset;
|
|
||||||
|
|
||||||
constexpr iterator(const multiset* multiset, size_t i)
|
|
||||||
: _set(multiset)
|
|
||||||
, _i(i) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class value_iterator {
|
|
||||||
public:
|
|
||||||
constexpr ~value_iterator() {
|
|
||||||
_set = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefix operator
|
|
||||||
constexpr value_iterator& operator++() {
|
|
||||||
while (_psl <= _set->_alloc[_i].psl) {
|
|
||||||
if (not _set->_alloc[_i].value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_i = npos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr value_iterator operator++(int) {
|
|
||||||
value_iterator prev = *this;
|
|
||||||
this->operator++();
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t& operator*() const {
|
|
||||||
return *_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t* operator->() const {
|
|
||||||
if (not _set->_alloc[_i].value) return nullptr;
|
|
||||||
return &*_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const iterator& it) const {
|
|
||||||
return _set == it._set and _i == it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator!=(const iterator& it) const {
|
|
||||||
return _set != it._set or _i != it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const multiset* _set;
|
|
||||||
size_t _i;
|
|
||||||
int _psl;
|
|
||||||
elem_t _value;
|
|
||||||
friend multiset;
|
|
||||||
|
|
||||||
constexpr value_iterator(const multiset* multiset, size_t i, int psl, const elem_t& value)
|
|
||||||
: _set(multiset)
|
|
||||||
, _i(i)
|
|
||||||
, _value(value) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE =============================================================================================================
|
|
||||||
|
|
||||||
private:
|
|
||||||
constexpr void _expand() {
|
|
||||||
multiset cpy; // Create a new multiset
|
|
||||||
cpy._alloc.callocate(
|
|
||||||
fennec::next_prime2(_alloc.capacity())
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename...ArgsT>
|
|
||||||
constexpr void _insert(ArgsT&&...args) {
|
|
||||||
if (_size == 0 or static_cast<float>(_size) / capacity() >= _load) { // expand when full
|
|
||||||
_expand();
|
|
||||||
}
|
|
||||||
|
|
||||||
elem_t value(fennec::forward<ArgsT>(args)...);
|
|
||||||
size_t i = _hash(value) % capacity(); // Initial search index
|
|
||||||
int psl = 0;
|
|
||||||
while (_alloc[i].value) { // Search for empty cell
|
|
||||||
if (_equal(*_alloc[i].value, value)) { // Check to see if this element is already inserted
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (psl > _alloc[i].psl) { // When psl is higher, swap
|
|
||||||
_sumpsl += psl - _alloc[i].psl;
|
|
||||||
fennec::swap(_alloc[i].psl, psl);
|
|
||||||
fennec::swap(*_alloc[i].value, value);
|
|
||||||
}
|
|
||||||
i = (i + 1) % capacity(); ++psl;
|
|
||||||
}
|
|
||||||
_alloc[i].value = fennec::move(value);
|
|
||||||
_sumpsl += (_alloc[i].psl = psl);
|
|
||||||
++_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocation<node, alloc_t> _alloc;
|
|
||||||
hash_t _hash;
|
|
||||||
equal_t _equal;
|
|
||||||
size_t _size;
|
|
||||||
size_t _sumpsl;
|
|
||||||
float _load;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_CONTAINERS_SET_H
|
|
||||||
@@ -48,8 +48,9 @@ struct object_pool {
|
|||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using value_t = TypeT;
|
using value_t = TypeT;
|
||||||
using elem_t = optional<TypeT>;
|
using elem_t = optional<value_t>;
|
||||||
using table_t = dynarray<elem_t, AllocT>;
|
using table_t = dynarray<elem_t, AllocT>;
|
||||||
|
using freed_t = list<size_t, AllocT>;
|
||||||
|
|
||||||
|
|
||||||
// Constructors & Destructor ===========================================================================================
|
// Constructors & Destructor ===========================================================================================
|
||||||
@@ -119,7 +120,7 @@ public:
|
|||||||
/// \returns a reference to the object with id `i`
|
/// \returns a reference to the object with id `i`
|
||||||
constexpr value_t& operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
assert(i < capacity(), "Index out of Bounds!");
|
assert(i < capacity(), "Index out of Bounds!");
|
||||||
assert(_table[i], "Attempted to access Null Object.");
|
assert(_table[i], "Attempted to access null object.")
|
||||||
return *_table[i];
|
return *_table[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +130,7 @@ public:
|
|||||||
/// \returns a const-qualified reference to the object with id `i`
|
/// \returns a const-qualified reference to the object with id `i`
|
||||||
constexpr const value_t& operator[](size_t i) const {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
assert(i < capacity(), "Index out of Bounds!");
|
assert(i < capacity(), "Index out of Bounds!");
|
||||||
assert(_table[i], "Attempted to access Null Object.");
|
assert(_table[i], "Attempted to access null object.")
|
||||||
return *_table[i];
|
return *_table[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,11 +177,21 @@ public:
|
|||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clear the object pool
|
||||||
|
constexpr void clear() {
|
||||||
|
for (auto& it : _table) {
|
||||||
|
it = nullopt;
|
||||||
|
}
|
||||||
|
_size = 0;
|
||||||
|
_freed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dynarray<elem_t, AllocT> _table;
|
table_t _table;
|
||||||
list<size_t> _freed;
|
freed_t _freed;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
|
|
||||||
size_t _next_free() {
|
size_t _next_free() {
|
||||||
@@ -197,7 +208,7 @@ private:
|
|||||||
size_t _insert(ArgsT&&...args) {
|
size_t _insert(ArgsT&&...args) {
|
||||||
size_t i = _next_free();
|
size_t i = _next_free();
|
||||||
if (i >= _table.size()) {
|
if (i >= _table.size()) {
|
||||||
_table.emplace_back();
|
_table.resize(fennec::max(_table.size() * 2, size_t(8)));
|
||||||
}
|
}
|
||||||
_table[i].emplace(fennec::forward<ArgsT>(args)...);
|
_table[i].emplace(fennec::forward<ArgsT>(args)...);
|
||||||
return i;
|
return i;
|
||||||
|
|||||||
@@ -294,9 +294,35 @@ public:
|
|||||||
/// \name Modifiers
|
/// \name Modifiers
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Assignment, Move overload
|
||||||
|
/// \param val The object to take ownership of
|
||||||
|
constexpr T& emplace(T&& val) {
|
||||||
|
if (_set) {
|
||||||
|
_val = fennec::forward<T>(val);
|
||||||
|
} else {
|
||||||
|
fennec::construct(&_val, fennec::forward<T>(val));
|
||||||
|
_set = true;
|
||||||
|
}
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Assignment, Copy overload
|
||||||
|
/// \param val The object to copy
|
||||||
|
constexpr T& emplace(const T& val) {
|
||||||
|
if (_set) {
|
||||||
|
_val = val;
|
||||||
|
} else {
|
||||||
|
fennec::construct(&_val, val);
|
||||||
|
_set = true;
|
||||||
|
}
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Emplace Assignment
|
/// \brief Emplace Assignment
|
||||||
/// \val The optional to move
|
/// \param args The arguments to construct with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr T& emplace(ArgsT&&...args) {
|
constexpr T& emplace(ArgsT&&...args) {
|
||||||
if (_set) {
|
if (_set) {
|
||||||
|
|||||||
@@ -95,19 +95,33 @@ struct pair {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Constructor, copies both elements
|
/// \brief Copy Constructor, copies both elements
|
||||||
constexpr pair(const pair&) = default;
|
constexpr pair(const pair& pair)
|
||||||
|
: first(fennec::copy(pair.first))
|
||||||
|
, second(fennec::copy(pair.second)) {
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Constructor, moves both elements
|
/// \brief Move Constructor, moves both elements
|
||||||
constexpr pair(pair&&) noexcept = default;
|
constexpr pair(pair&& pair) noexcept
|
||||||
|
: first(fennec::move(pair.first))
|
||||||
|
, second(fennec::move(pair.second)) {
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Assignment, copies both elements
|
/// \brief Copy Assignment, copies both elements
|
||||||
constexpr pair& operator=(const pair&) = default;
|
constexpr pair& operator=(const pair& pair) {
|
||||||
|
first = fennec::copy(pair.first);
|
||||||
|
second = fennec::copy(pair.second);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Assignment, moves both elements
|
/// \brief Move Assignment, moves both elements
|
||||||
constexpr pair& operator=(pair&&) noexcept = default;
|
constexpr pair& operator=(pair&& pair) {
|
||||||
|
first = fennec::move(pair.first);
|
||||||
|
second = fennec::move(pair.second);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
192
include/fennec/containers/priority_queue.h
Normal file
192
include/fennec/containers/priority_queue.h
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file priority_queue.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_PRIORITY_QUEUE_H
|
||||||
|
#define FENNEC_CONTAINERS_PRIORITY_QUEUE_H
|
||||||
|
|
||||||
|
#include <fennec/containers/object_pool.h>
|
||||||
|
#include <fennec/lang/compare.h>
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
|
// Binary heaps are just kinda busted.
|
||||||
|
// In-array binary heaps are one of the most efficient data structures for computers
|
||||||
|
// -> Cache Locality
|
||||||
|
// -> log(n) runtime
|
||||||
|
// -> No auxiliary structures or constant runtimes
|
||||||
|
//
|
||||||
|
// I tried just about every heap under the sun
|
||||||
|
// -> strict fibonacci heap, got blown out of the water by std::priority_queue
|
||||||
|
// -> fibonacci heap, got blown out of the water by std::priority_queue
|
||||||
|
// -> binomial heap, on-par with std::set, blown out of the water by std::priority_queue
|
||||||
|
//
|
||||||
|
// Then I relented and fell back to ye old binary heap
|
||||||
|
// This implementation roughly matches gcc's std::priority_queue
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename ValueT, class CompareT = less<ValueT>, class AllocT = allocator<ValueT>>
|
||||||
|
struct priority_queue {
|
||||||
|
|
||||||
|
// Definitions & Constants =============================================================================================
|
||||||
|
public:
|
||||||
|
using value_t = ValueT;
|
||||||
|
using compare_t = CompareT;
|
||||||
|
using alloc_t = allocation<value_t, AllocT>;
|
||||||
|
|
||||||
|
static constexpr size_t npos = -1;
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr size_t left(size_t n) const {
|
||||||
|
n = n * 2 + 1;
|
||||||
|
return n >= _size ? npos : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t right(size_t n) const {
|
||||||
|
n = n * 2 + 2;
|
||||||
|
return n >= _size ? npos : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t parent(size_t n) const {
|
||||||
|
return n == 0 ? npos : (n - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors & Destructor ===========================================================================================
|
||||||
|
public:
|
||||||
|
constexpr priority_queue()
|
||||||
|
: _size(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ~priority_queue() {
|
||||||
|
while (_size > 0) {
|
||||||
|
--_size;
|
||||||
|
fennec::destruct(&_table[_size]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
constexpr size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t capacity() const {
|
||||||
|
return _table.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool empty() const {
|
||||||
|
return size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
|
constexpr const value_t& front() const {
|
||||||
|
return _table[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
constexpr void push(const value_t& key) {
|
||||||
|
this->_insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void push(value_t&& key) {
|
||||||
|
this->_insert(fennec::forward<value_t>(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr void emplace(ArgsT&&...args) {
|
||||||
|
this->_insert(fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void pop() {
|
||||||
|
fennec::swap(_table[0], _table[--_size]);
|
||||||
|
fennec::destruct(&_table[_size]);
|
||||||
|
_fix_erase(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Members =============================================================================================================
|
||||||
|
private:
|
||||||
|
compare_t _compare;
|
||||||
|
alloc_t _table;
|
||||||
|
size_t _size;
|
||||||
|
|
||||||
|
// Helpers =============================================================================================================
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr void _insert(ArgsT&&...args) {
|
||||||
|
if (_size == _table.capacity()) {
|
||||||
|
_expand();
|
||||||
|
}
|
||||||
|
fennec::construct(&_table[_size], fennec::forward<ArgsT>(args)...);
|
||||||
|
_fix_insert(_size++);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _expand() {
|
||||||
|
_table.reallocate((_table.capacity() + 1) * 2 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t _min(size_t a, size_t b) {
|
||||||
|
if (a == npos) { return b; }
|
||||||
|
if (b == npos) { return a; }
|
||||||
|
return _compare(_table[a], _table[b]) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fix_insert(size_t n) {
|
||||||
|
size_t p = parent(n);
|
||||||
|
while (p != npos && _compare(_table[n], _table[p])) {
|
||||||
|
fennec::swap(_table[n], _table[p]);
|
||||||
|
n = p;
|
||||||
|
p = parent(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fix_erase(size_t n) {
|
||||||
|
size_t c = _min(left(n), right(n));
|
||||||
|
while (n != npos && c != npos && _compare(_table[c], _table[n])) {
|
||||||
|
fennec::swap(_table[c], _table[n]);
|
||||||
|
n = c;
|
||||||
|
c = _min(left(n), right(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_PRIORITY_QUEUE_H
|
||||||
@@ -34,6 +34,8 @@
|
|||||||
#include <fennec/containers/list.h>
|
#include <fennec/containers/list.h>
|
||||||
#include <fennec/containers/optional.h>
|
#include <fennec/containers/optional.h>
|
||||||
#include <fennec/containers/traversal.h>
|
#include <fennec/containers/traversal.h>
|
||||||
|
#include <fennec/containers/pair.h>
|
||||||
|
|
||||||
#include <fennec/memory/allocator.h>
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
@@ -58,7 +60,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct node {
|
struct node {
|
||||||
optional<TypeT> value;
|
value_t value;
|
||||||
size_t parent, child, prev, next;
|
size_t parent, child, prev, next;
|
||||||
size_t depth, num_children;
|
size_t depth, num_children;
|
||||||
|
|
||||||
@@ -194,7 +196,7 @@ public:
|
|||||||
/// \param i The id of the node to check
|
/// \param i The id of the node to check
|
||||||
/// \returns The id of the child node
|
/// \returns The id of the child node
|
||||||
constexpr size_t child(size_t i, size_t n = 0) const {
|
constexpr size_t child(size_t i, size_t n = 0) const {
|
||||||
if (i >= _table.capacity()) return npos;
|
if (i >= _table.capacity() && n != npos) return npos;
|
||||||
size_t c = i == npos ? npos : _table[i].child;
|
size_t c = i == npos ? npos : _table[i].child;
|
||||||
if (n != 0)
|
if (n != 0)
|
||||||
return next(c, n == npos ? npos : n - 1);
|
return next(c, n == npos ? npos : n - 1);
|
||||||
@@ -205,7 +207,7 @@ public:
|
|||||||
/// \param i The id of the node to check
|
/// \param i The id of the node to check
|
||||||
/// \returns The id of the next node
|
/// \returns The id of the next node
|
||||||
constexpr size_t next(size_t i, size_t n = 0) const {
|
constexpr size_t next(size_t i, size_t n = 0) const {
|
||||||
if (i >= _table.capacity()) return npos;
|
if (i >= _table.capacity() && n != npos) return npos;
|
||||||
if (i == npos) {
|
if (i == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
@@ -315,25 +317,15 @@ public:
|
|||||||
///
|
///
|
||||||
/// \param i The id of the node to access
|
/// \param i The id of the node to access
|
||||||
/// \returns A reference to the value of the node wrapped in an optional
|
/// \returns A reference to the value of the node wrapped in an optional
|
||||||
constexpr value_t* operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
auto& it = _table[i].value;
|
return _table[i].value;
|
||||||
if (it) {
|
|
||||||
return &*_table[i].value;
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \param i The id of the node to access
|
/// \param i The id of the node to access
|
||||||
/// \returns A const-qualified reference to the value of the node wrapped in an optional
|
/// \returns A const-qualified reference to the value of the node wrapped in an optional
|
||||||
constexpr const value_t* operator[](size_t i) const {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
const auto& it = _table[i].value;
|
return _table[i].value;
|
||||||
if (it) {
|
|
||||||
return &*_table[i].value;
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -342,7 +334,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Insertion, creates a node in the tree with parent `parent`
|
/// \brief Insertion, creates a node in the tree with parent `parent`
|
||||||
/// \param parent the parent node, if `npos` sets the value of the root node
|
/// \param parent the parent node, if `npos` sets the value of the root node
|
||||||
/// \param next the next node, as an index relative to the parent
|
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
|
||||||
/// \param val the value to insert
|
/// \param val the value to insert
|
||||||
/// \returns the index of the created node
|
/// \returns the index of the created node
|
||||||
constexpr size_t insert(size_t parent, size_t next, const value_t& val) {
|
constexpr size_t insert(size_t parent, size_t next, const value_t& val) {
|
||||||
@@ -359,10 +351,33 @@ public:
|
|||||||
return this->_insert(parent, next, fennec::forward<value_t>(val));
|
return this->_insert(parent, next, fennec::forward<value_t>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) {
|
||||||
|
list<pair<size_t, size_t>> visit;
|
||||||
|
visit.push_front({ root, parent });
|
||||||
|
size_t res = npos;
|
||||||
|
|
||||||
|
while (not visit.empty()) {
|
||||||
|
auto node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
|
||||||
|
size_t p = this->_insert(node.second, node.second == parent ? next : npos, tree[node.first]);
|
||||||
|
|
||||||
|
res = (res == npos) ? p : res;
|
||||||
|
|
||||||
|
size_t c = tree.child(node.first, npos);
|
||||||
|
while (c != npos) {
|
||||||
|
visit.push_front({ c, p });
|
||||||
|
c = tree._table[c].prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Insertion, creates a node in the tree with parent `parent`
|
/// \brief Insertion, creates a node in the tree with parent `parent`
|
||||||
/// \param parent the parent node, if `npos` sets the value of the root node
|
/// \param parent the parent node, if `npos` sets the value of the root node
|
||||||
/// \param next the next node, as an index relative to the parent
|
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
|
||||||
/// \param args the args to construct the value to insert
|
/// \param args the args to construct the value to insert
|
||||||
/// \returns the index of the created node
|
/// \returns the index of the created node
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
@@ -400,6 +415,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Traversal ===========================================================================================================
|
// Traversal ===========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -414,13 +431,13 @@ public:
|
|||||||
/// \param visit The visiting object
|
/// \param visit The visiting object
|
||||||
/// \param i The node to start at
|
/// \param i The node to start at
|
||||||
template<typename OrderT, typename VisitorT>
|
template<typename OrderT, typename VisitorT>
|
||||||
void traverse(VisitorT&& visit, size_t i = root) {
|
constexpr void traverse(VisitorT&& visit, size_t i = root) {
|
||||||
OrderT order;
|
OrderT order;
|
||||||
i = order(*this, i);
|
i = order(*this, i);
|
||||||
while (i != npos) {
|
while (i != npos) {
|
||||||
uint8_t mode = traversal_control_continue;
|
uint8_t mode = traversal_control_continue;
|
||||||
if (_table[i].value) {
|
if (_table[i].value) {
|
||||||
mode = visit(*_table[i].value, i);
|
mode = visit(_table[i].value, i);
|
||||||
}
|
}
|
||||||
if (mode == traversal_control_break) {
|
if (mode == traversal_control_break) {
|
||||||
break;
|
break;
|
||||||
@@ -429,16 +446,52 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pre_order {
|
struct breadth_first {
|
||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
|
||||||
size_t operator()(const rdtree&, size_t start) {
|
constexpr size_t operator()(const rdtree&, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nxt = tree.next(node);
|
||||||
|
size_t chd = tree.next(node);
|
||||||
|
|
||||||
|
if (nxt != npos && node != head) {
|
||||||
|
visit.push_front(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chd != npos && mode != traversal_control_jump_over) {
|
||||||
|
visit.push_back(chd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pre_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const rdtree&, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
@@ -469,12 +522,12 @@ public:
|
|||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
|
||||||
size_t operator()(const rdtree& tree, size_t start) {
|
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
@@ -507,12 +560,12 @@ public:
|
|||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
|
||||||
size_t operator()(const rdtree& tree, size_t start) {
|
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
|||||||
717
include/fennec/containers/sequence.h
Normal file
717
include/fennec/containers/sequence.h
Normal file
@@ -0,0 +1,717 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file sequence.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
|
#define FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
|
#include <fennec/containers/bintree.h>
|
||||||
|
#include <fennec/containers/bintree.h>
|
||||||
|
#include <fennec/containers/pair.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/lang/compare.h>
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
|
||||||
|
// https://www.geeksforgeeks.org/dsa/insertion-in-red-black-tree/
|
||||||
|
// https://github.com/anandarao/Red-Black-Tree/blob/master/RBTree.cpp
|
||||||
|
|
||||||
|
// After rewriting the _fix_insert and _fix_erase functions the performance decreased significantly in the lower end
|
||||||
|
// but now in the higher end it remains consistent. Something I was doing was disturbing both the rb-tree and bst tree
|
||||||
|
// properties, now that is fixed. I'll see about optimizing more in the future.
|
||||||
|
|
||||||
|
// I realized that the way bintree is setup makes some insert calls O(n + log n) = O(n), so I switched to a pointer based model.
|
||||||
|
// This increased performance overall maintaining O(log n).
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \brief wrapper for ordered sets of elements, called sequences in mathematics
|
||||||
|
/// \details
|
||||||
|
/// This data-structure behaves like an ordered-set, but does not use pointers, instead storing the table in-array
|
||||||
|
///
|
||||||
|
/// | Property | Value |
|
||||||
|
/// |:----------:|:---------------:|
|
||||||
|
/// | stable | ⛔ |
|
||||||
|
/// | dynamic | ✅ |
|
||||||
|
/// | homogenous | ✅ |
|
||||||
|
/// | distinct | ✅ |
|
||||||
|
/// | ordered | ✅ |
|
||||||
|
/// | space | \f$O(N)\f$ |
|
||||||
|
/// | linear | ✅ |
|
||||||
|
/// | access | \f$O(\log N)\f$ |
|
||||||
|
/// | find | \f$O(\log N)\f$ |
|
||||||
|
/// | insertion | \f$O(\log N)\f$ |
|
||||||
|
/// | deletion | \f$O(\log N)\f$ |
|
||||||
|
///
|
||||||
|
/// \tparam TypeT The type to contain
|
||||||
|
/// \tparam CompareT Function for comparing two values
|
||||||
|
/// \tparam AllocT An allocator class
|
||||||
|
template<typename TypeT, typename CompareT = less<TypeT>, class AllocT = allocator<pair<TypeT, bool>>>
|
||||||
|
struct sequence {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
protected:
|
||||||
|
struct _node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_t = TypeT;
|
||||||
|
using node_t = pair<TypeT, bool>;
|
||||||
|
using alloc_t = allocator_traits<AllocT>::template rebind<_node>;
|
||||||
|
using compare_t = CompareT;
|
||||||
|
|
||||||
|
enum color_ : bool {
|
||||||
|
black = false,
|
||||||
|
red = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dir_ : bool {
|
||||||
|
dir_left = false,
|
||||||
|
dir_right = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
class iterator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using node = _node*;
|
||||||
|
|
||||||
|
struct _node {
|
||||||
|
node parent;
|
||||||
|
node child[2];
|
||||||
|
value_t key;
|
||||||
|
bool color;
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr _node(ArgsT&&...args)
|
||||||
|
: parent(nullptr)
|
||||||
|
, child { nullptr, nullptr }
|
||||||
|
, key(fennec::forward<ArgsT>(args)...)
|
||||||
|
, color(red) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr _node(node p, node l, node r, ArgsT&&...args)
|
||||||
|
: parent(p)
|
||||||
|
, child { l, r }
|
||||||
|
, key(fennec::forward<ArgsT>(args)...)
|
||||||
|
, color(red) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ~_node() {
|
||||||
|
parent = nullptr;
|
||||||
|
child[0] = nullptr;
|
||||||
|
child[1] = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Member Access Helpers
|
||||||
|
|
||||||
|
constexpr value_t& _key(node n) {
|
||||||
|
return n->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool& _color(node n) {
|
||||||
|
return n->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node& _parent(node n) {
|
||||||
|
return n->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node& _child(node n, bool dir) {
|
||||||
|
return n->child[dir];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node& _left(node n) {
|
||||||
|
return n->child[dir_left];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node& _right(node n) {
|
||||||
|
return n->child[dir_right];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Safe Member Access Helpers
|
||||||
|
|
||||||
|
|
||||||
|
constexpr const value_t& key(node n) const {
|
||||||
|
return n->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool color(node n) {
|
||||||
|
return n ? n->color : (bool)black;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node parent(node n) {
|
||||||
|
return n ? n->parent : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node child(node n, bool dir) {
|
||||||
|
return n ? n->child[dir] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node left(node n) {
|
||||||
|
return n ? n->child[dir_left] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node right(node n) {
|
||||||
|
return n ? n->child[dir_right] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node leftmost(node n) {
|
||||||
|
if (n == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (this->_left(n)) {
|
||||||
|
n = this->_left(n);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node rightmost(node n) {
|
||||||
|
if (n == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (this->_right(n)) {
|
||||||
|
n = this->_right(n);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructors & Destructors ==========================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, initializes an empty sequence
|
||||||
|
constexpr sequence()
|
||||||
|
: _root(nullptr), _size(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor, takes ownership of a sequence
|
||||||
|
constexpr sequence(sequence&&) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor, copies a sequence
|
||||||
|
constexpr sequence(const sequence&) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Destructor, destructs elements *in-order*
|
||||||
|
constexpr ~sequence() {
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Search ==============================================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Search
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Find Function, finds the iterator position for `val`, otherwise returns `end()`
|
||||||
|
/// \param val The value to find
|
||||||
|
/// \returns An iterator at the value
|
||||||
|
constexpr iterator find(const value_t& val) {
|
||||||
|
node node = _root;
|
||||||
|
while (node) {
|
||||||
|
if (_compare(val, _key(node))) {
|
||||||
|
node = _left(node);
|
||||||
|
} else if (_compare(_key(node), val)) {
|
||||||
|
node = _right(node);
|
||||||
|
} else {
|
||||||
|
return sequence::iterator(this, _root, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sequence::iterator(this, _root, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Contains Function, checks if the sequence contains a value
|
||||||
|
/// \param val The value to find
|
||||||
|
/// \returns `true` if `val` is in the sequence, `false` otherwise
|
||||||
|
bool contains(const value_t& val) {
|
||||||
|
return find(val) != end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Properties
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The number of elements in the sequence
|
||||||
|
constexpr size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no elements in the sequence, `false` otherwise.
|
||||||
|
constexpr bool empty() const {
|
||||||
|
return _size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Modifiers
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Insertion, moves `val` into the sequence
|
||||||
|
/// \param val The value to insert
|
||||||
|
constexpr void insert(value_t&& val) {
|
||||||
|
node i = _insert_bst(fennec::forward<value_t>(val));
|
||||||
|
_fix_insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Insertion, inserts a copy of `val` into the sequence
|
||||||
|
/// \param val The value to insert
|
||||||
|
constexpr void insert(const value_t& val) {
|
||||||
|
node i = _insert_bst(val);
|
||||||
|
_fix_insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplacement, constructs and adds a value into the sequence
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param args The arguments to construct with
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr void emplace(ArgsT&&...args) {
|
||||||
|
node i = _insert_bst(fennec::forward<ArgsT>(args)...);
|
||||||
|
_fix_insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void erase(const value_t& val) {
|
||||||
|
_erase(find(val)._node);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructs all elements, *in-order*, contained in the sequence
|
||||||
|
constexpr void clear() {
|
||||||
|
list<node> visit;
|
||||||
|
for (iterator it = begin(); it != end(); ++it) {
|
||||||
|
visit.push_back(it._node);
|
||||||
|
}
|
||||||
|
for (node n : visit) {
|
||||||
|
_free_node(n);
|
||||||
|
}
|
||||||
|
_root = nullptr;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns An iterator at the smallest element in the sequence
|
||||||
|
constexpr iterator begin() {
|
||||||
|
return sequence::iterator(this, _root);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns An iterator after the largest element in the sequence
|
||||||
|
constexpr iterator end() {
|
||||||
|
return sequence::iterator(this, _root, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
protected:
|
||||||
|
sequence* _seq;
|
||||||
|
node _head;
|
||||||
|
node _node;
|
||||||
|
list<node> _visit;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr iterator(sequence* seq, node start)
|
||||||
|
: _seq(seq)
|
||||||
|
, _head(start)
|
||||||
|
, _node(seq->leftmost(start)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator(sequence* seq, node root, node start)
|
||||||
|
: _seq(seq)
|
||||||
|
, _head(root)
|
||||||
|
, _node(start) {
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator& operator++() {
|
||||||
|
if (_node == nullptr) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
node parent = _seq->_parent(_node);
|
||||||
|
node pright = _seq->right(parent);
|
||||||
|
node next = _seq->leftmost(_seq->right(_node));
|
||||||
|
|
||||||
|
if (_node != pright && parent != nullptr) {
|
||||||
|
_visit.push_front(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next != nullptr) {
|
||||||
|
_visit.push_front(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not _visit.empty()) {
|
||||||
|
_node = _visit.front();
|
||||||
|
_visit.pop_front();
|
||||||
|
} else {
|
||||||
|
_node = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator operator++(int) {
|
||||||
|
iterator prev = *this;
|
||||||
|
this->operator++();
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return _node->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return &_node->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr friend bool operator==(const iterator& lhs, const iterator& rhs) {
|
||||||
|
return lhs._node == rhs._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend struct sequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Fields ==============================================================================================================
|
||||||
|
protected:
|
||||||
|
alloc_t _alloc;
|
||||||
|
node _root;
|
||||||
|
compare_t _compare;
|
||||||
|
size_t _size;
|
||||||
|
|
||||||
|
// Helpers =============================================================================================================
|
||||||
|
protected:
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr node _make_node(ArgsT&&...args) {
|
||||||
|
node res = _alloc.allocate(1);
|
||||||
|
fennec::construct(res, fennec::forward<ArgsT>(args)...);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _free_node(node n) {
|
||||||
|
fennec::destruct(n);
|
||||||
|
_alloc.deallocate(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node _rotate(node sub, bool dir) {
|
||||||
|
if (sub == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
node sub_parent = _parent(sub);
|
||||||
|
node new_root = _child(sub, not dir);
|
||||||
|
node new_child = _child(new_root, dir);
|
||||||
|
|
||||||
|
_child(sub, not dir) = new_child;
|
||||||
|
if (new_child != nullptr) {
|
||||||
|
_parent(new_child) = sub;
|
||||||
|
}
|
||||||
|
_child(new_root, dir) = sub;
|
||||||
|
|
||||||
|
_parent(new_root) = sub_parent;
|
||||||
|
_parent(sub) = new_root;
|
||||||
|
if (sub_parent != nullptr) {
|
||||||
|
_child(sub_parent, sub == _right(sub_parent)) = new_root;
|
||||||
|
} else {
|
||||||
|
_root = new_root;
|
||||||
|
}
|
||||||
|
return new_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _recolor(node n) {
|
||||||
|
bool c = color(n) == black;
|
||||||
|
if (n == _root) { // Only recolor if not the root node
|
||||||
|
_color(n) = c;
|
||||||
|
}
|
||||||
|
_color(_left(n)) = !_color(_left(n)) ;
|
||||||
|
_color(_right(n)) = !_color(_right(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
// run-of-the-mill bst insert
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr node _insert_bst(ArgsT&&...args) {
|
||||||
|
node res = _make_node(fennec::forward<ArgsT>(args)...);
|
||||||
|
|
||||||
|
if (_root == nullptr) {
|
||||||
|
++_size;
|
||||||
|
_color(res) = black;
|
||||||
|
return _root = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
node i = _root;
|
||||||
|
node p = nullptr;
|
||||||
|
bool d = dir_left;
|
||||||
|
while (i != nullptr) {
|
||||||
|
p = i;
|
||||||
|
|
||||||
|
if (_compare(_key(res), _key(i))) {
|
||||||
|
i = _left(i);
|
||||||
|
d = dir_left;
|
||||||
|
} else if (_compare(_key(i), _key(res))) {
|
||||||
|
i = _right(i);
|
||||||
|
d = dir_right;
|
||||||
|
} else {
|
||||||
|
_free_node(res);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++_size;
|
||||||
|
_child(p, d) = res;
|
||||||
|
_parent(res) = p;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes some cheats given that the structure is modified only by internal functions
|
||||||
|
// If such is the case, ONLY LL, LR, RL, and RR will show up
|
||||||
|
// Then we just need to handle splitting a 4-node
|
||||||
|
constexpr void _fix_insert(node n) {
|
||||||
|
if (n == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node p = _parent(n);
|
||||||
|
while (n != _root && color(n) == red && color(p) == red) {
|
||||||
|
node g = _parent(p);
|
||||||
|
bool d = n == _right(p);
|
||||||
|
bool r = p == _right(g);
|
||||||
|
node u = _child(g, !r);
|
||||||
|
|
||||||
|
if (color(u) == red) {
|
||||||
|
_recolor(g);
|
||||||
|
n = g;
|
||||||
|
p = _parent(n);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d != r) {
|
||||||
|
_rotate(p, r);
|
||||||
|
n = p;
|
||||||
|
p = _parent(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rotate(g, not r);
|
||||||
|
fennec::swap(_color(p), _color(g));
|
||||||
|
n = p;
|
||||||
|
p = _parent(n);
|
||||||
|
}
|
||||||
|
_color(_root) = black;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _swap_val(node a, node b) {
|
||||||
|
fennec::swap(_key(a), _key(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr node _red_child(node x) {
|
||||||
|
node l = _left(x);
|
||||||
|
node r = _right(x);
|
||||||
|
|
||||||
|
if (color(l) == red) {
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color(r) == red) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _fix_erase(node n) {
|
||||||
|
if (n == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == _root) {
|
||||||
|
_root = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node o = n;
|
||||||
|
node p = _parent(n);
|
||||||
|
if (p == nullptr) {
|
||||||
|
_root = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool d = n == _right(p);
|
||||||
|
node c = _red_child(n);
|
||||||
|
node s = nullptr;
|
||||||
|
if (_color(n) == red || c != nullptr) {
|
||||||
|
_child(p, d) = c;
|
||||||
|
if (c != nullptr) {
|
||||||
|
_parent(c) = p;
|
||||||
|
}
|
||||||
|
_color(c) = black;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n != _root) {
|
||||||
|
p = _parent(n);
|
||||||
|
d = n == _right(p);
|
||||||
|
s = _child(p, !d);
|
||||||
|
|
||||||
|
if (s == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_color(s) == red) {
|
||||||
|
_color(s) = black;
|
||||||
|
_color(p) = red;
|
||||||
|
_rotate(p, d);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
node nc = _child(s, d);
|
||||||
|
node nf = _child(s, !d);
|
||||||
|
|
||||||
|
if (color(nc) == black && color(nf) == black) {
|
||||||
|
_color(s) = red;
|
||||||
|
if (_color(p) == red) {
|
||||||
|
_color(p) = black;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n = p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color(nf) == black) {
|
||||||
|
_color(nc) = black;
|
||||||
|
_color(s) = red;
|
||||||
|
_rotate(s, !d);
|
||||||
|
s = nc;
|
||||||
|
nf = s;
|
||||||
|
}
|
||||||
|
_color(s) = _color(p);
|
||||||
|
_color(p) = black;
|
||||||
|
_color(nf) = black;
|
||||||
|
_rotate(p, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = parent(o);
|
||||||
|
if (p != nullptr) {
|
||||||
|
if (o == _left(p)) {
|
||||||
|
_left(p) = nullptr;
|
||||||
|
} else {
|
||||||
|
_right(p) = nullptr;
|
||||||
|
}
|
||||||
|
_color(_root) = black;
|
||||||
|
} else {
|
||||||
|
_root = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _erase(node n) {
|
||||||
|
if (n == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node l = _left(n);
|
||||||
|
node r = _right(n);
|
||||||
|
|
||||||
|
// 2 children
|
||||||
|
if (l != nullptr && r != nullptr) {
|
||||||
|
node s = leftmost(r);
|
||||||
|
_swap_val(n, s);
|
||||||
|
n = s;
|
||||||
|
l = _left(n);
|
||||||
|
r = _right(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
node p = _parent(n);
|
||||||
|
bool d = n == right(p);
|
||||||
|
node c = l != nullptr ? l : r;
|
||||||
|
|
||||||
|
// Single child
|
||||||
|
if (c != nullptr) {
|
||||||
|
_parent(c) = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles root cases
|
||||||
|
if (p == nullptr) {
|
||||||
|
_root = c;
|
||||||
|
if (c == nullptr) {
|
||||||
|
_free_node(n);
|
||||||
|
--_size;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_color(c) = black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single Child, Red, and Root cases
|
||||||
|
if (p == nullptr || c != nullptr || _color(n) == red) {
|
||||||
|
if (p != nullptr) {
|
||||||
|
_child(p, d) = c;
|
||||||
|
}
|
||||||
|
_free_node(n);
|
||||||
|
--_size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fix_erase(n);
|
||||||
|
_free_node(n);
|
||||||
|
--_size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
@@ -330,7 +330,7 @@ public:
|
|||||||
while (_alloc[i = (i + 1) % capacity()].value) {
|
while (_alloc[i = (i + 1) % capacity()].value) {
|
||||||
if (_alloc[i].psl == 0) break;
|
if (_alloc[i].psl == 0) break;
|
||||||
|
|
||||||
fennec::swap(_alloc[i - 1].value, _alloc[i].value);
|
fennec::swap(_alloc[p].value, _alloc[i].value);
|
||||||
--_alloc[p].psl, --_sumpsl;
|
--_alloc[p].psl, --_sumpsl;
|
||||||
p = i;
|
p = i;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,13 +76,15 @@ constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<T
|
|||||||
|
|
||||||
|
|
||||||
template<typename ...TypesT>
|
template<typename ...TypesT>
|
||||||
struct tuple : public detail::_tuple<make_index_sequence_t<sizeof...(TypesT)>, TypesT...>
|
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>
|
||||||
{
|
{
|
||||||
using base_t = detail::_tuple<make_index_sequence_t<sizeof...(TypesT)>, TypesT...>;
|
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>;
|
||||||
|
|
||||||
template<size_t i>
|
template<size_t i>
|
||||||
using elem_t = typename nth_element<i, TypesT...>::type;
|
using elem_t = typename nth_element<i, TypesT...>::type;
|
||||||
|
|
||||||
|
static constexpr size_t size = sizeof...(TypesT);
|
||||||
|
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
tuple(ArgsT&&...args)
|
tuple(ArgsT&&...args)
|
||||||
: base_t(fennec::forward<ArgsT>(args)...) {
|
: base_t(fennec::forward<ArgsT>(args)...) {
|
||||||
|
|||||||
@@ -31,4 +31,216 @@
|
|||||||
#ifndef FENNEC_CONTAINERS_VARIANT_H
|
#ifndef FENNEC_CONTAINERS_VARIANT_H
|
||||||
#define FENNEC_CONTAINERS_VARIANT_H
|
#define FENNEC_CONTAINERS_VARIANT_H
|
||||||
|
|
||||||
|
#include <fennec/containers/optional.h>
|
||||||
|
#include <fennec/lang/type_sequences.h>
|
||||||
|
#include <fennec/math/ext/common.h>
|
||||||
|
#include <fennec/rtti/type.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief A structure that represents a union between `TypesT...`
|
||||||
|
/// \tparam TypesT The types to hold in the variant
|
||||||
|
template<typename...TypesT>
|
||||||
|
struct variant {
|
||||||
|
// Assertions ==========================================================================================================
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
is_unique_v<TypesT...> and // No two types in TypesT... may be equivalent
|
||||||
|
not (is_reference_v<TypesT> or ...) and // No type in TypesT... may be a reference
|
||||||
|
not (is_array_v<TypesT> or ...) and // No type in TypesT... may be an array
|
||||||
|
not (is_void_v<TypesT> or ...) // No type in TypesT... may be void
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Typedefs & Constants ================================================================================================
|
||||||
|
|
||||||
|
static constexpr size_t size = max_element_size_v<TypesT...>;
|
||||||
|
static constexpr size_t nulltype = sizeof...(TypesT);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, constructs the first type in `TypesT...` that is default constructible
|
||||||
|
variant()
|
||||||
|
: _bytes {}
|
||||||
|
, _type(nulltype) {
|
||||||
|
using construct_t = search_element_t<is_default_constructible, TypesT...>;
|
||||||
|
fennec::construct<construct_t>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Conversion Constructor, constructs the type in `TypesT...` that is identical to `T`
|
||||||
|
/// or the first that is constructible with `T`
|
||||||
|
/// \tparam T The type of the value
|
||||||
|
/// \param t The value to forward
|
||||||
|
template<typename T>
|
||||||
|
variant(T&& t)
|
||||||
|
: _bytes {}
|
||||||
|
, _type() {
|
||||||
|
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>;
|
||||||
|
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
|
||||||
|
using construct_t = conditional_t<is_void_v<same_t>, convert_t, convert_t>;
|
||||||
|
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Constructor, constructs the first type in `TypesT...` that is constructible with `ArgsT...`
|
||||||
|
/// \tparam ArgsT The arguments of the constructor
|
||||||
|
/// \param args The argument values
|
||||||
|
template<typename T, typename...ArgsT>
|
||||||
|
variant(type_identity<T>, ArgsT&&...args)
|
||||||
|
: _bytes{}
|
||||||
|
, _type(nulltype) {
|
||||||
|
static_assert(contains_element_v<T, TypesT...>, "T must be in TypesT...");
|
||||||
|
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||||
|
_type = find_element_v<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor
|
||||||
|
/// \param v The variant to copy
|
||||||
|
variant(const variant& v)
|
||||||
|
: _bytes {}
|
||||||
|
, _type(nulltype) {
|
||||||
|
|
||||||
|
if (v._type == nulltype) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((v._type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
fennec::construct<TypesT>(_handle, v.get<TypesT>()) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
_type = v._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor
|
||||||
|
/// \param v The variant to move
|
||||||
|
variant(variant&& v) noexcept
|
||||||
|
: _bytes {}
|
||||||
|
, _type() {
|
||||||
|
|
||||||
|
if (v._type == nulltype) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((v._type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
fennec::construct<TypesT>(_handle, fennec::move(v.get<TypesT>())) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
_type = v._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor, if a type is held, destruct it.
|
||||||
|
~variant() {
|
||||||
|
_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
variant& operator=(T&& t) {
|
||||||
|
|
||||||
|
// First, check if `T` is in `TypesT...`
|
||||||
|
if constexpr((contains_element_v<T, TypesT> or ...)) {
|
||||||
|
using type_t = remove_reference_t<T>;
|
||||||
|
if (_type == find_element_v<type_t, TypesT...>) {
|
||||||
|
*static_cast<type_t*>(_handle) = fennec::forward<T>(t);
|
||||||
|
} else {
|
||||||
|
_clear();
|
||||||
|
fennec::construct<type_t>(_handle, fennec::forward<T>(t));
|
||||||
|
_type = find_element_v<type_t, TypesT...>;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, try to assign using the currently held type
|
||||||
|
bool assigned = false;
|
||||||
|
if (_type != nulltype) {
|
||||||
|
((_type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
(*static_cast<TypesT*>(_handle) = fennec::forward<T>(t), assigned = true) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assigned) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, destruct, then construct
|
||||||
|
_clear();
|
||||||
|
using construct_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
|
||||||
|
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
|
||||||
|
void emplace(ArgsT&&...args) {
|
||||||
|
_clear();
|
||||||
|
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename...ArgsT>
|
||||||
|
void emplace(ArgsT&&...args) {
|
||||||
|
using type_t = nth_element_t<I, TypesT...>;
|
||||||
|
_clear();
|
||||||
|
fennec::construct<type_t>(fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
|
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||||
|
T& get() {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||||
|
const T& get() const {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||||
|
T& get() {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||||
|
const T& get() const {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
byte_t _bytes[size];
|
||||||
|
void* _handle;
|
||||||
|
};
|
||||||
|
size_t _type;
|
||||||
|
|
||||||
|
void _clear() {
|
||||||
|
if (_type == nulltype) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((_type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
fennec::destruct<TypesT>(_handle) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
_type = nulltype;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FENNEC_CONTAINERS_VARIANT_H
|
#endif // FENNEC_CONTAINERS_VARIANT_H
|
||||||
@@ -20,27 +20,32 @@
|
|||||||
#define FENNEC_CORE_EVENT_H
|
#define FENNEC_CORE_EVENT_H
|
||||||
|
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
#include <fennec/lang/typeuuid.h>
|
#include <fennec/rtti/enable.h>
|
||||||
|
|
||||||
|
#include <fennec/rtti/typeid.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
struct event;
|
struct event;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Class outlining the interface for an object that listens for events
|
||||||
class event_listener {
|
class event_listener {
|
||||||
public:
|
public:
|
||||||
virtual ~event_listener() = default;
|
virtual ~event_listener() = default;
|
||||||
virtual void handle_event(event* event) = 0;
|
virtual void handle_event(event* event) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Main event interface, includes static methods for registering listeners and dispatching events
|
||||||
struct event {
|
struct event {
|
||||||
const uint64_t type;
|
virtual ~event() = default;
|
||||||
|
|
||||||
event() = delete;
|
|
||||||
|
|
||||||
template<typename EventT>
|
|
||||||
event() : type(typeuuid<EventT>()) { }
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Registers a listener for the event type
|
||||||
|
/// \tparam EventT
|
||||||
|
/// \param listener
|
||||||
template<typename EventT>
|
template<typename EventT>
|
||||||
static void add_listener(event_listener* listener) {
|
static void add_listener(event_listener* listener) {
|
||||||
event::add_listener(listener, typeuuid<EventT, event>());
|
event::add_listener(listener, typeuuid<EventT, event>());
|
||||||
@@ -54,6 +59,10 @@ struct event {
|
|||||||
static void add_listener(event_listener* listener, uint64_t type);
|
static void add_listener(event_listener* listener, uint64_t type);
|
||||||
static void remove_listener(event_listener* listener);
|
static void remove_listener(event_listener* listener);
|
||||||
static void dispatch(event* event);
|
static void dispatch(event* event);
|
||||||
|
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE() {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
88
include/fennec/core/logger.h
Normal file
88
include/fennec/core/logger.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file logger.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_CORE_LOGGER_H
|
||||||
|
#define FENNEC_CORE_LOGGER_H
|
||||||
|
|
||||||
|
#include <fennec/filesystem/file.h>
|
||||||
|
#include <fennec/rtti/singleton.h>
|
||||||
|
#include <fennec/containers/tuple.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class logger : public singleton<logger> {
|
||||||
|
public:
|
||||||
|
logger();
|
||||||
|
~logger();
|
||||||
|
|
||||||
|
static void log(const cstring& str,
|
||||||
|
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||||
|
const char* const _file = FENNEC_BUILTIN_FILE()
|
||||||
|
) {
|
||||||
|
logger& inst = instance();
|
||||||
|
|
||||||
|
if (inst._logfile.is_open()) {
|
||||||
|
inst._logfile.print(cstring(_file, strlen(_file)));
|
||||||
|
inst._logfile.printf("({}): ", _line);
|
||||||
|
inst._logfile.println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
inst._cout->print(cstring(_file, strlen(_file)));
|
||||||
|
inst._cout->printf("({}): ", _line);
|
||||||
|
inst._cout->println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log(const string& str,
|
||||||
|
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||||
|
const char* const _file = FENNEC_BUILTIN_FILE()
|
||||||
|
) {
|
||||||
|
logger& inst = instance();
|
||||||
|
|
||||||
|
if (inst._logfile.is_open()) {
|
||||||
|
inst._logfile.print(cstring(_file, strlen(_file)));
|
||||||
|
inst._logfile.printf("({}): ", _line);
|
||||||
|
inst._logfile.println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
inst._cout->print(cstring(_file, strlen(_file)));
|
||||||
|
inst._cout->printf("({}): ", _line);
|
||||||
|
inst._cout->println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
file _logfile;
|
||||||
|
file* _cout;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CORE_LOGGER_H
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#ifndef FENNEC_CORE_SYSTEM_H
|
#ifndef FENNEC_CORE_SYSTEM_H
|
||||||
#define FENNEC_CORE_SYSTEM_H
|
#define FENNEC_CORE_SYSTEM_H
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|||||||
48
include/fennec/core/version.h
Normal file
48
include/fennec/core/version.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file version.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_CORE_VERSION_H
|
||||||
|
#define FENNEC_CORE_VERSION_H
|
||||||
|
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
struct version {
|
||||||
|
uint32_t major, minor, patch;
|
||||||
|
string str;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CORE_VERSION_H
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
#ifndef FENNEC_FILESYSTEM_DETAIL_CTYPE_H
|
||||||
#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
#define FENNEC_FILESYSTEM_DETAIL_CTYPE_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H
|
#endif // FENNEC_FILESYSTEM_DETAIL_CTYPE_H
|
||||||
@@ -16,14 +16,15 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_LANGPROC_IO_FILE_H
|
#ifndef FENNEC_FILESYSTEM_FILE_H
|
||||||
#define FENNEC_LANGPROC_IO_FILE_H
|
#define FENNEC_FILESYSTEM_FILE_H
|
||||||
|
|
||||||
#include <fennec/langproc/filesystem/path.h>
|
#include <fennec/filesystem/path.h>
|
||||||
|
#include <fennec/format/format.h>
|
||||||
|
|
||||||
#include <fennec/langproc/strings/cstring.h>
|
#include <fennec/string/cstring.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/string/string.h>
|
||||||
#include <fennec/langproc/strings/wstring.h>
|
#include <fennec/string/wstring.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -108,6 +109,21 @@ public:
|
|||||||
/// \brief default constructor, initializes an empty stream
|
/// \brief default constructor, initializes an empty stream
|
||||||
file();
|
file();
|
||||||
|
|
||||||
|
file(const cstring& path, uint8_t mode)
|
||||||
|
: file() {
|
||||||
|
open(path, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
file(const string& path, uint8_t mode)
|
||||||
|
: file() {
|
||||||
|
open(path, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
file(const path& path, uint8_t mode)
|
||||||
|
: file() {
|
||||||
|
open(path, mode);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief default destructor, cleans up an open stream
|
/// \brief default destructor, cleans up an open stream
|
||||||
~file();
|
~file();
|
||||||
@@ -250,9 +266,6 @@ public:
|
|||||||
|
|
||||||
// Binary Read Operations ==============================================================================================
|
// Binary Read Operations ==============================================================================================
|
||||||
|
|
||||||
char getc();
|
|
||||||
wchar_t getwc();
|
|
||||||
|
|
||||||
size_t read(void* data, size_t size, size_t n);
|
size_t read(void* data, size_t size, size_t n);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -265,9 +278,6 @@ public:
|
|||||||
return read(static_cast<void*>(data), sizeof(T), n);
|
return read(static_cast<void*>(data), sizeof(T), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
string getline();
|
|
||||||
wstring getwline();
|
|
||||||
|
|
||||||
|
|
||||||
// Binary Write Operations =============================================================================================
|
// Binary Write Operations =============================================================================================
|
||||||
|
|
||||||
@@ -297,8 +307,29 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read Operations =====================================================================================================
|
||||||
|
|
||||||
|
char getc();
|
||||||
|
wchar_t getwc();
|
||||||
|
|
||||||
|
string getline();
|
||||||
|
wstring getwline();
|
||||||
|
|
||||||
|
|
||||||
// Printing Operations =================================================================================================
|
// Printing Operations =================================================================================================
|
||||||
|
|
||||||
|
void print(const cstring& str);
|
||||||
|
void print(const string& str);
|
||||||
|
|
||||||
|
void println(const cstring& str);
|
||||||
|
void println(const string& str);
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
void printf(const cstring& str, ArgsT&&...args) {
|
||||||
|
string fmt = fennec::format(str, fennec::forward<ArgsT>(args)...);
|
||||||
|
this->print(cstring(fmt.cstr(), fmt.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -316,4 +347,4 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANGPROC_IO_FILE_H
|
#endif // FENNEC_FILESYSTEM_FILE_H
|
||||||
@@ -16,10 +16,11 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_LANGPROC_IO_PATH_H
|
#ifndef FENNEC_FILESYSTEM_PATH_H
|
||||||
#define FENNEC_LANGPROC_IO_PATH_H
|
#define FENNEC_FILESYSTEM_PATH_H
|
||||||
|
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/filesystem/path.h>
|
||||||
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -32,6 +33,12 @@ namespace fennec
|
|||||||
struct path
|
struct path
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
|
||||||
|
class iterator;
|
||||||
|
friend iterator;
|
||||||
|
|
||||||
|
|
||||||
// Static Functions ====================================================================================================
|
// Static Functions ====================================================================================================
|
||||||
|
|
||||||
/// \brief Get the current working directory
|
/// \brief Get the current working directory
|
||||||
@@ -154,6 +161,11 @@ public:
|
|||||||
return _str == p._str;
|
return _str == p._str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string filename() const {
|
||||||
|
size_t i = _str.rfind('/');
|
||||||
|
return _str.substring(i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
const string& str() const { return _str; }
|
const string& str() const { return _str; }
|
||||||
const char* cstr() const { return _str.cstr(); }
|
const char* cstr() const { return _str.cstr(); }
|
||||||
|
|
||||||
@@ -238,10 +250,85 @@ public:
|
|||||||
return working;
|
return working;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
iterator begin() const {
|
||||||
|
return iterator(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() const {
|
||||||
|
return iterator(this, _str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
public:
|
||||||
|
constexpr iterator(const path* path, size_t p)
|
||||||
|
: _str(&path->_str)
|
||||||
|
, _pos(p) {
|
||||||
|
|
||||||
|
// Handle end()
|
||||||
|
if (p == _str->size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle rooted paths
|
||||||
|
#ifdef FENNEC_PLATFORM_WINDOWS
|
||||||
|
if ((*_str)[1] == ':') {
|
||||||
|
_pos = max(_pos, size_t(3));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((*_str)[0] == '/') {
|
||||||
|
_pos = max(_pos, size_t(1));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Ensure we are at the start of a directory/file name
|
||||||
|
if (_pos != 0 && (*_str)[_pos - 1] != '/') {
|
||||||
|
_pos = _str->find('/', _pos) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator(const iterator&) = default;
|
||||||
|
constexpr iterator(iterator&&) noexcept = default;
|
||||||
|
|
||||||
|
constexpr string operator*() const {
|
||||||
|
if ((*_str)[_pos] == '/') {
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t e = _str->find('/', _pos);
|
||||||
|
return _str->substring(_pos, e - _pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator& operator++() {
|
||||||
|
_pos = min(_str->find('/', _pos) + 1, _str->size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator operator++(int) {
|
||||||
|
iterator it = *this;
|
||||||
|
this->operator++();
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const iterator& rhs) const {
|
||||||
|
return _str == rhs._str and _pos == rhs._pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const iterator& rhs) const {
|
||||||
|
return _str != rhs._str or _pos != rhs._pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const string* _str;
|
||||||
|
size_t _pos;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string _str;
|
string _str;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANGPROC_IO_PATH_H
|
#endif // FENNEC_FILESYSTEM_PATH_H
|
||||||
67
include/fennec/format/charconv.h
Normal file
67
include/fennec/format/charconv.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file charconv.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_FORMAT_CHARCONV_H
|
||||||
|
#define FENNEC_FORMAT_CHARCONV_H
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, char x, int base);
|
||||||
|
char* to_chars(char* first, char* last, signed char x, int base);
|
||||||
|
char* to_chars(char* first, char* last, unsigned char x, int base);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, signed short x, int base);
|
||||||
|
char* to_chars(char* first, char* last, unsigned short x, int base);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, signed int x, int base);
|
||||||
|
char* to_chars(char* first, char* last, unsigned int x, int base);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, signed long x, int base);
|
||||||
|
char* to_chars(char* first, char* last, unsigned long x, int base);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, signed long long x, int base);
|
||||||
|
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, signed long long x, int base);
|
||||||
|
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, float x);
|
||||||
|
char* to_chars(char* first, char* last, float x, char fmt);
|
||||||
|
char* to_chars(char* first, char* last, float x, char fmt, int precision);
|
||||||
|
|
||||||
|
char* to_chars(char* first, char* last, double x);
|
||||||
|
char* to_chars(char* first, char* last, double x, char fmt);
|
||||||
|
char* to_chars(char* first, char* last, double x, char fmt, int precision);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_FORMAT_CHARCONV_H
|
||||||
164
include/fennec/format/detail/_format.h
Normal file
164
include/fennec/format/detail/_format.h
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file _format.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_FORMAT_DETAIL_FORMAT_H
|
||||||
|
#define FENNEC_FORMAT_DETAIL_FORMAT_H
|
||||||
|
|
||||||
|
#include <fennec/memory/pointers.h>
|
||||||
|
#include <fennec/format/formatter.h>
|
||||||
|
#include <fennec/format/format_arg.h>
|
||||||
|
|
||||||
|
namespace fennec::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// Impl interface for templated polymorphism fuckery
|
||||||
|
struct _format_argimpl {
|
||||||
|
_format_argimpl() {};
|
||||||
|
virtual ~_format_argimpl() {};
|
||||||
|
virtual string format(const format_arg& fmt) = 0;
|
||||||
|
virtual bool is_integer() = 0;
|
||||||
|
virtual int64_t int_value() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Polymorphic template specialization
|
||||||
|
template<typename T>
|
||||||
|
struct _format_arg : _format_argimpl {
|
||||||
|
formatter<T> fmtr;
|
||||||
|
const T& val;
|
||||||
|
_format_arg(const T& arg) : val(arg) {
|
||||||
|
}
|
||||||
|
virtual ~_format_arg() = default;
|
||||||
|
string format(const format_arg& fmt) override {
|
||||||
|
return fennec::forward<string>(fmtr(fmt, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_integer() override {
|
||||||
|
return is_integral_v<T> or is_convertible_v<T, int64_t>;
|
||||||
|
}
|
||||||
|
virtual int64_t int_value() override {
|
||||||
|
if constexpr(is_integral_v<T>) {
|
||||||
|
return val;
|
||||||
|
} else if constexpr(is_convertible_v<T, int64_t>) {
|
||||||
|
return val;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Polymorphic template specialization for x/r/xr value references
|
||||||
|
template<typename T>
|
||||||
|
struct _format_arg<T&> : _format_arg<T> {
|
||||||
|
_format_arg(const T& arg) : _format_arg<T>(arg) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Polymorphic template specialization for x/r/xr value references
|
||||||
|
template<typename T>
|
||||||
|
struct _format_arg<const T> : _format_arg<T> {
|
||||||
|
_format_arg(const T& arg) : _format_arg<T>(arg) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Polymorphic template specialization for x/r/xr value references
|
||||||
|
template<typename T>
|
||||||
|
struct _format_arg<const T&> : _format_arg<T> {
|
||||||
|
_format_arg(const T& arg) : _format_arg<T>(arg) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Containing array for format args
|
||||||
|
template<size_t N>
|
||||||
|
struct _format_argarray {
|
||||||
|
array<unique_ptr<_format_argimpl>, N> args;
|
||||||
|
template<typename...ArgsT>
|
||||||
|
_format_argarray(ArgsT&&...args)
|
||||||
|
: args { unique_ptr<_format_argimpl>(new _format_arg<ArgsT>(fennec::forward<ArgsT>(args)))... } {
|
||||||
|
}
|
||||||
|
|
||||||
|
string format(size_t i, const format_arg& fmt) {
|
||||||
|
return args[i]->format(fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_integer(size_t i) {
|
||||||
|
return args[i]->is_integer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t int_value(size_t i) {
|
||||||
|
return args[i]->int_value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// checks if character is a valid format type
|
||||||
|
constexpr bool _isfmt_t(char c) {
|
||||||
|
switch (c) {
|
||||||
|
default: return false;
|
||||||
|
case 's': case '?': // strings
|
||||||
|
case 'c': // char
|
||||||
|
case 'd': // decimal
|
||||||
|
case 'b': case 'B': // binary
|
||||||
|
case 'o': // octal
|
||||||
|
case 'x': case 'X': // hex
|
||||||
|
case 'a': case 'A': // float hex
|
||||||
|
case 'e': case 'E': // scientific notation
|
||||||
|
case 'f': case 'F': // fixed precision
|
||||||
|
case 'g': case 'G': // general precision
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if character is a valid format int type
|
||||||
|
constexpr bool _isfmt_i(char c) {
|
||||||
|
switch (c) {
|
||||||
|
default: return false;
|
||||||
|
case 'd': // decimal
|
||||||
|
case 'b': case 'B': // binary
|
||||||
|
case 'o': // octal
|
||||||
|
case 'x': case 'X': // hex
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if character is a valid format float type
|
||||||
|
constexpr bool _isfmt_f(char c) {
|
||||||
|
switch (c) {
|
||||||
|
default: return false;
|
||||||
|
case 'a': case 'A': // float hex
|
||||||
|
case 'e': case 'E': // scientific notation
|
||||||
|
case 'f': case 'F': // fixed precision
|
||||||
|
case 'g': case 'G': // general precision
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_FORMAT_DETAIL_FORMAT_H
|
||||||
378
include/fennec/format/format.h
Normal file
378
include/fennec/format/format.h
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file format.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_FORMAT_FORMAT_H
|
||||||
|
#define FENNEC_FORMAT_FORMAT_H
|
||||||
|
|
||||||
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
|
#include <fennec/format/detail/_format.h>
|
||||||
|
#include <fennec/format/formatter.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
string format(const cstring& str, ArgsT&&...args) {
|
||||||
|
static constexpr size_t argc = sizeof...(ArgsT);
|
||||||
|
static constexpr format_arg default_fmt = {
|
||||||
|
.fill = ' ',
|
||||||
|
.align = '\0', // default to locale
|
||||||
|
.sign = '\0', // default to sign only for negative numbers, gets handled later in code
|
||||||
|
.alt = false, // default no prefix
|
||||||
|
.upper = false,
|
||||||
|
.width = 0,
|
||||||
|
.precision = 6, // default to 6 sigfigs
|
||||||
|
.base = 10,
|
||||||
|
.type = '\0',
|
||||||
|
};
|
||||||
|
|
||||||
|
// empty case
|
||||||
|
if constexpr(argc == 0) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::_format_argarray<argc> argarray = { fennec::forward<ArgsT>(args)... };
|
||||||
|
string res;
|
||||||
|
size_t i = 0;
|
||||||
|
size_t arg_c = -1;
|
||||||
|
|
||||||
|
while (i <= str.length()) {
|
||||||
|
size_t brace = str.find('{', i);
|
||||||
|
size_t end = str.find('}', i);
|
||||||
|
format_arg fmt = default_fmt;
|
||||||
|
|
||||||
|
// check for '}}'
|
||||||
|
if (end < brace) {
|
||||||
|
if (str[end + 1] == '}') {
|
||||||
|
res += string(str.data() + i, end - i);
|
||||||
|
i = end + 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assertf(false, "fennec::format syntax error, encountered unexpected '{'")
|
||||||
|
}
|
||||||
|
|
||||||
|
// append string
|
||||||
|
if (brace >= str.length()) { // handle end case
|
||||||
|
res += string(str.data() + i, str.length() - i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res += string(str.data() + i, brace - i);
|
||||||
|
|
||||||
|
// next brace, validate escape
|
||||||
|
size_t next_brace = str.find('{', brace + 1);
|
||||||
|
if (brace + 1 == next_brace) {
|
||||||
|
res += '{';
|
||||||
|
i = next_brace + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find contained colon
|
||||||
|
size_t colon = str.find(':', brace);
|
||||||
|
|
||||||
|
// validate colon and brace location
|
||||||
|
assertf(colon < next_brace or end < next_brace, "fennec::format syntax error, mismatched '{}'");
|
||||||
|
|
||||||
|
// parse index if present
|
||||||
|
size_t id = min(colon, end) - 1;
|
||||||
|
if (id > brace) {
|
||||||
|
arg_c = 0;
|
||||||
|
} else {
|
||||||
|
++arg_c;
|
||||||
|
}
|
||||||
|
for (size_t j = id, k = 1; j > brace; --j, k *= 10) {
|
||||||
|
size_t u = (str[j] - '0');
|
||||||
|
assertf(u < 10, "fennec::format syntax error, invalid argument index");
|
||||||
|
arg_c += k * u;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store argument to allow nested replacement fields
|
||||||
|
size_t arg = arg_c;
|
||||||
|
|
||||||
|
// validate index
|
||||||
|
assertf(arg < argc, "fennec::format syntax error, invalid argument index");
|
||||||
|
|
||||||
|
// early return case for no colon
|
||||||
|
if (colon > end) {
|
||||||
|
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||||
|
res += argarray.format(arg, fmt);
|
||||||
|
i = end + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse format specifiers
|
||||||
|
|
||||||
|
// we're going to parse right-to-left since the valid combinations
|
||||||
|
// of specifiers change based on the type of the argument
|
||||||
|
|
||||||
|
// to compensate for this, the nested replacement fields need to be computed in this loop
|
||||||
|
// (nested replacement deduced)
|
||||||
|
size_t nrfd = 0;
|
||||||
|
size_t nnrf = 0;
|
||||||
|
|
||||||
|
// first find the matching '}' brace, e is not necessarily the matching brace
|
||||||
|
// since some specifiers allow nested replacement fields
|
||||||
|
size_t parse = colon;
|
||||||
|
while (str[parse + 1] != '}') {
|
||||||
|
if (next_brace < end) { // if the next brace is before the next closing brace
|
||||||
|
++nnrf;
|
||||||
|
nrfd += str[end - 1] == '{';
|
||||||
|
parse = end + 1;
|
||||||
|
end = str.find('}', parse);
|
||||||
|
next_brace = str.find('{', parse);
|
||||||
|
} else {
|
||||||
|
parse = end - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertf(nrfd <= 2 and parse < str.length() - 1 and str[parse + 1] == '}',
|
||||||
|
"fennec::format syntax error, mismatched '{}'");
|
||||||
|
|
||||||
|
// check type
|
||||||
|
switch (str[parse]) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case 's': case '?': // strings
|
||||||
|
case 'c': // char
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'd': // decimal
|
||||||
|
fmt.base = 10;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B': // binary
|
||||||
|
fmt.upper = true; [[fallthrough]];
|
||||||
|
case 'b':
|
||||||
|
fmt.base = 2;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o': // octal
|
||||||
|
fmt.base = 8;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X': // hex
|
||||||
|
fmt.upper = true; [[fallthrough]];
|
||||||
|
case 'x':
|
||||||
|
fmt.base = 16;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'A':
|
||||||
|
fmt.upper = true; [[fallthrough]];
|
||||||
|
case 'a': // float hex
|
||||||
|
fmt.base = 16;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'E': // scientific notation
|
||||||
|
fmt.upper = true; [[fallthrough]];
|
||||||
|
case 'e':
|
||||||
|
fmt.base = 16;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F': // fixed precision
|
||||||
|
fmt.upper = true; [[fallthrough]];
|
||||||
|
case 'f':
|
||||||
|
fmt.base = 10;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'G': // general precision
|
||||||
|
fmt.upper = true; [[fallthrough]];
|
||||||
|
case 'g':
|
||||||
|
fmt.base = 10;
|
||||||
|
fmt.type = str[parse--];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// early return
|
||||||
|
if (parse == colon) {
|
||||||
|
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||||
|
res += argarray.format(arg, fmt);
|
||||||
|
i = end + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for width and precision
|
||||||
|
size_t x = 0, j = 1;
|
||||||
|
bool found_decimal = false;
|
||||||
|
size_t num_decimals = 0;
|
||||||
|
bool is_float_t = detail::_isfmt_f(fmt.type);
|
||||||
|
bool is_str_t = fmt.type == 's';
|
||||||
|
bool is_integer_t = detail::_isfmt_i(fmt.type);
|
||||||
|
bool ded_width_f = false;
|
||||||
|
bool ded_width = false;
|
||||||
|
size_t ded_temp_i = 0;
|
||||||
|
|
||||||
|
// default "precision" for strings should be 0 for no limit
|
||||||
|
if (is_str_t) {
|
||||||
|
fmt.precision = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse width and precision
|
||||||
|
while (isdigit(str[parse]) or (found_decimal = (str[parse] == '.')) or str[parse] == '{' or str[parse] == '}') {
|
||||||
|
// handle decimal point for precision
|
||||||
|
if (found_decimal) {
|
||||||
|
assertf(is_float_t or is_str_t, "fennec::format syntax error, encountered precision argument on non-floating point format");
|
||||||
|
assertf(num_decimals == 0, "fennec::format syntax error, multiple decimals detected in floating point format");
|
||||||
|
++num_decimals;
|
||||||
|
found_decimal = false;
|
||||||
|
|
||||||
|
fmt.precision = x;
|
||||||
|
x = 0, j = 1;
|
||||||
|
--parse;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for nested replacement field
|
||||||
|
if (str[parse] == '{') {
|
||||||
|
assertf(str[parse - 1] == '0' or str[parse - 1] == '.' or not isdigit(str[parse - 1]),
|
||||||
|
"fennec::format syntax error, unexpected digit preceding nested replacement field");
|
||||||
|
|
||||||
|
bool prec = str[parse - 1] == '.';
|
||||||
|
bool ded = str[parse + 1] == '}';
|
||||||
|
|
||||||
|
size_t sub;
|
||||||
|
if (nrfd == 2) { // if both are deduced, parse normally. Hack with prefix and postfix.
|
||||||
|
sub = prec ? ++arg_c + 1 : arg_c++;
|
||||||
|
} else if (nrfd == 1 and nnrf == 2 and prec and ded) { // if only precision is nrf, deduce width first
|
||||||
|
ded_width_f = true;
|
||||||
|
ded_temp_i = parse;
|
||||||
|
continue;
|
||||||
|
} else { // otherwise deduce normally
|
||||||
|
sub = ded ? ++arg_c : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertf(sub < argc, "fennec::format syntax error, argument index out of range in nested replacement field");
|
||||||
|
assertf(argarray.is_integer(sub), "fennec::format argument error, nested replacement field argument is not convertible to integral type");
|
||||||
|
|
||||||
|
(prec ? fmt.precision : fmt.width) = argarray.int_value(sub);
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
if (ded_width_f) {
|
||||||
|
ded_width_f = false;
|
||||||
|
ded_width = true;
|
||||||
|
swap(ded_temp_i, parse);
|
||||||
|
arg_c = sub;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ded_width) {
|
||||||
|
parse = ded_temp_i;
|
||||||
|
ded_width = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse -= 1 + prec;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore closing brace for nested replacement fields
|
||||||
|
if (str[parse] == '}') {
|
||||||
|
--parse;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// crude way to only handle 0 case if 0 is the last digit
|
||||||
|
fmt.fill = str[parse] == '0' ? '0' : ' ';
|
||||||
|
|
||||||
|
// parse the number
|
||||||
|
x += j * (str[parse] - '0');
|
||||||
|
j *= 10;
|
||||||
|
--parse;
|
||||||
|
}
|
||||||
|
if (x != 0) {
|
||||||
|
fmt.width = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// early return
|
||||||
|
if (parse == colon) {
|
||||||
|
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||||
|
res += argarray.format(arg, fmt);
|
||||||
|
i = end + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for alt form
|
||||||
|
if (str[parse] == '#') {
|
||||||
|
assertf(is_float_t or is_integer_t, "fennec::format syntax error, encountered alt spec ('#') with non-decimal type");
|
||||||
|
fmt.alt = true;
|
||||||
|
--parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for sign
|
||||||
|
if (str[parse] == '-' or str[parse] == '+' or str[parse] == ' ') {
|
||||||
|
fmt.sign = str[parse];
|
||||||
|
if (str[parse] == ' ') { // handle fill if only space, gets overwritten if encounters fill character
|
||||||
|
fmt.fill = ' ';
|
||||||
|
}
|
||||||
|
--parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for alignment
|
||||||
|
if (str[parse] == '<' or str[parse] == '>' or str[parse] == '^') {
|
||||||
|
fmt.align = str[parse];
|
||||||
|
--parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill character
|
||||||
|
if (str[parse] != ':') {
|
||||||
|
fmt.fill = str[parse];
|
||||||
|
if (str[parse] == ' ') {
|
||||||
|
fmt.sign = fmt.sign == '\0' ? ' ' : fmt.sign;
|
||||||
|
}
|
||||||
|
--parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default sign
|
||||||
|
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||||
|
|
||||||
|
// validate that we handled the entire format arg
|
||||||
|
assertf(parse == colon, "fennec::format syntax error, malformed format string detected, possible double colon");
|
||||||
|
|
||||||
|
|
||||||
|
// add formatted argument
|
||||||
|
res += argarray.format(arg, fmt);
|
||||||
|
i = end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_FORMAT_FORMAT_H
|
||||||
50
include/fennec/format/format_arg.h
Normal file
50
include/fennec/format/format_arg.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file format_arg.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_FORMAT_FORMAT_ARG_H
|
||||||
|
#define FENNEC_FORMAT_FORMAT_ARG_H
|
||||||
|
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
struct format_arg {
|
||||||
|
char fill;
|
||||||
|
char align, sign;
|
||||||
|
bool alt, upper;
|
||||||
|
size_t width, precision;
|
||||||
|
size_t base;
|
||||||
|
char type;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_FORMAT_FORMAT_ARG_H
|
||||||
249
include/fennec/format/formatter.h
Normal file
249
include/fennec/format/formatter.h
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file formatter.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_FORMAT_FORMATTER_H
|
||||||
|
#define FENNEC_FORMAT_FORMATTER_H
|
||||||
|
|
||||||
|
#include <fennec/format/charconv.h>
|
||||||
|
#include <fennec/string/string.h>
|
||||||
|
#include <fennec/format/format_arg.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
// base template =======================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Formatter struct, used to turn values into formatted strings
|
||||||
|
/// \tparam T The type to format
|
||||||
|
template<typename T>
|
||||||
|
struct formatter {
|
||||||
|
string operator()(const format_arg&, const T&) {
|
||||||
|
static_assert(false, "Formatter not implemented for the provided type.");
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// strings =============================================================================================================
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
struct formatter<char[N]> {
|
||||||
|
string operator()(const format_arg&, const char (&str)[N]) {
|
||||||
|
return string(str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
struct formatter<const char[N]> {
|
||||||
|
string operator()(const format_arg&, const char (&str)[N]) {
|
||||||
|
return string(str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct formatter<cstring> {
|
||||||
|
string operator()(const format_arg&, const cstring& str) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct formatter<string> {
|
||||||
|
string operator()(const format_arg&, const string& str) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// decimal types =======================================================================================================
|
||||||
|
|
||||||
|
template<typename IntT> requires(is_integral_v<IntT> and not is_bool_v<IntT>)
|
||||||
|
struct formatter<IntT> {
|
||||||
|
string operator()(const format_arg& fmt, IntT x) {
|
||||||
|
char digits[128] = {};
|
||||||
|
auto chk = fennec::to_chars(digits, digits + sizeof(digits), fennec::abs(x), fmt.base);
|
||||||
|
assertf(chk != nullptr, "fennec::format error, to_chars error");
|
||||||
|
size_t len = chk - digits;
|
||||||
|
|
||||||
|
// handle uppercase
|
||||||
|
if (fmt.upper) {
|
||||||
|
for (auto& digit : digits) {
|
||||||
|
if (digit == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
digit = toupper(digit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool has_sign = (x < 0 or fmt.sign != '-');
|
||||||
|
const bool zero = fmt.fill == '0';
|
||||||
|
const size_t prefix = fmt.alt ? (fmt.type == 'd' ? 0 : 2 - (fmt.type == 'o')) : 0;
|
||||||
|
const size_t sgnlen = len + (zero ? has_sign + prefix : 0);
|
||||||
|
const size_t explen = fennec::max(sgnlen, fmt.width) + (zero ? 0 : has_sign + prefix);
|
||||||
|
const size_t fill = fmt.width > sgnlen ? fmt.width - sgnlen : 0;
|
||||||
|
size_t sign = 0;
|
||||||
|
|
||||||
|
string res = string(explen);
|
||||||
|
|
||||||
|
if (fill > 0) {
|
||||||
|
switch (fmt.align) {
|
||||||
|
case '<':
|
||||||
|
memcpy(res.data() + has_sign + prefix, digits, len);
|
||||||
|
memset(res.data() + has_sign + prefix + len, fmt.fill == '0' ? ' ' : fmt.fill, fill);
|
||||||
|
break;
|
||||||
|
case '>': case '\0':
|
||||||
|
memcpy(res.data() + explen - len, digits, len);
|
||||||
|
sign = fmt.fill == '0' ? 0 : explen - len - 1 - prefix;
|
||||||
|
memset(res.data(), fmt.fill, explen - len);
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
size_t bef = fill / 2 + has_sign + prefix;
|
||||||
|
size_t aft = explen - bef;
|
||||||
|
memcpy(res.data() + bef, digits, len);
|
||||||
|
sign = fmt.fill == '0' ? 0 : bef - 1 - prefix;
|
||||||
|
memset(res.data(), fmt.fill, bef);
|
||||||
|
memset(res.data() + bef + len, fmt.fill == '0' ? ' ' : fmt.fill, aft);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(res.data() + has_sign + prefix, digits, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_sign) {
|
||||||
|
res[sign] = (x < 0) ? '-' : fmt.sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix) {
|
||||||
|
res[sign + has_sign] = '0';
|
||||||
|
if (fmt.type != 'o') {
|
||||||
|
res[sign + has_sign + 1] = fmt.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename BoolT> requires(is_bool_v<BoolT>)
|
||||||
|
struct formatter<BoolT> {
|
||||||
|
string operator()(const format_arg& fmt, BoolT x) {
|
||||||
|
if (fmt.type == 's' or fmt.type == '\0') {
|
||||||
|
return x ? string("true") : string("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatter<uint8_t>{}(fmt, static_cast<uint8_t>(x));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename FloatT> requires(is_floating_point_v<FloatT>)
|
||||||
|
struct formatter<FloatT> {
|
||||||
|
string operator()(const format_arg& fmt, FloatT x) {
|
||||||
|
|
||||||
|
// nan & inf cases
|
||||||
|
if (fennec::isnan(x)) {
|
||||||
|
return string("nan");
|
||||||
|
}
|
||||||
|
if (fennec::isinf(x)) {
|
||||||
|
return string("inf");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char digits[128] = {};
|
||||||
|
auto chk = fennec::to_chars(digits, digits + sizeof(digits), fennec::abs(x), fmt.type, fmt.precision);
|
||||||
|
assertf(chk != nullptr, "fennec::format error, to_chars error");
|
||||||
|
size_t len = chk - digits;
|
||||||
|
|
||||||
|
// handle uppercase
|
||||||
|
if (fmt.upper) {
|
||||||
|
for (auto& digit : digits) {
|
||||||
|
if (digit == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
digit = toupper(digit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool has_sign = (x < 0 or fmt.sign != '-');
|
||||||
|
const bool zero = fmt.fill == '0';
|
||||||
|
const size_t prefix = fmt.alt ? 2 : 0;
|
||||||
|
const size_t sgnlen = len + (zero ? has_sign + prefix : 0);
|
||||||
|
const size_t explen = fennec::max(sgnlen, fmt.width) + (zero ? 0 : has_sign + prefix);
|
||||||
|
const size_t fill = fmt.width > sgnlen ? fmt.width - sgnlen : 0;
|
||||||
|
size_t sign = 0;
|
||||||
|
|
||||||
|
string res = string(explen);
|
||||||
|
|
||||||
|
if (fill > 0) {
|
||||||
|
switch (fmt.align) {
|
||||||
|
case '<':
|
||||||
|
memcpy(res.data() + has_sign + prefix, digits, len);
|
||||||
|
memset(res.data() + has_sign + prefix + len, fmt.fill == '0' ? ' ' : fmt.fill, fill);
|
||||||
|
break;
|
||||||
|
case '>': case '\0':
|
||||||
|
memcpy(res.data() + explen - len, digits, len);
|
||||||
|
sign = fmt.fill == '0' ? 0 : explen - len - 1 - prefix;
|
||||||
|
memset(res.data(), fmt.fill, explen - len);
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
size_t bef = fill / 2 + has_sign + prefix;
|
||||||
|
size_t aft = explen - bef;
|
||||||
|
memcpy(res.data() + bef, digits, len);
|
||||||
|
sign = fmt.fill == '0' ? 0 : bef - 1 - prefix;
|
||||||
|
memset(res.data(), fmt.fill, bef);
|
||||||
|
memset(res.data() + bef + len, fmt.fill == '0' ? ' ' : fmt.fill, aft);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(res.data() + has_sign + prefix, digits, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_sign) {
|
||||||
|
res[sign] = (x < 0) ? '-' : fmt.sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix) {
|
||||||
|
res[sign + has_sign] = '0';
|
||||||
|
res[sign + has_sign + 1] = fmt.type + ('x' - 'a');
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_FORMAT_FORMATTER_H
|
||||||
47
include/fennec/gfx3d/mesh_instance.h
Normal file
47
include/fennec/gfx3d/mesh_instance.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file mesh_instance.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_GFX3D_MESH_INSTANCE_H
|
||||||
|
#define FENNEC_GFX3D_MESH_INSTANCE_H
|
||||||
|
#include <fennec/scene/component.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class mesh_instance : component {
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_GFX3D_MESH_INSTANCE_H
|
||||||
112
include/fennec/interpret/tokenizer.h
Normal file
112
include/fennec/interpret/tokenizer.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file tokenizer.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_INTERPRET_TOKENIZER_H
|
||||||
|
#define FENNEC_INTERPRET_TOKENIZER_H
|
||||||
|
|
||||||
|
#include <fennec/containers/list.h>
|
||||||
|
#include <fennec/containers/map.h>
|
||||||
|
#include <fennec/containers/priority_queue.h>
|
||||||
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// escape sequences are tricky, sometimes they must be separated by white space,
|
||||||
|
// other times they don't. Requiring a list of all possible escape sequences is unrealistic.
|
||||||
|
// We need to allow the user of this struct to specify rules for escape sequences. Here are some basic rules:
|
||||||
|
//
|
||||||
|
// An escape sequence is marked by an escape character, e.g. %, \, {{
|
||||||
|
// Multiple escape characters may be used in a single tokenizer and will have different rules
|
||||||
|
// Escape characters may also be operators, brackets, or quotes
|
||||||
|
// Escape sequences may contain operators, brackets, or quotes
|
||||||
|
//
|
||||||
|
// Here are a few examples of escape sequences from various formats and languages
|
||||||
|
// C: \\, \n, \0, \u200b
|
||||||
|
// PrintF: %s, %2.2f
|
||||||
|
// Python FMT: {{, }}
|
||||||
|
// SPSS: ''
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
struct escape_sequence {
|
||||||
|
virtual size_t operator[](const string& str, size_t i) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tokenizer {
|
||||||
|
using escseq = escape_sequence*;
|
||||||
|
using escmap = map<char, escape_sequence*>;
|
||||||
|
|
||||||
|
string delimiter; // markers that separate tokens
|
||||||
|
string operators; // operators are treated as individual tokens
|
||||||
|
string brackets; // characters that mark brackets
|
||||||
|
string quotes; // characters that mark a string sequence, entire string sequence is treated as one token
|
||||||
|
escmap escapes; // characters that mark the start of an escape sequence and validate them
|
||||||
|
bool numbers; // Anything that resembles a number
|
||||||
|
|
||||||
|
enum token_ : uint8_t {
|
||||||
|
token_text = 0,
|
||||||
|
token_integer,
|
||||||
|
token_string,
|
||||||
|
token_newline,
|
||||||
|
token_escaped,
|
||||||
|
token_operator,
|
||||||
|
token_bracket,
|
||||||
|
token_quoted,
|
||||||
|
|
||||||
|
num_token_types
|
||||||
|
};
|
||||||
|
|
||||||
|
using token = pair<string, uint8_t>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr uint8_t token_delimiter = num_token_types;
|
||||||
|
|
||||||
|
constexpr list<token> operator()(const string& line) {
|
||||||
|
list<token> res;
|
||||||
|
priority_queue<pair<size_t, uint8_t>> idx;
|
||||||
|
|
||||||
|
for (char c : delimiter) {
|
||||||
|
size_t i = 0;
|
||||||
|
while (i != line.size()) {
|
||||||
|
size_t n = line.find(c, i);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_INTERPRET_TOKENIZER_H
|
||||||
48
include/fennec/lang/declval.h
Normal file
48
include/fennec/lang/declval.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file declval.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_LANGCPP_DECLVAL_H
|
||||||
|
#define FENNEC_LANGCPP_DECLVAL_H
|
||||||
|
|
||||||
|
#include <fennec/lang/detail/_declval.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
// fennec::declval =====================================================================================================
|
||||||
|
|
||||||
|
template<typename T> auto declval() noexcept -> decltype(detail::_declval<T>(0)) {
|
||||||
|
static_assert(detail::_declval_protector<T>{}, "declval must not be used");
|
||||||
|
return detail::_declval<T>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_LANGCPP_DECLVAL_H
|
||||||
46
include/fennec/lang/detail/_declval.h
Normal file
46
include/fennec/lang/detail/_declval.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file _declval.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_LANG_DETAIL_DECLVAL_H
|
||||||
|
#define FENNEC_LANG_DETAIL_DECLVAL_H
|
||||||
|
|
||||||
|
#include <fennec/lang/constants.h>
|
||||||
|
|
||||||
|
namespace fennec::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T, typename U = T&&> U _declval(int);
|
||||||
|
template<typename T> T _declval(long);
|
||||||
|
|
||||||
|
template<typename T> struct _declval_protector : bool_constant<false> {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_LANG_DETAIL_DECLVAL_H
|
||||||
@@ -19,13 +19,19 @@
|
|||||||
#ifndef FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
#ifndef FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||||
#define FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
#define FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||||
|
|
||||||
|
#include <fennec/math/common.h>
|
||||||
#include <fennec/lang/type_transforms.h>
|
#include <fennec/lang/type_transforms.h>
|
||||||
|
|
||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
template<typename...TypesT> struct _type_sequence {};
|
||||||
|
|
||||||
template<typename FirstT, typename... RestT> struct _first_element : type_identity<FirstT> {};
|
template<typename FirstT, typename... RestT> struct _first_element : type_identity<FirstT> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::nth_element =================================================================================================
|
||||||
|
|
||||||
template<size_t n, size_t i, typename...TypesT> struct _nth_element;
|
template<size_t n, size_t i, typename...TypesT> struct _nth_element;
|
||||||
|
|
||||||
template<size_t n, size_t i> struct _nth_element<n, i> : type_identity<void> {};
|
template<size_t n, size_t i> struct _nth_element<n, i> : type_identity<void> {};
|
||||||
@@ -35,6 +41,56 @@ namespace fennec::detail
|
|||||||
n == i, HeadT,
|
n == i, HeadT,
|
||||||
typename _nth_element<n, i + 1, RestT...>::type
|
typename _nth_element<n, i + 1, RestT...>::type
|
||||||
> {};
|
> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::max_element_size ============================================================================================
|
||||||
|
|
||||||
|
template<size_t, typename...> struct _max_element_size;
|
||||||
|
|
||||||
|
template<size_t M, typename HeadT>
|
||||||
|
struct _max_element_size<M, HeadT>
|
||||||
|
: integral_constant<size_t, fennec::max(M, sizeof(HeadT))> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t M, typename HeadT, typename...RestT>
|
||||||
|
struct _max_element_size<M, HeadT, RestT...>
|
||||||
|
: _max_element_size<fennec::max(M, sizeof(HeadT)), RestT...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::find_element ================================================================================================
|
||||||
|
|
||||||
|
template<size_t N, typename, typename...> struct _find_element;
|
||||||
|
|
||||||
|
template<size_t N, typename FindT, typename HeadT>
|
||||||
|
struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {};
|
||||||
|
|
||||||
|
template<size_t N, typename FindT, typename HeadT, typename...RestT> requires(is_same_v<FindT, HeadT>)
|
||||||
|
struct _find_element<N, FindT, HeadT, RestT...>
|
||||||
|
: conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {};
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::search_element ==============================================================================================
|
||||||
|
|
||||||
|
template<template<typename> typename, typename...> struct _search_element;
|
||||||
|
|
||||||
|
template<template<typename> typename SearchT> struct _search_element<SearchT> : type_identity<void> {};
|
||||||
|
|
||||||
|
template<template<typename> typename SearchT, typename HeadT, typename...RestT> requires(SearchT<HeadT>{})
|
||||||
|
struct _search_element<SearchT, HeadT, RestT...>
|
||||||
|
: conditional_t<SearchT<HeadT>{}, type_identity<HeadT>, _search_element<SearchT, RestT...>> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename, typename, typename...> struct _search_element_args;
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename SearchT, typename...ArgsT>
|
||||||
|
struct _search_element_args<SearchT, _type_sequence<ArgsT...>> : type_identity<void> {};
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename SearchT, typename HeadT, typename...RestT, typename...ArgsT>
|
||||||
|
struct _search_element_args<SearchT, _type_sequence<ArgsT...>, HeadT, RestT...>
|
||||||
|
: conditional_t<SearchT<HeadT, ArgsT...>{}, type_identity<HeadT>, _search_element_args<SearchT, _type_sequence<ArgsT...>, RestT...>> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||||
|
|||||||
@@ -19,8 +19,9 @@
|
|||||||
#ifndef FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
#ifndef FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||||
#define FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
#define FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||||
|
|
||||||
|
#include <fennec/lang/ranges.h>
|
||||||
#include <fennec/lang/constants.h>
|
#include <fennec/lang/constants.h>
|
||||||
#include <fennec/lang/float.h>
|
#include <fennec/lang/declval.h>
|
||||||
|
|
||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
@@ -65,11 +66,80 @@ namespace fennec::detail
|
|||||||
template<typename> struct _is_pointer : false_type {};
|
template<typename> struct _is_pointer : false_type {};
|
||||||
template<typename T> struct _is_pointer<T*> : true_type {};
|
template<typename T> struct _is_pointer<T*> : true_type {};
|
||||||
|
|
||||||
template<typename T, typename U = T&&> U _declval(int);
|
template<typename> struct _is_reference : false_type {};
|
||||||
template<typename T> T _declval(long);
|
template<typename T> struct _is_reference<T&> : true_type {};
|
||||||
|
template<typename T> struct _is_reference<T&&> : true_type {};
|
||||||
|
|
||||||
template<typename T> struct _declval_protector : bool_constant<false> {};
|
template<typename> struct _is_lvalue_reference : false_type {};
|
||||||
|
template<typename T> struct _is_lvalue_reference<T&> : true_type {};
|
||||||
|
|
||||||
|
template<typename> struct _is_rvalue_reference : false_type {};
|
||||||
|
template<typename T> struct _is_rvalue_reference<T&&> : true_type {};
|
||||||
|
|
||||||
|
template<typename T> struct _is_complete {
|
||||||
|
template<typename U>
|
||||||
|
static auto test(U*) -> bool_constant<sizeof(U) == sizeof(U)>;
|
||||||
|
static auto test(...) -> false_type;
|
||||||
|
using type = decltype(_is_complete::test(static_cast<T*>(nullptr)));
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> struct _is_destructible {
|
||||||
|
template<typename U, typename = decltype(declval<T&>().~T())>
|
||||||
|
static auto test(int) -> true_type;
|
||||||
|
template<typename>
|
||||||
|
static auto test(...) -> false_type;
|
||||||
|
using type = decltype(test<T>(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> struct _is_nothrow_destructible {
|
||||||
|
template<typename U, typename = decltype(noexcept(declval<T&>().~T()))>
|
||||||
|
static auto test(int) -> true_type;
|
||||||
|
template<typename>
|
||||||
|
static auto test(...) -> false_type;
|
||||||
|
using type = decltype(test<T>(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/13830158/how-to-write-a-trait-which-checks-whether-a-type-is-iterable
|
||||||
|
template<typename T>
|
||||||
|
auto _is_iterable(int) -> decltype(
|
||||||
|
fennec::begin(declval<T&>()) != fennec::end(declval<T&>()),
|
||||||
|
void(),
|
||||||
|
++declval<decltype(fennec::begin(declval<T&>()))&>(),
|
||||||
|
void(*fennec::begin(declval<T&>())),
|
||||||
|
true_type{}
|
||||||
|
);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto _is_iterable(...) -> false_type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto _is_indexable(int) -> decltype(
|
||||||
|
declval<T&>()[0],
|
||||||
|
true_type{}
|
||||||
|
);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto _is_indexable(...) -> false_type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto _is_mappable(int) -> decltype(
|
||||||
|
declval<T&>()[declval<typename T::key_t&>()],
|
||||||
|
true_type{}
|
||||||
|
);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto _is_mappable(...) -> false_type;
|
||||||
|
|
||||||
|
|
||||||
|
template<typename B> auto _ptr_conv(const volatile B*) -> true_type;
|
||||||
|
template<typename> auto _ptr_conv(const volatile void*) -> false_type;
|
||||||
|
|
||||||
|
template<typename B, typename D> auto _is_base_of(int) -> decltype(detail::_ptr_conv<B>(static_cast<D*>(nullptr)));
|
||||||
|
template<typename, typename> auto _is_base_of(...) -> false_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
#endif // FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||||
|
|||||||
@@ -102,6 +102,9 @@
|
|||||||
// Most major compilers support __has_builtin, notably GCC, MINGW, and CLANG
|
// Most major compilers support __has_builtin, notably GCC, MINGW, and CLANG
|
||||||
#if defined(__has_builtin)
|
#if defined(__has_builtin)
|
||||||
|
|
||||||
|
|
||||||
|
// UTILITIES ===========================================================================================================
|
||||||
|
|
||||||
// addressof is very difficult to implement without intrinsics.
|
// addressof is very difficult to implement without intrinsics.
|
||||||
#if __has_builtin(__builtin_addressof)
|
#if __has_builtin(__builtin_addressof)
|
||||||
# define FENNEC_HAS_BUILTIN_ADDRESSOF 1
|
# define FENNEC_HAS_BUILTIN_ADDRESSOF 1
|
||||||
@@ -118,6 +121,37 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_BIT_CAST 0
|
# define FENNEC_HAS_BUILTIN_BIT_CAST 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_LINE)
|
||||||
|
# define FENNEC_HAS_BUILTIN_LINE 1
|
||||||
|
# define FENNEC_BUILTIN_LINE() __builtin_LINE()
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_LINE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_COLUMN)
|
||||||
|
# define FENNEC_HAS_BUILTIN_COLUMN 1
|
||||||
|
# define FENNEC_BUILTIN_COLUMN() __builtin_COLUMN()
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_COLUMN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_FILE)
|
||||||
|
# define FENNEC_HAS_BUILTIN_FILE 1
|
||||||
|
# define FENNEC_BUILTIN_FILE() __builtin_FILE()
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_FILE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_FUNCTION)
|
||||||
|
# define FENNEC_HAS_BUILTIN_FUNCTION 1
|
||||||
|
# define FENNEC_BUILTIN_FUNCTION() __builtin_FUNCTION()
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_FUNCTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// PROPERTIES ==========================================================================================================
|
||||||
|
|
||||||
// Inconsistent without intrinsics
|
// Inconsistent without intrinsics
|
||||||
#if __has_builtin(__is_abstract)
|
#if __has_builtin(__is_abstract)
|
||||||
# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 1
|
# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 1
|
||||||
@@ -142,6 +176,7 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_CLASS
|
# define FENNEC_HAS_BUILTIN_IS_CLASS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// CONSTRUCTORS ========================================================================================================
|
// CONSTRUCTORS ========================================================================================================
|
||||||
|
|
||||||
// Difficult and Inconsistent without intrinsics
|
// Difficult and Inconsistent without intrinsics
|
||||||
@@ -213,6 +248,14 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_ENUM 0
|
# define FENNEC_HAS_BUILTIN_IS_ENUM 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics.
|
||||||
|
#if __has_builtin(__is_union)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_UNION 1
|
||||||
|
# define FENNEC_BUILTIN_IS_UNION(arg) __is_union(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_UNION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// Inconsistent without intrinsics
|
// Inconsistent without intrinsics
|
||||||
#if __has_builtin(__is_final)
|
#if __has_builtin(__is_final)
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
||||||
@@ -221,12 +264,20 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Inconsistent with dynamic intrinsics, requires a massive table for static intrinsics
|
// Inconsistent without intrinsics
|
||||||
#if __has_builtin(__is_fundamental)
|
#if __has_builtin(__is_function)
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 1
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 1
|
||||||
# define FENNEC_BUILTIN_IS_FUNDAMENTAL(arg) __is_fundamental(arg)
|
# define FENNEC_BUILTIN_IS_FUNCTION(arg) __is_function(arg)
|
||||||
#else
|
#else
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 0
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics
|
||||||
|
#if __has_builtin(__is_object)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_OBJECT 1
|
||||||
|
# define FENNEC_BUILTIN_IS_OBJECT(arg) __is_object(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Inconsistent without intrinsics
|
// Inconsistent without intrinsics
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
/// - \subpage fennec_lang_constants
|
/// - \subpage fennec_lang_constants
|
||||||
/// - \subpage fennec_lang_conditional_types
|
/// - \subpage fennec_lang_conditional_types
|
||||||
/// - \subpage fennec_lang_numeric_transforms
|
/// - \subpage fennec_lang_numeric_transforms
|
||||||
/// - \subpage fennec_lang_sequences
|
/// - \subpage fennec_lang_metasequences
|
||||||
|
/// - \subpage fennec_lang_type_identity
|
||||||
/// - \subpage fennec_lang_type_sequences
|
/// - \subpage fennec_lang_type_sequences
|
||||||
/// - \subpage fennec_lang_type_traits
|
/// - \subpage fennec_lang_type_traits
|
||||||
/// - \subpage fennec_lang_type_transforms
|
/// - \subpage fennec_lang_type_transforms
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \file sequences.h
|
/// \file metasequences.h
|
||||||
/// \brief \ref fennec_lang_sequences
|
/// \brief \ref fennec_lang_metasequences
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
@@ -32,40 +32,40 @@
|
|||||||
#define FENNEC_LANG_SEQUENCES_H
|
#define FENNEC_LANG_SEQUENCES_H
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \page fennec_lang_sequences Sequences
|
/// \page fennec_lang_metasequences Metasequences
|
||||||
///
|
///
|
||||||
/// \brief This header is part of the metaprogramming library. It defines structures for sequences of values, used during compile time.
|
/// \brief This header is part of the metaprogramming library. It defines structures for metasequences of values, used during compile time.
|
||||||
///
|
///
|
||||||
/// \code #include <fennec/lang/sequences.h> \endcode
|
/// \code #include <fennec/lang/metasequences.h> \endcode
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_sequences">
|
/// <table width="100%" class="fieldtable" id="table_fennec_lang_metasequences">
|
||||||
/// <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::sequence "sequence<ValueT, Values...>"<br>
|
/// \ref fennec::metasequence "metasequence<ValueT, Values...>"<br>
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::sequence
|
/// \copydetails fennec::metasequence
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::integer_sequence "integer_sequence<IntT, Values...>"<br>
|
/// \ref fennec::integer_metasequence "integer_metasequence<IntT, Values...>"<br>
|
||||||
/// \ref fennec::make_integer_sequence "typename make_integer_sequence<IntT, N>::type"<br>
|
/// \ref fennec::make_integer_metasequence "typename make_integer_metasequence<IntT, N>::type"<br>
|
||||||
/// \ref fennec::make_integer_sequence_t "make_integer_sequence_t<IntT, N>"
|
/// \ref fennec::make_integer_metasequence_t "make_integer_metasequence_t<IntT, N>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::integer_sequence
|
/// \copydetails fennec::integer_metasequence
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::index_sequence "index_sequence<Indices...>"<br>
|
/// \ref fennec::index_metasequence "index_metasequence<Indices...>"<br>
|
||||||
/// \ref fennec::make_index_sequence "typename make_index_sequence<N>::type"<br>
|
/// \ref fennec::make_index_metasequence "typename make_index_metasequence<N>::type"<br>
|
||||||
/// \ref fennec::make_index_sequence_t "make_index_sequence_t<N>"
|
/// \ref fennec::make_index_metasequence_t "make_index_metasequence_t<N>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::index_sequence
|
/// \copydetails fennec::index_metasequence
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::concat_sequence "typename concat_sequence<SequenceT0, SequenceT1>::type"<br>
|
/// \ref fennec::concat_metasequence "typename concat_metasequence<metasequenceT0, metasequenceT1>::type"<br>
|
||||||
/// \ref fennec::concat_sequence_t "concat_sequence_t<SequenceT0, SequenceT1>"<br>
|
/// \ref fennec::concat_metasequence_t "concat_metasequence_t<metasequenceT0, metasequenceT1>"<br>
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::concat_sequence
|
/// \copydetails fennec::concat_metasequence
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
// fennec::sequence ====================================================================================================
|
// fennec::metasequence ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief metaprogramming sequence
|
/// \brief metaprogramming sequence
|
||||||
@@ -84,20 +84,20 @@ namespace fennec
|
|||||||
/// You can access the parameter pack in another template function, i.e.
|
/// You can access the parameter pack in another template function, i.e.
|
||||||
/// \code{cpp}
|
/// \code{cpp}
|
||||||
/// template<typename TypeT, TypeT...Values>
|
/// template<typename TypeT, TypeT...Values>
|
||||||
/// constexpr TypeT summation(sequence<TypeT, Values...>)
|
/// constexpr TypeT summation(metasequence<TypeT, Values...>)
|
||||||
/// {
|
/// {
|
||||||
/// return (Values + ...);
|
/// return (Values + ...);
|
||||||
/// }
|
/// }
|
||||||
/// \endcode
|
/// \endcode
|
||||||
/// \tparam ValueT type of the values
|
/// \tparam ValueT type of the values
|
||||||
/// \tparam Values sequence values
|
/// \tparam Values sequence values
|
||||||
template<typename ValueT, ValueT...Values> struct const_sequence
|
template<typename ValueT, ValueT...Values> struct metasequence
|
||||||
{
|
{
|
||||||
/// \brief type of the sequence
|
/// \brief type of the metasequence
|
||||||
using value_type = ValueT;
|
using value_type = ValueT;
|
||||||
|
|
||||||
/// \brief self-referential type
|
/// \brief self-referential type
|
||||||
using type = const_sequence;
|
using type = metasequence;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief returns the number of elements
|
/// \brief returns the number of elements
|
||||||
@@ -110,22 +110,22 @@ template<typename ValueT, ValueT...Values> struct const_sequence
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::integer_sequence ============================================================================================
|
// fennec::integer_metasequence ============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief metaprogramming integral sequence
|
/// \brief metaprogramming integral metasequence
|
||||||
///
|
///
|
||||||
/// \details A `fennec::sequence` specialized integer types.
|
/// \details A `fennec::metasequence` specialized integer types.
|
||||||
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
|
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
|
||||||
/// \tparam Values sequence values
|
/// \tparam Values sequence values
|
||||||
template<typename IntT, IntT...Values> requires(is_integral_v<IntT>)
|
template<typename IntT, IntT...Values> requires(is_integral_v<IntT>)
|
||||||
struct const_integer_sequence : const_sequence<IntT, Values...>
|
struct integer_metasequence : metasequence<IntT, Values...>
|
||||||
{
|
{
|
||||||
/// \brief type of the sequence
|
/// \brief type of the sequence
|
||||||
using value_type = IntT;
|
using value_type = IntT;
|
||||||
|
|
||||||
/// \brief self-referential type
|
/// \brief self-referential type
|
||||||
using type = const_integer_sequence;
|
using type = integer_metasequence;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief returns the number of elements
|
/// \brief returns the number of elements
|
||||||
@@ -138,33 +138,33 @@ struct const_integer_sequence : const_sequence<IntT, Values...>
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief generate a fennec::integer_sequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
/// \brief generate a fennec::integer_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
|
/// \tparam IntT type of the values, must satisfy ```fennec::is_integral<T>```
|
||||||
/// \tparam N size of the sequence to generate
|
/// \tparam N size of the metasequence to generate
|
||||||
template<typename IntT, size_t N> struct make_integer_sequence;
|
template<typename IntT, size_t N> struct make_integer_metasequence;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```typename make_integer_sequence<T, N>::type```
|
/// \brief shorthand for ```typename make_integer_sequence<T, N>::type```
|
||||||
template<typename IntT, size_t N> using make_integer_sequence_t = typename make_integer_sequence<IntT, N>::type;
|
template<typename IntT, size_t N> using make_integer_metasequence_t = typename make_integer_metasequence<IntT, N>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::index_sequence ==============================================================================================
|
// fennec::index_metasequence ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief metaprogramming integral sequence
|
/// \brief metaprogramming integral metasequence
|
||||||
///
|
///
|
||||||
/// \details A `fennec::integer_sequence` specialized for sequences of `size_t` indices.
|
/// \details A `fennec::integer_metasequence` specialized for sequences of `size_t` indices.
|
||||||
/// \tparam Indices sequence values
|
/// \tparam Indices sequence values
|
||||||
template<size_t...Indices> struct const_index_sequence : const_integer_sequence<size_t, Indices...>
|
template<size_t...Indices> struct index_metasequence : integer_metasequence<size_t, Indices...>
|
||||||
{
|
{
|
||||||
/// \brief type of the sequence
|
/// \brief type of the sequence
|
||||||
using value_type = size_t;
|
using value_type = size_t;
|
||||||
|
|
||||||
/// \brief self-referential type
|
/// \brief self-referential type
|
||||||
using type = const_index_sequence;
|
using type = index_metasequence;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief returns the number of elements
|
/// \brief returns the number of elements
|
||||||
@@ -177,67 +177,67 @@ template<size_t...Indices> struct const_index_sequence : const_integer_sequence<
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief generate a fennec::index_sequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
/// \brief generate a fennec::index_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
|
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
|
||||||
/// \tparam N size of the sequence to generate
|
/// \tparam N size of the sequence to generate
|
||||||
template<size_t N> struct make_index_sequence;
|
template<size_t N> struct make_index_metasequence;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```typename make_index_sequence<N>::type```
|
/// \brief shorthand for ```typename make_index_metasequence<N>::type```
|
||||||
template<size_t N> using make_index_sequence_t = typename make_index_sequence<N>::type;
|
template<size_t N> using make_index_metasequence_t = typename make_index_metasequence<N>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::concat_sequence =============================================================================================
|
// fennec::concat_metasequence =============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief concatenate two sequences
|
/// \brief concatenate two metasequences
|
||||||
///
|
///
|
||||||
/// \details A tool for concatenating two `fennec::sequence` types.
|
/// \details A tool for concatenating two `fennec::metasequence` types.
|
||||||
/// \tparam SequenceT0 lhs
|
/// \tparam SequenceT0 lhs
|
||||||
/// \tparam SequenceT1 rhs
|
/// \tparam SequenceT1 rhs
|
||||||
template<typename SequenceT0, typename SequenceT1> struct concat_sequence;
|
template<typename SequenceT0, typename SequenceT1> struct concat_metasequence;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```typename concat_sequence<SequenceT0, SequenceT1>::type```
|
/// \brief shorthand for ```typename concat_metasequence<SequenceT0, SequenceT1>::type```
|
||||||
template<typename SequenceT0, typename SequenceT1> using concat_sequence_t
|
template<typename SequenceT0, typename SequenceT1> using concat_metasequence_t
|
||||||
= typename concat_sequence<SequenceT0, SequenceT1>::type;
|
= typename concat_metasequence<SequenceT0, SequenceT1>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Internal ============================================================================================================
|
// Internal ============================================================================================================
|
||||||
|
|
||||||
// Implementation for Generating an integer_sequence
|
// Implementation for Generating an integer_sequence
|
||||||
template<typename T, size_t N> struct make_integer_sequence : concat_sequence_t<make_integer_sequence_t<T, N / 2>, make_integer_sequence_t<T, N - N / 2>>{};
|
template<typename T, size_t N> struct make_integer_metasequence : concat_metasequence_t<make_integer_metasequence_t<T, N / 2>, make_integer_metasequence_t<T, N - N / 2>>{};
|
||||||
|
|
||||||
// Base Case of N=0
|
// Base Case of N=0
|
||||||
template<typename T> struct make_integer_sequence<T, 0> : const_integer_sequence<T> {};
|
template<typename T> struct make_integer_metasequence<T, 0> : integer_metasequence<T> {};
|
||||||
|
|
||||||
// Base Case of N=1
|
// Base Case of N=1
|
||||||
template<typename T> struct make_integer_sequence<T, 1> : const_integer_sequence<T, 0>{};
|
template<typename T> struct make_integer_metasequence<T, 1> : integer_metasequence<T, 0>{};
|
||||||
|
|
||||||
|
|
||||||
// Implementation for Generating an index_sequence
|
// Implementation for Generating an index_sequence
|
||||||
template<size_t N> struct make_index_sequence : concat_sequence_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>{};
|
template<size_t N> struct make_index_metasequence : concat_metasequence_t<make_index_metasequence_t<N / 2>, make_index_metasequence_t<N - N / 2>>{};
|
||||||
|
|
||||||
// Base Case of N=0
|
// Base Case of N=0
|
||||||
template<> struct make_index_sequence<0> : const_index_sequence<> {};
|
template<> struct make_index_metasequence<0> : index_metasequence<> {};
|
||||||
|
|
||||||
// Base Case of N=1
|
// Base Case of N=1
|
||||||
template<> struct make_index_sequence<1> : const_index_sequence<0>{};
|
template<> struct make_index_metasequence<1> : index_metasequence<0>{};
|
||||||
|
|
||||||
|
|
||||||
// Specialization for integer sequences
|
// Specialization for integer sequences
|
||||||
template<typename T, T...SequenceV0, T...SequenceV1>
|
template<typename T, T...SequenceV0, T...SequenceV1>
|
||||||
struct concat_sequence<const_integer_sequence<T, SequenceV0...>, const_integer_sequence<T, SequenceV1...>>
|
struct concat_metasequence<integer_metasequence<T, SequenceV0...>, integer_metasequence<T, SequenceV1...>>
|
||||||
: const_integer_sequence<T, SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
|
: integer_metasequence<T, SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
|
||||||
|
|
||||||
// Specialization for index sequences
|
// Specialization for index sequences
|
||||||
template<size_t...SequenceV0, size_t...SequenceV1>
|
template<size_t...SequenceV0, size_t...SequenceV1>
|
||||||
struct concat_sequence<const_index_sequence<SequenceV0...>, const_index_sequence<SequenceV1...>>
|
struct concat_metasequence<index_metasequence<SequenceV0...>, index_metasequence<SequenceV1...>>
|
||||||
: const_index_sequence<SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
|
: index_metasequence<SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
72
include/fennec/lang/ranges.h
Normal file
72
include/fennec/lang/ranges.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file ranges.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_LANGCPP_RANGES_H
|
||||||
|
#define FENNEC_LANGCPP_RANGES_H
|
||||||
|
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename ContainerT>
|
||||||
|
inline constexpr auto begin(ContainerT& c) noexcept(noexcept(c.begin())) -> decltype(c.begin()) {
|
||||||
|
return c.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ContainerT>
|
||||||
|
inline constexpr auto begin(const ContainerT& c) noexcept(noexcept(c.begin())) -> decltype(c.begin()) {
|
||||||
|
return c.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, size_t N>
|
||||||
|
inline constexpr T* begin(T (&arr)[N]) noexcept {
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename ContainerT>
|
||||||
|
inline constexpr auto end(ContainerT& c) noexcept(noexcept(c.end())) -> decltype(c.end()) {
|
||||||
|
return c.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ContainerT>
|
||||||
|
inline constexpr auto end(const ContainerT& c) noexcept(noexcept(c.end())) -> decltype(c.end()) {
|
||||||
|
return c.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, size_t N>
|
||||||
|
inline constexpr T* end(T (&arr)[N]) noexcept {
|
||||||
|
return arr + N;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_LANGCPP_RANGES_H
|
||||||
@@ -20,9 +20,13 @@
|
|||||||
#define FENNEC_LANG_STARTUP_H
|
#define FENNEC_LANG_STARTUP_H
|
||||||
|
|
||||||
// Helper for running a function before main()
|
// Helper for running a function before main()
|
||||||
#define STATIC_CONSTRUCTOR(f) \
|
#define FENNEC_PRIVATE_STATIC_CONSTRUCTOR(f) \
|
||||||
inline static void f(void); \
|
inline static void f(void); \
|
||||||
struct f##_t_ { inline f##_t_(void) { f(); } }; inline static f##_t_ f##_; \
|
struct f##_t_ { inline f##_t_(void) { f(); } }; inline static f##_t_ f##_; \
|
||||||
inline static void f(void)
|
inline static void f(void)
|
||||||
|
|
||||||
|
#define FENNEC_CLASS_STATIC_CONSTRUCTOR(f) \
|
||||||
|
struct f##_t_ { inline f##_t_(void) { f(); } }; inline static f##_t_ f##_; \
|
||||||
|
inline static void f(void)
|
||||||
|
|
||||||
#endif // FENNEC_LANG_STARTUP_H
|
#endif // FENNEC_LANG_STARTUP_H
|
||||||
@@ -51,6 +51,12 @@
|
|||||||
/// \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
|
/// \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydoc fennec::replace_first_element
|
/// \copydoc fennec::replace_first_element
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_unique "is_unique<TypesT...>::value"<br>
|
||||||
|
/// \ref fennec::is_unique_v "is_unique_v<TypesT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydoc fennec::is_unique
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
|
|
||||||
@@ -59,6 +65,12 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
template<typename...TypesT> struct type_sequence {};
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::first_element ===============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Get the first element of a template parameter pack
|
/// \brief Get the first element of a template parameter pack
|
||||||
/// \tparam TypesT the Parameter Pack
|
/// \tparam TypesT the Parameter Pack
|
||||||
@@ -69,8 +81,20 @@ template<typename...TypesT> struct first_element : detail::_first_element<TypesT
|
|||||||
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
|
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::nth_element =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Gets the type of the nth element of the type sequence `TypesT...`
|
||||||
|
/// \tparam n The index in the type sequence
|
||||||
|
/// \tparam TypesT The type sequence
|
||||||
template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};
|
template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};
|
||||||
|
|
||||||
|
template<size_t n, typename...TypesT> using nth_element_t = nth_element<n, TypesT...>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::replace_first_element =======================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
||||||
@@ -84,6 +108,99 @@ template<
|
|||||||
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
|
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
|
||||||
{ using type = ClassT<SubT, RestT...>; }; // Definition
|
{ using type = ClassT<SubT, RestT...>; }; // Definition
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::max_element_size ============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Gets the max value of the size of each type in the sequence, i.e. `max(sizeof(Ts)...)`
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> struct max_element_size : detail::_max_element_size<0, Ts...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `max_element_size<Ts...>::value`
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> constexpr size_t max_element_size_v = max_element_size<Ts...>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::find_element ================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Finds the index of `T` in `Ts`, if `T` is not found, results in `sizeof...(Ts)`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> struct find_element : detail::_find_element<0, T, Ts...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `find_element<T, Ts...>::value`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> constexpr size_t find_element_v = find_element<T, Ts...>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::search_element ==============================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Find the first element in `TypesT...` that satisfies `SearchT<T>`
|
||||||
|
/// \tparam SearchT A type that satisfies `template<typename>` and contains `static constexpr bool value;` to use for searching
|
||||||
|
/// \tparam TypesT The type sequence to search
|
||||||
|
template<template<typename> typename SearchT, typename...TypesT> struct search_element : detail::_search_element<SearchT, TypesT...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `search_element_t<T, Ts...>::type`
|
||||||
|
/// \tparam SearchT A type that satisfies `template<typename>` and contains `static constexpr bool value;` to use for searching
|
||||||
|
/// \tparam TypesT The type sequence to search
|
||||||
|
template<template<typename> typename SearchT, typename...TypesT> using search_element_t = search_element<SearchT, TypesT...>::type;
|
||||||
|
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename, typename, typename...> struct search_element_args;
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename SearchT, typename...TypesT, typename...ArgsT>
|
||||||
|
struct search_element_args<SearchT, type_sequence<ArgsT...>, TypesT...>
|
||||||
|
: detail::_search_element_args<SearchT, detail::_type_sequence<ArgsT...>, TypesT...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::contains_element ============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if the type sequence `Ts...` contains `T`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> struct contains_element : bool_constant<(is_same_v<T, Ts> or ...)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `contains_element_v<T, Ts...>::value`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> constexpr bool contains_element_v = contains_element<T, Ts...>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_unique ===================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if all types in a type sequence are unique
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> struct is_unique : false_type {};
|
||||||
|
|
||||||
|
// Single type case
|
||||||
|
template<typename T> struct is_unique<T> : true_type {};
|
||||||
|
|
||||||
|
// Recursion case
|
||||||
|
template<typename T, typename...Ts> requires(not is_same_v<T, Ts> && ...)
|
||||||
|
struct is_unique<T, Ts...> : is_unique<Ts...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_unique<Ts...>::value`
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> constexpr bool is_unique_v = is_unique<Ts...>::value;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,10 @@
|
|||||||
/// \code #include <fennec/lang/type_traits.h> \endcode
|
/// \code #include <fennec/lang/type_traits.h> \endcode
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits">
|
///
|
||||||
|
/// \section Primary Type Categories
|
||||||
|
///
|
||||||
|
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits_primary_categories">
|
||||||
/// <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>
|
||||||
@@ -50,6 +53,12 @@
|
|||||||
/// \copydetails fennec::is_void
|
/// \copydetails fennec::is_void
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_null_pointer "is_null_pointer<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_null_pointer_v "is_null_pointer_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_null_pointer
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_bool "is_bool<TypeT>::value"<br>
|
/// \ref fennec::is_bool "is_bool<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_bool_v "is_bool_v<TypeT>"
|
/// \ref fennec::is_bool_v "is_bool_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
@@ -62,6 +71,212 @@
|
|||||||
/// \copydetails fennec::is_integral
|
/// \copydetails fennec::is_integral
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_floating_point "is_floating_point<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_floating_point_v "is_floating_point_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_floating_point
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_array "is_array<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_array_v "is_array_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_array
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_enum "is_enum<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_enum_v "is_enum_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_enum
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_union "is_union<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_union_v "is_union_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_union
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_class "is_class<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_class_v "is_class_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_class
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_function "is_function<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_function_v "is_function_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_function
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_pointer "is_pointer<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_pointer_v "is_pointer_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_pointer
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_lvalue_reference "is_lvalue_reference<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_lvalue_reference_v "is_lvalue_reference_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_lvalue_reference
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_rvalue_reference "is_rvalue_reference<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_rvalue_reference_v "is_rvalue_reference_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_rvalue_reference
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_member_object_pointer "is_member_object_pointer<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_member_object_pointer_v "is_member_object_pointer_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_member_object_pointer
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_member_function_pointer "is_member_function_pointer<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_member_function_pointer_v "is_member_function_pointer_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_member_function_pointer
|
||||||
|
///
|
||||||
|
/// </table>
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \section Composite Type Categories
|
||||||
|
///
|
||||||
|
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits_composite_categories">
|
||||||
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
|
/// <th style="vertical-align: top">Description
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_fundamental "is_fundamental<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_fundamental_v "is_fundamental_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_fundamental
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_arithmetic "is_arithmetic<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_arithmetic_v "is_arithmetic_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_arithmetic
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_scalar "is_scalar<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_scalar_v "is_scalar_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_scalar
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_object "is_object<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_object_v "is_object_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_object
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_compound "is_compound<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_compound_v "is_compound_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_compound
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_reference "is_reference<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_reference_v "is_reference_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_reference
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_member_pointer "is_member_pointer<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_member_pointer_v "is_member_pointer_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_member_pointer
|
||||||
|
///
|
||||||
|
/// </table>
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \section Type Properties
|
||||||
|
///
|
||||||
|
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits_type_properties">
|
||||||
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
|
/// <th style="vertical-align: top">Description
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_const "is_const<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_const_v "is_const_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_const
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_volatile "is_volatile<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_volatile_v "is_volatile_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_volatile
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_trivial "is_trivial<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_trivial_v "is_trivial_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_trivial
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_trivially_copyable "is_trivially_copyable<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_copyable_v "is_trivially_copyable_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_trivially_copyable
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_standard_layout "is_standard_layout<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_standard_layout_v "is_standard_layout_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_standard_layout
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::has_unique_object_representations "has_unique_object_representations<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::has_unique_object_representations_v "has_unique_object_representations_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::has_unique_object_representations
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_empty "is_empty<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_empty_v "is_empty_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_empty
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_polymorphic "is_polymorphic<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_polymorphic_v "is_polymorphic_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_polymorphic
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_abstract "is_abstract<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_abstract_v "is_abstract_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_abstract
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_complete "is_complete<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_complete_v "is_complete_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_complete
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_final "is_final<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_final_v "is_final_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_final
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_aggregate "is_aggregate<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_aggregate_v "is_aggregate_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_aggregate
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_implicit_lifetime "is_implicit_lifetime<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_implicit_lifetime_v "is_implicit_lifetime_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_implicit_lifetime
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_signed "is_signed<TypeT>::value"<br>
|
/// \ref fennec::is_signed "is_signed<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_signed_v "is_signed_v<TypeT>"
|
/// \ref fennec::is_signed_v "is_signed_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
@@ -74,22 +289,32 @@
|
|||||||
/// \copydetails fennec::is_unsigned
|
/// \copydetails fennec::is_unsigned
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_floating_point "is_floating_point<TypeT>::value"<br>
|
/// \ref fennec::is_bounded_array "is_bounded_array<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_floating_point_v "is_floating_point_v<TypeT>"
|
/// \ref fennec::is_bounded_array_v "is_bounded_array_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::is_floating_point
|
/// \copydetails fennec::is_bounded_array
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_arithmetic "is_arithmetic<TypeT>::value"<br>
|
/// \ref fennec::is_unbounded_array "is_unbounded_array<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_arithmetic_v "is_arithmetic_v<TypeT>"
|
/// \ref fennec::is_unbounded_array_v "is_unbounded_array_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::is_arithmetic
|
/// \copydetails fennec::is_unbounded_array
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_same "is_same<TypeT>::value"<br>
|
/// \ref fennec::is_scoped_enum "is_scoped_enum<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_same_v "is_same_v<TypeT>"
|
/// \ref fennec::is_scoped_enum_v "is_scoped_enum_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::is_same
|
/// \copydetails fennec::is_scoped_enum
|
||||||
|
///
|
||||||
|
/// </table>
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \section Supported Operations
|
||||||
|
///
|
||||||
|
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits_supported_operations">
|
||||||
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
|
/// <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::is_convertible "is_convertible<TypeT0, TypeT1>::value"<br>
|
/// \ref fennec::is_convertible "is_convertible<TypeT0, TypeT1>::value"<br>
|
||||||
@@ -100,25 +325,115 @@
|
|||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_constructible "is_constructible<ClassT, ArgsT...>::value"<br>
|
/// \ref fennec::is_constructible "is_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
/// \ref fennec::is_constructible_v "is_constructible_v<ClassT, ArgsT...>"
|
/// \ref fennec::is_constructible_v "is_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_constructible "is_trivially_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_constructible_v "is_trivially_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_constructible "is_nothrow_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_constructible_v "is_nothrow_constructible_v<ClassT, ArgsT...>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydoc fennec::is_constructible
|
/// \copydetails fennec::is_constructible
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_default_constructible "is_default_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_default_constructible_v "is_default_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_default_constructible "is_trivially_default_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_default_constructible_v "is_trivially_default_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_default_constructible "is_nothrow_default_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_default_constructible_v "is_nothrow_default_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_default_constructible
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_copy_constructible "is_copy_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_copy_constructible_v "is_copy_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_copy_constructible "is_trivially_copy_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_copy_constructible_v "is_trivially_copy_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_copy_constructible "is_nothrow_copy_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_copy_constructible_v "is_nothrow_copy_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_copy_constructible
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_move_constructible "is_move_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_move_constructible_v "is_move_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_move_constructible "is_trivially_move_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_move_constructible_v "is_trivially_move_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_move_constructible "is_nothrow_move_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_move_constructible_v "is_nothrow_move_constructible_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_move_constructible
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_assignable "is_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_assignable_v "is_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_assignable "is_trivially_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_assignable_v "is_trivially_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_assignable "is_nothrow_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_assignable_v "is_nothrow_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_assignable
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_copy_assignable "is_copy_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_copy_assignable_v "is_copy_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_copy_assignable "is_trivially_copy_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_copy_assignable_v "is_trivially_copy_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_copy_assignable "is_nothrow_copy_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_copy_assignable_v "is_nothrow_copy_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_copy_assignable
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_move_assignable "is_move_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_move_assignable_v "is_move_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_move_assignable "is_trivially_move_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_move_assignable_v "is_trivially_move_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_move_assignable "is_nothrow_move_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_move_assignable_v "is_nothrow_move_assignable_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_move_assignable
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_destructible "is_destructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_destructible_v "is_destructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_trivially_destructible "is_trivially_destructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_trivially_destructible_v "is_trivially_destructible_v<ClassT, ArgsT...>"
|
||||||
|
/// \ref fennec::is_nothrow_destructible "is_nothrow_destructible<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::is_nothrow_destructible_v "is_nothrow_destructible_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_destructible
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::has_virtual_destructor "has_virtual_destructor<ClassT, ArgsT...>::value"<br>
|
||||||
|
/// \ref fennec::has_virtual_destructor_v "has_virtual_destructor_v<ClassT, ArgsT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::has_virtual_destructor
|
||||||
|
///
|
||||||
|
/// </table>
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \section Type Relationships
|
||||||
|
///
|
||||||
|
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_traits_type_relationships">
|
||||||
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
|
/// <th style="vertical-align: top">Description
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_same "is_same<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_same_v "is_same_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_same
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
|
|
||||||
|
#include <fennec/lang/intrinsics.h>
|
||||||
#include <fennec/lang/type_transforms.h>
|
#include <fennec/lang/type_transforms.h>
|
||||||
#include <fennec/lang/detail/_type_traits.h>
|
#include <fennec/lang/detail/_type_traits.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
// fennec::declval =====================================================================================================
|
|
||||||
|
|
||||||
template<typename T> auto declval() noexcept -> decltype(detail::_declval<T>(0)) {
|
|
||||||
static_assert(detail::_declval_protector<T>{}, "declval must not be used");
|
|
||||||
return detail::_declval<T>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr inline bool is_constant_evaluated() noexcept {
|
constexpr inline bool is_constant_evaluated() noexcept {
|
||||||
if consteval {
|
if consteval {
|
||||||
return true;
|
return true;
|
||||||
@@ -131,7 +446,7 @@ constexpr inline bool is_constant_evaluated() noexcept {
|
|||||||
// fennec::is_void =====================================================================================================
|
// fennec::is_void =====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of type void
|
/// \brief Check if \p T is of type void
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -139,33 +454,16 @@ template<typename T> struct is_void
|
|||||||
: detail::_is_void<remove_cvr_t<T>>{};
|
: detail::_is_void<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_void<T>::value```
|
/// \brief Shorthand for ```is_void<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_bool =====================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief check if \p T is of type bool
|
|
||||||
///
|
|
||||||
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_bool
|
|
||||||
: detail::_is_bool<remove_cvr_t<T>>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief shorthand for ```is_bool<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_null_pointer =============================================================================================
|
// fennec::is_null_pointer =============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of type nullptr_t
|
/// \brief Check if \p T is of type nullptr_t
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -173,7 +471,7 @@ template<typename T> struct is_null_pointer
|
|||||||
: detail::_is_null_pointer<remove_cvr_t<T>>{};
|
: detail::_is_null_pointer<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_null_pointer<T>::value```
|
/// \brief Shorthand for ```is_null_pointer<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
|
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
|
||||||
|
|
||||||
@@ -181,10 +479,10 @@ template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::va
|
|||||||
|
|
||||||
// fennec::is_array ====================================================================================================
|
// fennec::is_array ====================================================================================================
|
||||||
|
|
||||||
#if FENNEC_HAS_BUILTIN_IS_ARRAY
|
#ifdef FENNEC_BUILTIN_IS_ARRAY
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an array type
|
/// \brief Check if \p T is of an array type
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_array
|
template<typename T> struct is_array
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_ARRAY(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_ARRAY(T)> {};
|
||||||
@@ -192,7 +490,7 @@ template<typename T> struct is_array
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an array type
|
/// \brief Check if \p T is of an array type
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_array
|
template<typename T> struct is_array
|
||||||
: false_type {};
|
: false_type {};
|
||||||
@@ -208,29 +506,97 @@ template<typename T> struct is_array<T[]>
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_array<T>::value```
|
/// \brief Shorthand for ```is_array<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
|
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_enum ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an enum
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_enum
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_ENUM(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr size_t is_enum_v = is_enum<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_union ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a union
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_union
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_UNION(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr size_t is_union_v = is_union<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_class ====================================================================================================
|
// fennec::is_class ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is a class
|
/// \brief Check if \p T is a class
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_class
|
template<typename T> struct is_class
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CLASS(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CLASS(T)> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is a class
|
/// \brief Check if \p T is a class
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Integral Types ======================================================================================================
|
// fennec::is_function ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an integral
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_function
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_FUNCTION(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr size_t is_function_v = is_function<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Integral Types ======================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_bool =====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of type bool
|
||||||
|
///
|
||||||
|
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_bool
|
||||||
|
: detail::_is_bool<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_bool<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_integral =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of an integral
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -238,13 +604,17 @@ template<typename T> struct is_integral
|
|||||||
: detail::_is_integral<remove_cvr_t<T>> {};
|
: detail::_is_integral<remove_cvr_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_integral<T>::value```
|
/// \brief Shorthand for ```is_integral<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_signed =================================================================================================
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of a signed integral
|
/// \brief Check if \p T is of a signed integral
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -252,13 +622,17 @@ template<typename T> struct is_signed
|
|||||||
: detail::_is_signed<remove_cvr_t<T>> {};
|
: detail::_is_signed<remove_cvr_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_signed<T>::value```
|
/// \brief Shorthand for ```is_signed<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_unsigned =================================================================================================
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an unsigned integral
|
/// \brief Check if \p T is of an unsigned integral
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -266,7 +640,7 @@ template<typename T> struct is_unsigned
|
|||||||
: detail::_is_unsigned<remove_cvr_t<T>> {};
|
: detail::_is_unsigned<remove_cvr_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_unsigned<T>::value```
|
/// \brief Shorthand for ```is_unsigned<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
||||||
|
|
||||||
@@ -275,15 +649,15 @@ template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
|||||||
// Floating Point Types ================================================================================================
|
// Floating Point Types ================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of a floating point type
|
/// \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`.
|
/// \details Stores a boolean value in `is_floating_point::value`, representing whether the provided type is of a base floating point type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_floating_point
|
template<typename T> struct is_floating_point
|
||||||
: detail::_is_floating_point<remove_cvr_t<T>>{};
|
: detail::_is_floating_point<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_floating_point<T>::value```
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
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> {};
|
||||||
|
|
||||||
@@ -291,24 +665,69 @@ template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T>
|
|||||||
// Pointer Types =======================================================================================================
|
// Pointer Types =======================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of a floating point type
|
/// \brief Check if \p T is of a pointer type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
/// \details Stores a boolean value in `is_pointer::value`, representing whether the provided type is of a base pointer type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_pointer
|
template<typename T> struct is_pointer
|
||||||
: detail::_is_pointer<remove_cvr_t<T>>{};
|
: detail::_is_pointer<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_floating_point<T>::value```
|
/// \brief Shorthand for ```is_pointer<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
// Reference 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_reference
|
||||||
|
: detail::_is_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \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_lvalue_reference
|
||||||
|
: detail::_is_lvalue_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \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_rvalue_reference
|
||||||
|
: detail::_is_rvalue_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Arithmetic Types ====================================================================================================
|
// Arithmetic Types ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is an arithmetic type
|
/// \brief Check if \p T is an arithmetic type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -316,21 +735,38 @@ template<typename T> struct is_arithmetic
|
|||||||
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_arithmetic<T>::value```
|
/// \brief Shorthand for ```is_arithmetic<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Arithmetic Types ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an arithmetic type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_scalar
|
||||||
|
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_scalar<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_fundamental ==============================================================================================
|
// fennec::is_fundamental ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
/// \brief Check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_fundamental
|
template<typename T> struct is_fundamental
|
||||||
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
|
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_fundamental<T>::value```
|
/// \brief Shorthand for ```is_fundamental<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
||||||
|
|
||||||
@@ -338,7 +774,7 @@ template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::valu
|
|||||||
// fennec::is_same =====================================================================================================
|
// fennec::is_same =====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if the two types are identical
|
/// \brief Check if the two types are identical
|
||||||
///
|
///
|
||||||
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
|
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
|
||||||
/// \tparam T0 first type to check
|
/// \tparam T0 first type to check
|
||||||
@@ -349,14 +785,90 @@ template<typename T0, typename T1> struct is_same : false_type {};
|
|||||||
template<typename T> struct is_same<T, T> : true_type {};
|
template<typename T> struct is_same<T, T> : true_type {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_same<T0, T1>::value```
|
/// \brief Shorthand for ```is_same<T0, T1>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T0 first type to check
|
||||||
|
/// \tparam T1 second type to check
|
||||||
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_base_of =====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if `Derived` has a base type of `Base`
|
||||||
|
///
|
||||||
|
/// \details Checks if `Base` is a base type of `Derived` and stores it in `is_base_of::value`
|
||||||
|
/// \tparam Base base type to check
|
||||||
|
/// \tparam Derived derived type to check
|
||||||
|
template<typename Base, typename Derived> struct is_base_of : bool_constant<
|
||||||
|
is_class_v<Base> and is_class_v<Derived> and decltype(detail::_is_base_of<Base, Derived>(0))::value
|
||||||
|
> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_base_of<T0, T1>::value```
|
||||||
|
/// \tparam Base base type to check
|
||||||
|
/// \tparam Derived derived type to check
|
||||||
|
template<typename Base, typename Derived> constexpr bool_t is_base_of_v = is_base_of<Base, Derived> {};
|
||||||
|
|
||||||
|
// fennec::is_complete ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is complete
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_complete<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
||||||
|
|
||||||
|
// fennec::is_iterable ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is iterable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_iterable<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
||||||
|
|
||||||
|
// fennec::is_indexable ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is indexable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_indexable<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
||||||
|
|
||||||
|
// fennec::is_mappable ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is mappable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_mappable<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_mappable_v = is_mappable<T>{};
|
||||||
|
|
||||||
// fennec::is_convertible ==============================================================================================
|
// fennec::is_convertible ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if type `T0` can be converted `T1`
|
/// \brief Check if type `T0` can be converted `T1`
|
||||||
///
|
///
|
||||||
/// \details Checks if `TypeT0`
|
/// \details Checks if `TypeT0`
|
||||||
/// \tparam FromT First type
|
/// \tparam FromT First type
|
||||||
@@ -365,7 +877,7 @@ template<typename FromT, typename ToT> struct is_convertible
|
|||||||
: bool_constant<FENNEC_BUILTIN_IS_CONVERTIBLE(FromT, ToT)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONVERTIBLE(FromT, ToT)> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `can_convert<TypeT0, TypeT1>::value`
|
/// \brief Shorthand for `can_convert<TypeT0, TypeT1>::value`
|
||||||
/// \param FromT First type
|
/// \param FromT First type
|
||||||
/// \param ToT Second type
|
/// \param ToT Second type
|
||||||
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>{};
|
||||||
@@ -387,6 +899,18 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \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>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is default constructible
|
/// \brief Check if `ClassT` is default constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
@@ -395,7 +919,7 @@ template<typename ClassT> struct is_default_constructible
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
|
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
|
||||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -422,19 +946,19 @@ template<typename ClassT> struct is_move_constructible
|
|||||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
|
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_destructible ===================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially constructible
|
/// \brief Check if `ClassT` is destructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_constructible
|
template<typename ClassT> struct is_destructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
|
: detail::_is_destructible<ClassT>::type {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for `is_trivially_constructible<ClassT, ArgsT...>::value`
|
/// \brief Shorthand for `is_destructible<ClassT, ArgsT...>::value`
|
||||||
template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_trivially_constructible<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_destructible_v = is_destructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_trivially_destructible ===================================================================================
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially destructible
|
/// \brief Check if `ClassT` is trivially destructible
|
||||||
@@ -447,6 +971,18 @@ template<typename ClassT> struct is_trivially_destructible
|
|||||||
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if `ClassT` is nothrow destructible
|
||||||
|
/// \tparam ClassT The class type to test
|
||||||
|
template<typename ClassT> struct is_nothrow_destructible
|
||||||
|
: detail::_is_nothrow_destructible<ClassT>::type {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_nothrow_destructible<ClassT, ArgsT...>::value`
|
||||||
|
template<typename ClassT> constexpr bool_t is_nothrow_destructible_v = is_nothrow_destructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_assignable ===============================================================================================
|
// fennec::is_assignable ===============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -487,7 +1023,6 @@ template<typename ClassT> struct is_move_assignable
|
|||||||
/// \brief Shorthand for `is_move_assignable<ClassT>::value`
|
/// \brief Shorthand for `is_move_assignable<ClassT>::value`
|
||||||
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +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/conditional_types.h>
|
||||||
#include <fennec/lang/type_identity.h>
|
#include <fennec/lang/type_identity.h>
|
||||||
|
#include <fennec/lang/detail/_type_traits.h>
|
||||||
#include <fennec/lang/detail/_type_transforms.h>
|
#include <fennec/lang/detail/_type_transforms.h>
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -154,6 +156,20 @@ template<typename T> struct remove_pointer<T*> : type_identity<T> {};
|
|||||||
template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
|
template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief removes all pointer levels from \p T
|
||||||
|
///
|
||||||
|
/// \details removes all pointers from the provided type such that `T*`, `T**`, etc. becomes `T`
|
||||||
|
/// \tparam T Resultant Type
|
||||||
|
template<typename T> struct strip_pointers : conditional_t<
|
||||||
|
detail::_is_pointer<T>::value,
|
||||||
|
strip_pointers<remove_pointer_t<T>>,
|
||||||
|
type_identity<T>
|
||||||
|
> {};
|
||||||
|
|
||||||
|
template<typename T> using strip_pointers_t = strip_pointers<T>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Reference Conversions ===============================================================================================
|
// Reference Conversions ===============================================================================================
|
||||||
|
|
||||||
@@ -347,6 +363,20 @@ template<typename T> struct remove_cvr : type_identity<remove_cv_t<remove_refere
|
|||||||
/// \brief shorthand for `typename remove_cvr<T>::type`
|
/// \brief shorthand for `typename remove_cvr<T>::type`
|
||||||
template<typename T> using remove_cvr_t = typename remove_cvr<T>::type;
|
template<typename T> using remove_cvr_t = typename remove_cvr<T>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief removes references and pointers as well as the const and volatile qualifiers from the provided type \p T
|
||||||
|
///
|
||||||
|
/// \details removes const and volatile from the provided type such that
|
||||||
|
/// \tparam T Reference Type
|
||||||
|
template<typename T> struct remove_cvrp : type_identity<remove_cv_t<remove_reference_t<strip_pointers_t<T>>>> {};
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief shorthand for `typename remove_cvrp_t<T>::type`
|
||||||
|
template<typename T> using remove_cvrp_t = typename remove_cvrp<T>::type;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANG_TYPE_TRANSFORMS_H
|
#endif // FENNEC_LANG_TYPE_TRANSFORMS_H
|
||||||
|
|||||||
@@ -203,8 +203,6 @@
|
|||||||
|
|
||||||
#include <fennec/lang/detail/_int.h>
|
#include <fennec/lang/detail/_int.h>
|
||||||
|
|
||||||
#include <fennec/lang/conditional_types.h>
|
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
// Basic Types =========================================================================================================
|
// Basic Types =========================================================================================================
|
||||||
@@ -215,6 +213,8 @@ namespace fennec
|
|||||||
|
|
||||||
using bool_t = bool; ///< \brief A conditional type
|
using bool_t = bool; ///< \brief A conditional type
|
||||||
|
|
||||||
|
using byte_t = unsigned char; ///< \brief A type capable of holding a single byte
|
||||||
|
|
||||||
using char_t = char; ///< \brief A type capable of holding an ascii value
|
using char_t = char; ///< \brief A type capable of holding an ascii value
|
||||||
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer
|
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer
|
||||||
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer
|
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer
|
||||||
|
|||||||
@@ -123,9 +123,18 @@ constexpr void swap(T& x, T& y) noexcept {
|
|||||||
/// \param x first value
|
/// \param x first value
|
||||||
/// \param y second value
|
/// \param y second value
|
||||||
template<typename T> constexpr void swap(T& x, T& y) noexcept {
|
template<typename T> constexpr void swap(T& x, T& y) noexcept {
|
||||||
|
#if FENNEC_COMPILER_GCC
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||||
|
#endif
|
||||||
|
|
||||||
T a = fennec::move(x);
|
T a = fennec::move(x);
|
||||||
x = fennec::move(y);
|
x = fennec::move(y);
|
||||||
y = fennec::move(a);
|
y = fennec::move(a);
|
||||||
|
|
||||||
|
#if FENNEC_COMPILER_GCC
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,81 +44,81 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section section_sign_functions Sign
|
/// \section fennec_math_common_section_sign_functions Sign Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_sign_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_sign_functions">
|
||||||
/// <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::abs(fennec::genType) "genIType abs(genIType x)" <br>
|
/// \ref fennec::abs "genIType abs(genIType x)" <br>
|
||||||
/// \ref fennec::abs(fennec::genType) "genFType abs(genFType x)" <br>
|
/// \ref fennec::abs "genFType abs(genFType x)" <br>
|
||||||
/// \ref fennec::abs(fennec::genType) "genDType abs(genDType x)"
|
/// \ref fennec::abs "genDType abs(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::abs(fennec::genType)
|
/// \copydetails fennec::abs
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::sign(fennec::genType) "genIType sign(genIType x)" <br>
|
/// \ref fennec::sign "genIType sign(genIType x)" <br>
|
||||||
/// \ref fennec::sign(fennec::genType) "genFType sign(genFType x)" <br>
|
/// \ref fennec::sign "genFType sign(genFType x)" <br>
|
||||||
/// \ref fennec::sign(fennec::genType) "genDType sign(genDType x)"
|
/// \ref fennec::sign "genDType sign(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::sign(fennec::genType)
|
/// \copydetails fennec::sign
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section section_rounding_functions Rounding
|
/// \section fennec_math_common_section_rounding_functions Rounding Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_rounding_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_rounding_functions">
|
||||||
/// <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::floor(fennec::genType) "genFType floor(genFType x)" <br>
|
/// \ref fennec::floor "genFType floor(genFType x)" <br>
|
||||||
/// \ref fennec::floor(fennec::genType) "genDType floor(genDType x)"
|
/// \ref fennec::floor "genDType floor(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::floor(fennec::genType)
|
/// \copydetails fennec::floor
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::ceil(fennec::genType) "genFType ceil(genFType x)" <br>
|
/// \ref fennec::ceil "genFType ceil(genFType x)" <br>
|
||||||
/// \ref fennec::ceil(fennec::genType) "genDType ceil(genDType x)"
|
/// \ref fennec::ceil "genDType ceil(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::ceil(fennec::genType)
|
/// \copydetails fennec::ceil
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::round(fennec::genType) "genFType round(genFType x)" <br>
|
/// \ref fennec::round "genFType round(genFType x)" <br>
|
||||||
/// \ref fennec::round(fennec::genType) "genDType round(genDType x)"
|
/// \ref fennec::round "genDType round(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::round(fennec::genType)
|
/// \copydetails fennec::round
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::roundEven(fennec::genType) "genFType roundEven(genFType x)" <br>
|
/// \ref fennec::roundEven "genFType roundEven(genFType x)" <br>
|
||||||
/// \ref fennec::roundEven(fennec::genType) "genDType roundEven(genDType x)"
|
/// \ref fennec::roundEven "genDType roundEven(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::roundEven(fennec::genType)
|
/// \copydetails fennec::roundEven
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::trunc(fennec::genType) "genFType trunc(genFType x)" <br>
|
/// \ref fennec::trunc "genFType trunc(genFType x)" <br>
|
||||||
/// \ref fennec::trunc(fennec::genType) "genDType trunc(genDType x)"
|
/// \ref fennec::trunc "genDType trunc(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::trunc(fennec::genType)
|
/// \copydetails fennec::trunc
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section section_decimal_functions Decimal-Point
|
/// \section fennec_math_common_section_decimal_functions Decimal-Point Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_decimal_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_decimal_functions">
|
||||||
/// <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::fract(fennec::genType) "genFType fract(genFType x)" <br>
|
/// \ref fennec::fract "genFType fract(genFType x)" <br>
|
||||||
/// \ref fennec::fract(fennec::genType) "genDType fract(genDType x)"
|
/// \ref fennec::fract "genDType fract(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::fract(fennec::genType)
|
/// \copydetails fennec::fract
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::mod "genFType mod(genFType x, float y)" <br>
|
/// \ref fennec::mod "genFType mod(genFType x, float y)" <br>
|
||||||
@@ -129,59 +129,59 @@
|
|||||||
/// \copydetails fennec::mod
|
/// \copydetails fennec::mod
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::modf(fennec::genType, fennec::genType&) "genFType modf(genFType x, out genFType i)" <br>
|
/// \ref fennec::modf "genFType modf(genFType x, out genFType i)" <br>
|
||||||
/// \ref fennec::modf(fennec::genType, fennec::genType&) "genDType modf(genDType x, out genDType i)"
|
/// \ref fennec::modf "genDType modf(genDType x, out genDType i)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::modf(fennec::genType, fennec::genType&)
|
/// \copydetails fennec::modf
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::isnan(fennec::genType) "genBType isnan(genFType x)" <br>
|
/// \ref fennec::isnan "genBType isnan(genFType x)" <br>
|
||||||
/// \ref fennec::isnan(fennec::genType) "genBType isnan(genDType x)"
|
/// \ref fennec::isnan "genBType isnan(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::isnan(fennec::genType)
|
/// \copydetails fennec::isnan
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::isinf(fennec::genType) "genBType isinf(genFType x)" <br>
|
/// \ref fennec::isinf "genBType isinf(genFType x)" <br>
|
||||||
/// \ref fennec::isinf(fennec::genType) "genBType isinf(genDType x)"
|
/// \ref fennec::isinf "genBType isinf(genDType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::isinf(fennec::genType)
|
/// \copydetails fennec::isinf
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::frexp(fennec::genType, fennec::genIType&) "genFType frexp(genFType x, out genIType exp)" <br>
|
/// \ref fennec::frexp "genFType frexp(genFType x, out genIType exp)" <br>
|
||||||
/// \ref fennec::frexp(fennec::genType, fennec::genIType&) "genDType frexp(genDType x, out genIType exp)"
|
/// \ref fennec::frexp "genDType frexp(genDType x, out genIType exp)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::frexp(fennec::genType, fennec::genIType&)
|
/// \copydetails fennec::frexp
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::ldexp(fennec::genType, fennec::genIType) "genFType ldexp(genFType x, genIType exp)" <br>
|
/// \ref fennec::ldexp "genFType ldexp(genFType x, genIType exp)" <br>
|
||||||
/// \ref fennec::ldexp(fennec::genType, fennec::genIType) "genDType ldexp(genDType x, genIType exp)"
|
/// \ref fennec::ldexp "genDType ldexp(genDType x, genIType exp)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::ldexp(fennec::genType, fennec::genIType)
|
/// \copydetails fennec::ldexp
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section section_bit_conversion_functions Bit Conversion
|
/// \section fennec_math_common_section_bit_functions Bit Conversion
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_bit_conversions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_bit_conversions">
|
||||||
/// <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::floatBitsToInt(fennec::genType) "genIType floatBitsToInt(genType value)" <br>
|
/// \ref fennec::floatBitsToInt "genIType floatBitsToInt(genType value)" <br>
|
||||||
/// \ref fennec::floatBitsToUint(fennec::genType) "genUType floatBitsToUint(genType value)"
|
/// \ref fennec::floatBitsToUint "genUType floatBitsToUint(genType value)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::floatBitsToUint(fennec::genType)
|
/// \copydetails fennec::floatBitsToUint
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::intBitsToFloat(fennec::genIType) "genFType intBitsToFloat(genIType value)" <br>
|
/// \ref fennec::intBitsToFloat "genFType intBitsToFloat(genIType value)" <br>
|
||||||
/// \ref fennec::uintBitsToFloat(fennec::genUType) "genFType uintBitsToFloat(genUType value)"
|
/// \ref fennec::uintBitsToFloat "genFType uintBitsToFloat(genUType value)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::uintBitsToFloat(fennec::genType)
|
/// \copydetails fennec::uintBitsToFloat
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section section_comparison_functions Comparison
|
/// \section fennec_math_common_section_comparison_functions Comparison Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_comparison_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_common_comparison_functions">
|
||||||
/// <tr><th style="vertical-align: top">Syntax
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section section_curve_functions Curves
|
/// \section fennec_math_common_section_curve_functions Curve Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_curve_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_curve_functions">
|
||||||
/// <tr><th style="vertical-align: top">Syntax
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
@@ -256,11 +256,11 @@
|
|||||||
/// \copydetails fennec::mix
|
/// \copydetails fennec::mix
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::mix(fennec::genBType, fennec::genBType, fennec::genBType) "mix(genBType x, genBType y, genBType a)" <br>
|
/// \ref fennec::mix "mix(genBType x, genBType y, genBType a)" <br>
|
||||||
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genIType x, genIType y, genBType a)" <br>
|
/// \ref fennec::mix "mix(genIType x, genIType y, genBType a)" <br>
|
||||||
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genUType x, genUType y, genBType a)" <br>
|
/// \ref fennec::mix "mix(genUType x, genUType y, genBType a)" <br>
|
||||||
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genFType x, genFType y, genBType a)" <br>
|
/// \ref fennec::mix "mix(genFType x, genFType y, genBType a)" <br>
|
||||||
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genDType x, genDType y, genBType a)"
|
/// \ref fennec::mix "mix(genDType x, genDType y, genBType a)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::mix
|
/// \copydetails fennec::mix
|
||||||
///
|
///
|
||||||
@@ -308,14 +308,6 @@ constexpr genType sign(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> sign(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::sign(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Absolute Value ======================================================================================================
|
// Absolute Value ======================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -331,14 +323,6 @@ constexpr genType abs(genType x) {
|
|||||||
return x * fennec::sign(x);
|
return x * fennec::sign(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> abs(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::abs(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -366,14 +350,6 @@ constexpr genType floor(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> floor(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::floor(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Ceil ================================================================================================================
|
// Ceil ================================================================================================================
|
||||||
|
|
||||||
@@ -391,14 +367,6 @@ constexpr genType ceil(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> ceil(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::ceil(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Round ===============================================================================================================
|
// Round ===============================================================================================================
|
||||||
|
|
||||||
@@ -416,14 +384,6 @@ template<typename genType> constexpr genType round(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> round(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::round(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Trunc ===============================================================================================================
|
// Trunc ===============================================================================================================
|
||||||
|
|
||||||
@@ -441,14 +401,6 @@ constexpr genType trunc(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> trunc(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::trunc(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Round Even ==========================================================================================================
|
// Round Even ==========================================================================================================
|
||||||
|
|
||||||
@@ -486,13 +438,6 @@ constexpr genType roundEven(genType x) {
|
|||||||
//return i + static_cast<genType>(up);
|
//return i + static_cast<genType>(up);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::roundEven(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -519,14 +464,6 @@ constexpr genType fract(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> fract(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::fract(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mod =================================================================================================================
|
// Mod =================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -544,19 +481,6 @@ constexpr genType mod(genType x, genType y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, genType y) {
|
|
||||||
return x - y * fennec::floor(x / y);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector<genType, i...>& y) {
|
|
||||||
return x - y * fennec::floor(x / y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ModF ================================================================================================================
|
// ModF ================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -574,14 +498,6 @@ constexpr genType modf(genType x, genType& i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genType, i...>& I) {
|
|
||||||
I = fennec::floor(x); return fennec::fract(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Is NaN ==============================================================================================================
|
// Is NaN ==============================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -603,14 +519,6 @@ constexpr genBType isnan(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
|
|
||||||
constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x) {
|
|
||||||
return vector<genBType, i...>(fennec::isnan(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Is Inf ==============================================================================================================
|
// Is Inf ==============================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -627,19 +535,11 @@ constexpr genBType isinf(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
|
|
||||||
constexpr vector<genBType, i...> isinf(const vector<genType, i...>& x) {
|
|
||||||
return vector<genBType, i...>(fennec::isinf(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Bit Conversion ======================================================================================================
|
// Bit Conversion ======================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \copydetails fennec::floatBitsToUint(fennec::genFType)
|
/// \copydetails fennec::floatBitsToUint
|
||||||
template<typename genType, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
template<typename genType, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
||||||
constexpr genIType floatBitsToInt(genType x) {
|
constexpr genIType floatBitsToInt(genType x) {
|
||||||
return fennec::bit_cast<genIType>(x);
|
return fennec::bit_cast<genIType>(x);
|
||||||
@@ -669,7 +569,7 @@ constexpr genUType floatBitsToUint(genType x) {
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \copydetails fennec::uintBitsToFloat(fennec::genUType)
|
/// \copydetails fennec::uintBitsToFloat
|
||||||
template<typename genType = float_t, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
template<typename genType = float_t, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
||||||
constexpr genType intBitsToFloat(genIType x) {
|
constexpr genType intBitsToFloat(genIType x) {
|
||||||
return fennec::bit_cast<genType>(x);
|
return fennec::bit_cast<genType>(x);
|
||||||
@@ -696,29 +596,6 @@ constexpr genType uintBitsToFloat(genUType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
|
||||||
constexpr vector<genIType, i...> floatBitsToInt(const vector<genType, i...>& x) {
|
|
||||||
return vector<genIType, i...>(fennec::bit_cast<genIType>(x[i])...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
|
|
||||||
constexpr vector<genUType, i...> floatBitsToUint(const vector<genType, i...>& x) {
|
|
||||||
return vector<genUType, i...>(fennec::bit_cast<genUType>(x[i])...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
|
||||||
constexpr vector<genType, i...> intBitsToFloat(const vector<genIType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
|
|
||||||
constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fma =================================================================================================================
|
// fma =================================================================================================================
|
||||||
|
|
||||||
@@ -738,14 +615,6 @@ constexpr genType fma(genType a, genType b, genType c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> fma(const vector<genType, i...>& a, const vector<genType, i...>& b, const vector<genType, i...>& c) {
|
|
||||||
return vector<genType, i...>(fennec::fma(a[i], b[i], c[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// frexp ===============================================================================================================
|
// frexp ===============================================================================================================
|
||||||
|
|
||||||
@@ -769,14 +638,6 @@ constexpr genType frexp(genType x, genIType& exp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
|
|
||||||
constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<genIType, i...>& exp) {
|
|
||||||
return vector<genType, i...>(fennec::frexp(x[i], exp[i])...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ldexp ===============================================================================================================
|
// ldexp ===============================================================================================================
|
||||||
|
|
||||||
@@ -802,14 +663,6 @@ constexpr genType ldexp(genType x, genIType exp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
|
|
||||||
constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vector<genIType, i...>& exp) {
|
|
||||||
return vector<genType, i...>(fennec::ldexp(x[i], exp[i])...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -837,24 +690,6 @@ constexpr genType min(genType x, genType y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> min(genType x, const vector<genType, i...>& y) {
|
|
||||||
return vector<genType, i...>(fennec::min(x, y[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> min(const vector<genType, i...>& x, genType y) {
|
|
||||||
return vector<genType, i...>(fennec::min(x[i], y) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> min(const vector<genType, i...>& x, const vector<genType, i...>& y) {
|
|
||||||
return vector<genType, i...>(fennec::min(x[i], y[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Max =================================================================================================================
|
// Max =================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -872,24 +707,6 @@ constexpr genType max(genType x, genType y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> max(genType x, const vector<genType, i...>& y) {
|
|
||||||
return vector<genType, i...>(fennec::max(x, y[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> max(const vector<genType, i...>& x, genType y) {
|
|
||||||
return vector<genType, i...>(fennec::max(x[i], y) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> max(const vector<genType, i...>& x, const vector<genType, i...>& y) {
|
|
||||||
return vector<genType, i...>(fennec::max(x[i], y[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Clamp ===============================================================================================================
|
// Clamp ===============================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -908,19 +725,6 @@ constexpr genType clamp(genType x, genType minVal, genType maxVal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, genType minVal, genType maxVal) {
|
|
||||||
return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal), maxVal)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, const vector<genType, i...>& minVal, const vector<genType, i...>& maxVal) {
|
|
||||||
return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal[i]), maxVal[i])...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -948,19 +752,6 @@ constexpr genType step(genType edge, genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
|
||||||
constexpr vector<genType, i...> step(genType edge, const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::step(edge, x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
|
||||||
constexpr vector<genType, i...> step(const vector<genType, i...>& edge, const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::step(edge[i], x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Smoothstep ==========================================================================================================
|
// Smoothstep ==========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -989,19 +780,6 @@ constexpr genType smoothstep(genType edge0, genType edge1, genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
|
||||||
constexpr vector<genType, i...> smoothstep(genType edge0, genType edge1, const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::smoothstep(edge0, edge1, x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
|
||||||
constexpr vector<genType, i...> smoothstep(const vector<genType, i...>& edge0, const vector<genType, i...>& edge1, const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::smoothstep(edge0[i], edge1[i], x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mix =================================================================================================================
|
// Mix =================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -1022,18 +800,6 @@ constexpr genType mix(genType x, genType y, genType a) {
|
|||||||
return x * (genType(1.0) - a) + y * a;
|
return x * (genType(1.0) - a) + y * a;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
|
||||||
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genType a) {
|
|
||||||
return x * (genType(1.0) - a) + y * a;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
|
||||||
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, const vector<genType, i...>& a) {
|
|
||||||
return x * (genType(1.0) - a) + y * a;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mix (Bool) ==========================================================================================================
|
// Mix (Bool) ==========================================================================================================
|
||||||
|
|
||||||
@@ -1058,7 +824,177 @@ constexpr genType mix(genType x, genType y, genBType a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
// Internal ============================================================================================================
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> sign(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::sign(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> abs(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::abs(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> floor(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::floor(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> ceil(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::ceil(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> round(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::round(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> trunc(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::trunc(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::roundEven(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> fract(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::fract(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, genType y) {
|
||||||
|
return x - y * fennec::floor(x / y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector<genType, i...>& y) {
|
||||||
|
return x - y * fennec::floor(x / y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genType, i...>& I) {
|
||||||
|
I = fennec::floor(x); return fennec::fract(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
|
||||||
|
constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x) {
|
||||||
|
return vector<genBType, i...>(fennec::isnan(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
|
||||||
|
constexpr vector<genBType, i...> isinf(const vector<genType, i...>& x) {
|
||||||
|
return vector<genBType, i...>(fennec::isinf(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
||||||
|
constexpr vector<genIType, i...> floatBitsToInt(const vector<genType, i...>& x) {
|
||||||
|
return vector<genIType, i...>(fennec::bit_cast<genIType>(x[i])...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
|
||||||
|
constexpr vector<genUType, i...> floatBitsToUint(const vector<genType, i...>& x) {
|
||||||
|
return vector<genUType, i...>(fennec::bit_cast<genUType>(x[i])...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
|
||||||
|
constexpr vector<genType, i...> intBitsToFloat(const vector<genIType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
|
||||||
|
constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> fma(const vector<genType, i...>& a, const vector<genType, i...>& b, const vector<genType, i...>& c) {
|
||||||
|
return vector<genType, i...>(fennec::fma(a[i], b[i], c[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
|
||||||
|
constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<genIType, i...>& exp) {
|
||||||
|
return vector<genType, i...>(fennec::frexp(x[i], exp[i])...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
|
||||||
|
constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vector<genIType, i...>& exp) {
|
||||||
|
return vector<genType, i...>(fennec::ldexp(x[i], exp[i])...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> min(genType x, const vector<genType, i...>& y) {
|
||||||
|
return vector<genType, i...>(fennec::min(x, y[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> min(const vector<genType, i...>& x, genType y) {
|
||||||
|
return vector<genType, i...>(fennec::min(x[i], y) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> min(const vector<genType, i...>& x, const vector<genType, i...>& y) {
|
||||||
|
return vector<genType, i...>(fennec::min(x[i], y[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> max(genType x, const vector<genType, i...>& y) {
|
||||||
|
return vector<genType, i...>(fennec::max(x, y[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> max(const vector<genType, i...>& x, genType y) {
|
||||||
|
return vector<genType, i...>(fennec::max(x[i], y) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> max(const vector<genType, i...>& x, const vector<genType, i...>& y) {
|
||||||
|
return vector<genType, i...>(fennec::max(x[i], y[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, genType minVal, genType maxVal) {
|
||||||
|
return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal), maxVal)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, const vector<genType, i...>& minVal, const vector<genType, i...>& maxVal) {
|
||||||
|
return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal[i]), maxVal[i])...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
||||||
|
constexpr vector<genType, i...> step(genType edge, const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::step(edge, x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
||||||
|
constexpr vector<genType, i...> step(const vector<genType, i...>& edge, const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::step(edge[i], x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
||||||
|
constexpr vector<genType, i...> smoothstep(genType edge0, genType edge1, const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::smoothstep(edge0, edge1, x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
||||||
|
constexpr vector<genType, i...> smoothstep(const vector<genType, i...>& edge0, const vector<genType, i...>& edge1, const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::smoothstep(edge0[i], edge1[i], x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
||||||
|
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genType a) {
|
||||||
|
return x * (genType(1.0) - a) + y * a;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
|
||||||
|
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, const vector<genType, i...>& a) {
|
||||||
|
return x * (genType(1.0) - a) + y * a;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType> and is_floating_point_v<genType>)
|
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType> and is_floating_point_v<genType>)
|
||||||
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genBType a) {
|
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genBType a) {
|
||||||
|
|||||||
@@ -24,15 +24,15 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename ScalarT, size_t...IndicesV> struct vector; // Forward def for vectors
|
template<typename ScalarT, size_t...IndicesV> requires(is_scalar_v<ScalarT>) struct vector; // Forward def for vectors
|
||||||
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct matrix; // Forward def for matrices
|
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> requires(is_scalar_v<ScalarT>) struct matrix; // Forward def for matrices
|
||||||
|
|
||||||
// Simplified interface for creating sized vectors or matrices
|
// Simplified interface for creating sized vectors or matrices
|
||||||
template<typename ScalarT, size_t SizeV> using vec
|
template<typename ScalarT, size_t SizeV> using vec
|
||||||
= decltype(detail::_gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); // Gets the type returned by this function
|
= decltype(detail::_gen_vector<vector, ScalarT>(make_index_metasequence<SizeV>{})); // Gets the type returned by this function
|
||||||
|
|
||||||
template<typename ScalarT, size_t ColsV, size_t RowsV> using mat
|
template<typename ScalarT, size_t ColsV, size_t RowsV> using mat
|
||||||
= decltype(detail::_gen_matrix<matrix, ScalarT, RowsV>(make_index_sequence<ColsV>{})); // Gets the type returned by this function
|
= decltype(detail::_gen_matrix<matrix, ScalarT, RowsV>(make_index_metasequence<ColsV>{})); // Gets the type returned by this function
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#ifndef FENNEC_MATH_DETAIL_TYPES_H
|
#ifndef FENNEC_MATH_DETAIL_TYPES_H
|
||||||
#define FENNEC_MATH_DETAIL_TYPES_H
|
#define FENNEC_MATH_DETAIL_TYPES_H
|
||||||
|
|
||||||
#include <fennec/lang/const_sequences.h>
|
#include <fennec/lang/metasequences.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -28,11 +28,11 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
template<template<typename, size_t...> typename VectorT, typename ScalarT, size_t...IndicesV>
|
template<template<typename, size_t...> typename VectorT, typename ScalarT, size_t...IndicesV>
|
||||||
VectorT<ScalarT, IndicesV...> _gen_vector(const_index_sequence<IndicesV...>); // Helper for substituting a size N with sequence of integers
|
VectorT<ScalarT, IndicesV...> _gen_vector(index_metasequence<IndicesV...>); // Helper for substituting a size N with sequence of integers
|
||||||
|
|
||||||
|
|
||||||
template<template<typename, size_t...> typename MatrixT, typename ScalarT, size_t RowsV, size_t...IndicesV>
|
template<template<typename, size_t...> typename MatrixT, typename ScalarT, size_t RowsV, size_t...IndicesV>
|
||||||
MatrixT<ScalarT, RowsV, IndicesV...> _gen_matrix(const_index_sequence<IndicesV...>); // Helper for substituting a size Columns with sequence of integers
|
MatrixT<ScalarT, RowsV, IndicesV...> _gen_matrix(index_metasequence<IndicesV...>); // Helper for substituting a size Columns with sequence of integers
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,45 +42,45 @@
|
|||||||
/// \code #include <fennec/math/exponential.h> \endcode
|
/// \code #include <fennec/math/exponential.h> \endcode
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section Exponential Functions
|
/// \section fennec_math_exponential_section_functions Exponential Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_exponential_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_exponential_functions">
|
||||||
/// <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::pow(fennec::genType, fennec::genType) "genFType pow(genFType x, genFType y)"
|
/// \ref fennec::pow "genFType pow(genFType x, genFType y)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::pow(fennec::genType, fennec::genType)
|
/// \copydetails fennec::pow
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::exp(fennec::genType)"genFType exp(genFType x)"
|
/// \ref fennec::exp"genFType exp(genFType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::exp(fennec::genType)
|
/// \copydetails fennec::exp
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::exp2(fennec::genType) "genFType exp2(genFType x)"
|
/// \ref fennec::exp2 "genFType exp2(genFType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::exp2(fennec::genType)
|
/// \copydetails fennec::exp2
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::log(fennec::genType) "genFType log(genFType x)"
|
/// \ref fennec::log "genFType log(genFType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::log(fennec::genType)
|
/// \copydetails fennec::log
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::log2(fennec::genType) "genFType log2(genFType x)"
|
/// \ref fennec::log2 "genFType log2(genFType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::log2(fennec::genType)
|
/// \copydetails fennec::log2
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
|
||||||
/// \ref fennec::sqrt(fennec::genType) "genFType sqrt(genFType x)"
|
/// \ref fennec::sqrt "genFType sqrt(genFType x)"
|
||||||
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
/// <td width="50%" style="vertical-align: top" class="odd_c">
|
||||||
/// \copydetails fennec::sqrt(fennec::genType)
|
/// \copydetails fennec::sqrt
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::inversesqrt(fennec::genType) "genFType inversesqrt(genFType x)"
|
/// \ref fennec::inversesqrt "genFType inversesqrt(genFType x)"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::inversesqrt(fennec::genType)
|
/// \copydetails fennec::inversesqrt
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
@@ -110,14 +110,6 @@ constexpr genType pow(genType x, genType y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> pow(const vector<genType, i...> & x, const vector<genType, i...> & y) {
|
|
||||||
return vector<genType, i...>(fennec::pow(x[i], y[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// exp =================================================================================================================
|
// exp =================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -132,13 +124,6 @@ constexpr genType exp(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::exp(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// exp2 ================================================================================================================
|
// exp2 ================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -152,13 +137,6 @@ template<typename genType> constexpr genType exp2(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::exp2(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// log =================================================================================================================
|
// log =================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -173,13 +151,6 @@ template<typename genType> constexpr genType log(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(log(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// log2 ================================================================================================================
|
// log2 ================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -195,13 +166,6 @@ template<typename genType> constexpr genType log2(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(log2(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// sqrt ================================================================================================================
|
// sqrt ================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -216,13 +180,6 @@ template<typename genType> constexpr genType sqrt(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::sqrt(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// inversesqrt =========================================================================================================
|
// inversesqrt =========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -237,7 +194,32 @@ template<typename genType> constexpr genType inversesqrt(genType x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vector Specialization -----------------------------------------------------------------------------------------------
|
// Internal ============================================================================================================
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> pow(const vector<genType, i...> & x, const vector<genType, i...> & y) {
|
||||||
|
return vector<genType, i...>(fennec::pow(x[i], y[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::exp(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::exp2(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(log(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(log2(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::sqrt(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
template<typename genType, size_t...i>
|
||||||
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x) {
|
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x) {
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
|
|
||||||
#include <fennec/lang/limits.h>
|
#include <fennec/lang/limits.h>
|
||||||
|
|
||||||
|
#include <fennec/math/common.h>
|
||||||
#include <fennec/math/trigonometric.h>
|
#include <fennec/math/trigonometric.h>
|
||||||
|
|
||||||
#include <fennec/math/ext/quaternion.h>
|
#include <fennec/math/ext/quaternion.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#ifndef FENNEC_MATH_EXT_QUATERNION_H
|
#ifndef FENNEC_MATH_EXT_QUATERNION_H
|
||||||
#define FENNEC_MATH_EXT_QUATERNION_H
|
#define FENNEC_MATH_EXT_QUATERNION_H
|
||||||
|
|
||||||
|
#include <fennec/math/geometric.h>
|
||||||
#include <fennec/math/vector_base.h>
|
#include <fennec/math/vector_base.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
@@ -31,15 +32,13 @@ template<typename genType> using qua = quaternion<genType>;
|
|||||||
using quat = qua<float>;
|
using quat = qua<float>;
|
||||||
using dquat = qua<double>;
|
using dquat = qua<double>;
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Dot Function
|
#ifndef FENNEC_DOXYGEN
|
||||||
/// \param x the first quaternion
|
|
||||||
/// \param y the second quaternion
|
|
||||||
/// \returns The sum of component products.
|
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr genType dot(const qua<genType>& x, const qua<genType>& y) {
|
constexpr genType dot(const qua<genType>& x, const qua<genType>& y) {
|
||||||
return x.w*y.w + x.x*y.x + x.y*y.y + x.z*y.z;
|
return x.w*y.w + x.x*y.x + x.y*y.y + x.z*y.z;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Square Norm Function
|
/// \brief Square Norm Function
|
||||||
@@ -283,7 +282,6 @@ public:
|
|||||||
|
|
||||||
// Quaternion Vector Arithmetic Operators ==============================================================================
|
// Quaternion Vector Arithmetic Operators ==============================================================================
|
||||||
|
|
||||||
/// \brief
|
|
||||||
constexpr friend vec3_t operator*(const quat_t& q, const vec3_t& v) {
|
constexpr friend vec3_t operator*(const quat_t& q, const vec3_t& v) {
|
||||||
const vec3_t u = q.xyz;
|
const vec3_t u = q.xyz;
|
||||||
const vec3_t uv = fennec::cross(u, v);
|
const vec3_t uv = fennec::cross(u, v);
|
||||||
@@ -306,8 +304,8 @@ public:
|
|||||||
|
|
||||||
// Quaternion Quaternion Arithmetic Operators ==========================================================================
|
// Quaternion Quaternion Arithmetic Operators ==========================================================================
|
||||||
|
|
||||||
constexpr friend quaternion operator+(const quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t operator+(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return quaternion(
|
return quat_t(
|
||||||
lhs.w + rhs.w,
|
lhs.w + rhs.w,
|
||||||
lhs.x + rhs.x,
|
lhs.x + rhs.x,
|
||||||
lhs.y + rhs.y,
|
lhs.y + rhs.y,
|
||||||
@@ -315,8 +313,8 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion operator-(const quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t operator-(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return quaternion(
|
return quat_t(
|
||||||
lhs.w - rhs.w,
|
lhs.w - rhs.w,
|
||||||
lhs.x - rhs.x,
|
lhs.x - rhs.x,
|
||||||
lhs.y - rhs.y,
|
lhs.y - rhs.y,
|
||||||
@@ -324,8 +322,8 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion operator*(const quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t operator*(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return quaternion(
|
return quat_t(
|
||||||
lhs.w*rhs.w - lhs.x*rhs.x - lhs.y*rhs.y - lhs.z * rhs.z,
|
lhs.w*rhs.w - lhs.x*rhs.x - lhs.y*rhs.y - lhs.z * rhs.z,
|
||||||
lhs.w*rhs.x + lhs.x*rhs.w + lhs.y*rhs.z - lhs.z * rhs.y,
|
lhs.w*rhs.x + lhs.x*rhs.w + lhs.y*rhs.z - lhs.z * rhs.y,
|
||||||
lhs.w*rhs.y - lhs.x*rhs.z + lhs.y*rhs.w + lhs.z * rhs.x,
|
lhs.w*rhs.y - lhs.x*rhs.z + lhs.y*rhs.w + lhs.z * rhs.x,
|
||||||
@@ -336,7 +334,7 @@ public:
|
|||||||
|
|
||||||
// Quaternion Quaternion Arithmetic Assignment Operators ===============================================================
|
// Quaternion Quaternion Arithmetic Assignment Operators ===============================================================
|
||||||
|
|
||||||
constexpr friend quaternion& operator+=(quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t& operator+=(quat_t& lhs, const quat_t& rhs) {
|
||||||
lhs.w += rhs.w;
|
lhs.w += rhs.w;
|
||||||
lhs.x += rhs.x;
|
lhs.x += rhs.x;
|
||||||
lhs.y += rhs.y;
|
lhs.y += rhs.y;
|
||||||
@@ -344,7 +342,7 @@ public:
|
|||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion& operator-=(quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t& operator-=(quat_t& lhs, const quat_t& rhs) {
|
||||||
lhs.w -= rhs.w;
|
lhs.w -= rhs.w;
|
||||||
lhs.x -= rhs.x;
|
lhs.x -= rhs.x;
|
||||||
lhs.y -= rhs.y;
|
lhs.y -= rhs.y;
|
||||||
@@ -352,7 +350,7 @@ public:
|
|||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion& operator*=(quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t& operator*=(quat_t& lhs, const quat_t& rhs) {
|
||||||
return lhs = lhs * rhs;
|
return lhs = lhs * rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
include/fennec/math/ext/rect.h
Normal file
52
include/fennec/math/ext/rect.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file rect.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_MATH_EXT_RECT_H
|
||||||
|
#define FENNEC_MATH_EXT_RECT_H
|
||||||
|
|
||||||
|
#include <fennec/math/vector.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename ScalarT>
|
||||||
|
struct rectangle {
|
||||||
|
tvec2<ScalarT> position, size;
|
||||||
|
};
|
||||||
|
|
||||||
|
using rect = rectangle<float_t>;
|
||||||
|
using irect = rectangle<int32_t>;
|
||||||
|
using urect = rectangle<uint32_t>;
|
||||||
|
using drect = rectangle<double_t>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_MATH_EXT_RECT_H
|
||||||
@@ -32,7 +32,7 @@ namespace fennec
|
|||||||
/// \param x a vector containing the position
|
/// \param x a vector containing the position
|
||||||
/// \returns An identity matrix with the last column set to x
|
/// \returns An identity matrix with the last column set to x
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr mat<genType, 3, 3> translation(const vec<genType, 2>& x) {
|
constexpr mat<genType, 3, 3> translation(const vector<genType, 0, 1>& x) {
|
||||||
return mat<genType, 3, 3>(
|
return mat<genType, 3, 3>(
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, 1, 0,
|
0, 1, 0,
|
||||||
@@ -45,7 +45,7 @@ constexpr mat<genType, 3, 3> translation(const vec<genType, 2>& x) {
|
|||||||
/// \param x a vector containing the position
|
/// \param x a vector containing the position
|
||||||
/// \returns An identity matrix with the last column set to x
|
/// \returns An identity matrix with the last column set to x
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr mat<genType, 4, 4> translation(const vec<genType, 3>& x) {
|
constexpr mat<genType, 4, 4> translation(const vector<genType, 0, 1, 2>& x) {
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, 1, 0, 0,
|
0, 1, 0, 0,
|
||||||
@@ -59,7 +59,7 @@ constexpr mat<genType, 4, 4> translation(const vec<genType, 3>& x) {
|
|||||||
/// \param x a vector containing the scale for each axis
|
/// \param x a vector containing the scale for each axis
|
||||||
/// \returns A diagonal matrix with the terms of x
|
/// \returns A diagonal matrix with the terms of x
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr mat<genType, 3, 3> scaling(const vec<genType, 2>& x) {
|
constexpr mat<genType, 3, 3> scaling(const vector<genType, 0, 1>& x) {
|
||||||
return mat<genType, 3, 3>(
|
return mat<genType, 3, 3>(
|
||||||
x.x, 0, 0,
|
x.x, 0, 0,
|
||||||
0, x.y, 0,
|
0, x.y, 0,
|
||||||
@@ -72,7 +72,7 @@ constexpr mat<genType, 3, 3> scaling(const vec<genType, 2>& x) {
|
|||||||
/// \param x a vector containing the scale for each axis
|
/// \param x a vector containing the scale for each axis
|
||||||
/// \returns A diagonal matrix with the terms of x
|
/// \returns A diagonal matrix with the terms of x
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr mat<genType, 4, 4> scaling(const vec<genType, 3>& x) {
|
constexpr mat<genType, 4, 4> scaling(const vector<genType, 0, 1, 2>& x) {
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
x.x, 0, 0, 0,
|
x.x, 0, 0, 0,
|
||||||
0, x.y, 0, 0,
|
0, x.y, 0, 0,
|
||||||
@@ -81,6 +81,15 @@ constexpr mat<genType, 4, 4> scaling(const vec<genType, 3>& x) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename genType>
|
||||||
|
constexpr mat<genType, 3, 3> shear(const vector<genType, 0, 1>& x) {
|
||||||
|
return mat<genType, 3, 3>(
|
||||||
|
1, x.x, 0,
|
||||||
|
x.y, 1, 0,
|
||||||
|
0, 0, 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Create a 2d rotation matrix
|
/// \brief Create a 2d rotation matrix
|
||||||
/// \param a the angle of the rotation in radians
|
/// \param a the angle of the rotation in radians
|
||||||
@@ -106,7 +115,7 @@ constexpr mat<genType, 3, 3> rotation(const genType a) {
|
|||||||
/// \param a The rotation about the axis in radians
|
/// \param a The rotation about the axis in radians
|
||||||
/// \returns A rotation matrix about A
|
/// \returns A rotation matrix about A
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr mat<genType, 4, 4> rotation(const vec<genType, 3>& A, genType a) {
|
constexpr mat<genType, 4, 4> rotation(const vector<genType, 0, 1, 2>& A, genType a) {
|
||||||
// https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
|
// https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
|
||||||
|
|
||||||
// Calculate sin and cos terms
|
// Calculate sin and cos terms
|
||||||
@@ -114,8 +123,8 @@ constexpr mat<genType, 4, 4> rotation(const vec<genType, 3>& A, genType a) {
|
|||||||
const genType s = fennec::sin(a);
|
const genType s = fennec::sin(a);
|
||||||
|
|
||||||
// Calculate axis term
|
// Calculate axis term
|
||||||
const vec<genType, 3> u = (fennec::one<genType>() - c) * A;
|
const vector<genType, 0, 1, 2> u = (fennec::one<genType>() - c) * A;
|
||||||
const vec<genType, 3> v = s * A;
|
const vector<genType, 0, 1, 2> v = s * A;
|
||||||
|
|
||||||
// Calculate the Matrix
|
// Calculate the Matrix
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
@@ -126,20 +135,20 @@ constexpr mat<genType, 4, 4> rotation(const vec<genType, 3>& A, genType a) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType>
|
// template<typename genType>
|
||||||
constexpr qua<genType> rotation(const vec<genType, 3>& axis, genType angle) {
|
// constexpr qua<genType> rotation(const vector<genType, 0, 1, 2>& axis, genType angle) {
|
||||||
vec<genType, 3> a = fennec::normalize(axis);
|
// vector<genType, 0, 1, 2> 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);
|
// 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
|
||||||
enum rot_
|
enum rotation_
|
||||||
{
|
{
|
||||||
rot_x = 0
|
rotation_x = 0
|
||||||
, rot_y
|
, rotation_y
|
||||||
, rot_z
|
, rotation_z
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -147,7 +156,7 @@ enum rot_
|
|||||||
/// \tparam axis the unit axis to rotate around
|
/// \tparam axis the unit axis to rotate around
|
||||||
/// \param a the angle, in radians
|
/// \param a the angle, in radians
|
||||||
/// \returns a matrix that rotates vectors around a unit axis
|
/// \returns a matrix that rotates vectors around a unit axis
|
||||||
template<typename genType, rot_ axis>
|
template<typename genType, rotation_ axis>
|
||||||
constexpr mat<genType, 4, 4> rotation(genType a) {
|
constexpr mat<genType, 4, 4> rotation(genType a) {
|
||||||
// https://en.wikipedia.org/wiki/Rotation_matrix#Basic_3D_rotations
|
// https://en.wikipedia.org/wiki/Rotation_matrix#Basic_3D_rotations
|
||||||
|
|
||||||
@@ -156,7 +165,7 @@ constexpr mat<genType, 4, 4> rotation(genType a) {
|
|||||||
const genType s = fennec::sin(a);
|
const genType s = fennec::sin(a);
|
||||||
|
|
||||||
// Calculate the matrix
|
// Calculate the matrix
|
||||||
if constexpr(axis == rot_x) {
|
if constexpr(axis == rotation_x) {
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, c, -s, 0,
|
0, c, -s, 0,
|
||||||
@@ -164,7 +173,7 @@ constexpr mat<genType, 4, 4> rotation(genType a) {
|
|||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if constexpr(axis == rot_y) {
|
else if constexpr(axis == rotation_y) {
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
c, 0, s, 0,
|
c, 0, s, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
@@ -172,7 +181,7 @@ constexpr mat<genType, 4, 4> rotation(genType a) {
|
|||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if constexpr(axis == rot_z) {
|
else if constexpr(axis == rotation_z) {
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
c, -s, 0, 0,
|
c, -s, 0, 0,
|
||||||
s, c, 0, 0,
|
s, c, 0, 0,
|
||||||
@@ -202,7 +211,7 @@ enum order_
|
|||||||
/// \param E the euler angles, taken as tait-bryan (pitch, yaw, roll)
|
/// \param E the euler angles, taken as tait-bryan (pitch, yaw, roll)
|
||||||
/// \returns a matrix that rotates vectors
|
/// \returns a matrix that rotates vectors
|
||||||
template<typename genType, order_ order = order_zxy>
|
template<typename genType, order_ order = order_zxy>
|
||||||
constexpr mat<genType, 4, 4> rotation(const vec<genType, 3>& E) {
|
constexpr mat<genType, 4, 4> rotation(const vector<genType, 0, 1, 2>& E) {
|
||||||
// expanded using a CAS
|
// expanded using a CAS
|
||||||
|
|
||||||
// Calculate sin and cos terms
|
// Calculate sin and cos terms
|
||||||
@@ -221,40 +230,35 @@ constexpr mat<genType, 4, 4> rotation(const vec<genType, 3>& E) {
|
|||||||
sa*sg - ca*cg*sb, ca*sb*sg + cg*sa, ca*cb, 0,
|
sa*sg - ca*cg*sb, ca*sb*sg + cg*sa, ca*cb, 0,
|
||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
} else if constexpr(order == order_xzy) {
|
||||||
else if constexpr(order == order_xzy) {
|
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
cb*cg, -sg, cg*sb, 0,
|
cb*cg, -sg, cg*sb, 0,
|
||||||
ca*cb*sg + sa*sb, ca*cg, cb*sa*sg - ca*sb, 0,
|
ca*cb*sg + sa*sb, ca*cg, cb*sa*sg - ca*sb, 0,
|
||||||
cb*sa*sg - ca*sb, cg*sa, ca*cb + sa*sb*sg, 0,
|
cb*sa*sg - ca*sb, cg*sa, ca*cb + sa*sb*sg, 0,
|
||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
} else if constexpr(order == order_yxz) {
|
||||||
else if constexpr(order == order_yxz) {
|
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
cb*cg + sa*sb*sg, cg*sa*sb - cb*sg, ca*sb, 0,
|
cb*cg + sa*sb*sg, cg*sa*sb - cb*sg, ca*sb, 0,
|
||||||
ca*sg, ca*cg, -sa, 0,
|
ca*sg, ca*cg, -sa, 0,
|
||||||
cb*sa*sg - cg*sb, cb*cg*sa + sb*sg, ca*cb, 0,
|
cb*sa*sg - cg*sb, cb*cg*sa + sb*sg, ca*cb, 0,
|
||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
} else if constexpr(order == order_yzx) {
|
||||||
else if constexpr(order == order_yzx) {
|
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
cb*cg, sa*sb - ca*cb*sg, ca*sb + cb*sa*sg, 0,
|
cb*cg, sa*sb - ca*cb*sg, ca*sb + cb*sa*sg, 0,
|
||||||
sg, ca*cg, -cg*sa, 0,
|
sg, ca*cg, -cg*sa, 0,
|
||||||
-cg*sb, ca*sb*sg + cb*sa, ca*cb - sa*sb*sg, 0,
|
-cg*sb, ca*sb*sg + cb*sa, ca*cb - sa*sb*sg, 0,
|
||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
} else if constexpr(order == order_zxy) {
|
||||||
else if constexpr(order == order_zxy) {
|
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
cb*cg - sa*sb*sg, -ca*sg, cb*sa*sg + cg*sb, 0,
|
cb*cg - sa*sb*sg, -ca*sg, cb*sa*sg + cg*sb, 0,
|
||||||
cb*sg + cg*sa*sb, ca*cg, sb*sg - cb*cg*sa, 0,
|
cb*sg + cg*sa*sb, ca*cg, sb*sg - cb*cg*sa, 0,
|
||||||
-ca*sb, sa, ca*cb, 0,
|
-ca*sb, sa, ca*cb, 0,
|
||||||
0, 0, 0, 1
|
0, 0, 0, 1
|
||||||
);
|
);
|
||||||
}
|
} else if constexpr(order == order_zyx) {
|
||||||
else if constexpr(order == order_zyx) {
|
|
||||||
return mat<genType, 4, 4>(
|
return mat<genType, 4, 4>(
|
||||||
cb*cg, cg*sa*sb - ca*sg, ca*cg*sb + sa*sg, 0,
|
cb*cg, cg*sa*sb - ca*sg, ca*cg*sb + sa*sg, 0,
|
||||||
cb*sg, ca*cg + sa*sb*sg, ca*sb*sg - cg*sa, 0,
|
cb*sg, ca*cg + sa*sb*sg, ca*sb*sg - cg*sa, 0,
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#ifndef FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
#ifndef FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
||||||
#define FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
#define FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
||||||
|
|
||||||
#include <fennec/math/trigonometric.h>
|
|
||||||
#include <fennec/math/ext/quaternion.h>
|
#include <fennec/math/ext/quaternion.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
@@ -27,6 +26,7 @@ namespace fennec
|
|||||||
|
|
||||||
// Angle Conversions ===================================================================================================
|
// Angle Conversions ===================================================================================================
|
||||||
|
|
||||||
|
#ifndef FENNEC_DOXYGEN
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr qua<genType> radians(const qua<genType>& degrees) {
|
constexpr qua<genType> radians(const qua<genType>& degrees) {
|
||||||
return qua<genType>(degrees * 0.01745329251994329576923690768489);
|
return qua<genType>(degrees * 0.01745329251994329576923690768489);
|
||||||
@@ -37,7 +37,6 @@ constexpr qua<genType> degrees(const qua<genType>& radians) {
|
|||||||
return qua<genType>(radians * 57.29577951308232087679815481410517);
|
return qua<genType>(radians * 57.29577951308232087679815481410517);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Trigonometric Functions =============================================================================================
|
// Trigonometric Functions =============================================================================================
|
||||||
|
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
@@ -162,6 +161,7 @@ constexpr qua<genType> atanh(const qua<genType>& x) {
|
|||||||
fennec::atanh(x.z)
|
fennec::atanh(x.z)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
/// \code #include <fennec/math/geometric.h> \endcode
|
/// \code #include <fennec/math/geometric.h> \endcode
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section Geometric Functions
|
/// \section fennec_math_geometric_section_functions Geometric Functions
|
||||||
///
|
///
|
||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_geometric_functions">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_geometric_functions">
|
||||||
/// <tr><th style="vertical-align: top">Syntax
|
/// <tr><th style="vertical-align: top">Syntax
|
||||||
@@ -118,7 +118,7 @@ namespace fennec
|
|||||||
// dot -----------------------------------------------------------------------------------------------------------------
|
// dot -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$
|
/// \brief Returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_1 \cdot y_1 + \ldots\f$
|
||||||
///
|
///
|
||||||
/// \returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$ <br><br>
|
/// \returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$ <br><br>
|
||||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols.
|
|||||||
/// \tparam ScalarT
|
/// \tparam ScalarT
|
||||||
/// \tparam RowsV
|
/// \tparam RowsV
|
||||||
/// \tparam ColIndicesV
|
/// \tparam ColIndicesV
|
||||||
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV>
|
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> requires(is_scalar_v<ScalarT>)
|
||||||
struct matrix
|
struct matrix
|
||||||
{
|
{
|
||||||
// Assertions ==========================================================================================================
|
// Assertions ==========================================================================================================
|
||||||
@@ -251,7 +251,6 @@ struct matrix
|
|||||||
/// \param mat matrix to copy
|
/// \param mat matrix to copy
|
||||||
constexpr matrix(const matrix_t& mat)
|
constexpr matrix(const matrix_t& mat)
|
||||||
: data{ mat.data } {
|
: data{ mat.data } {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -261,7 +260,26 @@ struct matrix
|
|||||||
/// \param mat matrix to move
|
/// \param mat matrix to move
|
||||||
constexpr matrix(matrix_t&& mat) noexcept
|
constexpr matrix(matrix_t&& mat) noexcept
|
||||||
: data{ mat.data } {
|
: data{ mat.data } {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OScalarT>
|
||||||
|
constexpr matrix(const matrix<OScalarT, RowsV, ColIndicesV...>& mat)
|
||||||
|
: matrix() {
|
||||||
|
for (size_t i = 0; i < columns; ++i) {
|
||||||
|
for (size_t j = 0; j < rows; ++j) {
|
||||||
|
data[i][j] = scalar_t(mat[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OScalarT>
|
||||||
|
constexpr matrix(matrix<OScalarT, RowsV, ColIndicesV...>&& mat) noexcept
|
||||||
|
: matrix() {
|
||||||
|
for (size_t i = 0; i < columns; ++i) {
|
||||||
|
for (size_t j = 0; j < rows; ++j) {
|
||||||
|
data[i][j] = scalar_t(mat[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -629,6 +647,11 @@ struct matrix
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<size_t ORowsV, size_t...OColIndicesV> requires(columns == ORowsV)
|
||||||
|
constexpr matrix<scalar_t, RowsV, OColIndicesV...>& operator*=(const matrix<scalar_t, ORowsV, OColIndicesV...>& rhs) {
|
||||||
|
return *this = *this * rhs;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|
||||||
#include <fennec/lang/const_sequences.h>
|
#include <fennec/lang/metasequences.h>
|
||||||
|
|
||||||
#include <fennec/math/swizzle_storage.h>
|
#include <fennec/math/swizzle_storage.h>
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ public:
|
|||||||
/// \return The Value of the Swizzle as a Vector
|
/// \return The Value of the Swizzle as a Vector
|
||||||
constexpr VectorT decay() const {
|
constexpr VectorT decay() const {
|
||||||
VectorT res;
|
VectorT res;
|
||||||
return decay_impl(res, make_index_sequence<size>{});
|
return decay_impl(res, make_index_metasequence<size>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -93,7 +93,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
template<size_t...VecIndicesV>
|
template<size_t...VecIndicesV>
|
||||||
constexpr VectorT& decay_impl(VectorT& vec, const_index_sequence<VecIndicesV...>) {
|
constexpr VectorT& decay_impl(VectorT& vec, index_metasequence<VecIndicesV...>) {
|
||||||
return ((vec[VecIndicesV] = this->data[IndicesV]), ..., vec);
|
return ((vec[VecIndicesV] = this->data[IndicesV]), ..., vec);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -145,6 +145,8 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#include <fennec/math/detail/_math.h>
|
#include <fennec/math/detail/_math.h>
|
||||||
|
#include <fennec/math/vector.h>
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -167,11 +169,6 @@ constexpr genType radians(genType degrees) {
|
|||||||
return genType(degrees * 0.01745329251994329576923690768489);
|
return genType(degrees * 0.01745329251994329576923690768489);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) {
|
|
||||||
return vector<genType, i...>(degrees * 0.01745329251994329576923690768489);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Converts \f$radians\f$ to \f$degrees\f$, i.e., \f$radians\cdot\frac{\pi}{180}\f$
|
/// \brief Converts \f$radians\f$ to \f$degrees\f$, i.e., \f$radians\cdot\frac{\pi}{180}\f$
|
||||||
@@ -186,11 +183,6 @@ constexpr genType degrees(genType radians) {
|
|||||||
return genType(radians * 57.29577951308232087679815481410517);
|
return genType(radians * 57.29577951308232087679815481410517);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians) {
|
|
||||||
return genType(radians * 57.29577951308232087679815481410517);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -213,11 +205,6 @@ constexpr genType sin(genType x) {
|
|||||||
return ::sin(x);
|
return ::sin(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> sin(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::sin(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief The Standard Trigonometric Cosine
|
/// \brief The Standard Trigonometric Cosine
|
||||||
@@ -232,11 +219,6 @@ constexpr genType cos(genType x) {
|
|||||||
return ::cos(x);
|
return ::cos(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> cos(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::cos(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief The Standard Trigonometric Tangent
|
/// \brief The Standard Trigonometric Tangent
|
||||||
@@ -251,11 +233,6 @@ constexpr genType tan(genType x) {
|
|||||||
return ::tan(x);
|
return ::tan(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> tan(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::tan(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -277,11 +254,6 @@ constexpr genType asin(genType x) {
|
|||||||
return ::asin(x);
|
return ::asin(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> asin(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::asin(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Arc Cosine. Returns an angle \f$\theta\f$ whose cosine is /a x.
|
/// \brief Arc Cosine. Returns an angle \f$\theta\f$ whose cosine is /a x.
|
||||||
@@ -297,11 +269,6 @@ constexpr genType acos(genType x) {
|
|||||||
return ::acos(x);
|
return ::acos(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> acos(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::acos(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Arc Tangent. Returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
|
/// \brief Arc Tangent. Returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
|
||||||
@@ -317,11 +284,6 @@ constexpr genType atan(genType y_over_x) {
|
|||||||
return ::atan(y_over_x);
|
return ::atan(y_over_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) {
|
|
||||||
return vector<genType, i...>(fennec::atan(y_over_x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Arc Tangent. Returns an angle whose tangent is \f$\frac{y}{x}\f$.
|
/// \brief Arc Tangent. Returns an angle whose tangent is \f$\frac{y}{x}\f$.
|
||||||
@@ -338,11 +300,6 @@ constexpr genType atan(genType y, genType x) {
|
|||||||
return ::atan2(y, x);
|
return ::atan2(y, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::atan(y[i], x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -364,11 +321,6 @@ constexpr genType sinh(genType x) {
|
|||||||
return ::sinh(x);
|
return ::sinh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::sinh(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Returns the Hyperbolic Cosine Function, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$
|
/// \brief Returns the Hyperbolic Cosine Function, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$
|
||||||
@@ -381,11 +333,6 @@ constexpr genType cosh(genType x) {
|
|||||||
return ::cosh(x);
|
return ::cosh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::cosh(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Returns the Hyperbolic Tangent Function, \f$\frac{\text{sinh}(x)}{\text{cosh}(x)}\f$
|
/// \brief Returns the Hyperbolic Tangent Function, \f$\frac{\text{sinh}(x)}{\text{cosh}(x)}\f$
|
||||||
@@ -398,10 +345,6 @@ constexpr genType tanh(genType x) {
|
|||||||
return ::tanh(x);
|
return ::tanh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::tanh(x[i]) ...);
|
|
||||||
}
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -421,11 +364,6 @@ constexpr genType asinh(genType x) {
|
|||||||
return ::asinh(x);
|
return ::asinh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::asinh(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief The Inverse Hyperbolic Cosine Function
|
/// \brief The Inverse Hyperbolic Cosine Function
|
||||||
@@ -439,11 +377,6 @@ constexpr genType acosh(genType x) {
|
|||||||
return ::acosh(x);
|
return ::acosh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
|
||||||
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) {
|
|
||||||
return vector<genType, i...>(fennec::acosh(x[i]) ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief The Inverse Hyperbolic Tangent Function
|
/// \brief The Inverse Hyperbolic Tangent Function
|
||||||
@@ -457,12 +390,88 @@ constexpr genType atanh(genType x) {
|
|||||||
return ::atanh(x);
|
return ::atanh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Internal ============================================================================================================
|
||||||
|
|
||||||
|
#ifndef FENNEC_DOXYGEN
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) {
|
||||||
|
return vector<genType, i...>(degrees * 0.01745329251994329576923690768489);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians) {
|
||||||
|
return genType(radians * 57.29577951308232087679815481410517);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> sin(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::sin(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> cos(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::cos(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> tan(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::tan(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> asin(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::asin(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> acos(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::acos(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) {
|
||||||
|
return vector<genType, i...>(fennec::atan(y_over_x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::atan(y[i], x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::sinh(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::cosh(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::tanh(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::asinh(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename genType, size_t...i>
|
||||||
|
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) {
|
||||||
|
return vector<genType, i...>(fennec::acosh(x[i]) ...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename genType, size_t...i>
|
template<typename genType, size_t...i>
|
||||||
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) {
|
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) {
|
||||||
return vector<genType, i...>(fennec::atanh(x[i]) ...);
|
return vector<genType, i...>(fennec::atanh(x[i]) ...);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|
||||||
|
#include <fennec/containers/initializer_list.h>
|
||||||
#include <fennec/math/detail/_fwd.h>
|
#include <fennec/math/detail/_fwd.h>
|
||||||
|
|
||||||
#include <fennec/math/vector_base.h>
|
#include <fennec/math/vector_base.h>
|
||||||
@@ -120,7 +121,7 @@ namespace fennec
|
|||||||
/// \tparam ScalarT The type of the Components
|
/// \tparam ScalarT The type of the Components
|
||||||
/// \tparam SizeV The number of Components
|
/// \tparam SizeV The number of Components
|
||||||
template<typename ScalarT, size_t SizeV>
|
template<typename ScalarT, size_t SizeV>
|
||||||
using vec = decltype(detail::_gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{}));
|
using vec = decltype(detail::_gen_vector<vector, ScalarT>(make_index_metasequence<SizeV>{}));
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -177,7 +178,7 @@ using dvec4 = tvec4<double_t>;
|
|||||||
/// \tparam ScalarT base \ref scalar type of each Component
|
/// \tparam ScalarT base \ref scalar type of each Component
|
||||||
/// \tparam IndicesV index of each Component
|
/// \tparam IndicesV index of each Component
|
||||||
/// \nosubgrouping
|
/// \nosubgrouping
|
||||||
template<typename ScalarT, size_t... IndicesV>
|
template<typename ScalarT, size_t... IndicesV> requires(is_scalar_v<ScalarT>)
|
||||||
struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||||
{
|
{
|
||||||
// Assertions ==========================================================================================================
|
// Assertions ==========================================================================================================
|
||||||
@@ -337,6 +338,21 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
|||||||
vector::_construct<0>(args...);
|
vector::_construct<0>(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr vector(initializer_list<ScalarT> init) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (ScalarT x : init) {
|
||||||
|
data[i++] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OScalarT>
|
||||||
|
constexpr vector(initializer_list<OScalarT> init) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (OScalarT x : init) {
|
||||||
|
data[i++] = ScalarT(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -1086,22 +1102,22 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t OffsetV>
|
template<size_t OffsetV>
|
||||||
constexpr void _insert(ScalarT& x) {
|
constexpr void _insert(const ScalarT& x) {
|
||||||
data[OffsetV] = x;
|
data[OffsetV] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t OffsetV, typename OScalarT>
|
template<size_t OffsetV, typename OScalarT>
|
||||||
constexpr void _insert(OScalarT& x) {
|
constexpr void _insert(const OScalarT& x) {
|
||||||
data[OffsetV] = ScalarT(x);
|
data[OffsetV] = ScalarT(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t OffsetV = 0, typename OScalarT, size_t... OIndicesV>
|
template<size_t OffsetV = 0, typename OScalarT, size_t... OIndicesV>
|
||||||
constexpr void _insert(vector<OScalarT, OIndicesV...>& vec) {
|
constexpr void _insert(const vector<OScalarT, OIndicesV...>& vec) {
|
||||||
((data[OffsetV + OIndicesV] = fennec::forward<OScalarT>(vec[OIndicesV])), ...);
|
((data[OffsetV + OIndicesV] = fennec::forward<OScalarT>(vec[OIndicesV])), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t OffsetV = 0, typename OVectorT, typename ODataT, typename OScalarT, size_t... OIndicesV>
|
template<size_t OffsetV = 0, typename OVectorT, typename ODataT, typename OScalarT, size_t... OIndicesV>
|
||||||
constexpr void _insert(swizzle<OVectorT, ODataT, OScalarT, OIndicesV...>& vec) {
|
constexpr void _insert(const swizzle<OVectorT, ODataT, OScalarT, OIndicesV...>& vec) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
((data[OffsetV + (i++)] = vec.data[OIndicesV]), ...);
|
((data[OffsetV + (i++)] = vec.data[OIndicesV]), ...);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ public:
|
|||||||
/// \details This simply acts as a proxy for allocating memory. It does not call any constructors or
|
/// \details This simply acts as a proxy for allocating memory. It does not call any constructors or
|
||||||
/// initialize any values as if they were the provided data type. Any operations present work
|
/// initialize any values as if they were the provided data type. Any operations present work
|
||||||
/// only on individual bytes.
|
/// only on individual bytes.
|
||||||
template<typename T, class AllocT>
|
template<typename T, class AllocT = allocator<T>>
|
||||||
struct allocation
|
struct allocation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -366,7 +366,8 @@ public:
|
|||||||
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
|
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
|
||||||
: _alloc(alloc)
|
: _alloc(alloc)
|
||||||
, _data(nullptr)
|
, _data(nullptr)
|
||||||
, _capacity(0) {
|
, _capacity(0)
|
||||||
|
, _alignment(zero<align_t>()) {
|
||||||
callocate(n);
|
callocate(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +440,10 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Default Destructor, releases the memory block if still present
|
/// \brief Default Destructor, releases the memory block if still present
|
||||||
constexpr ~allocation() noexcept {
|
constexpr ~allocation() noexcept {
|
||||||
if (_data) _alloc.deallocate(_data);
|
if (_data) {
|
||||||
|
_alloc.deallocate(_data);
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -450,7 +454,7 @@ 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=(const allocation& alloc) {
|
constexpr allocation& operator=(const allocation& alloc) {
|
||||||
allocation::allocate(alloc.capacity());
|
allocation::allocate(alloc.capacity(), alloc.alignment());
|
||||||
fennec::memmove(_data, alloc, size());
|
fennec::memmove(_data, alloc, size());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -465,12 +469,13 @@ public:
|
|||||||
fennec::swap(_alloc, alloc._alloc);
|
fennec::swap(_alloc, alloc._alloc);
|
||||||
fennec::swap(_data, alloc._data);
|
fennec::swap(_data, alloc._data);
|
||||||
fennec::swap(_capacity, alloc._capacity);
|
fennec::swap(_capacity, alloc._capacity);
|
||||||
|
fennec::swap(_alignment, alloc._alignment);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Allocation and Deallocation =====================================================================================
|
// Allocation and Deallocation =========================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocate a block of memory for the allocation.
|
/// \brief Allocate a block of memory for the allocation.
|
||||||
@@ -627,7 +632,11 @@ public:
|
|||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
constexpr align_t alignment() const {
|
||||||
|
return _alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
alloc_t _alloc; // Allocator object
|
alloc_t _alloc; // Allocator object
|
||||||
value_t* _data; // Handle for the memory block
|
value_t* _data; // Handle for the memory block
|
||||||
size_t _capacity; // Capacity of the memory block in elements.
|
size_t _capacity; // Capacity of the memory block in elements.
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_LANG_BYTES_H
|
#ifndef FENNEC_MEMORY_BYTES_H
|
||||||
#define FENNEC_LANG_BYTES_H
|
#define FENNEC_MEMORY_BYTES_H
|
||||||
|
|
||||||
#include <fennec/lang/assert.h>
|
#include <fennec/lang/assert.h>
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
@@ -186,4 +186,4 @@ struct hash<byte_array> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANG_BYTES_H
|
#endif // FENNEC_MEMORY_BYTES_H
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ using ::wmemcmp;
|
|||||||
/// \param rhs The second object, interpreted as an array of bytes
|
/// \param rhs The second object, interpreted as an array of bytes
|
||||||
/// \param n0 The size, in bytes, of lhs
|
/// \param n0 The size, in bytes, of lhs
|
||||||
/// \param n1 The size, in bytes, of rhs
|
/// \param n1 The size, in bytes, of rhs
|
||||||
|
/// \returns \f$0\f$ if the first \f$min(n0, n1)\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise, returns \f$1\f$
|
||||||
|
/// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$
|
||||||
constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1) {
|
constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1) {
|
||||||
return memcmp(lhs, rhs, n0 < n1 ? n0 : n1);
|
return memcmp(lhs, rhs, n0 < n1 ? n0 : n1);
|
||||||
}
|
}
|
||||||
@@ -98,6 +100,7 @@ using ::wmemcpy;
|
|||||||
/// \param src The source object, interpreted as an array of bytes
|
/// \param src The source object, interpreted as an array of bytes
|
||||||
/// \param n0 The size, in bytes, of dst
|
/// \param n0 The size, in bytes, of dst
|
||||||
/// \param n1 The size, in bytes, of src
|
/// \param n1 The size, in bytes, of src
|
||||||
|
/// \returns \f$dst\f$
|
||||||
constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1) {
|
constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1) {
|
||||||
return memcpy(dst, src, n0 < n1 ? n0 : n1);
|
return memcpy(dst, src, n0 < n1 ? n0 : n1);
|
||||||
}
|
}
|
||||||
@@ -117,6 +120,7 @@ using ::wmemmove;
|
|||||||
/// \param src The source object, interpreted as an array of bytes
|
/// \param src The source object, interpreted as an array of bytes
|
||||||
/// \param n0 The size, in bytes, of dst
|
/// \param n0 The size, in bytes, of dst
|
||||||
/// \param n1 The size, in bytes, of src
|
/// \param n1 The size, in bytes, of src
|
||||||
|
/// \returns \f$dst\f$
|
||||||
constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1) {
|
constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1) {
|
||||||
return memmove(dst, src, n0 < n1 ? n0 : n1);
|
return memmove(dst, src, n0 < n1 ? n0 : n1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ struct default_delete
|
|||||||
/// \param ptr Memory resource to delete
|
/// \param ptr Memory resource to delete
|
||||||
constexpr void operator()(TypeT* ptr) const noexcept {
|
constexpr void operator()(TypeT* ptr) const noexcept {
|
||||||
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||||
static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
|
static_assert(is_complete_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||||
delete ptr;
|
delete ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -70,7 +70,7 @@ struct default_delete<TypeT[]>
|
|||||||
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
|
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
|
||||||
constexpr void operator()(TypeT* ptr) const noexcept {
|
constexpr void operator()(TypeT* ptr) const noexcept {
|
||||||
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||||
static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
|
static_assert(is_complete_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||||
delete[] ptr;
|
delete[] ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -91,6 +91,9 @@ public:
|
|||||||
/// \brief pointer to element type
|
/// \brief pointer to element type
|
||||||
using pointer_t = element_t*;
|
using pointer_t = element_t*;
|
||||||
|
|
||||||
|
/// \brief pointer to element type
|
||||||
|
using const_pointer_t = const element_t*;
|
||||||
|
|
||||||
/// \brief the deleter
|
/// \brief the deleter
|
||||||
using delete_t = DeleteT;
|
using delete_t = DeleteT;
|
||||||
|
|
||||||
@@ -100,22 +103,13 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Nullptr Constructor, creates a unique_ptr that owns nothing.
|
/// \brief Nullptr Constructor, creates a unique_ptr that owns nothing.
|
||||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr) {}
|
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr, delete_t()) {}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
|
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
|
||||||
/// \param ptr The resource to own
|
/// \param ptr The resource to own
|
||||||
/// \param del The deleter
|
/// \param del The deleter
|
||||||
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del)
|
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del = delete_t())
|
||||||
: _delete(del)
|
|
||||||
, _handle(ptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
|
|
||||||
/// \param ptr The resource to own
|
|
||||||
/// \param del The deleter
|
|
||||||
explicit constexpr unique_ptr(pointer_t ptr, delete_t&& del)
|
|
||||||
: _delete(del)
|
: _delete(del)
|
||||||
, _handle(ptr) {
|
, _handle(ptr) {
|
||||||
}
|
}
|
||||||
@@ -134,7 +128,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t`
|
/// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t`
|
||||||
constexpr ~unique_ptr() {
|
constexpr ~unique_ptr() {
|
||||||
if(_handle) _delete(_handle);
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr unique_ptr& operator=(const unique_ptr&) = delete;
|
constexpr unique_ptr& operator=(const unique_ptr&) = delete;
|
||||||
@@ -146,18 +140,59 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset(pointer_t ptr) {
|
||||||
|
if(_handle) {
|
||||||
|
_delete(_handle);
|
||||||
|
_handle = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(nullptr_t = nullptr) {
|
||||||
|
if(_handle) {
|
||||||
|
_delete(_handle);
|
||||||
|
_handle = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pointer_t release() {
|
pointer_t release() {
|
||||||
pointer_t retval = _handle;
|
pointer_t retval = _handle;
|
||||||
_handle = nullptr;
|
_handle = nullptr;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pointer_t get() {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() {
|
||||||
|
return _handle == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer_t operator->() {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_pointer_t operator->() const {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
delete_t _delete;
|
delete_t _delete;
|
||||||
pointer_t _handle;
|
pointer_t _handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Creates a unique pointer holding an object of type `TypeT`
|
||||||
|
/// \tparam TypeT The type
|
||||||
|
/// \tparam ArgsT The constructor arguments, automatically deduced
|
||||||
|
/// \param args The constructor arguments
|
||||||
|
/// \returns A unique pointer holding a heap allocated object of type `TypeT` constructed with arguments `args`
|
||||||
|
template<typename TypeT, typename...ArgsT>
|
||||||
|
unique_ptr<TypeT> make_unique(ArgsT&&...args) {
|
||||||
|
return unique_ptr<TypeT>(new TypeT(fennec::forward<ArgsT>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_MEMORY_POINTERS_H
|
#endif // FENNEC_MEMORY_POINTERS_H
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
// =====================================================================================================================
|
|
||||||
// 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/langproc/strings/string.h>
|
|
||||||
#include <fennec/lang/types.h>
|
|
||||||
#include <fennec/lang/typeuuid.h>
|
|
||||||
#include <fennec/platform/interface/fwd.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
class display : public typed<display>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct pixel_format {
|
|
||||||
uint8_t depth;
|
|
||||||
uint8_t r, g, b;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct config {
|
|
||||||
pixel_format format;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual bool connected() const = 0;
|
|
||||||
virtual ~display();
|
|
||||||
|
|
||||||
virtual window* create_window(window* parent) = 0;
|
|
||||||
|
|
||||||
const pixel_format& get_color_format() const {
|
|
||||||
return _config.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void select_context();
|
|
||||||
virtual void* get_native_handle() = 0;
|
|
||||||
|
|
||||||
platform* get_platform() { return _platform; }
|
|
||||||
gfxcontext* get_context() { return _context; }
|
|
||||||
|
|
||||||
const string name;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
platform* _platform;
|
|
||||||
gfxcontext* _context;
|
|
||||||
config _config;
|
|
||||||
|
|
||||||
template<typename DisplayT>
|
|
||||||
explicit display(platform* platform, const cstring& name, DisplayT* type)
|
|
||||||
: typed(type)
|
|
||||||
, name(name)
|
|
||||||
, _platform(platform)
|
|
||||||
, _context(nullptr)
|
|
||||||
, _config {
|
|
||||||
.format = {
|
|
||||||
.depth = 24,
|
|
||||||
.r = 8,
|
|
||||||
.g = 8,
|
|
||||||
.b = 8,
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_INTERFACE_DISPLAY_H
|
|
||||||
158
include/fennec/platform/interface/display_server.h
Normal file
158
include/fennec/platform/interface/display_server.h
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file display_server.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_INTERFACE_DISPLAY_SERVER_H
|
||||||
|
#define FENNEC_PLATFORM_INTERFACE_DISPLAY_SERVER_H
|
||||||
|
|
||||||
|
#include <fennec/containers/bitfield.h>
|
||||||
|
|
||||||
|
#include <fennec/platform/interface/fwd.h>
|
||||||
|
#include <fennec/platform/interface/window.h>
|
||||||
|
|
||||||
|
#include <fennec/renderers/interface/gfxcontext.h>
|
||||||
|
|
||||||
|
#include <fennec/rtti/enable.h>
|
||||||
|
#include <fennec/rtti/type_registry.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class display_server;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Interface resembling the API for a display server of an operating system, e.g. Linux X11/Wayland
|
||||||
|
///
|
||||||
|
/// \details An implementation for a display server should inherit `display_server_base` and note the following:
|
||||||
|
///
|
||||||
|
/// For a server type `DisplayT`; any `gfxcontext` implementation that wishes to implement `DisplayT`
|
||||||
|
/// must provide a constructor that accepts a `DisplayT*`. `DisplayT::ctx_registry::register_type` must then be
|
||||||
|
/// called for the `gfxcontext` implementation.
|
||||||
|
class display_server : public type_registry<display_server, platform*> {
|
||||||
|
// Typedefs/Constants/Enums ============================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum feature_ : uint32_t {
|
||||||
|
feature_subwindows = 0,
|
||||||
|
feature_icon,
|
||||||
|
|
||||||
|
feature_window_drag,
|
||||||
|
|
||||||
|
feature_mouse,
|
||||||
|
feature_cursors,
|
||||||
|
feature_custom_cursors,
|
||||||
|
|
||||||
|
feature_clipboard,
|
||||||
|
feature_clipboard_primary,
|
||||||
|
feature_virtual_keyboard,
|
||||||
|
|
||||||
|
feature_status_indicators,
|
||||||
|
feature_dialogues,
|
||||||
|
feature_input_dialogues,
|
||||||
|
feature_file_dialogues,
|
||||||
|
feature_filtered_file_dialogues,
|
||||||
|
|
||||||
|
feature_orientation,
|
||||||
|
feature_hidpi,
|
||||||
|
feature_hdr,
|
||||||
|
feature_swap_buffers,
|
||||||
|
feature_window_transparency,
|
||||||
|
|
||||||
|
feature_screen_reader,
|
||||||
|
feature_text_to_speech,
|
||||||
|
feature_touchscreen,
|
||||||
|
feature_system_theme,
|
||||||
|
|
||||||
|
feature_count,
|
||||||
|
};
|
||||||
|
|
||||||
|
using featureset_t = bitfield<feature_count>;
|
||||||
|
using window_id = uint32_t;
|
||||||
|
using window_pool = object_pool<window*>;
|
||||||
|
|
||||||
|
struct config {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Public Members ======================================================================================================
|
||||||
|
platform* const platform;
|
||||||
|
|
||||||
|
explicit display_server(fennec::platform* p)
|
||||||
|
: platform(p) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~display_server() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool has_feature(uint32_t feature) const {
|
||||||
|
return features.test(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual window* create_window(const window::config& conf) = 0;
|
||||||
|
|
||||||
|
window* get_window(size_t id) {
|
||||||
|
return id == window::nullid ? nullptr : windows[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void connect() = 0;
|
||||||
|
virtual void disconnect() = 0;
|
||||||
|
virtual bool connected() const = 0;
|
||||||
|
|
||||||
|
virtual void dispatch() = 0;
|
||||||
|
|
||||||
|
virtual void* get_native_handle() = 0;
|
||||||
|
|
||||||
|
gfxcontext* get_gfx_context() {
|
||||||
|
return gfx_context.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
featureset_t features;
|
||||||
|
window_pool windows;
|
||||||
|
unique_ptr<gfxcontext> gfx_context;
|
||||||
|
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DisplayT, typename WindowT>
|
||||||
|
class display_server_base : public display_server, public type_registry<gfxcontext, DisplayT*> {
|
||||||
|
public:
|
||||||
|
display_server_base(fennec::platform* p)
|
||||||
|
: display_server(p) {
|
||||||
|
}
|
||||||
|
|
||||||
|
using ctx_registry = type_registry<gfxcontext, DisplayT*>;
|
||||||
|
using window_t = WindowT;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_INTERFACE_DISPLAY_SERVER_H
|
||||||
@@ -22,12 +22,12 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class platform; // Handles OS level functionality
|
class platform;
|
||||||
class display; // Handles display protocols
|
|
||||||
|
class display_server; // The display server used by the OS, e.g. WDM, Wayland, X11, etc.
|
||||||
|
class gfxcontext; // Handles the GFX API context of a display server, e.g. OpenGL, Vulkan, etc.
|
||||||
class window; // Handles window surfaces of the display protocol
|
class window; // Handles window surfaces of the display protocol
|
||||||
class inputdevice; // Handles input devices
|
class gfxsurface; // Handles the GFX surface of a window for a specific gfxcontext
|
||||||
class gfxcontext; // Handle Driver Contexts, i.e. EGL, WGL, VkWayland, etc.
|
|
||||||
class gfxsurface; // Handle surface targets for windows
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,12 @@
|
|||||||
#ifndef FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
#ifndef FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
||||||
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
||||||
|
|
||||||
#include <fennec/containers/list.h>
|
#include <fennec/platform/interface/display_server.h>
|
||||||
#include <fennec/langproc/strings/cstring.h>
|
#include <fennec/string/cstring.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
|
||||||
#include <fennec/lang/typeuuid.h>
|
#include <fennec/rtti/enable.h>
|
||||||
#include <fennec/platform/interface/fwd.h>
|
#include <fennec/rtti/singleton.h>
|
||||||
|
#include <fennec/rtti/detail/_this_t.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This class should resemble the target platform as a whole. By itself, it will represent the OS, i.e. Linux, Windows,
|
* This class should resemble the target platform as a whole. By itself, it will represent the OS, i.e. Linux, Windows,
|
||||||
@@ -59,14 +60,16 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class platform : public typed<platform> {
|
///
|
||||||
|
/// \brief Main platform class
|
||||||
|
class platform : public singleton<platform*> {
|
||||||
public:
|
public:
|
||||||
using shared_object = struct shared_object;
|
using shared_object = struct shared_object;
|
||||||
using symbol = void*;
|
using symbol = void*;
|
||||||
|
|
||||||
const string name;
|
platform();
|
||||||
|
|
||||||
virtual ~platform() = default;
|
virtual ~platform() = default;
|
||||||
|
platform(const platform&) = delete;
|
||||||
|
|
||||||
// Dynamically linked objects
|
// Dynamically linked objects
|
||||||
virtual shared_object* load_object(const cstring& file) = 0;
|
virtual shared_object* load_object(const cstring& file) = 0;
|
||||||
@@ -76,63 +79,12 @@ public:
|
|||||||
virtual void initialize(); // Initialize Drivers and Contexts
|
virtual void initialize(); // Initialize Drivers and Contexts
|
||||||
virtual void shutdown(); // Close Drivers and Contexts
|
virtual void shutdown(); // Close Drivers and Contexts
|
||||||
|
|
||||||
display* get_display() { return _display; }
|
display_server* get_display_server() { return display.get(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename PlatformT>
|
unique_ptr<display_server> display;
|
||||||
explicit platform(const cstring& name, PlatformT* type)
|
|
||||||
: typed(type)
|
|
||||||
, name(name) {
|
|
||||||
auto& globals = _get_globals();
|
|
||||||
assertf(globals.singleton == nullptr, "Conflicting Platform Definitions.");
|
|
||||||
globals.singleton = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void load_display();
|
FENNEC_RTTI_CLASS_ENABLE() {
|
||||||
|
|
||||||
display* _display;
|
|
||||||
|
|
||||||
private:
|
|
||||||
platform(const platform&) = delete;
|
|
||||||
|
|
||||||
// Static Stuff ========================================================================================================
|
|
||||||
|
|
||||||
public:
|
|
||||||
using display_ctor = display* (*)(platform*);
|
|
||||||
using input_ctor = inputdevice* (*)(display*);
|
|
||||||
using gfxctx_ctor = gfxcontext* (*)(display*);
|
|
||||||
|
|
||||||
template<typename ctor>
|
|
||||||
struct driver {
|
|
||||||
int priority;
|
|
||||||
ctor constructor;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct global_context {
|
|
||||||
platform* singleton;
|
|
||||||
list<driver<display_ctor>> displays;
|
|
||||||
list<driver<input_ctor>> inputs;
|
|
||||||
list<driver<gfxctx_ctor>> graphics;
|
|
||||||
|
|
||||||
global_context()
|
|
||||||
: singleton(nullptr) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void add_driver(display_ctor ctor, int priority);
|
|
||||||
static void add_driver(input_ctor ctor, int priority);
|
|
||||||
static void add_driver(gfxctx_ctor ctor, int priority);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static global_context& _get_globals();
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const global_context& get_globals() {
|
|
||||||
return _get_globals();
|
|
||||||
}
|
|
||||||
|
|
||||||
static platform* instance() {
|
|
||||||
return _get_globals().singleton;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,152 +16,179 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file window.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
#ifndef FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
||||||
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
||||||
|
|
||||||
#include <fennec/containers/optional.h>
|
|
||||||
#include <fennec/langproc/strings/string.h>
|
|
||||||
#include <fennec/platform/interface/fwd.h>
|
#include <fennec/platform/interface/fwd.h>
|
||||||
#include <fennec/platform/linux/wayland/display.h>
|
|
||||||
|
#include <fennec/math/ext/rect.h>
|
||||||
|
|
||||||
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
|
#include <fennec/containers/bitfield.h>
|
||||||
|
#include <fennec/containers/optional.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
///
|
class window {
|
||||||
/// \brief interface for handling windows
|
// Structures & Typedefs ===============================================================================================
|
||||||
/// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation.
|
|
||||||
class window : public typed<window> {
|
|
||||||
public:
|
public:
|
||||||
enum class fullscreen_mode {
|
static constexpr size_t nullid = -1;
|
||||||
windowed = 0,
|
|
||||||
borderless,
|
enum mode_ : uint8_t {
|
||||||
fullscreen
|
mode_windowed = 0,
|
||||||
|
mode_minimized,
|
||||||
|
mode_maximized,
|
||||||
|
mode_fullscreen,
|
||||||
|
mode_exclusive_fullscreen,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum flags_ : uint32_t {
|
enum vsync_ : uint8_t {
|
||||||
flags_none = 0,
|
vsync_disabled = 0,
|
||||||
flags_child = 0x1 << 0,
|
vsync_enabled,
|
||||||
flags_modal = 0x1 << 1,
|
vsync_adaptive
|
||||||
flags_grab_mouse = 0x1 << 2,
|
};
|
||||||
flags_grab_keyboard = 0x1 << 3,
|
|
||||||
flags_block_screensaver = 0x1 << 4,
|
enum flag_ : uint8_t {
|
||||||
|
flag_always_on_top = 0, // Window always appears on top level
|
||||||
|
flag_borderless, // Window has no border decorations
|
||||||
|
flag_modal, // Window always appears above parent and blocks input going to parent
|
||||||
|
flag_pass_mouse, // Mouse interaction passes to next underlying window in the application
|
||||||
|
flag_popup, // Window does not show in taskbar and closes when loses focus
|
||||||
|
flag_resizable, // Window can be resized through functions defined by Desktop Environment
|
||||||
|
flag_transparent, // Window has an alpha value
|
||||||
|
flag_no_focus, // Window can be focused
|
||||||
|
|
||||||
|
flag_count
|
||||||
|
};
|
||||||
|
|
||||||
|
enum state_ : uint8_t {
|
||||||
|
state_running = 0, // Window is running
|
||||||
|
state_child, // Window is a child
|
||||||
|
state_suspended, // Window is suspended
|
||||||
|
state_visible, // Window is visible
|
||||||
|
|
||||||
|
state_count
|
||||||
|
};
|
||||||
|
|
||||||
|
using flags_t = bitfield<flag_count>;
|
||||||
|
using state_t = bitfield<state_count>;
|
||||||
|
|
||||||
|
struct accessibility {
|
||||||
|
string name, description;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config {
|
struct config {
|
||||||
string title;
|
string title;
|
||||||
uint32_t flags;
|
flags_t flags;
|
||||||
size_t width, height;
|
uint8_t mode;
|
||||||
fullscreen_mode fullscreen;
|
|
||||||
|
size_t parent;
|
||||||
|
irect rect;
|
||||||
|
|
||||||
|
double_t fractional_scaling;
|
||||||
|
|
||||||
|
accessibility accessibility;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct state {
|
||||||
|
uint8_t mode;
|
||||||
|
irect rect;
|
||||||
|
state_t flags;
|
||||||
|
int_t buffer_scale;
|
||||||
|
double_t fractional_scaling;
|
||||||
|
};
|
||||||
|
|
||||||
|
window(display_server* server, size_t id, const config& conf)
|
||||||
|
: server(server), id(id)
|
||||||
|
, cfg(conf), state(), root(nullptr) {
|
||||||
|
state.mode = conf.mode;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~window() = default;
|
virtual ~window() = default;
|
||||||
|
|
||||||
virtual bool running() = 0;
|
size_t get_id() const { return id; }
|
||||||
virtual void configure(const config& config) = 0;
|
size_t get_parent_id() const { return cfg.parent; }
|
||||||
virtual bool initialize(bool modal) = 0;
|
|
||||||
virtual bool shutdown() = 0;
|
|
||||||
|
|
||||||
virtual bool set_title(const cstring& title) = 0;
|
const config& get_config() const { return cfg; }
|
||||||
virtual bool set_title(const string& title) = 0;
|
|
||||||
|
|
||||||
virtual bool set_width(size_t w) = 0;
|
window* get_parent() const;
|
||||||
virtual bool set_height(size_t h) = 0;
|
|
||||||
virtual bool resize(size_t w, size_t h) = 0;
|
|
||||||
|
|
||||||
virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0;
|
const ivec2& get_size() const { return state.rect.size; }
|
||||||
|
const ivec2& get_position() const { return state.rect.position; }
|
||||||
|
|
||||||
virtual bool set_resizable(bool e) = 0;
|
int get_width() const { return state.rect.size.x; }
|
||||||
|
int get_height() const { return state.rect.size.y; }
|
||||||
virtual bool grab_keyboard(bool e) = 0;
|
int get_pos_x() const { return state.rect.position.x; }
|
||||||
virtual bool grab_mouse(bool e) = 0;
|
int get_pos_y() const { return state.rect.position.y; }
|
||||||
virtual bool block_screensaver(bool e) = 0;
|
|
||||||
|
|
||||||
virtual struct wl_surface* get_native_handle() = 0;
|
|
||||||
|
|
||||||
bool is_child() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_child;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_modal() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_modal;
|
|
||||||
}
|
|
||||||
|
|
||||||
display* get_display() {
|
|
||||||
return _display;
|
|
||||||
}
|
|
||||||
|
|
||||||
const display* get_display() const {
|
|
||||||
return _display;
|
|
||||||
}
|
|
||||||
|
|
||||||
const config& get_config() const {
|
|
||||||
return *_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const string& get_title() const {
|
bool is_visible() const { return state.flags.test(state_visible); }
|
||||||
static const string _null{"null"};
|
bool is_child() const { return state.flags.test(state_child); }
|
||||||
if (not _config) return _null;
|
bool is_running() const { return state.flags.test(state_running); }
|
||||||
return _config->title;
|
bool is_suspended() const { return state.flags.test(state_suspended); }
|
||||||
}
|
|
||||||
|
bool get_flag(uint8_t flag) const { return cfg.flags.test(flag); }
|
||||||
|
|
||||||
|
bool is_always_on_top() const { return get_flag(flag_always_on_top); }
|
||||||
|
bool is_borderless() const { return get_flag(flag_borderless); }
|
||||||
|
bool is_modal() const { return get_flag(flag_modal); }
|
||||||
|
bool is_passing_mouse() const { return get_flag(flag_pass_mouse); }
|
||||||
|
bool is_popup() const { return get_flag(flag_popup); }
|
||||||
|
bool is_resizable() const { return get_flag(flag_resizable); }
|
||||||
|
bool is_transparent() const { return get_flag(flag_transparent); }
|
||||||
|
bool is_no_focus() const { return get_flag(flag_no_focus); }
|
||||||
|
|
||||||
|
|
||||||
size_t get_width() const {
|
virtual bool set_flag(uint8_t flag, bool val) = 0;
|
||||||
if (not _config) return false;
|
|
||||||
return _config->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t get_height() const {
|
bool set_always_on_top(bool val) { return set_flag(flag_always_on_top, val); }
|
||||||
if (not _config) return false;
|
bool set_borderless(bool val) { return set_flag(flag_borderless, val); }
|
||||||
return _config->height;
|
bool set_modal(bool val) { return set_flag(flag_modal, val); }
|
||||||
}
|
bool set_passing_mouse(bool val) { return set_flag(flag_pass_mouse, val); }
|
||||||
|
bool set_popup(bool val) { return set_flag(flag_popup, val); }
|
||||||
|
bool set_resizable(bool val) { return set_flag(flag_resizable, val); }
|
||||||
|
bool set_transparent(bool val) { return set_flag(flag_transparent, val); }
|
||||||
|
bool set_no_focus(bool val) { return set_flag(flag_no_focus, val); }
|
||||||
|
|
||||||
|
virtual void initialize() = 0;
|
||||||
|
virtual void shutdown() = 0;
|
||||||
|
|
||||||
fullscreen_mode get_fullscreen_mode() const {
|
virtual void begin_frame();
|
||||||
if (not _config) return fullscreen_mode::windowed;
|
virtual void end_frame();
|
||||||
return _config->fullscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
virtual void* get_native_handle() = 0;
|
||||||
bool is_keyboard_grabbed() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_grab_keyboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_mouse_grabbed() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_grab_mouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_screensaver_blocked() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_block_screensaver;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class DisplayT>
|
|
||||||
DisplayT* get_display() {
|
|
||||||
return static_cast<DisplayT*>(_display);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename TypeT>
|
display_server* const server;
|
||||||
window(display* display, window* parent, TypeT* type)
|
const size_t id;
|
||||||
: typed(type)
|
config cfg;
|
||||||
, _display(display)
|
state state;
|
||||||
, _parent(parent)
|
window* root;
|
||||||
, _surface(nullptr) {
|
gfxsurface* gfx_surface;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DisplayT>
|
||||||
|
class window_base : public window {
|
||||||
|
public:
|
||||||
|
window_base(display_server* display, size_t id, const config& conf)
|
||||||
|
: window(display, id, conf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
display* _display;
|
using display_t = DisplayT;
|
||||||
window* _parent;
|
|
||||||
optional<config> _config;
|
|
||||||
gfxsurface* _surface;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,15 @@ namespace fennec
|
|||||||
class linux_platform : public unix_platform {
|
class linux_platform : public unix_platform {
|
||||||
public:
|
public:
|
||||||
linux_platform()
|
linux_platform()
|
||||||
: unix_platform("linux", this) {
|
: unix_platform() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
|
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE(unix_platform) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
// =====================================================================================================================
|
|
||||||
// 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/platform/interface/display.h>
|
|
||||||
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
class wayland_display : public display {
|
|
||||||
public:
|
|
||||||
explicit wayland_display(platform* platform);
|
|
||||||
~wayland_display() override;
|
|
||||||
|
|
||||||
bool connected() const override;
|
|
||||||
void* get_native_handle() override { return _handle; }
|
|
||||||
|
|
||||||
window* create_window(window* parent) override;
|
|
||||||
|
|
||||||
wl_registry* get_registry() { return _registry; }
|
|
||||||
const wl_registry* get_registry() const { return _registry; }
|
|
||||||
|
|
||||||
wl_compositor* get_compositor() { return _compositor; }
|
|
||||||
const wl_compositor* get_compositor() const { return _compositor; }
|
|
||||||
|
|
||||||
// xdg_wm_base* get_shell() { return _shell; }
|
|
||||||
//const xdg_wm_base* get_shell() const { return _shell; }
|
|
||||||
|
|
||||||
wl_seat* get_seat() { return _seat; }
|
|
||||||
const wl_seat* get_seat() const { return _seat; }
|
|
||||||
|
|
||||||
wl_shm* get_shm() { return _shm; }
|
|
||||||
const wl_shm* get_shm() const { return _shm; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
wl_display* _handle;
|
|
||||||
wl_registry* _registry;
|
|
||||||
wl_compositor* _compositor;
|
|
||||||
//xdg_wm_base* _shell;
|
|
||||||
wl_seat* _seat;
|
|
||||||
wl_shm* _shm;
|
|
||||||
bool _fifo;
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
static void listen_global(void*, wl_registry*, uint32_t, const char*, uint32_t);
|
|
||||||
static void listen_global_remove(void*, wl_registry*, uint32_t);
|
|
||||||
static void listen_seat(void*, wl_seat*, uint32_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H
|
|
||||||
55
include/fennec/platform/linux/wayland/egl/context.h
Normal file
55
include/fennec/platform/linux/wayland/egl/context.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file context.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_EGL_CONTEXT_H
|
||||||
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_EGL_CONTEXT_H
|
||||||
|
|
||||||
|
#include <fennec/platform/opengl/egl/context.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class wayland_eglcontext : public eglcontext {
|
||||||
|
public:
|
||||||
|
explicit wayland_eglcontext(display_server* display);
|
||||||
|
~wayland_eglcontext();
|
||||||
|
|
||||||
|
gfxsurface* create_surface(window* window) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE(eglcontext) {
|
||||||
|
wayland_server::ctx_registry::register_type<wayland_eglcontext>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_EGL_CONTEXT_H
|
||||||
53
include/fennec/platform/linux/wayland/egl/surface.h
Normal file
53
include/fennec/platform/linux/wayland/egl/surface.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file surface.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LATFORM_LINUX_WAYLAND_EGL_SURFACE_H
|
||||||
|
#define LATFORM_LINUX_WAYLAND_EGL_SURFACE_H
|
||||||
|
|
||||||
|
#include <fennec/platform/opengl/egl/surface.h>
|
||||||
|
#include <fennec/platform/linux/wayland/fwd.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class wayland_eglsurface : public eglsurface {
|
||||||
|
public:
|
||||||
|
wayland_eglsurface(wayland_window* win, eglcontext* ctx);
|
||||||
|
~wayland_eglsurface();
|
||||||
|
|
||||||
|
void resize(const ivec2& size) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LATFORM_LINUX_WAYLAND_EGL_SURFACE_H
|
||||||
43
include/fennec/platform/linux/wayland/fwd.h
Normal file
43
include/fennec/platform/linux/wayland/fwd.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file fwd.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
|
||||||
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class wayland_server;
|
||||||
|
class wayland_window;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Generated by wayland-scanner 1.23.1 */
|
/* Generated by wayland-scanner 1.24.0 */
|
||||||
|
|
||||||
#ifndef WAYLAND_CLIENT_PROTOCOL_H
|
#ifndef WAYLAND_CLIENT_PROTOCOL_H
|
||||||
#define WAYLAND_CLIENT_PROTOCOL_H
|
#define WAYLAND_CLIENT_PROTOCOL_H
|
||||||
@@ -36,6 +36,7 @@ extern "C" {
|
|||||||
* - @subpage page_iface_wl_region - region interface
|
* - @subpage page_iface_wl_region - region interface
|
||||||
* - @subpage page_iface_wl_subcompositor - sub-surface compositing
|
* - @subpage page_iface_wl_subcompositor - sub-surface compositing
|
||||||
* - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface
|
* - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface
|
||||||
|
* - @subpage page_iface_wl_fixes - wayland protocol fixes
|
||||||
* @section page_copyright_wayland Copyright
|
* @section page_copyright_wayland Copyright
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
@@ -73,6 +74,7 @@ struct wl_data_device_manager;
|
|||||||
struct wl_data_offer;
|
struct wl_data_offer;
|
||||||
struct wl_data_source;
|
struct wl_data_source;
|
||||||
struct wl_display;
|
struct wl_display;
|
||||||
|
struct wl_fixes;
|
||||||
struct wl_keyboard;
|
struct wl_keyboard;
|
||||||
struct wl_output;
|
struct wl_output;
|
||||||
struct wl_pointer;
|
struct wl_pointer;
|
||||||
@@ -940,6 +942,25 @@ extern const struct wl_interface wl_subcompositor_interface;
|
|||||||
*/
|
*/
|
||||||
extern const struct wl_interface wl_subsurface_interface;
|
extern const struct wl_interface wl_subsurface_interface;
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef WL_FIXES_INTERFACE
|
||||||
|
#define WL_FIXES_INTERFACE
|
||||||
|
/**
|
||||||
|
* @page page_iface_wl_fixes wl_fixes
|
||||||
|
* @section page_iface_wl_fixes_desc Description
|
||||||
|
*
|
||||||
|
* This global fixes problems with other core-protocol interfaces that
|
||||||
|
* cannot be fixed in these interfaces themselves.
|
||||||
|
* @section page_iface_wl_fixes_api API
|
||||||
|
* See @ref iface_wl_fixes.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @defgroup iface_wl_fixes The wl_fixes interface
|
||||||
|
*
|
||||||
|
* This global fixes problems with other core-protocol interfaces that
|
||||||
|
* cannot be fixed in these interfaces themselves.
|
||||||
|
*/
|
||||||
|
extern const struct wl_interface wl_fixes_interface;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WL_DISPLAY_ERROR_ENUM
|
#ifndef WL_DISPLAY_ERROR_ENUM
|
||||||
#define WL_DISPLAY_ERROR_ENUM
|
#define WL_DISPLAY_ERROR_ENUM
|
||||||
@@ -2076,8 +2097,10 @@ struct wl_buffer_listener {
|
|||||||
* compositor releases buffer
|
* compositor releases buffer
|
||||||
*
|
*
|
||||||
* Sent when this wl_buffer is no longer used by the compositor.
|
* Sent when this wl_buffer is no longer used by the compositor.
|
||||||
* The client is now free to reuse or destroy this buffer and its
|
*
|
||||||
* backing storage.
|
* For more information on when release events may or may not be
|
||||||
|
* sent, and what consequences it has, please see the description
|
||||||
|
* of wl_surface.attach.
|
||||||
*
|
*
|
||||||
* If a client receives a release event before the frame callback
|
* If a client receives a release event before the frame callback
|
||||||
* requested in the same wl_surface.commit that attaches this
|
* requested in the same wl_surface.commit that attaches this
|
||||||
@@ -3915,7 +3938,8 @@ wl_surface_destroy(struct wl_surface *wl_surface)
|
|||||||
* the delivery of wl_buffer.release events becomes undefined. A well
|
* the delivery of wl_buffer.release events becomes undefined. A well
|
||||||
* behaved client should not rely on wl_buffer.release events in this
|
* behaved client should not rely on wl_buffer.release events in this
|
||||||
* case. Alternatively, a client could create multiple wl_buffer objects
|
* case. Alternatively, a client could create multiple wl_buffer objects
|
||||||
* from the same backing storage or use wp_linux_buffer_release.
|
* from the same backing storage or use a protocol extension providing
|
||||||
|
* per-commit release notifications.
|
||||||
*
|
*
|
||||||
* Destroying the wl_buffer after wl_buffer.release does not change
|
* Destroying the wl_buffer after wl_buffer.release does not change
|
||||||
* the surface contents. Destroying the wl_buffer before wl_buffer.release
|
* the surface contents. Destroying the wl_buffer before wl_buffer.release
|
||||||
@@ -4247,6 +4271,9 @@ wl_surface_damage_buffer(struct wl_surface *wl_surface, int32_t x, int32_t y, in
|
|||||||
* x and y, combined with the new surface size define in which
|
* x and y, combined with the new surface size define in which
|
||||||
* directions the surface's size changes.
|
* directions the surface's size changes.
|
||||||
*
|
*
|
||||||
|
* The exact semantics of wl_surface.offset are role-specific. Refer to
|
||||||
|
* the documentation of specific roles for more information.
|
||||||
|
*
|
||||||
* Surface location offset is double-buffered state, see
|
* Surface location offset is double-buffered state, see
|
||||||
* wl_surface.commit.
|
* wl_surface.commit.
|
||||||
*
|
*
|
||||||
@@ -4310,9 +4337,10 @@ struct wl_seat_listener {
|
|||||||
/**
|
/**
|
||||||
* seat capabilities changed
|
* seat capabilities changed
|
||||||
*
|
*
|
||||||
* This is emitted whenever a seat gains or loses the pointer,
|
* This is sent on binding to the seat global or whenever a seat
|
||||||
* keyboard or touch capabilities. The argument is a capability
|
* gains or loses the pointer, keyboard or touch capabilities. The
|
||||||
* enum containing the complete set of capabilities this seat has.
|
* argument is a capability enum containing the complete set of
|
||||||
|
* capabilities this seat has.
|
||||||
*
|
*
|
||||||
* When the pointer capability is added, a client may create a
|
* When the pointer capability is added, a client may create a
|
||||||
* wl_pointer object using the wl_seat.get_pointer request. This
|
* wl_pointer object using the wl_seat.get_pointer request. This
|
||||||
@@ -4356,9 +4384,10 @@ struct wl_seat_listener {
|
|||||||
* be shared across processes to refer to a specific wl_seat
|
* be shared across processes to refer to a specific wl_seat
|
||||||
* global.
|
* global.
|
||||||
*
|
*
|
||||||
* The name event is sent after binding to the seat global. This
|
* The name event is sent after binding to the seat global, and
|
||||||
* event is only sent once per seat object, and the name does not
|
* should be sent before announcing capabilities. This event only
|
||||||
* change over the lifetime of the wl_seat global.
|
* sent once per seat object, and the name does not change over the
|
||||||
|
* lifetime of the wl_seat global.
|
||||||
*
|
*
|
||||||
* Compositors may re-use the same seat name if the wl_seat global
|
* Compositors may re-use the same seat name if the wl_seat global
|
||||||
* is destroyed and re-created later.
|
* is destroyed and re-created later.
|
||||||
@@ -5157,6 +5186,14 @@ enum wl_keyboard_keymap_format {
|
|||||||
* physical key state
|
* physical key state
|
||||||
*
|
*
|
||||||
* Describes the physical state of a key that produced the key event.
|
* Describes the physical state of a key that produced the key event.
|
||||||
|
*
|
||||||
|
* Since version 10, the key can be in a "repeated" pseudo-state which
|
||||||
|
* means the same as "pressed", but is used to signal repetition in the
|
||||||
|
* key event.
|
||||||
|
*
|
||||||
|
* The key may only enter the repeated state after entering the pressed
|
||||||
|
* state and before entering the released state. This event may be
|
||||||
|
* generated multiple times while the key is down.
|
||||||
*/
|
*/
|
||||||
enum wl_keyboard_key_state {
|
enum wl_keyboard_key_state {
|
||||||
/**
|
/**
|
||||||
@@ -5167,7 +5204,16 @@ enum wl_keyboard_key_state {
|
|||||||
* key is pressed
|
* key is pressed
|
||||||
*/
|
*/
|
||||||
WL_KEYBOARD_KEY_STATE_PRESSED = 1,
|
WL_KEYBOARD_KEY_STATE_PRESSED = 1,
|
||||||
|
/**
|
||||||
|
* key was repeated
|
||||||
|
* @since 10
|
||||||
|
*/
|
||||||
|
WL_KEYBOARD_KEY_STATE_REPEATED = 2,
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* @ingroup iface_wl_keyboard
|
||||||
|
*/
|
||||||
|
#define WL_KEYBOARD_KEY_STATE_REPEATED_SINCE_VERSION 10
|
||||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
|
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5207,6 +5253,9 @@ struct wl_keyboard_listener {
|
|||||||
* down to the keys in the keys argument. The compositor must not
|
* down to the keys in the keys argument. The compositor must not
|
||||||
* send this event if the wl_keyboard already had an active surface
|
* send this event if the wl_keyboard already had an active surface
|
||||||
* immediately before this event.
|
* immediately before this event.
|
||||||
|
*
|
||||||
|
* Clients should not use the list of pressed keys to emulate
|
||||||
|
* key-press events. The order of keys in the list is unspecified.
|
||||||
* @param serial serial number of the enter event
|
* @param serial serial number of the enter event
|
||||||
* @param surface surface gaining keyboard focus
|
* @param surface surface gaining keyboard focus
|
||||||
* @param keys the keys currently logically down
|
* @param keys the keys currently logically down
|
||||||
@@ -5257,6 +5306,11 @@ struct wl_keyboard_listener {
|
|||||||
* event if state is pressed (resp. released) and the key was
|
* event if state is pressed (resp. released) and the key was
|
||||||
* already logically down (resp. was not logically down)
|
* already logically down (resp. was not logically down)
|
||||||
* immediately before this event.
|
* immediately before this event.
|
||||||
|
*
|
||||||
|
* Since version 10, compositors may send key events with the
|
||||||
|
* "repeated" key state when a wl_keyboard.repeat_info event with a
|
||||||
|
* rate argument of 0 has been received. This allows the compositor
|
||||||
|
* to take over the responsibility of key repetition.
|
||||||
* @param serial serial number of the key event
|
* @param serial serial number of the key event
|
||||||
* @param time timestamp with millisecond granularity
|
* @param time timestamp with millisecond granularity
|
||||||
* @param key key that produced the event
|
* @param key key that produced the event
|
||||||
@@ -6403,6 +6457,69 @@ wl_subsurface_set_desync(struct wl_subsurface *wl_subsurface)
|
|||||||
WL_SUBSURFACE_SET_DESYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0);
|
WL_SUBSURFACE_SET_DESYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WL_FIXES_DESTROY 0
|
||||||
|
#define WL_FIXES_DESTROY_REGISTRY 1
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup iface_wl_fixes
|
||||||
|
*/
|
||||||
|
#define WL_FIXES_DESTROY_SINCE_VERSION 1
|
||||||
|
/**
|
||||||
|
* @ingroup iface_wl_fixes
|
||||||
|
*/
|
||||||
|
#define WL_FIXES_DESTROY_REGISTRY_SINCE_VERSION 1
|
||||||
|
|
||||||
|
/** @ingroup iface_wl_fixes */
|
||||||
|
static inline void
|
||||||
|
wl_fixes_set_user_data(struct wl_fixes *wl_fixes, void *user_data)
|
||||||
|
{
|
||||||
|
wl_proxy_set_user_data((struct wl_proxy *) wl_fixes, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @ingroup iface_wl_fixes */
|
||||||
|
static inline void *
|
||||||
|
wl_fixes_get_user_data(struct wl_fixes *wl_fixes)
|
||||||
|
{
|
||||||
|
return wl_proxy_get_user_data((struct wl_proxy *) wl_fixes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
wl_fixes_get_version(struct wl_fixes *wl_fixes)
|
||||||
|
{
|
||||||
|
return wl_proxy_get_version((struct wl_proxy *) wl_fixes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup iface_wl_fixes
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
wl_fixes_destroy(struct wl_fixes *wl_fixes)
|
||||||
|
{
|
||||||
|
wl_proxy_marshal_flags((struct wl_proxy *) wl_fixes,
|
||||||
|
WL_FIXES_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_fixes), WL_MARSHAL_FLAG_DESTROY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup iface_wl_fixes
|
||||||
|
*
|
||||||
|
* This request destroys a wl_registry object.
|
||||||
|
*
|
||||||
|
* The client should no longer use the wl_registry after making this
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* The compositor will emit a wl_display.delete_id event with the object ID
|
||||||
|
* of the registry and will no longer emit any events on the registry. The
|
||||||
|
* client should re-use the object ID once it receives the
|
||||||
|
* wl_display.delete_id event.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
wl_fixes_destroy_registry(struct wl_fixes *wl_fixes, struct wl_registry *registry)
|
||||||
|
{
|
||||||
|
wl_proxy_marshal_flags((struct wl_proxy *) wl_fixes,
|
||||||
|
WL_FIXES_DESTROY_REGISTRY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_fixes), 0, registry);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Generated by wayland-scanner 1.23.1 */
|
/* Generated by wayland-scanner 1.24.0 */
|
||||||
|
|
||||||
#ifndef XDG_SHELL_CLIENT_PROTOCOL_H
|
#ifndef XDG_SHELL_CLIENT_PROTOCOL_H
|
||||||
#define XDG_SHELL_CLIENT_PROTOCOL_H
|
#define XDG_SHELL_CLIENT_PROTOCOL_H
|
||||||
@@ -1390,6 +1390,46 @@ enum xdg_toplevel_state {
|
|||||||
* @since 6
|
* @since 6
|
||||||
*/
|
*/
|
||||||
XDG_TOPLEVEL_STATE_SUSPENDED = 9,
|
XDG_TOPLEVEL_STATE_SUSPENDED = 9,
|
||||||
|
/**
|
||||||
|
* the surface’s left edge is constrained
|
||||||
|
*
|
||||||
|
* The left edge of the window is currently constrained, meaning
|
||||||
|
* it shouldn't attempt to resize from that edge. It can for
|
||||||
|
* example mean it's tiled next to a monitor edge on the
|
||||||
|
* constrained side of the window.
|
||||||
|
* @since 7
|
||||||
|
*/
|
||||||
|
XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT = 10,
|
||||||
|
/**
|
||||||
|
* the surface’s right edge is constrained
|
||||||
|
*
|
||||||
|
* The right edge of the window is currently constrained, meaning
|
||||||
|
* it shouldn't attempt to resize from that edge. It can for
|
||||||
|
* example mean it's tiled next to a monitor edge on the
|
||||||
|
* constrained side of the window.
|
||||||
|
* @since 7
|
||||||
|
*/
|
||||||
|
XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT = 11,
|
||||||
|
/**
|
||||||
|
* the surface’s top edge is constrained
|
||||||
|
*
|
||||||
|
* The top edge of the window is currently constrained, meaning
|
||||||
|
* it shouldn't attempt to resize from that edge. It can for
|
||||||
|
* example mean it's tiled next to a monitor edge on the
|
||||||
|
* constrained side of the window.
|
||||||
|
* @since 7
|
||||||
|
*/
|
||||||
|
XDG_TOPLEVEL_STATE_CONSTRAINED_TOP = 12,
|
||||||
|
/**
|
||||||
|
* the surface’s bottom edge is tiled
|
||||||
|
*
|
||||||
|
* The bottom edge of the window is currently constrained,
|
||||||
|
* meaning it shouldn't attempt to resize from that edge. It can
|
||||||
|
* for example mean it's tiled next to a monitor edge on the
|
||||||
|
* constrained side of the window.
|
||||||
|
* @since 7
|
||||||
|
*/
|
||||||
|
XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM = 13,
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_xdg_toplevel
|
* @ingroup iface_xdg_toplevel
|
||||||
@@ -1411,6 +1451,22 @@ enum xdg_toplevel_state {
|
|||||||
* @ingroup iface_xdg_toplevel
|
* @ingroup iface_xdg_toplevel
|
||||||
*/
|
*/
|
||||||
#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6
|
#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6
|
||||||
|
/**
|
||||||
|
* @ingroup iface_xdg_toplevel
|
||||||
|
*/
|
||||||
|
#define XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION 7
|
||||||
|
/**
|
||||||
|
* @ingroup iface_xdg_toplevel
|
||||||
|
*/
|
||||||
|
#define XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT_SINCE_VERSION 7
|
||||||
|
/**
|
||||||
|
* @ingroup iface_xdg_toplevel
|
||||||
|
*/
|
||||||
|
#define XDG_TOPLEVEL_STATE_CONSTRAINED_TOP_SINCE_VERSION 7
|
||||||
|
/**
|
||||||
|
* @ingroup iface_xdg_toplevel
|
||||||
|
*/
|
||||||
|
#define XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM_SINCE_VERSION 7
|
||||||
#endif /* XDG_TOPLEVEL_STATE_ENUM */
|
#endif /* XDG_TOPLEVEL_STATE_ENUM */
|
||||||
|
|
||||||
#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM
|
#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM
|
||||||
|
|||||||
@@ -501,8 +501,10 @@
|
|||||||
<event name="release">
|
<event name="release">
|
||||||
<description summary="compositor releases buffer">
|
<description summary="compositor releases buffer">
|
||||||
Sent when this wl_buffer is no longer used by the compositor.
|
Sent when this wl_buffer is no longer used by the compositor.
|
||||||
The client is now free to reuse or destroy this buffer and its
|
|
||||||
backing storage.
|
For more information on when release events may or may not be sent,
|
||||||
|
and what consequences it has, please see the description of
|
||||||
|
wl_surface.attach.
|
||||||
|
|
||||||
If a client receives a release event before the frame callback
|
If a client receives a release event before the frame callback
|
||||||
requested in the same wl_surface.commit that attaches this
|
requested in the same wl_surface.commit that attaches this
|
||||||
@@ -1504,7 +1506,8 @@
|
|||||||
the delivery of wl_buffer.release events becomes undefined. A well
|
the delivery of wl_buffer.release events becomes undefined. A well
|
||||||
behaved client should not rely on wl_buffer.release events in this
|
behaved client should not rely on wl_buffer.release events in this
|
||||||
case. Alternatively, a client could create multiple wl_buffer objects
|
case. Alternatively, a client could create multiple wl_buffer objects
|
||||||
from the same backing storage or use wp_linux_buffer_release.
|
from the same backing storage or use a protocol extension providing
|
||||||
|
per-commit release notifications.
|
||||||
|
|
||||||
Destroying the wl_buffer after wl_buffer.release does not change
|
Destroying the wl_buffer after wl_buffer.release does not change
|
||||||
the surface contents. Destroying the wl_buffer before wl_buffer.release
|
the surface contents. Destroying the wl_buffer before wl_buffer.release
|
||||||
@@ -1832,6 +1835,9 @@
|
|||||||
x and y, combined with the new surface size define in which
|
x and y, combined with the new surface size define in which
|
||||||
directions the surface's size changes.
|
directions the surface's size changes.
|
||||||
|
|
||||||
|
The exact semantics of wl_surface.offset are role-specific. Refer to
|
||||||
|
the documentation of specific roles for more information.
|
||||||
|
|
||||||
Surface location offset is double-buffered state, see
|
Surface location offset is double-buffered state, see
|
||||||
wl_surface.commit.
|
wl_surface.commit.
|
||||||
|
|
||||||
@@ -1880,7 +1886,7 @@
|
|||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_seat" version="9">
|
<interface name="wl_seat" version="10">
|
||||||
<description summary="group of input devices">
|
<description summary="group of input devices">
|
||||||
A seat is a group of keyboards, pointer and touch devices. This
|
A seat is a group of keyboards, pointer and touch devices. This
|
||||||
object is published as a global during start up, or when such a
|
object is published as a global during start up, or when such a
|
||||||
@@ -1908,9 +1914,10 @@
|
|||||||
|
|
||||||
<event name="capabilities">
|
<event name="capabilities">
|
||||||
<description summary="seat capabilities changed">
|
<description summary="seat capabilities changed">
|
||||||
This is emitted whenever a seat gains or loses the pointer,
|
This is sent on binding to the seat global or whenever a seat gains
|
||||||
keyboard or touch capabilities. The argument is a capability
|
or loses the pointer, keyboard or touch capabilities.
|
||||||
enum containing the complete set of capabilities this seat has.
|
The argument is a capability enum containing the complete set of
|
||||||
|
capabilities this seat has.
|
||||||
|
|
||||||
When the pointer capability is added, a client may create a
|
When the pointer capability is added, a client may create a
|
||||||
wl_pointer object using the wl_seat.get_pointer request. This object
|
wl_pointer object using the wl_seat.get_pointer request. This object
|
||||||
@@ -1992,9 +1999,9 @@
|
|||||||
The same seat names are used for all clients. Thus, the name can be
|
The same seat names are used for all clients. Thus, the name can be
|
||||||
shared across processes to refer to a specific wl_seat global.
|
shared across processes to refer to a specific wl_seat global.
|
||||||
|
|
||||||
The name event is sent after binding to the seat global. This event is
|
The name event is sent after binding to the seat global, and should be sent
|
||||||
only sent once per seat object, and the name does not change over the
|
before announcing capabilities. This event only sent once per seat object,
|
||||||
lifetime of the wl_seat global.
|
and the name does not change over the lifetime of the wl_seat global.
|
||||||
|
|
||||||
Compositors may re-use the same seat name if the wl_seat global is
|
Compositors may re-use the same seat name if the wl_seat global is
|
||||||
destroyed and re-created later.
|
destroyed and re-created later.
|
||||||
@@ -2013,7 +2020,7 @@
|
|||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_pointer" version="9">
|
<interface name="wl_pointer" version="10">
|
||||||
<description summary="pointer input device">
|
<description summary="pointer input device">
|
||||||
The wl_pointer interface represents one or more input devices,
|
The wl_pointer interface represents one or more input devices,
|
||||||
such as mice, which control the pointer location and pointer_focus
|
such as mice, which control the pointer location and pointer_focus
|
||||||
@@ -2426,7 +2433,7 @@
|
|||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_keyboard" version="9">
|
<interface name="wl_keyboard" version="10">
|
||||||
<description summary="keyboard input device">
|
<description summary="keyboard input device">
|
||||||
The wl_keyboard interface represents one or more keyboards
|
The wl_keyboard interface represents one or more keyboards
|
||||||
associated with a seat.
|
associated with a seat.
|
||||||
@@ -2479,6 +2486,9 @@
|
|||||||
the surface argument and the keys currently logically down to the keys
|
the surface argument and the keys currently logically down to the keys
|
||||||
in the keys argument. The compositor must not send this event if the
|
in the keys argument. The compositor must not send this event if the
|
||||||
wl_keyboard already had an active surface immediately before this event.
|
wl_keyboard already had an active surface immediately before this event.
|
||||||
|
|
||||||
|
Clients should not use the list of pressed keys to emulate key-press
|
||||||
|
events. The order of keys in the list is unspecified.
|
||||||
</description>
|
</description>
|
||||||
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
||||||
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
|
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
|
||||||
@@ -2505,9 +2515,18 @@
|
|||||||
<enum name="key_state">
|
<enum name="key_state">
|
||||||
<description summary="physical key state">
|
<description summary="physical key state">
|
||||||
Describes the physical state of a key that produced the key event.
|
Describes the physical state of a key that produced the key event.
|
||||||
|
|
||||||
|
Since version 10, the key can be in a "repeated" pseudo-state which
|
||||||
|
means the same as "pressed", but is used to signal repetition in the
|
||||||
|
key event.
|
||||||
|
|
||||||
|
The key may only enter the repeated state after entering the pressed
|
||||||
|
state and before entering the released state. This event may be
|
||||||
|
generated multiple times while the key is down.
|
||||||
</description>
|
</description>
|
||||||
<entry name="released" value="0" summary="key is not pressed"/>
|
<entry name="released" value="0" summary="key is not pressed"/>
|
||||||
<entry name="pressed" value="1" summary="key is pressed"/>
|
<entry name="pressed" value="1" summary="key is pressed"/>
|
||||||
|
<entry name="repeated" value="2" summary="key was repeated" since="10"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<event name="key">
|
<event name="key">
|
||||||
@@ -2530,6 +2549,11 @@
|
|||||||
compositor must not send this event if state is pressed (resp. released)
|
compositor must not send this event if state is pressed (resp. released)
|
||||||
and the key was already logically down (resp. was not logically down)
|
and the key was already logically down (resp. was not logically down)
|
||||||
immediately before this event.
|
immediately before this event.
|
||||||
|
|
||||||
|
Since version 10, compositors may send key events with the "repeated"
|
||||||
|
key state when a wl_keyboard.repeat_info event with a rate argument of
|
||||||
|
0 has been received. This allows the compositor to take over the
|
||||||
|
responsibility of key repetition.
|
||||||
</description>
|
</description>
|
||||||
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
||||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
@@ -2590,7 +2614,7 @@
|
|||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_touch" version="9">
|
<interface name="wl_touch" version="10">
|
||||||
<description summary="touchscreen input device">
|
<description summary="touchscreen input device">
|
||||||
The wl_touch interface represents a touchscreen
|
The wl_touch interface represents a touchscreen
|
||||||
associated with a seat.
|
associated with a seat.
|
||||||
@@ -3245,4 +3269,31 @@
|
|||||||
</request>
|
</request>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
|
<interface name="wl_fixes" version="1">
|
||||||
|
<description summary="wayland protocol fixes">
|
||||||
|
This global fixes problems with other core-protocol interfaces that
|
||||||
|
cannot be fixed in these interfaces themselves.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroys this object"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy_registry">
|
||||||
|
<description summary="destroy a wl_registry">
|
||||||
|
This request destroys a wl_registry object.
|
||||||
|
|
||||||
|
The client should no longer use the wl_registry after making this
|
||||||
|
request.
|
||||||
|
|
||||||
|
The compositor will emit a wl_display.delete_id event with the object ID
|
||||||
|
of the registry and will no longer emit any events on the registry. The
|
||||||
|
client should re-use the object ID once it receives the
|
||||||
|
wl_display.delete_id event.
|
||||||
|
</description>
|
||||||
|
<arg name="registry" type="object" interface="wl_registry"
|
||||||
|
summary="the registry to destroy"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
</protocol>
|
</protocol>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
<interface name="xdg_wm_base" version="6">
|
<interface name="xdg_wm_base" version="7">
|
||||||
<description summary="create desktop-style surfaces">
|
<description summary="create desktop-style surfaces">
|
||||||
The xdg_wm_base interface is exposed as a global object enabling clients
|
The xdg_wm_base interface is exposed as a global object enabling clients
|
||||||
to turn their wl_surfaces into windows in a desktop environment. It
|
to turn their wl_surfaces into windows in a desktop environment. It
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="xdg_positioner" version="6">
|
<interface name="xdg_positioner" version="7">
|
||||||
<description summary="child surface positioner">
|
<description summary="child surface positioner">
|
||||||
The xdg_positioner provides a collection of rules for the placement of a
|
The xdg_positioner provides a collection of rules for the placement of a
|
||||||
child surface relative to a parent surface. Rules can be defined to ensure
|
child surface relative to a parent surface. Rules can be defined to ensure
|
||||||
@@ -407,7 +407,7 @@
|
|||||||
</request>
|
</request>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="xdg_surface" version="6">
|
<interface name="xdg_surface" version="7">
|
||||||
<description summary="desktop user interface surface base interface">
|
<description summary="desktop user interface surface base interface">
|
||||||
An interface that may be implemented by a wl_surface, for
|
An interface that may be implemented by a wl_surface, for
|
||||||
implementations that provide a desktop-style user interface.
|
implementations that provide a desktop-style user interface.
|
||||||
@@ -617,7 +617,7 @@
|
|||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="xdg_toplevel" version="6">
|
<interface name="xdg_toplevel" version="7">
|
||||||
<description summary="toplevel surface">
|
<description summary="toplevel surface">
|
||||||
This interface defines an xdg_surface role which allows a surface to,
|
This interface defines an xdg_surface role which allows a surface to,
|
||||||
among other things, set window-like properties such as maximize,
|
among other things, set window-like properties such as maximize,
|
||||||
@@ -911,6 +911,38 @@
|
|||||||
outputs are switched off due to screen locking.
|
outputs are switched off due to screen locking.
|
||||||
</description>
|
</description>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry name="constrained_left" value="10" since="7">
|
||||||
|
<description summary="the surface’s left edge is constrained">
|
||||||
|
The left edge of the window is currently constrained, meaning it
|
||||||
|
shouldn't attempt to resize from that edge. It can for example mean
|
||||||
|
it's tiled next to a monitor edge on the constrained side of the
|
||||||
|
window.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="constrained_right" value="11" since="7">
|
||||||
|
<description summary="the surface’s right edge is constrained">
|
||||||
|
The right edge of the window is currently constrained, meaning it
|
||||||
|
shouldn't attempt to resize from that edge. It can for example mean
|
||||||
|
it's tiled next to a monitor edge on the constrained side of the
|
||||||
|
window.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="constrained_top" value="12" since="7">
|
||||||
|
<description summary="the surface’s top edge is constrained">
|
||||||
|
The top edge of the window is currently constrained, meaning it
|
||||||
|
shouldn't attempt to resize from that edge. It can for example mean
|
||||||
|
it's tiled next to a monitor edge on the constrained side of the
|
||||||
|
window.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="constrained_bottom" value="13" since="7">
|
||||||
|
<description summary="the surface’s bottom edge is tiled">
|
||||||
|
The bottom edge of the window is currently constrained, meaning it
|
||||||
|
shouldn't attempt to resize from that edge. It can for example mean
|
||||||
|
it's tiled next to a monitor edge on the constrained side of the
|
||||||
|
window.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<request name="set_max_size">
|
<request name="set_max_size">
|
||||||
@@ -1207,7 +1239,7 @@
|
|||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="xdg_popup" version="6">
|
<interface name="xdg_popup" version="7">
|
||||||
<description summary="short-lived, popup surfaces for menus">
|
<description summary="short-lived, popup surfaces for menus">
|
||||||
A popup surface is a short-lived, temporary surface. It can be used to
|
A popup surface is a short-lived, temporary surface. It can be used to
|
||||||
implement for example menus, popovers, tooltips and other similar user
|
implement for example menus, popovers, tooltips and other similar user
|
||||||
|
|||||||
80
include/fennec/platform/linux/wayland/libdecor/libdecor.h
Normal file
80
include/fennec/platform/linux/wayland/libdecor/libdecor.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file libdecor.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_LIBDECOR_H
|
||||||
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIBDECOR_H
|
||||||
|
|
||||||
|
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
||||||
|
#include <libdecor.h>
|
||||||
|
|
||||||
|
#define FENNEC_LIB(name) extern "C" bool FENNEC_HAS_LIB_##name;
|
||||||
|
#define FENNEC_SYMBOL(ret, fn, ...) using LIBDECOR_sym_##fn = ret(*)(__VA_ARGS__); \
|
||||||
|
extern "C" LIBDECOR_sym_##fn LIBDECOR_##fn;
|
||||||
|
#define FENNEC_GLOBAL(type, name) extern "C" type* LIBDECOR_##name;
|
||||||
|
#include <fennec/platform/linux/wayland/libdecor/sym.h>
|
||||||
|
|
||||||
|
#define libdecor_unref LIBDECOR_libdecor_unref
|
||||||
|
#define libdecor_new LIBDECOR_libdecor_new
|
||||||
|
#define libdecor_decorate LIBDECOR_libdecor_decorate
|
||||||
|
#define libdecor_frame_unref LIBDECOR_libdecor_frame_unref
|
||||||
|
#define libdecor_frame_set_title LIBDECOR_libdecor_frame_set_title
|
||||||
|
#define libdecor_frame_set_app_id LIBDECOR_libdecor_frame_set_app_id
|
||||||
|
#define libdecor_frame_set_max_content_size LIBDECOR_libdecor_frame_set_max_content_size
|
||||||
|
#define libdecor_frame_get_max_content_size LIBDECOR_libdecor_frame_get_max_content_size
|
||||||
|
#define libdecor_frame_set_min_content_size LIBDECOR_libdecor_frame_set_min_content_size
|
||||||
|
#define libdecor_frame_get_min_content_size LIBDECOR_libdecor_frame_get_min_content_size
|
||||||
|
#define libdecor_frame_resize LIBDECOR_libdecor_frame_resize
|
||||||
|
#define libdecor_frame_move LIBDECOR_libdecor_frame_move
|
||||||
|
#define libdecor_frame_commit LIBDECOR_libdecor_frame_commit
|
||||||
|
#define libdecor_frame_set_minimized LIBDECOR_libdecor_frame_set_minimized
|
||||||
|
#define libdecor_frame_set_maximized LIBDECOR_libdecor_frame_set_maximized
|
||||||
|
#define libdecor_frame_unset_maximized LIBDECOR_libdecor_frame_unset_maximized
|
||||||
|
#define libdecor_frame_set_fullscreen LIBDECOR_libdecor_frame_set_fullscreen
|
||||||
|
#define libdecor_frame_unset_fullscreen LIBDECOR_libdecor_frame_unset_fullscreen
|
||||||
|
#define libdecor_frame_set_capabilities LIBDECOR_libdecor_frame_set_capabilities
|
||||||
|
#define libdecor_frame_unset_capabilities LIBDECOR_libdecor_frame_unset_capabilities
|
||||||
|
#define libdecor_frame_has_capability LIBDECOR_libdecor_frame_has_capability
|
||||||
|
#define libdecor_frame_set_visibility LIBDECOR_libdecor_frame_set_visibility
|
||||||
|
#define libdecor_frame_is_visible LIBDECOR_libdecor_frame_is_visible
|
||||||
|
#define libdecor_frame_is_floating LIBDECOR_libdecor_frame_is_floating
|
||||||
|
#define libdecor_frame_set_parent LIBDECOR_libdecor_frame_set_parent
|
||||||
|
#define libdecor_frame_show_window_menu LIBDECOR_libdecor_frame_show_window_menu
|
||||||
|
#define libdecor_frame_get_xdg_surface LIBDECOR_libdecor_frame_get_xdg_surface
|
||||||
|
#define libdecor_frame_get_xdg_toplevel LIBDECOR_libdecor_frame_get_xdg_toplevel
|
||||||
|
#define libdecor_frame_translate_coordinate LIBDECOR_libdecor_frame_translate_coordinate
|
||||||
|
#define libdecor_frame_map LIBDECOR_libdecor_frame_map
|
||||||
|
#define libdecor_state_new LIBDECOR_libdecor_state_new
|
||||||
|
#define libdecor_state_free LIBDECOR_libdecor_state_free
|
||||||
|
#define libdecor_configuration_get_content_size LIBDECOR_libdecor_configuration_get_content_size
|
||||||
|
#define libdecor_configuration_get_window_state LIBDECOR_libdecor_configuration_get_window_state
|
||||||
|
#define libdecor_dispatch LIBDECOR_libdecor_dispatch
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_LIBDECOR_H
|
||||||
@@ -16,23 +16,35 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_TEST_LANG_SEQUENCES_H
|
///
|
||||||
#define FENNEC_TEST_LANG_SEQUENCES_H
|
/// \file loader.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#include <fennec/lang/const_sequences.h>
|
|
||||||
|
|
||||||
namespace fennec::test
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_LIBDECOR_LOADER_H
|
||||||
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIBDECOR_LOADER_H
|
||||||
|
|
||||||
|
#include <fennec/platform/interface/platform.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
inline void test_sequences()
|
namespace libdecor
|
||||||
{
|
{
|
||||||
static_assert(fennec::is_same_v<make_index_sequence_t<2>, const_index_sequence<0, 1>>);
|
|
||||||
static_assert(fennec::is_same_v<make_index_sequence_t<3>, const_index_sequence<0, 1, 2>>);
|
|
||||||
static_assert(fennec::is_same_v<make_index_sequence_t<4>, const_index_sequence<0, 1, 2, 3>>);
|
|
||||||
|
|
||||||
// TODO
|
bool load_symbols(platform* platform);
|
||||||
}
|
void unload_symbols(platform* platform);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_TEST_LANG_SEQUENCES_H
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_LIBDECOR_LOADER_H
|
||||||
88
include/fennec/platform/linux/wayland/libdecor/sym.h
Normal file
88
include/fennec/platform/linux/wayland/libdecor/sym.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/lang/types.h>
|
||||||
|
|
||||||
|
#ifndef FENNEC_LIB
|
||||||
|
#define FENNEC_LIB(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FENNEC_SYMBOL
|
||||||
|
#define FENNEC_SYMBOL(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FENNEC_GLOBAL
|
||||||
|
#define FENNEC_GLOBAL(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FENNEC_LIB(LIBDECOR)
|
||||||
|
|
||||||
|
FENNEC_SYMBOL(void, libdecor_unref, struct libdecor*)
|
||||||
|
FENNEC_SYMBOL(int, libdecor_dispatch, struct libdecor*, int)
|
||||||
|
FENNEC_SYMBOL(struct libdecor*, libdecor_new, struct wl_display*, \
|
||||||
|
struct libdecor_interface*)
|
||||||
|
FENNEC_SYMBOL(struct libdecor_frame*, libdecor_decorate, struct libdecor*, \
|
||||||
|
struct wl_surface*, \
|
||||||
|
struct libdecor_frame_interface*, void*)
|
||||||
|
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_unref, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_title, struct libdecor_frame*, const char*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_app_id, struct libdecor_frame*, const char*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_max_content_size, struct libdecor_frame*, int, int)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_min_content_size, struct libdecor_frame*, int, int)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_get_min_content_size, const struct libdecor_frame*, int*, int*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_get_max_content_size, const struct libdecor_frame*, int*, int*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_resize, struct libdecor_frame*, struct wl_seat*, uint32_t, \
|
||||||
|
enum libdecor_resize_edge)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_move, struct libdecor_frame*, struct wl_seat*, uint32_t)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_commit, struct libdecor_frame*, struct libdecor_state*,\
|
||||||
|
struct libdecor_configuration*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_minimized, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_maximized, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_unset_maximized, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_fullscreen, struct libdecor_frame*, struct wl_output*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_unset_fullscreen, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_capabilities, struct libdecor_frame*, enum libdecor_capabilities)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_unset_capabilities, struct libdecor_frame*, enum libdecor_capabilities)
|
||||||
|
FENNEC_SYMBOL(bool, libdecor_frame_has_capability, struct libdecor_frame*, enum libdecor_capabilities)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_visibility, struct libdecor_frame*, bool)
|
||||||
|
FENNEC_SYMBOL(bool, libdecor_frame_is_visible, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(bool, libdecor_frame_is_floating, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_set_parent, struct libdecor_frame*,\
|
||||||
|
struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_show_window_menu, struct libdecor_frame*, struct wl_seat*, uint32_t, int, int)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_translate_coordinate, struct libdecor_frame*, int, int, int*, int*)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_frame_map, struct libdecor_frame*)
|
||||||
|
|
||||||
|
FENNEC_SYMBOL(struct xdg_surface*, libdecor_frame_get_xdg_surface, struct libdecor_frame*)
|
||||||
|
FENNEC_SYMBOL(struct xdg_toplevel*, libdecor_frame_get_xdg_toplevel, struct libdecor_frame*)
|
||||||
|
|
||||||
|
FENNEC_SYMBOL(struct libdecor_state*, libdecor_state_new, int, int)
|
||||||
|
FENNEC_SYMBOL(void, libdecor_state_free, struct libdecor_state*)
|
||||||
|
|
||||||
|
FENNEC_SYMBOL(bool, libdecor_configuration_get_content_size, struct libdecor_configuration*,\
|
||||||
|
struct libdecor_frame*,\
|
||||||
|
int*,\
|
||||||
|
int*)
|
||||||
|
FENNEC_SYMBOL(bool, libdecor_configuration_get_window_state, struct libdecor_configuration*,\
|
||||||
|
enum libdecor_window_state*)
|
||||||
|
|
||||||
|
|
||||||
|
#undef FENNEC_LIB
|
||||||
|
#undef FENNEC_SYMBOL
|
||||||
|
#undef FENNEC_GLOBAL
|
||||||
110
include/fennec/platform/linux/wayland/server.h
Normal file
110
include/fennec/platform/linux/wayland/server.h
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file wayland_server.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
|
||||||
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
|
||||||
|
|
||||||
|
#include <fennec/platform/linux/wayland/fwd.h>
|
||||||
|
#include <fennec/platform/interface/display_server.h>
|
||||||
|
|
||||||
|
#if FENNEC_HAS_LIBDECOR
|
||||||
|
#include <fennec/platform/linux/wayland/libdecor/libdecor.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// forward defs to avoid flooding global namespace
|
||||||
|
struct wl_display;
|
||||||
|
struct wl_shm;
|
||||||
|
struct wl_compositor;
|
||||||
|
struct wl_registry;
|
||||||
|
struct wl_seat;
|
||||||
|
|
||||||
|
struct wp_viewporter;
|
||||||
|
struct xdg_wm_base;
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Class for handling the Wayland Display Server
|
||||||
|
class wayland_server : public display_server_base<wayland_server, wayland_window> {
|
||||||
|
public:
|
||||||
|
explicit wayland_server(fennec::platform* p);
|
||||||
|
~wayland_server() override;
|
||||||
|
|
||||||
|
void connect() override;
|
||||||
|
void disconnect() override;
|
||||||
|
bool connected() const override;
|
||||||
|
|
||||||
|
void dispatch() override;
|
||||||
|
|
||||||
|
window* create_window(const window::config& conf) override;
|
||||||
|
|
||||||
|
void* get_native_handle() override { return display; }
|
||||||
|
|
||||||
|
|
||||||
|
// Fields ==============================================================================================================
|
||||||
|
private:
|
||||||
|
wl_display* display;
|
||||||
|
wl_registry* registry;
|
||||||
|
|
||||||
|
wl_compositor* compositor;
|
||||||
|
xdg_wm_base* xdg;
|
||||||
|
wl_seat* seat;
|
||||||
|
bool fifo, has_libdecor;
|
||||||
|
|
||||||
|
#if FENNEC_HAS_LIBDECOR
|
||||||
|
libdecor* libdecor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Listeners ===========================================================================================================
|
||||||
|
|
||||||
|
static void _wl_registry_listen_global(void*, wl_registry*, uint32_t, const char*, uint32_t);
|
||||||
|
static void _wl_registry_on_global_remove(void*, wl_registry*, uint32_t);
|
||||||
|
|
||||||
|
static void _wl_seat_listen_capabilities(void*, wl_seat*, uint32_t);
|
||||||
|
static void _wl_seat_listen_name(void*, wl_seat*, const char*);
|
||||||
|
|
||||||
|
static void _xdg_listen_ping(void*, xdg_wm_base*, uint32_t);
|
||||||
|
|
||||||
|
#if FENNEC_HAS_LIBDECOR
|
||||||
|
static void _libdecor_on_error(struct libdecor*, libdecor_error error, const char* message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE(display_server) {
|
||||||
|
display_server::register_type<wayland_server>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class wayland_window;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \file window.h
|
/// \file wayland_window.h
|
||||||
/// \brief
|
/// \brief
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -31,51 +31,76 @@
|
|||||||
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||||
|
|
||||||
|
#include <fennec/platform/linux/wayland/fwd.h>
|
||||||
#include <fennec/platform/interface/window.h>
|
#include <fennec/platform/interface/window.h>
|
||||||
#include <fennec/platform/linux/wayland/display.h>
|
|
||||||
|
struct wl_array;
|
||||||
|
struct wl_callback;
|
||||||
|
struct wl_output;
|
||||||
|
struct wl_surface;
|
||||||
|
|
||||||
|
struct xdg_surface;
|
||||||
|
struct xdg_toplevel;
|
||||||
|
|
||||||
|
struct libdecor_frame;
|
||||||
|
struct libdecor_configuration;
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class wayland_window : public window {
|
class wayland_window : public window_base<wayland_server> {
|
||||||
public:
|
public:
|
||||||
bool running() override;
|
wayland_window(display_server* server, uint32_t id, const config& cfg);
|
||||||
|
~wayland_window();
|
||||||
|
|
||||||
void configure(const config& config) override;
|
void initialize() override;
|
||||||
|
void shutdown() override;
|
||||||
|
|
||||||
bool initialize(bool modal) override;
|
void* get_native_handle() override;
|
||||||
|
|
||||||
bool shutdown() override;
|
bool set_flag(uint8_t flag, bool val) override;
|
||||||
|
|
||||||
bool set_title(const cstring& title) override;
|
|
||||||
bool set_title(const string& title) override;
|
|
||||||
|
|
||||||
bool set_width(size_t w) override;
|
|
||||||
bool set_height(size_t h) override;
|
|
||||||
bool resize(size_t w, size_t h) override;
|
|
||||||
bool set_resizable(bool e) override;
|
|
||||||
bool set_fullscreen_mode(fullscreen_mode mode) override;
|
|
||||||
|
|
||||||
bool grab_keyboard(bool e) override;
|
|
||||||
bool grab_mouse(bool e) override;
|
|
||||||
|
|
||||||
bool block_screensaver(bool e) override;
|
|
||||||
|
|
||||||
wayland_window(wayland_display* display, wayland_window* parent);
|
|
||||||
~wayland_window() override;
|
|
||||||
|
|
||||||
struct wl_surface* get_native_handle() override {
|
|
||||||
return _handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Fields ==============================================================================================================
|
||||||
private:
|
private:
|
||||||
wl_surface* _handle;
|
wl_surface* surface;
|
||||||
wl_shell_surface* _shell;
|
xdg_surface* xdgsurface;
|
||||||
size_t _nfs_width, _nfs_height;
|
xdg_toplevel* xdgtoplevel;
|
||||||
|
wl_callback* frame_callback;
|
||||||
|
|
||||||
static void listen_ping(void*, wl_shell_surface*, uint32_t);
|
#if FENNEC_HAS_LIBDECOR
|
||||||
static void listen_configure(void*, wl_shell_surface*, uint32_t, int32_t, int32_t);
|
libdecor_frame* libdecorframe;
|
||||||
static void listen_popup_done(void*, wl_shell_surface*);
|
libdecor_configuration* libdecorcfg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Helpers =============================================================================================================
|
||||||
|
|
||||||
|
void _update_size(const ivec2& size);
|
||||||
|
|
||||||
|
|
||||||
|
// Listeners ===========================================================================================================
|
||||||
|
|
||||||
|
static void _wl_surface_listen_enter(void*, wl_surface*, wl_output*);
|
||||||
|
static void _wl_surface_listen_leave(void*, wl_surface*, wl_output*);
|
||||||
|
static void _wl_surface_listen_preferred_buffer_scale(void*, wl_surface*, int32_t);
|
||||||
|
static void _wl_surface_listen_preferred_buffer_transform(void*, wl_surface*, uint32_t);
|
||||||
|
|
||||||
|
static void _wl_frame_listen_done(void*, wl_callback*, uint32_t);
|
||||||
|
|
||||||
|
static void _xdg_surface_listen_configure(void*, xdg_surface*, uint32_t);
|
||||||
|
|
||||||
|
static void _xdg_toplevel_listen_configure(void*, xdg_toplevel*, int32_t, int32_t, wl_array*);
|
||||||
|
static void _xdg_toplevel_listen_configure_bounds(void*, xdg_toplevel*, int32_t, int32_t);
|
||||||
|
static void _xdg_toplevel_listen_close(void*, xdg_toplevel*);
|
||||||
|
static void _xdg_toplevel_listen_wm_capabilities(void*, xdg_toplevel*, wl_array*);
|
||||||
|
|
||||||
|
#if FENNEC_HAS_LIBDECOR
|
||||||
|
static void _libdecor_frame_listen_configure(libdecor_frame*, libdecor_configuration*, void*);
|
||||||
|
static void _libdecor_frame_listen_close(libdecor_frame*, void*);
|
||||||
|
static void _libdecor_frame_listen_commit(libdecor_frame*, void*);
|
||||||
|
static void _libdecor_frame_listen_dismiss_popup(libdecor_frame*, const char*, void*);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,34 +16,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
/*
|
#include <fennec/lang/types.h>
|
||||||
* Copyright © 2009-2012 Daniel Stone
|
|
||||||
* Copyright © 2012 Intel Corporation
|
|
||||||
* Copyright © 2012 Ran Benita
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifndef FENNEC_LIB
|
#ifndef FENNEC_LIB
|
||||||
#define FENNEC_LIB(...)
|
#define FENNEC_LIB(...)
|
||||||
|
|||||||
@@ -16,44 +16,37 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_PLATFORM_OPENGL_EGL_CONTEXT_H
|
///
|
||||||
#define FENNEC_PLATFORM_OPENGL_EGL_CONTEXT_H
|
/// \file context.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_OPENGL_EGLCONTEXT_H
|
||||||
|
#define FENNEC_PLATFORM_LINUX_WAYLAND_OPENGL_EGLCONTEXT_H
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <fennec/platform/interface/gfxcontext.h>
|
#include <fennec/platform/opengl/egl/error.h>
|
||||||
#include <fennec/platform/opengl/egl/fwd.h>
|
|
||||||
|
#include <fennec/platform/linux/wayland/server.h>
|
||||||
|
#include <fennec/renderers/opengl/glcontext.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class eglcontext : public gfxcontext {
|
class eglcontext : public glcontext {
|
||||||
public:
|
public:
|
||||||
eglcontext(display* display);
|
eglcontext(display_server* display);
|
||||||
|
~eglcontext();
|
||||||
|
|
||||||
~eglcontext() override;
|
bool is_valid() override;
|
||||||
|
|
||||||
bool connected() override;
|
|
||||||
int32_t get_version_major() override { return _eglvmajor; }
|
|
||||||
int32_t get_version_minor() override { return _eglvminor; }
|
|
||||||
int32_t get_version() override { return _eglctype; }
|
|
||||||
const cstring& get_name() override;
|
|
||||||
bool check_extension(const cstring& ext) override;
|
|
||||||
|
|
||||||
gfxsurface* create_surface(window* window) override;
|
|
||||||
|
|
||||||
void make_current(gfxsurface* surface) override;
|
|
||||||
|
|
||||||
EGLDisplay get_egl_display() {
|
|
||||||
return _egldisplay;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLDisplay get_egl_context() {
|
|
||||||
return _eglcontext;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLDisplay get_egl_config() {
|
|
||||||
return _eglconfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EGLDisplay _egldisplay;
|
EGLDisplay _egldisplay;
|
||||||
@@ -62,9 +55,12 @@ private:
|
|||||||
EGLint _eglvmajor, _eglvminor, _eglctype;
|
EGLint _eglvmajor, _eglvminor, _eglctype;
|
||||||
cstring _extensions;
|
cstring _extensions;
|
||||||
|
|
||||||
void cleanup();
|
FENNEC_RTTI_CLASS_ENABLE(glcontext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class eglsurface;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_CONTEXT_H
|
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_OPENGL_EGLCONTEXT_H
|
||||||
|
|||||||
59
include/fennec/platform/opengl/egl/error.h
Normal file
59
include/fennec/platform/opengl/egl/error.h
Normal 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file error.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_PLATFORM_OPENGL_EGL_ERROR_H
|
||||||
|
#define FENNEC_PLATFORM_OPENGL_EGL_ERROR_H
|
||||||
|
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <fennec/string/cstring.h>
|
||||||
|
|
||||||
|
inline fennec::cstring eglErrorString(EGLint err) {
|
||||||
|
switch (err) {
|
||||||
|
case EGL_SUCCESS: return "None";
|
||||||
|
case EGL_NOT_INITIALIZED: return "Not Initialized";
|
||||||
|
case EGL_BAD_ACCESS: return "Bad Access";
|
||||||
|
case EGL_BAD_ALLOC: return "Bad Alloc";
|
||||||
|
case EGL_BAD_ATTRIBUTE: return "Bad Attribute";
|
||||||
|
case EGL_BAD_CONTEXT: return "Bad Context";
|
||||||
|
case EGL_BAD_CONFIG: return "Bad Config";
|
||||||
|
case EGL_BAD_CURRENT_SURFACE: return "Bad Current Surface";
|
||||||
|
case EGL_BAD_DISPLAY: return "Bad Display";
|
||||||
|
case EGL_BAD_SURFACE: return "Bad Surface";
|
||||||
|
case EGL_BAD_MATCH: return "Bad Match";
|
||||||
|
case EGL_BAD_PARAMETER: return "Bad Parameter";
|
||||||
|
case EGL_BAD_NATIVE_PIXMAP: return "Bad Native Pixmap";
|
||||||
|
case EGL_BAD_NATIVE_WINDOW: return "Bad Native Window";
|
||||||
|
case EGL_CONTEXT_LOST: return "Context Lost";
|
||||||
|
default: return "Unknown Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_PLATFORM_OPENGL_EGL_ERROR_H
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user