1From 83eb39e3e87ffd63fdd8d76b64b7a5f5316e6248 Mon Sep 17 00:00:00 2001 2From: Aleksei Sidorov <> 3Date: Thu, 2 Jun 2022 20:19:47 +0300 4Subject: [PATCH] Simplify Zydis build 5 6--- 7 .gitmodules | 3 - 8 BUILD.gn | 52 + 9 CMakeLists.txt | 292 +---- 10 dependencies/zycore | 1 - 11 include/Zydis/Decoder.h | 6 +- 12 include/Zydis/Formatter.h | 22 +- 13 include/Zydis/FormatterBuffer.h | 15 +- 14 include/Zydis/Internal/DecoderData.h | 4 +- 15 include/Zydis/Internal/SharedData.h | 8 +- 16 include/Zydis/MetaInfo.h | 7 +- 17 include/Zydis/Mnemonic.h | 4 +- 18 include/Zydis/Register.h | 16 +- 19 include/Zydis/ShortString.h | 1 - 20 include/Zydis/Utils.h | 12 +- 21 include/Zydis/Zydis.h | 4 +- 22 zycore/CMakeLists.txt | 90 ++ 23 zycore/LICENSE | 22 + 24 zycore/README.md | 29 + 25 zycore/include/Zycore/API/Memory.h | 137 +++ 26 zycore/include/Zycore/API/Process.h | 70 ++ 27 zycore/include/Zycore/API/Synchronization.h | 132 +++ 28 zycore/include/Zycore/API/Terminal.h | 162 +++ 29 zycore/include/Zycore/API/Thread.h | 243 ++++ 30 zycore/include/Zycore/Allocator.h | 142 +++ 31 zycore/include/Zycore/ArgParse.h | 173 +++ 32 zycore/include/Zycore/Atomic.h | 236 ++++ 33 zycore/include/Zycore/Bitset.h | 483 ++++++++ 34 zycore/include/Zycore/Comparison.h | 316 ++++++ 35 zycore/include/Zycore/Defines.h | 521 +++++++++ 36 zycore/include/Zycore/Format.h | 285 +++++ 37 zycore/include/Zycore/Internal/AtomicGNU.h | 117 ++ 38 zycore/include/Zycore/Internal/AtomicMSVC.h | 141 +++ 39 zycore/include/Zycore/LibC.h | 511 +++++++++ 40 zycore/include/Zycore/List.h | 573 ++++++++++ 41 zycore/include/Zycore/Object.h | 84 ++ 42 zycore/include/Zycore/Status.h | 287 +++++ 43 zycore/include/Zycore/String.h | 1011 +++++++++++++++++ 44 zycore/include/Zycore/Types.h | 236 ++++ 45 zycore/include/Zycore/Vector.h | 722 ++++++++++++ 46 zycore/include/Zycore/Zycore.h | 110 ++ 47 zycore/src/API/Memory.c | 132 +++ 48 zycore/src/API/Process.c | 76 ++ 49 zycore/src/API/Synchronization.c | 204 ++++ 50 zycore/src/API/Terminal.c | 160 +++ 51 zycore/src/API/Thread.c | 244 +++++ 52 zycore/src/Allocator.c | 134 +++ 53 zycore/src/ArgParse.c | 279 +++++ 54 zycore/src/Bitset.c | 670 +++++++++++ 55 zycore/src/Format.c | 507 +++++++++ 56 zycore/src/List.c | 673 ++++++++++++ 57 zycore/src/String.c | 1098 +++++++++++++++++++ 58 zycore/src/Vector.c | 846 ++++++++++++++ 59 zycore/src/Zycore.c | 38 + 60 53 files changed, 12045 insertions(+), 296 deletions(-) 61 delete mode 100644 .gitmodules 62 create mode 100644 BUILD.gn 63 delete mode 160000 dependencies/zycore 64 create mode 100644 zycore/CMakeLists.txt 65 create mode 100644 zycore/LICENSE 66 create mode 100644 zycore/README.md 67 create mode 100644 zycore/include/Zycore/API/Memory.h 68 create mode 100644 zycore/include/Zycore/API/Process.h 69 create mode 100644 zycore/include/Zycore/API/Synchronization.h 70 create mode 100644 zycore/include/Zycore/API/Terminal.h 71 create mode 100644 zycore/include/Zycore/API/Thread.h 72 create mode 100644 zycore/include/Zycore/Allocator.h 73 create mode 100644 zycore/include/Zycore/ArgParse.h 74 create mode 100644 zycore/include/Zycore/Atomic.h 75 create mode 100644 zycore/include/Zycore/Bitset.h 76 create mode 100644 zycore/include/Zycore/Comparison.h 77 create mode 100644 zycore/include/Zycore/Defines.h 78 create mode 100644 zycore/include/Zycore/Format.h 79 create mode 100644 zycore/include/Zycore/Internal/AtomicGNU.h 80 create mode 100644 zycore/include/Zycore/Internal/AtomicMSVC.h 81 create mode 100644 zycore/include/Zycore/LibC.h 82 create mode 100644 zycore/include/Zycore/List.h 83 create mode 100644 zycore/include/Zycore/Object.h 84 create mode 100644 zycore/include/Zycore/Status.h 85 create mode 100644 zycore/include/Zycore/String.h 86 create mode 100644 zycore/include/Zycore/Types.h 87 create mode 100644 zycore/include/Zycore/Vector.h 88 create mode 100644 zycore/include/Zycore/Zycore.h 89 create mode 100644 zycore/src/API/Memory.c 90 create mode 100644 zycore/src/API/Process.c 91 create mode 100644 zycore/src/API/Synchronization.c 92 create mode 100644 zycore/src/API/Terminal.c 93 create mode 100644 zycore/src/API/Thread.c 94 create mode 100644 zycore/src/Allocator.c 95 create mode 100644 zycore/src/ArgParse.c 96 create mode 100644 zycore/src/Bitset.c 97 create mode 100644 zycore/src/Format.c 98 create mode 100644 zycore/src/List.c 99 create mode 100644 zycore/src/String.c 100 create mode 100644 zycore/src/Vector.c 101 create mode 100644 zycore/src/Zycore.c 102 103diff --git a/.gitmodules b/.gitmodules 104deleted file mode 100644 105index e0a443d..0000000 106--- a/.gitmodules 107+++ /dev/null 108@@ -1,3 +0,0 @@ 109-[submodule "dependencies/zycore"] 110- path = dependencies/zycore 111- url = https://github.com/zyantific/zycore-c 112diff --git a/BUILD.gn b/BUILD.gn 113new file mode 100644 114index 0000000..bc0c3e4 115--- /dev/null 116+++ b/BUILD.gn 117@@ -0,0 +1,52 @@ 118+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. 119+ 120+import("//ark/runtime_core/ark_config.gni") 121+import("//build/config/ohos/rules.gni") 122+import("//build/ohos.gni") 123+ 124+config("zydis_public_config") { 125+ include_dirs = [ 126+ "$ark_third_party_root/zydis/include", 127+ "$ark_third_party_root/zydis/zycore/include", 128+ "$ark_third_party_root/zydis/src", 129+ ] 130+} 131+ 132+ohos_static_library("libZydis") { 133+ sources = [ 134+ "include/Zydis/Decoder.h", 135+ "include/Zydis/DecoderTypes.h", 136+ "include/Zydis/Formatter.h", 137+ "include/Zydis/FormatterBuffer.h", 138+ "include/Zydis/Internal/DecoderData.h", 139+ "include/Zydis/Internal/FormatterATT.h", 140+ "include/Zydis/Internal/FormatterBase.h", 141+ "include/Zydis/Internal/FormatterIntel.h", 142+ "include/Zydis/Internal/SharedData.h", 143+ "include/Zydis/Internal/String.h", 144+ "include/Zydis/MetaInfo.h", 145+ "include/Zydis/Mnemonic.h", 146+ "include/Zydis/Register.h", 147+ "include/Zydis/SharedTypes.h", 148+ "include/Zydis/ShortString.h", 149+ "include/Zydis/Status.h", 150+ "include/Zydis/Utils.h", 151+ "include/Zydis/Zydis.h", 152+ "src/Decoder.c", 153+ "src/DecoderData.c", 154+ "src/Formatter.c", 155+ "src/FormatterATT.c", 156+ "src/FormatterBase.c", 157+ "src/FormatterBuffer.c", 158+ "src/FormatterIntel.c", 159+ "src/MetaInfo.c", 160+ "src/Mnemonic.c", 161+ "src/Register.c", 162+ "src/SharedData.c", 163+ "src/String.c", 164+ "src/Utils.c", 165+ "src/Zydis.c", 166+ ] 167+ 168+ configs = [ ":zydis_public_config" ] 169+} 170diff --git a/CMakeLists.txt b/CMakeLists.txt 171index 9898f42..a7b6d6c 100644 172--- a/CMakeLists.txt 173+++ b/CMakeLists.txt 174@@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) 175 176 project(Zydis VERSION 3.2.1.0 LANGUAGES C CXX) 177 178-include(GenerateExportHeader) 179 include(GNUInstallDirs) 180 include(CMakePackageConfigHelpers) 181 182@@ -22,87 +21,80 @@ option(ZYDIS_FEATURE_FORMATTER 183 ON) 184 option(ZYDIS_FEATURE_AVX512 185 "Enable support for AVX-512 instructions" 186- ON) 187+ OFF) 188 option(ZYDIS_FEATURE_KNC 189 "Enable support for KNC instructions" 190- ON) 191+ OFF) 192 193 # Build configuration 194-option(ZYDIS_BUILD_SHARED_LIB 195- "Build shared library" 196- OFF) 197-option(ZYDIS_BUILD_EXAMPLES 198- "Build examples" 199- ON) 200-option(ZYDIS_BUILD_TOOLS 201- "Build tools" 202- ON) 203-option(ZYDIS_FUZZ_AFL_FAST 204- "Enables AFL persistent mode and reduces prints in ZydisFuzzIn" 205- OFF) 206-option(ZYDIS_LIBFUZZER 207- "Enables LLVM libfuzzer mode and reduces prints in ZydisFuzzIn" 208- OFF) 209 set(ZYDIS_ZYCORE_PATH 210- "${CMAKE_CURRENT_LIST_DIR}/dependencies/zycore" 211+ "${CMAKE_CURRENT_LIST_DIR}/zycore" 212 CACHE 213 PATH 214 "The path to look for Zycore") 215 216-# =============================================================================================== # 217-# Dependencies # 218-# =============================================================================================== # 219- 220-# Try to initialize the Zycore submodule using Git 221-if (NOT EXISTS "${ZYDIS_ZYCORE_PATH}/CMakeLists.txt" AND 222- "${ZYDIS_ZYCORE_PATH}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}/dependencies/zycore") 223- find_package(Git QUIET) 224- if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") 225- execute_process( 226- COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive 227- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 228- ) 229- endif() 230-endif () 231- 232-if (NOT EXISTS "${ZYDIS_ZYCORE_PATH}/CMakeLists.txt") 233- message( 234- FATAL_ERROR 235- "Can't find zycore submodule. Please make sure to clone the repo recursively.\n" 236- "You can fix this by running\n" 237- " git submodule update --init\n" 238- "or by cloning using\n" 239- " git clone --recursive <url>\n" 240- "Alternatively, you can manually clone zycore to some path and set ZYDIS_ZYCORE_PATH." 241- ) 242-endif () 243- 244 add_subdirectory(${ZYDIS_ZYCORE_PATH} "zycore" EXCLUDE_FROM_ALL) 245 246 # =============================================================================================== # 247 # Library configuration # 248 # =============================================================================================== # 249 250-if (ZYDIS_BUILD_SHARED_LIB) 251- add_library("Zydis" SHARED) 252-else () 253- add_library("Zydis" STATIC) 254+set(ZYDIS_SOURCES 255+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/MetaInfo.h" 256+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Mnemonic.h" 257+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Register.h" 258+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/SharedTypes.h" 259+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/ShortString.h" 260+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Status.h" 261+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Utils.h" 262+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Zydis.h" 263+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/SharedData.h" 264+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/String.h" 265+ "src/MetaInfo.c" 266+ "src/Mnemonic.c" 267+ "src/Register.c" 268+ "src/SharedData.c" 269+ "src/String.c" 270+ "src/Utils.c" 271+ "src/Zydis.c" 272+) 273+ 274+if (ZYDIS_FEATURE_DECODER) 275+ list(APPEND ZYDIS_SOURCES 276+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Decoder.h" 277+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/DecoderTypes.h" 278+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/DecoderData.h" 279+ "src/Decoder.c" 280+ "src/DecoderData.c" 281+ ) 282+ 283+ if (ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE)) 284+ list(APPEND ZYDIS_SOURCES 285+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Formatter.h" 286+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/FormatterBuffer.h" 287+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterATT.h" 288+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterBase.h" 289+ "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterIntel.h" 290+ "src/Formatter.c" 291+ "src/FormatterBuffer.c" 292+ "src/FormatterATT.c" 293+ "src/FormatterBase.c" 294+ "src/FormatterIntel.c" 295+ ) 296+ endif () 297 endif () 298 299+add_library("Zydis" STATIC "${ZYDIS_SOURCES}") 300+set_property(TARGET Zydis PROPERTY POSITION_INDEPENDENT_CODE ON) 301+ 302 target_link_libraries("Zydis" PUBLIC "Zycore") 303 target_include_directories("Zydis" 304 PUBLIC 305 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> 306 $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}> 307- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> 308 PRIVATE "src") 309-target_compile_definitions("Zydis" PRIVATE "_CRT_SECURE_NO_WARNINGS" "ZYDIS_EXPORTS") 310-set_target_properties("Zydis" PROPERTIES 311- VERSION ${Zydis_VERSION} 312- SOVERSION ${Zydis_VERSION_MAJOR}.${Zydis_VERSION_MINOR}) 313-zyan_set_common_flags("Zydis") 314-zyan_maybe_enable_wpo_for_lib("Zydis") 315-generate_export_header("Zydis" BASE_NAME "ZYDIS" EXPORT_FILE_NAME "ZydisExportConfig.h") 316+target_compile_definitions("Zydis" PRIVATE "_CRT_SECURE_NO_WARNINGS") 317+target_compile_options("Zydis" PRIVATE "-std=c99") 318 319 if (ZYDIS_FEATURE_FORMATTER AND NOT ZYDIS_FEATURE_DECODER) 320 message( 321@@ -127,185 +119,3 @@ if (NOT ZYDIS_FEATURE_KNC) 322 target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_KNC") 323 endif () 324 325-target_sources("Zydis" 326- PRIVATE 327- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/MetaInfo.h" 328- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Mnemonic.h" 329- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Register.h" 330- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/SharedTypes.h" 331- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/ShortString.h" 332- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Status.h" 333- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Utils.h" 334- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Zydis.h" 335- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/SharedData.h" 336- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/String.h" 337- "src/MetaInfo.c" 338- "src/Mnemonic.c" 339- "src/Register.c" 340- "src/SharedData.c" 341- "src/String.c" 342- "src/Utils.c" 343- "src/Zydis.c") 344- 345-if (ZYDIS_FEATURE_DECODER) 346- target_sources("Zydis" 347- PRIVATE 348- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Decoder.h" 349- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/DecoderTypes.h" 350- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/DecoderData.h" 351- "src/Decoder.c" 352- "src/DecoderData.c") 353- if (ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE)) 354- target_sources("Zydis" 355- PRIVATE 356- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Formatter.h" 357- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/FormatterBuffer.h" 358- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterATT.h" 359- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterBase.h" 360- "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterIntel.h" 361- "src/Formatter.c" 362- "src/FormatterBuffer.c" 363- "src/FormatterATT.c" 364- "src/FormatterBase.c" 365- "src/FormatterIntel.c") 366- endif () 367-endif () 368- 369-if (ZYDIS_BUILD_SHARED_LIB AND WIN32) 370- target_sources("Zydis" PRIVATE "resources/VersionInfo.rc") 371-endif () 372- 373-zyan_set_source_group("Zydis") 374- 375-configure_package_config_file(cmake/zydis-config.cmake.in 376- "${CMAKE_CURRENT_BINARY_DIR}/zydis-config.cmake" 377- INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zydis" 378-) 379-write_basic_package_version_file( 380- "${CMAKE_CURRENT_BINARY_DIR}/zydis-config-version.cmake" 381- COMPATIBILITY SameMajorVersion 382-) 383-install(FILES 384- "${CMAKE_CURRENT_BINARY_DIR}/zydis-config.cmake" 385- "${CMAKE_CURRENT_BINARY_DIR}/zydis-config-version.cmake" 386- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zydis" 387-) 388- 389-install(TARGETS "Zydis" 390- EXPORT "zydis-targets" 391- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 392- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 393- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 394-install(EXPORT "zydis-targets" 395- NAMESPACE "Zydis::" 396- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zydis") 397-install(FILES 398- "${PROJECT_BINARY_DIR}/ZydisExportConfig.h" 399- DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") 400-install(DIRECTORY "include/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 401- 402-function (_maybe_set_emscripten_cfg target) 403- if (EMSCRIPTEN) 404- # Yep, that madness below is how Emscripten likes its quotes. 405- set_target_properties("${target}" 406- PROPERTIES COMPILE_FLAGS 407- "-s \"EXPORT_NAME='${target}'\" -s MODULARIZE=1") 408- set_target_properties("${target}" 409- PROPERTIES LINK_FLAGS_RELEASE 410- "-s \"EXPORT_NAME='${target}'\" -s MODULARIZE=1") 411- endif () 412-endfunction () 413- 414-# =============================================================================================== # 415-# Examples # 416-# =============================================================================================== # 417- 418-if (ZYDIS_BUILD_EXAMPLES AND NOT ZYAN_NO_LIBC) 419- if (ZYDIS_FEATURE_DECODER AND ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE)) 420- add_executable("Formatter01" "examples/Formatter01.c") 421- target_link_libraries("Formatter01" "Zydis") 422- set_target_properties("Formatter01" PROPERTIES FOLDER "Examples/Formatter") 423- target_compile_definitions("Formatter01" PRIVATE "_CRT_SECURE_NO_WARNINGS") 424- zyan_set_common_flags("Formatter01") 425- zyan_maybe_enable_wpo("Formatter01") 426- _maybe_set_emscripten_cfg("Formatter01") 427- 428- add_executable("Formatter02" "examples/Formatter02.c") 429- target_link_libraries("Formatter02" "Zydis") 430- set_target_properties("Formatter02" PROPERTIES FOLDER "Examples/Formatter") 431- target_compile_definitions("Formatter02" PRIVATE "_CRT_SECURE_NO_WARNINGS") 432- zyan_set_common_flags("Formatter02") 433- zyan_maybe_enable_wpo("Formatter02") 434- _maybe_set_emscripten_cfg("Formatter02") 435- 436- add_executable("Formatter03" "examples/Formatter03.c") 437- target_link_libraries("Formatter03" "Zydis") 438- set_target_properties("Formatter03" PROPERTIES FOLDER "Examples/Formatter") 439- target_compile_definitions("Formatter03" PRIVATE "_CRT_SECURE_NO_WARNINGS") 440- zyan_set_common_flags("Formatter03") 441- zyan_maybe_enable_wpo("Formatter03") 442- _maybe_set_emscripten_cfg("Formatter03") 443- 444- add_executable("ZydisPerfTest" "examples/ZydisPerfTest.c") 445- target_link_libraries("ZydisPerfTest" "Zydis") 446- set_target_properties("ZydisPerfTest" PROPERTIES FOLDER "Examples") 447- target_compile_definitions("ZydisPerfTest" PRIVATE "_CRT_SECURE_NO_WARNINGS") 448- zyan_set_common_flags("ZydisPerfTest") 449- zyan_maybe_enable_wpo("ZydisPerfTest") 450- _maybe_set_emscripten_cfg("ZydisPerfTest") 451- if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" 452- OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") 453- target_compile_definitions("ZydisPerfTest" PRIVATE "_GNU_SOURCE") 454- find_package(Threads REQUIRED) 455- target_link_libraries("ZydisPerfTest" Threads::Threads) 456- endif () 457- endif () 458-endif () 459- 460-# =============================================================================================== # 461-# Tools # 462-# =============================================================================================== # 463- 464-if (ZYDIS_BUILD_TOOLS AND NOT ZYAN_NO_LIBC) 465- if (ZYDIS_FEATURE_DECODER AND ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE)) 466- add_executable("ZydisDisasm" "tools/ZydisDisasm.c") 467- target_link_libraries("ZydisDisasm" "Zydis") 468- set_target_properties ("ZydisDisasm" PROPERTIES FOLDER "Tools") 469- target_compile_definitions("ZydisDisasm" PRIVATE "_CRT_SECURE_NO_WARNINGS") 470- zyan_set_common_flags("ZydisDisasm") 471- zyan_maybe_enable_wpo("ZydisDisasm") 472- _maybe_set_emscripten_cfg("ZydisDisasm") 473- install(TARGETS "ZydisDisasm" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 474- 475- add_executable("ZydisFuzzIn" "tools/ZydisFuzzIn.c") 476- target_link_libraries("ZydisFuzzIn" "Zydis") 477- set_target_properties("ZydisFuzzIn" PROPERTIES FOLDER "Tools") 478- target_compile_definitions("ZydisFuzzIn" PRIVATE "_CRT_SECURE_NO_WARNINGS") 479- zyan_set_common_flags("ZydisFuzzIn") 480- zyan_maybe_enable_wpo("ZydisFuzzIn") 481- _maybe_set_emscripten_cfg("ZydisFuzzIn") 482- if (ZYDIS_FUZZ_AFL_FAST) 483- target_compile_definitions("ZydisFuzzIn" PRIVATE "ZYDIS_FUZZ_AFL_FAST") 484- endif () 485- if (ZYDIS_LIBFUZZER) 486- target_compile_definitions("ZydisFuzzIn" PRIVATE "ZYDIS_LIBFUZZER") 487- endif () 488- 489- add_executable("ZydisInfo" "tools/ZydisInfo.c") 490- target_link_libraries("ZydisInfo" "Zydis") 491- set_target_properties ("ZydisInfo" PROPERTIES FOLDER "Tools") 492- target_compile_definitions("ZydisInfo" PRIVATE "_CRT_SECURE_NO_WARNINGS") 493- zyan_set_common_flags("ZydisInfo") 494- zyan_maybe_enable_wpo("ZydisInfo") 495- _maybe_set_emscripten_cfg("ZydisInfo") 496- install(TARGETS "ZydisInfo" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 497- 498- add_executable("ZydisPE" "tools/ZydisPE.c") 499- target_link_libraries("ZydisPE" "Zydis") 500- set_target_properties ("ZydisPE" PROPERTIES FOLDER "Tools") 501- target_compile_definitions("ZydisPE" PRIVATE "_CRT_SECURE_NO_WARNINGS") 502- zyan_set_common_flags("ZydisPE") 503- zyan_maybe_enable_wpo("ZydisPE") 504- _maybe_set_emscripten_cfg("ZydisPE") 505- endif () 506-endif () 507diff --git a/dependencies/zycore b/dependencies/zycore 508deleted file mode 160000 509index 6c93d9a..0000000 510--- a/dependencies/zycore 511+++ /dev/null 512@@ -1 +0,0 @@ 513-Subproject commit 6c93d9a38e62d4db82f99bf99159e1ee78341e36 514diff --git a/include/Zydis/Decoder.h b/include/Zydis/Decoder.h 515index 8cfbb0c..560145f 100644 516--- a/include/Zydis/Decoder.h 517+++ b/include/Zydis/Decoder.h 518@@ -194,7 +194,7 @@ typedef struct ZydisDecoder_ 519 * 520 * @return A zyan status code. 521 */ 522-ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode, 523+ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode, 524 ZydisAddressWidth address_width); 525 526 /** 527@@ -206,7 +206,7 @@ ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode 528 * 529 * @return A zyan status code. 530 */ 531-ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, 532+ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, 533 ZyanBool enabled); 534 535 /** 536@@ -223,7 +223,7 @@ ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecod 537 * 538 * @return A zyan status code. 539 */ 540-ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder, 541+ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder, 542 const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction); 543 544 /** @} */ 545diff --git a/include/Zydis/Formatter.h b/include/Zydis/Formatter.h 546index bf1dd30..75cc07d 100644 547--- a/include/Zydis/Formatter.h 548+++ b/include/Zydis/Formatter.h 549@@ -970,7 +970,7 @@ struct ZydisFormatter_ 550 * 551 * @return A zyan status code. 552 */ 553-ZYDIS_EXPORT ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style); 554+ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style); 555 556 /* ---------------------------------------------------------------------------------------------- */ 557 /* Setter */ 558@@ -988,7 +988,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisForma 559 * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a property can't be changed for the 560 * current formatter-style. 561 */ 562-ZYDIS_EXPORT ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, 563+ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, 564 ZydisFormatterProperty property, ZyanUPointer value); 565 566 /** 567@@ -1008,7 +1008,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, 568 * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a function can't be replaced for the 569 * current formatter-style. 570 */ 571-ZYDIS_EXPORT ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, 572+ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, 573 ZydisFormatterFunction type, const void** callback); 574 575 /* ---------------------------------------------------------------------------------------------- */ 576@@ -1027,7 +1027,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, 577 * 578 * @return A zyan status code. 579 */ 580-ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter, 581+ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter, 582 const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length, 583 ZyanU64 runtime_address); 584 585@@ -1045,7 +1045,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* fo 586 * 587 * @return A zyan status code. 588 */ 589-ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter, 590+ZyanStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter, 591 const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length, 592 ZyanU64 runtime_address, void* user_data); 593 594@@ -1065,7 +1065,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* 595 * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a 596 * complete instruction. 597 */ 598-ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter, 599+ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter, 600 const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length, 601 ZyanU64 runtime_address); 602 603@@ -1087,7 +1087,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* format 604 * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a 605 * complete instruction. 606 */ 607-ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter, 608+ZyanStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter, 609 const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length, 610 ZyanU64 runtime_address, void* user_data); 611 612@@ -1108,7 +1108,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* form 613 * 614 * @return A zyan status code. 615 */ 616-ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter, 617+ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter, 618 const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length, 619 ZyanU64 runtime_address, ZydisFormatterTokenConst** token); 620 621@@ -1127,7 +1127,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* 622 * 623 * @return A zyan status code. 624 */ 625-ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstructionEx(const ZydisFormatter* formatter, 626+ZyanStatus ZydisFormatterTokenizeInstructionEx(const ZydisFormatter* formatter, 627 const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length, 628 ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); 629 630@@ -1148,7 +1148,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstructionEx(const ZydisFormatter 631 * Use `ZydisFormatterTokenizeInstruction` or `ZydisFormatterTokenizeInstructionEx` to tokenize a 632 * complete instruction. 633 */ 634-ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter, 635+ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter, 636 const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length, 637 ZyanU64 runtime_address, ZydisFormatterTokenConst** token); 638 639@@ -1171,7 +1171,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* form 640 * Use `ZydisFormatterTokenizeInstruction` or `ZydisFormatterTokenizeInstructionEx` to tokenize a 641 * complete instruction. 642 */ 643-ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperandEx(const ZydisFormatter* formatter, 644+ZyanStatus ZydisFormatterTokenizeOperandEx(const ZydisFormatter* formatter, 645 const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length, 646 ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); 647 648diff --git a/include/Zydis/FormatterBuffer.h b/include/Zydis/FormatterBuffer.h 649index 2ae2efe..a06e67b 100644 650--- a/include/Zydis/FormatterBuffer.h 651+++ b/include/Zydis/FormatterBuffer.h 652@@ -32,7 +32,6 @@ 653 #ifndef ZYDIS_FORMATTER_TOKEN_H 654 #define ZYDIS_FORMATTER_TOKEN_H 655 656-#include <ZydisExportConfig.h> 657 #include <Zycore/String.h> 658 #include <Zycore/Types.h> 659 #include <Zydis/Status.h> 660@@ -201,7 +200,7 @@ typedef struct ZydisFormatterBuffer_ 661 * 662 * @return A zyan status code. 663 */ 664-ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token, 665+ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token, 666 ZydisTokenType* type, ZyanConstCharPointer* value); 667 668 /** 669@@ -212,7 +211,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* t 670 * 671 * @return A zyan status code. 672 */ 673-ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token); 674+ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token); 675 676 /* ---------------------------------------------------------------------------------------------- */ 677 /* Buffer */ 678@@ -229,7 +228,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token 679 * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least 680 * one token. 681 */ 682-ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer, 683+ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer, 684 ZydisFormatterTokenConst** token); 685 686 /** 687@@ -247,7 +246,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* 688 * The returned string always refers to the literal value of the current (most recently added) 689 * token and will remain valid until the buffer is destroyed. 690 */ 691-ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, 692+ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, 693 ZyanString** string); 694 695 /** 696@@ -261,7 +260,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buff 697 * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will 698 * automatically be updated by calling this function. 699 */ 700-ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, 701+ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, 702 ZydisTokenType type); 703 704 /** 705@@ -275,7 +274,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, 706 * Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon 707 * as the buffer gets overwritten or destroyed. 708 */ 709-ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, 710+ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, 711 ZyanUPointer* state); 712 713 /** 714@@ -292,7 +291,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* 715 * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will 716 * automatically be updated by calling this function. 717 */ 718-ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, 719+ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, 720 ZyanUPointer state); 721 722 /* ---------------------------------------------------------------------------------------------- */ 723diff --git a/include/Zydis/Internal/DecoderData.h b/include/Zydis/Internal/DecoderData.h 724index db6cf53..011d56f 100644 725--- a/include/Zydis/Internal/DecoderData.h 726+++ b/include/Zydis/Internal/DecoderData.h 727@@ -307,7 +307,7 @@ ZYAN_INLINE const ZydisDecoderTreeNode* ZydisDecoderTreeGetRootNode(void) 728 * 729 * @return The specified child node. 730 */ 731-ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode( 732+const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode( 733 const ZydisDecoderTreeNode* parent, ZyanU16 index); 734 735 /** 736@@ -317,7 +317,7 @@ ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode( 737 * @param node The instruction definition node. 738 * @param info A pointer to the `ZydisInstructionParts` struct. 739 */ 740-ZYDIS_NO_EXPORT void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node, 741+void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node, 742 const ZydisInstructionEncodingInfo** info); 743 744 /* ---------------------------------------------------------------------------------------------- */ 745diff --git a/include/Zydis/Internal/SharedData.h b/include/Zydis/Internal/SharedData.h 746index 5289a3c..fd7bfd3 100644 747--- a/include/Zydis/Internal/SharedData.h 748+++ b/include/Zydis/Internal/SharedData.h 749@@ -919,7 +919,7 @@ typedef struct ZydisAccessedFlags_ 750 * @param definition A pointer to the variable that receives a pointer to the instruction- 751 * definition. 752 */ 753-ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding encoding, 754+void ZydisGetInstructionDefinition(ZydisInstructionEncoding encoding, 755 ZyanU16 id, const ZydisInstructionDefinition** definition); 756 757 /* ---------------------------------------------------------------------------------------------- */ 758@@ -936,7 +936,7 @@ ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding enco 759 * 760 * @return The number of operands for the given instruction-definition. 761 */ 762-ZYDIS_NO_EXPORT ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition, 763+ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition, 764 const ZydisOperandDefinition** operand); 765 #endif 766 767@@ -952,7 +952,7 @@ ZYDIS_NO_EXPORT ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefiniti 768 * @param type The actual element type. 769 * @param size The element size. 770 */ 771-ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type, 772+void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type, 773 ZydisElementSize* size); 774 #endif 775 776@@ -969,7 +969,7 @@ ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, Zydis 777 * 778 * @return `ZYAN_TRUE`, if the instruction accesses any flags, or `ZYAN_FALSE`, if not. 779 */ 780-ZYDIS_NO_EXPORT ZyanBool ZydisGetAccessedFlags(const ZydisInstructionDefinition* definition, 781+ZyanBool ZydisGetAccessedFlags(const ZydisInstructionDefinition* definition, 782 const ZydisAccessedFlags** flags); 783 #endif 784 785diff --git a/include/Zydis/MetaInfo.h b/include/Zydis/MetaInfo.h 786index 6867d32..400dc09 100644 787--- a/include/Zydis/MetaInfo.h 788+++ b/include/Zydis/MetaInfo.h 789@@ -32,7 +32,6 @@ 790 #ifndef ZYDIS_METAINFO_H 791 #define ZYDIS_METAINFO_H 792 793-#include <ZydisExportConfig.h> 794 #include <Zycore/Defines.h> 795 #include <Zycore/Types.h> 796 797@@ -59,7 +58,7 @@ extern "C" { 798 * 799 * @return The instruction category string or `ZYAN_NULL`, if an invalid category was passed. 800 */ 801-ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory category); 802+const char* ZydisCategoryGetString(ZydisInstructionCategory category); 803 804 /** 805 * Returns the specified isa-set string. 806@@ -68,7 +67,7 @@ ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory categor 807 * 808 * @return The isa-set string or `ZYAN_NULL`, if an invalid isa-set was passed. 809 */ 810-ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set); 811+const char* ZydisISASetGetString(ZydisISASet isa_set); 812 813 /** 814 * Returns the specified isa-extension string. 815@@ -77,7 +76,7 @@ ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set); 816 * 817 * @return The isa-extension string or `ZYAN_NULL`, if an invalid isa-extension was passed. 818 */ 819-ZYDIS_EXPORT const char* ZydisISAExtGetString(ZydisISAExt isa_ext); 820+const char* ZydisISAExtGetString(ZydisISAExt isa_ext); 821 822 /* ============================================================================================== */ 823 824diff --git a/include/Zydis/Mnemonic.h b/include/Zydis/Mnemonic.h 825index dd8fec8..132d6f6 100644 826--- a/include/Zydis/Mnemonic.h 827+++ b/include/Zydis/Mnemonic.h 828@@ -62,7 +62,7 @@ extern "C" { 829 * 830 * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. 831 */ 832-ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic); 833+const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic); 834 835 /** 836 * Returns the specified instruction mnemonic as `ZydisShortString`. 837@@ -73,7 +73,7 @@ ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic); 838 * 839 * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. 840 */ 841-ZYDIS_EXPORT const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic); 842+const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic); 843 844 /** 845 * @} 846diff --git a/include/Zydis/Register.h b/include/Zydis/Register.h 847index 0ff955f..a59a597 100644 848--- a/include/Zydis/Register.h 849+++ b/include/Zydis/Register.h 850@@ -200,7 +200,7 @@ typedef struct ZydisRegisterContext_ 851 * @return The register specified by the `register_class` and `id` tuple or `ZYDIS_REGISTER_NONE`, 852 * if an invalid parameter was passed. 853 */ 854-ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id); 855+ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id); 856 857 /** 858 * Returns the id of the specified register. 859@@ -209,7 +209,7 @@ ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class 860 * 861 * @return The id of the specified register, or -1 if an invalid parameter was passed. 862 */ 863-ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg); 864+ZyanI8 ZydisRegisterGetId(ZydisRegister reg); 865 866 /** 867 * Returns the register-class of the specified register. 868@@ -218,7 +218,7 @@ ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg); 869 * 870 * @return The register-class of the specified register. 871 */ 872-ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg); 873+ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg); 874 875 /** 876 * Returns the width of the specified register. 877@@ -229,7 +229,7 @@ ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg); 878 * @return The width of the specified register, or `ZYDIS_REGISTER_NONE` if the register is 879 * invalid for the active machine-mode. 880 */ 881-ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg); 882+ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg); 883 884 /** 885 * Returns the largest enclosing register of the given register. 886@@ -240,7 +240,7 @@ ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, Zyd 887 * @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the 888 * register is invalid for the active machine-mode or does not have an enclosing-register. 889 */ 890-ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, 891+ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, 892 ZydisRegister reg); 893 894 /** 895@@ -250,7 +250,7 @@ ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mod 896 * 897 * @return The register string or `ZYAN_NULL`, if an invalid register was passed. 898 */ 899-ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg); 900+const char* ZydisRegisterGetString(ZydisRegister reg); 901 902 /** 903 * Returns the specified register string as `ZydisShortString`. 904@@ -261,7 +261,7 @@ ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg); 905 * 906 * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. 907 */ 908-ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg); 909+const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg); 910 911 /* ---------------------------------------------------------------------------------------------- */ 912 /* Register class */ 913@@ -275,7 +275,7 @@ ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister 914 * 915 * @return The width of the specified register. 916 */ 917-ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode, 918+ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode, 919 ZydisRegisterClass register_class); 920 921 /* ---------------------------------------------------------------------------------------------- */ 922diff --git a/include/Zydis/ShortString.h b/include/Zydis/ShortString.h 923index bed45af..f55330a 100644 924--- a/include/Zydis/ShortString.h 925+++ b/include/Zydis/ShortString.h 926@@ -33,7 +33,6 @@ 927 #ifndef ZYDIS_SHORTSTRING_H 928 #define ZYDIS_SHORTSTRING_H 929 930-#include <ZydisExportConfig.h> 931 #include <Zycore/Defines.h> 932 #include <Zycore/Types.h> 933 934diff --git a/include/Zydis/Utils.h b/include/Zydis/Utils.h 935index aef9e96..5e3e3ad 100644 936--- a/include/Zydis/Utils.h 937+++ b/include/Zydis/Utils.h 938@@ -175,7 +175,7 @@ typedef struct ZydisInstructionSegments_ 939 * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) 940 * - The displacement needs to get truncated and zero extended 941 */ 942-ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction, 943+ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction, 944 const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address); 945 946 /** 947@@ -195,7 +195,7 @@ ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* 948 * Note that `IP/EIP/RIP` from the register-context will be ignored in favor of the passed 949 * runtime-address. 950 */ 951-ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction, 952+ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction, 953 const ZydisDecodedOperand* operand, ZyanU64 runtime_address, 954 const ZydisRegisterContext* register_context, ZyanU64* result_address); 955 956@@ -212,7 +212,7 @@ ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction 957 * 958 * @return A zyan status code. 959 */ 960-ZYDIS_EXPORT ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruction* instruction, 961+ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruction* instruction, 962 ZydisCPUFlagAction action, ZydisCPUFlags* flags); 963 964 /** 965@@ -226,7 +226,7 @@ ZYDIS_EXPORT ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruct 966 * 967 * @return A zyan status code. 968 */ 969-ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsRead( 970+ZyanStatus ZydisGetAccessedFlagsRead( 971 const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags); 972 973 /** 974@@ -241,7 +241,7 @@ ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsRead( 975 * 976 * @return A zyan status code. 977 */ 978-ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsWritten( 979+ZyanStatus ZydisGetAccessedFlagsWritten( 980 const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags); 981 982 /* ---------------------------------------------------------------------------------------------- */ 983@@ -257,7 +257,7 @@ ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsWritten( 984 * 985 * @return A zyan status code. 986 */ 987-ZYDIS_EXPORT ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction, 988+ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction, 989 ZydisInstructionSegments* segments); 990 991 /* ---------------------------------------------------------------------------------------------- */ 992diff --git a/include/Zydis/Zydis.h b/include/Zydis/Zydis.h 993index 9578fa5..64d1889 100644 994--- a/include/Zydis/Zydis.h 995+++ b/include/Zydis/Zydis.h 996@@ -144,7 +144,7 @@ typedef enum ZydisFeature_ 997 * Use the macros provided in this file to extract the major, minor, patch and build part from the 998 * returned version value. 999 */ 1000-ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void); 1001+ZyanU64 ZydisGetVersion(void); 1002 1003 /** 1004 * Checks, if the specified feature is enabled in the current zydis library instance. 1005@@ -154,7 +154,7 @@ ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void); 1006 * @return `ZYAN_STATUS_TRUE` if the feature is enabled, `ZYAN_STATUS_FALSE` if not. Another 1007 * zyan status code, if an error occured. 1008 */ 1009-ZYDIS_EXPORT ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature); 1010+ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature); 1011 1012 /** 1013 * @} 1014diff --git a/zycore/CMakeLists.txt b/zycore/CMakeLists.txt 1015new file mode 100644 1016index 0000000..7037ebf 1017--- /dev/null 1018+++ b/zycore/CMakeLists.txt 1019@@ -0,0 +1,90 @@ 1020+if (TARGET Zycore) 1021+ return() 1022+endif () 1023+ 1024+cmake_minimum_required(VERSION 3.9 FATAL_ERROR) 1025+ 1026+project(Zycore VERSION 1.1.0.0 LANGUAGES C CXX) 1027+ 1028+include(GNUInstallDirs) 1029+include(CMakePackageConfigHelpers) 1030+ 1031+# =============================================================================================== # 1032+# Overridable options # 1033+# =============================================================================================== # 1034+ 1035+# Global configuration 1036+option(ZYAN_NO_LIBC 1037+ "Don't use any C standard library functions (for exotic build-envs like kernel drivers)" 1038+ OFF) 1039+ 1040+# =============================================================================================== # 1041+# Library configuration # 1042+# =============================================================================================== # 1043+ 1044+set(ZYCORE_SOURCES 1045+ # API 1046+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Memory.h" 1047+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Process.h" 1048+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Synchronization.h" 1049+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Terminal.h" 1050+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Thread.h" 1051+ # Common 1052+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Allocator.h" 1053+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/ArgParse.h" 1054+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Atomic.h" 1055+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Bitset.h" 1056+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Comparison.h" 1057+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Defines.h" 1058+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Format.h" 1059+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/LibC.h" 1060+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/List.h" 1061+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Object.h" 1062+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Status.h" 1063+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/String.h" 1064+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Types.h" 1065+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Vector.h" 1066+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Zycore.h" 1067+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Internal/AtomicGNU.h" 1068+ "${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Internal/AtomicMSVC.h" 1069+ # API 1070+ "src/API/Memory.c" 1071+ "src/API/Process.c" 1072+ "src/API/Synchronization.c" 1073+ "src/API/Terminal.c" 1074+ "src/API/Thread.c" 1075+ # Common 1076+ "src/Allocator.c" 1077+ "src/ArgParse.c" 1078+ "src/Bitset.c" 1079+ "src/Format.c" 1080+ "src/List.c" 1081+ "src/String.c" 1082+ "src/Vector.c" 1083+ "src/Zycore.c" 1084+) 1085+ 1086+add_library("Zycore" STATIC "${ZYCORE_SOURCES}") 1087+ 1088+set_target_properties("Zycore" PROPERTIES LINKER_LANGUAGE C) 1089+target_include_directories("Zycore" 1090+ PUBLIC 1091+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> 1092+ $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}> 1093+ PRIVATE "src") 1094+target_compile_definitions("Zycore" PRIVATE "_CRT_SECURE_NO_WARNINGS") 1095+target_compile_options("Zycore" PRIVATE "-std=c99") 1096+ 1097+if (ZYAN_NO_LIBC) 1098+ target_compile_definitions("Zycore" PUBLIC "ZYAN_NO_LIBC") 1099+ if (UNIX) 1100+ set_target_properties("Zycore" PROPERTIES LINK_FLAGS "-nostdlib -nodefaultlibs") 1101+ endif () 1102+endif () 1103+ 1104+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ZYAN_NO_LIBC) 1105+ target_compile_definitions("Zycore" PRIVATE "_GNU_SOURCE") 1106+ set(THREADS_PREFER_PTHREAD_FLAG ON) 1107+ find_package(Threads REQUIRED) 1108+ target_link_libraries("Zycore" Threads::Threads) 1109+endif () 1110diff --git a/zycore/LICENSE b/zycore/LICENSE 1111new file mode 100644 1112index 0000000..a7fd67c 1113--- /dev/null 1114+++ b/zycore/LICENSE 1115@@ -0,0 +1,22 @@ 1116+The MIT License (MIT) 1117+ 1118+Copyright (c) 2018-2020 Florian Bernd 1119+Copyright (c) 2018-2020 Joel Höner 1120+ 1121+Permission is hereby granted, free of charge, to any person obtaining a copy 1122+of this software and associated documentation files (the "Software"), to deal 1123+in the Software without restriction, including without limitation the rights 1124+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1125+copies of the Software, and to permit persons to whom the Software is 1126+furnished to do so, subject to the following conditions: 1127+ 1128+The above copyright notice and this permission notice shall be included in all 1129+copies or substantial portions of the Software. 1130+ 1131+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1132+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1133+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1134+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1135+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1136+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1137+SOFTWARE. 1138diff --git a/zycore/README.md b/zycore/README.md 1139new file mode 100644 1140index 0000000..ff2fc41 1141--- /dev/null 1142+++ b/zycore/README.md 1143@@ -0,0 +1,29 @@ 1144+# Zyan Core Library for C 1145+ 1146+<a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a> 1147+<a href="https://github.com/zyantific/zycore-c/actions"><img src="https://github.com/zyantific/zycore-c/workflows/GitHub%20Actions%20CI/badge.svg" alt="GitHub Actions"></a> 1148+<a href="https://discord.zyantific.com/"><img src="https://img.shields.io/discord/390136917779415060.svg?logo=discord&label=Discord" alt="Discord"></a> 1149+ 1150+Internal library providing platform independent types, macros and a fallback for environments without LibC. 1151+ 1152+## Features 1153+ 1154+- Platform independent types 1155+ - Integer types (`ZyanU8`, `ZyanI32`, `ZyanUSize`, ...) 1156+ - `ZyanBool` (+ `ZYAN_FALSE`, `ZYAN_TRUE`) 1157+ - `ZYAN_NULL` 1158+- Macros 1159+ - Compiler/Platform/Architecture detection 1160+ - Asserts and static asserts 1161+ - Utils (`ARRAY_LENGTH`, `FALLTHROUGH`, `UNUSED`, ...) 1162+- Common types 1163+ - `ZyanBitset` 1164+ - `ZyanString`/`ZyanStringView` 1165+- Container types 1166+ - `ZyanVector` 1167+ - `ZyanList` 1168+- LibC abstraction (WiP) 1169+ 1170+## License 1171+ 1172+Zycore is licensed under the MIT license. 1173diff --git a/zycore/include/Zycore/API/Memory.h b/zycore/include/Zycore/API/Memory.h 1174new file mode 100644 1175index 0000000..1030e83 1176--- /dev/null 1177+++ b/zycore/include/Zycore/API/Memory.h 1178@@ -0,0 +1,137 @@ 1179+/*************************************************************************************************** 1180+ 1181+ Zyan Core Library (Zycore-C) 1182+ 1183+ Original Author : Florian Bernd 1184+ 1185+ * Permission is hereby granted, free of charge, to any person obtaining a copy 1186+ * of this software and associated documentation files (the "Software"), to deal 1187+ * in the Software without restriction, including without limitation the rights 1188+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1189+ * copies of the Software, and to permit persons to whom the Software is 1190+ * furnished to do so, subject to the following conditions: 1191+ * 1192+ * The above copyright notice and this permission notice shall be included in all 1193+ * copies or substantial portions of the Software. 1194+ * 1195+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1196+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1197+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1198+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1199+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1200+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1201+ * SOFTWARE. 1202+ 1203+***************************************************************************************************/ 1204+ 1205+/** 1206+ * @file 1207+ * @brief 1208+ */ 1209+ 1210+#ifndef ZYCORE_API_MEMORY_H 1211+#define ZYCORE_API_MEMORY_H 1212+ 1213+#include <Zycore/Defines.h> 1214+#include <Zycore/Status.h> 1215+#include <Zycore/Types.h> 1216+ 1217+#ifndef ZYAN_NO_LIBC 1218+ 1219+#if defined(ZYAN_WINDOWS) 1220+# include <windows.h> 1221+#elif defined(ZYAN_POSIX) 1222+# include <sys/mman.h> 1223+#else 1224+# error "Unsupported platform detected" 1225+#endif 1226+ 1227+/* ============================================================================================== */ 1228+/* Enums and types */ 1229+/* ============================================================================================== */ 1230+ 1231+/** 1232+ * Defines the `ZyanMemoryPageProtection` enum. 1233+ */ 1234+typedef enum ZyanMemoryPageProtection_ 1235+{ 1236+#if defined(ZYAN_WINDOWS) 1237+ 1238+ ZYAN_PAGE_READONLY = PAGE_READONLY, 1239+ ZYAN_PAGE_READWRITE = PAGE_READWRITE, 1240+ ZYAN_PAGE_EXECUTE = PAGE_EXECUTE, 1241+ ZYAN_PAGE_EXECUTE_READ = PAGE_EXECUTE_READ, 1242+ ZYAN_PAGE_EXECUTE_READWRITE = PAGE_EXECUTE_READWRITE 1243+ 1244+#elif defined(ZYAN_POSIX) 1245+ 1246+ ZYAN_PAGE_READONLY = PROT_READ, 1247+ ZYAN_PAGE_READWRITE = PROT_READ | PROT_WRITE, 1248+ ZYAN_PAGE_EXECUTE = PROT_EXEC, 1249+ ZYAN_PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ, 1250+ ZYAN_PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE 1251+ 1252+#endif 1253+} ZyanMemoryPageProtection; 1254+ 1255+/* ============================================================================================== */ 1256+/* Exported functions */ 1257+/* ============================================================================================== */ 1258+ 1259+/* ---------------------------------------------------------------------------------------------- */ 1260+/* General */ 1261+/* ---------------------------------------------------------------------------------------------- */ 1262+ 1263+/** 1264+ * Returns the system page size. 1265+ * 1266+ * @return The system page size. 1267+ */ 1268+ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemPageSize(); 1269+ 1270+/** 1271+ * Returns the system allocation granularity. 1272+ * 1273+ * The system allocation granularity specifies the minimum amount of bytes which can be allocated 1274+ * at a specific address by a single call of `ZyanMemoryVirtualAlloc`. 1275+ * 1276+ * This value is typically 64KiB on Windows systems and equal to the page size on most POSIX 1277+ * platforms. 1278+ * 1279+ * @return The system allocation granularity. 1280+ */ 1281+ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemAllocationGranularity(); 1282+ 1283+/* ---------------------------------------------------------------------------------------------- */ 1284+/* Memory management */ 1285+/* ---------------------------------------------------------------------------------------------- */ 1286+ 1287+/** 1288+ * Changes the memory protection value of one or more pages. 1289+ * 1290+ * @param address The start address aligned to a page boundary. 1291+ * @param size The size. 1292+ * @param protection The new page protection value. 1293+ * 1294+ * @return A zyan status code. 1295+ */ 1296+ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size, 1297+ ZyanMemoryPageProtection protection); 1298+ 1299+/** 1300+ * Releases one or more memory pages starting at the given address. 1301+ * 1302+ * @param address The start address aligned to a page boundary. 1303+ * @param size The size. 1304+ * 1305+ * @return A zyan status code. 1306+ */ 1307+ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size); 1308+ 1309+/* ---------------------------------------------------------------------------------------------- */ 1310+ 1311+/* ============================================================================================== */ 1312+ 1313+#endif /* ZYAN_NO_LIBC */ 1314+ 1315+#endif /* ZYCORE_API_MEMORY_H */ 1316diff --git a/zycore/include/Zycore/API/Process.h b/zycore/include/Zycore/API/Process.h 1317new file mode 100644 1318index 0000000..f8e1e4f 1319--- /dev/null 1320+++ b/zycore/include/Zycore/API/Process.h 1321@@ -0,0 +1,70 @@ 1322+/*************************************************************************************************** 1323+ 1324+ Zyan Core Library (Zycore-C) 1325+ 1326+ Original Author : Florian Bernd 1327+ 1328+ * Permission is hereby granted, free of charge, to any person obtaining a copy 1329+ * of this software and associated documentation files (the "Software"), to deal 1330+ * in the Software without restriction, including without limitation the rights 1331+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1332+ * copies of the Software, and to permit persons to whom the Software is 1333+ * furnished to do so, subject to the following conditions: 1334+ * 1335+ * The above copyright notice and this permission notice shall be included in all 1336+ * copies or substantial portions of the Software. 1337+ * 1338+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1339+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1340+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1341+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1342+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1343+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1344+ * SOFTWARE. 1345+ 1346+***************************************************************************************************/ 1347+ 1348+/** 1349+ * @file 1350+ * @brief 1351+ */ 1352+ 1353+#ifndef ZYCORE_API_PROCESS_H 1354+#define ZYCORE_API_PROCESS_H 1355+ 1356+#include <Zycore/Status.h> 1357+#include <Zycore/Types.h> 1358+ 1359+#ifndef ZYAN_NO_LIBC 1360+ 1361+/* ============================================================================================== */ 1362+/* Enums and types */ 1363+/* ============================================================================================== */ 1364+ 1365+ 1366+ 1367+/* ============================================================================================== */ 1368+/* Exported functions */ 1369+/* ============================================================================================== */ 1370+ 1371+/* ---------------------------------------------------------------------------------------------- */ 1372+/* General */ 1373+/* ---------------------------------------------------------------------------------------------- */ 1374+ 1375+/** 1376+ * @brief Flushes the process instruction cache. 1377+ * 1378+ * @param address The address. 1379+ * @param size The size. 1380+ * 1381+ * @return A zyan status code. 1382+ */ 1383+ZYCORE_EXPORT ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size); 1384+ 1385+/* ---------------------------------------------------------------------------------------------- */ 1386+ 1387+/* ============================================================================================== */ 1388+ 1389+#endif /* ZYAN_NO_LIBC */ 1390+ 1391+#endif /* ZYCORE_API_PROCESS_H */ 1392diff --git a/zycore/include/Zycore/API/Synchronization.h b/zycore/include/Zycore/API/Synchronization.h 1393new file mode 100644 1394index 0000000..ec32f06 1395--- /dev/null 1396+++ b/zycore/include/Zycore/API/Synchronization.h 1397@@ -0,0 +1,132 @@ 1398+/*************************************************************************************************** 1399+ 1400+ Zyan Core Library (Zycore-C) 1401+ 1402+ Original Author : Florian Bernd 1403+ 1404+ * Permission is hereby granted, free of charge, to any person obtaining a copy 1405+ * of this software and associated documentation files (the "Software"), to deal 1406+ * in the Software without restriction, including without limitation the rights 1407+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1408+ * copies of the Software, and to permit persons to whom the Software is 1409+ * furnished to do so, subject to the following conditions: 1410+ * 1411+ * The above copyright notice and this permission notice shall be included in all 1412+ * copies or substantial portions of the Software. 1413+ * 1414+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1415+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1416+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1417+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1418+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1419+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1420+ * SOFTWARE. 1421+ 1422+***************************************************************************************************/ 1423+ 1424+/** 1425+ * @file 1426+ * @brief 1427+ */ 1428+ 1429+#ifndef ZYCORE_API_SYNCHRONIZATION_H 1430+#define ZYCORE_API_SYNCHRONIZATION_H 1431+ 1432+#include <Zycore/Defines.h> 1433+#include <Zycore/Status.h> 1434+ 1435+#ifndef ZYAN_NO_LIBC 1436+ 1437+#ifdef __cplusplus 1438+extern "C" { 1439+#endif 1440+ 1441+/* ============================================================================================== */ 1442+/* Enums and types */ 1443+/* ============================================================================================== */ 1444+ 1445+#if defined(ZYAN_POSIX) 1446+ 1447+#include <pthread.h> 1448+ 1449+/* ---------------------------------------------------------------------------------------------- */ 1450+/* Critical Section */ 1451+/* ---------------------------------------------------------------------------------------------- */ 1452+ 1453+typedef pthread_mutex_t ZyanCriticalSection; 1454+ 1455+/* ---------------------------------------------------------------------------------------------- */ 1456+ 1457+#elif defined(ZYAN_WINDOWS) 1458+ 1459+#include <windows.h> 1460+ 1461+/* ---------------------------------------------------------------------------------------------- */ 1462+/* Critical Section */ 1463+/* ---------------------------------------------------------------------------------------------- */ 1464+ 1465+typedef CRITICAL_SECTION ZyanCriticalSection; 1466+ 1467+/* ---------------------------------------------------------------------------------------------- */ 1468+ 1469+#else 1470+# error "Unsupported platform detected" 1471+#endif 1472+ 1473+/* ============================================================================================== */ 1474+/* Exported functions */ 1475+/* ============================================================================================== */ 1476+ 1477+/* ---------------------------------------------------------------------------------------------- */ 1478+/* Critical Section */ 1479+/* ---------------------------------------------------------------------------------------------- */ 1480+ 1481+/** 1482+ * Initializes a critical section. 1483+ * 1484+ * @param critical_section A pointer to the `ZyanCriticalSection` struct. 1485+ */ 1486+ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section); 1487+ 1488+/** 1489+ * Enters a critical section. 1490+ * 1491+ * @param critical_section A pointer to the `ZyanCriticalSection` struct. 1492+ */ 1493+ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section); 1494+ 1495+/** 1496+ * Tries to enter a critical section. 1497+ * 1498+ * @param critical_section A pointer to the `ZyanCriticalSection` struct. 1499+ * 1500+ * @return Returns `ZYAN_TRUE` if the critical section was successfully entered or `ZYAN_FALSE`, 1501+ * if not. 1502+ */ 1503+ZYCORE_EXPORT ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section); 1504+ 1505+/** 1506+ * Leaves a critical section. 1507+ * 1508+ * @param critical_section A pointer to the `ZyanCriticalSection` struct. 1509+ */ 1510+ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section); 1511+ 1512+/** 1513+ * Deletes a critical section. 1514+ * 1515+ * @param critical_section A pointer to the `ZyanCriticalSection` struct. 1516+ */ 1517+ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section); 1518+ 1519+/* ---------------------------------------------------------------------------------------------- */ 1520+ 1521+/* ============================================================================================== */ 1522+ 1523+#ifdef __cplusplus 1524+} 1525+#endif 1526+ 1527+#endif /* ZYAN_NO_LIBC */ 1528+ 1529+#endif /* ZYCORE_API_SYNCHRONIZATION_H */ 1530diff --git a/zycore/include/Zycore/API/Terminal.h b/zycore/include/Zycore/API/Terminal.h 1531new file mode 100644 1532index 0000000..3bff8c1 1533--- /dev/null 1534+++ b/zycore/include/Zycore/API/Terminal.h 1535@@ -0,0 +1,162 @@ 1536+/*************************************************************************************************** 1537+ 1538+ Zyan Core Library (Zycore-C) 1539+ 1540+ Original Author : Florian Bernd 1541+ 1542+ * Permission is hereby granted, free of charge, to any person obtaining a copy 1543+ * of this software and associated documentation files (the "Software"), to deal 1544+ * in the Software without restriction, including without limitation the rights 1545+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1546+ * copies of the Software, and to permit persons to whom the Software is 1547+ * furnished to do so, subject to the following conditions: 1548+ * 1549+ * The above copyright notice and this permission notice shall be included in all 1550+ * copies or substantial portions of the Software. 1551+ * 1552+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1553+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1554+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1555+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1556+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1557+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1558+ * SOFTWARE. 1559+ 1560+***************************************************************************************************/ 1561+ 1562+/** 1563+ * @file Provides cross-platform terminal helper functions. 1564+ * @brief 1565+ */ 1566+ 1567+#ifndef ZYCORE_API_TERMINAL_H 1568+#define ZYCORE_API_TERMINAL_H 1569+ 1570+#include <Zycore/LibC.h> 1571+#include <Zycore/Status.h> 1572+ 1573+#ifdef __cplusplus 1574+extern "C" { 1575+#endif 1576+ 1577+#ifndef ZYAN_NO_LIBC 1578+ 1579+/* ============================================================================================== */ 1580+/* VT100 CSI SGR sequences */ 1581+/* ============================================================================================== */ 1582+ 1583+/* ---------------------------------------------------------------------------------------------- */ 1584+/* General */ 1585+/* ---------------------------------------------------------------------------------------------- */ 1586+ 1587+#define ZYAN_VT100SGR_RESET "\033[0m" 1588+ 1589+/* ---------------------------------------------------------------------------------------------- */ 1590+/* Foreground colors */ 1591+/* ---------------------------------------------------------------------------------------------- */ 1592+ 1593+#define ZYAN_VT100SGR_FG_DEFAULT "\033[39m" 1594+ 1595+#define ZYAN_VT100SGR_FG_BLACK "\033[30m" 1596+#define ZYAN_VT100SGR_FG_RED "\033[31m" 1597+#define ZYAN_VT100SGR_FG_GREEN "\033[32m" 1598+#define ZYAN_VT100SGR_FG_YELLOW "\033[33m" 1599+#define ZYAN_VT100SGR_FG_BLUE "\033[34m" 1600+#define ZYAN_VT100SGR_FG_MAGENTA "\033[35m" 1601+#define ZYAN_VT100SGR_FG_CYAN "\033[36m" 1602+#define ZYAN_VT100SGR_FG_WHITE "\033[37m" 1603+#define ZYAN_VT100SGR_FG_BRIGHT_BLACK "\033[90m" 1604+#define ZYAN_VT100SGR_FG_BRIGHT_RED "\033[91m" 1605+#define ZYAN_VT100SGR_FG_BRIGHT_GREEN "\033[92m" 1606+#define ZYAN_VT100SGR_FG_BRIGHT_YELLOW "\033[93m" 1607+#define ZYAN_VT100SGR_FG_BRIGHT_BLUE "\033[94m" 1608+#define ZYAN_VT100SGR_FG_BRIGHT_MAGENTA "\033[95m" 1609+#define ZYAN_VT100SGR_FG_BRIGHT_CYAN "\033[96m" 1610+#define ZYAN_VT100SGR_FG_BRIGHT_WHITE "\033[97m" 1611+ 1612+/* ---------------------------------------------------------------------------------------------- */ 1613+/* Background color */ 1614+/* ---------------------------------------------------------------------------------------------- */ 1615+ 1616+#define ZYAN_VT100SGR_BG_DEFAULT "\033[49m" 1617+ 1618+#define ZYAN_VT100SGR_BG_BLACK "\033[40m" 1619+#define ZYAN_VT100SGR_BG_RED "\033[41m" 1620+#define ZYAN_VT100SGR_BG_GREEN "\033[42m" 1621+#define ZYAN_VT100SGR_BG_YELLOW "\033[43m" 1622+#define ZYAN_VT100SGR_BG_BLUE "\033[44m" 1623+#define ZYAN_VT100SGR_BG_MAGENTA "\033[45m" 1624+#define ZYAN_VT100SGR_BG_CYAN "\033[46m" 1625+#define ZYAN_VT100SGR_BG_WHITE "\033[47m" 1626+#define ZYAN_VT100SGR_BG_BRIGHT_BLACK "\033[100m" 1627+#define ZYAN_VT100SGR_BG_BRIGHT_RED "\033[101m" 1628+#define ZYAN_VT100SGR_BG_BRIGHT_GREEN "\033[102m" 1629+#define ZYAN_VT100SGR_BG_BRIGHT_YELLOW "\033[103m" 1630+#define ZYAN_VT100SGR_BG_BRIGHT_BLUE "\033[104m" 1631+#define ZYAN_VT100SGR_BG_BRIGHT_MAGENTA "\033[105m" 1632+#define ZYAN_VT100SGR_BG_BRIGHT_CYAN "\033[106m" 1633+#define ZYAN_VT100SGR_BG_BRIGHT_WHITE "\033[107m" 1634+ 1635+/* ---------------------------------------------------------------------------------------------- */ 1636+ 1637+/* ============================================================================================== */ 1638+/* Enums and types */ 1639+/* ============================================================================================== */ 1640+ 1641+/** 1642+ * Declares the `ZyanStandardStream` enum. 1643+ */ 1644+typedef enum ZyanStandardStream_ 1645+{ 1646+ /** 1647+ * The default input stream. 1648+ */ 1649+ ZYAN_STDSTREAM_IN, 1650+ /** 1651+ * The default output stream. 1652+ */ 1653+ ZYAN_STDSTREAM_OUT, 1654+ /** 1655+ * The default error stream. 1656+ */ 1657+ ZYAN_STDSTREAM_ERR 1658+} ZyanStandardStream; 1659+ 1660+/* ============================================================================================== */ 1661+/* Exported functions */ 1662+/* ============================================================================================== */ 1663+ 1664+/** 1665+ * Enables VT100 ansi escape codes for the given stream. 1666+ * 1667+ * @param stream Either `ZYAN_STDSTREAM_OUT` or `ZYAN_STDSTREAM_ERR`. 1668+ * 1669+ * @return A zyan status code. 1670+ * 1671+ * This functions returns `ZYAN_STATUS_SUCCESS` on all non-Windows systems without performing any 1672+ * operations, assuming that VT100 is supported by default. 1673+ * 1674+ * On Windows systems, VT100 functionality is only supported on Windows 10 build 1607 (anniversary 1675+ * update) and later. 1676+ */ 1677+ZYCORE_EXPORT ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream); 1678+ 1679+/** 1680+ * Checks, if the given standard stream reads from or writes to a terminal. 1681+ * 1682+ * @param stream The standard stream to check. 1683+ * 1684+ * @return `ZYAN_STATUS_TRUE`, if the stream is bound to a terminal, `ZYAN_STATUS_FALSE` if not, 1685+ * or another zyan status code if an error occured. 1686+ */ 1687+ZYCORE_EXPORT ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream); 1688+ 1689+/* ============================================================================================== */ 1690+ 1691+#endif // ZYAN_NO_LIBC 1692+ 1693+#ifdef __cplusplus 1694+} 1695+#endif 1696+ 1697+#endif /* ZYCORE_API_TERMINAL_H */ 1698diff --git a/zycore/include/Zycore/API/Thread.h b/zycore/include/Zycore/API/Thread.h 1699new file mode 100644 1700index 0000000..402a2da 1701--- /dev/null 1702+++ b/zycore/include/Zycore/API/Thread.h 1703@@ -0,0 +1,243 @@ 1704+/*************************************************************************************************** 1705+ 1706+ Zyan Core Library (Zycore-C) 1707+ 1708+ Original Author : Florian Bernd 1709+ 1710+ * Permission is hereby granted, free of charge, to any person obtaining a copy 1711+ * of this software and associated documentation files (the "Software"), to deal 1712+ * in the Software without restriction, including without limitation the rights 1713+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1714+ * copies of the Software, and to permit persons to whom the Software is 1715+ * furnished to do so, subject to the following conditions: 1716+ * 1717+ * The above copyright notice and this permission notice shall be included in all 1718+ * copies or substantial portions of the Software. 1719+ * 1720+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1721+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1722+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1723+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1724+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1725+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1726+ * SOFTWARE. 1727+ 1728+***************************************************************************************************/ 1729+ 1730+/** 1731+ * @file 1732+ * @brief 1733+ */ 1734+ 1735+#ifndef ZYCORE_API_THREAD_H 1736+#define ZYCORE_API_THREAD_H 1737+ 1738+#include <Zycore/Defines.h> 1739+#include <Zycore/Status.h> 1740+ 1741+#ifndef ZYAN_NO_LIBC 1742+ 1743+#ifdef __cplusplus 1744+extern "C" { 1745+#endif 1746+ 1747+/* ============================================================================================== */ 1748+/* Enums and types */ 1749+/* ============================================================================================== */ 1750+ 1751+#if defined(ZYAN_POSIX) 1752+ 1753+#include <pthread.h> 1754+ 1755+/* ---------------------------------------------------------------------------------------------- */ 1756+/* General */ 1757+/* ---------------------------------------------------------------------------------------------- */ 1758+ 1759+/** 1760+ * Defines the `ZyanThread` data-type. 1761+ */ 1762+typedef pthread_t ZyanThread; 1763+ 1764+/** 1765+ * Defines the `ZyanThreadId` data-type. 1766+ */ 1767+typedef ZyanU64 ZyanThreadId; 1768+ 1769+/* ---------------------------------------------------------------------------------------------- */ 1770+/* Thread Local Storage (TLS) */ 1771+/* ---------------------------------------------------------------------------------------------- */ 1772+ 1773+/** 1774+ * Defines the `ZyanThreadTlsIndex` data-type. 1775+ */ 1776+typedef pthread_key_t ZyanThreadTlsIndex; 1777+ 1778+/** 1779+ * Defines the `ZyanThreadTlsCallback` function prototype. 1780+ */ 1781+typedef void(*ZyanThreadTlsCallback)(void* data); 1782+ 1783+/** 1784+ * Declares a Thread Local Storage (TLS) callback function. 1785+ * 1786+ * @param name The callback function name. 1787+ * @param param_type The callback data parameter type. 1788+ * @param param_name The callback data parameter name. 1789+ */ 1790+#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \ 1791+ void name(param_type* param_name) 1792+ 1793+/* ---------------------------------------------------------------------------------------------- */ 1794+ 1795+#elif defined(ZYAN_WINDOWS) 1796+ 1797+#include <windows.h> 1798+ 1799+/* ---------------------------------------------------------------------------------------------- */ 1800+/* General */ 1801+/* ---------------------------------------------------------------------------------------------- */ 1802+ 1803+/** 1804+ * Defines the `ZyanThread` data-type. 1805+ */ 1806+typedef HANDLE ZyanThread; 1807+ 1808+/** 1809+ * Defines the `ZyanThreadId` data-type. 1810+ */ 1811+typedef DWORD ZyanThreadId; 1812+ 1813+/* ---------------------------------------------------------------------------------------------- */ 1814+/* Thread Local Storage (TLS) */ 1815+/* ---------------------------------------------------------------------------------------------- */ 1816+ 1817+/** 1818+ * Defines the `ZyanThreadTlsIndex` data-type. 1819+ */ 1820+typedef DWORD ZyanThreadTlsIndex; 1821+ 1822+/** 1823+ * Defines the `ZyanThreadTlsCallback` function prototype. 1824+ */ 1825+typedef PFLS_CALLBACK_FUNCTION ZyanThreadTlsCallback; 1826+ 1827+/** 1828+ * Declares a Thread Local Storage (TLS) callback function. 1829+ * 1830+ * @param name The callback function name. 1831+ * @param param_type The callback data parameter type. 1832+ * @param param_name The callback data parameter name. 1833+ */ 1834+#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \ 1835+ VOID NTAPI name(param_type* param_name) 1836+ 1837+/* ---------------------------------------------------------------------------------------------- */ 1838+ 1839+#else 1840+# error "Unsupported platform detected" 1841+#endif 1842+ 1843+/* ============================================================================================== */ 1844+/* Exported functions */ 1845+/* ============================================================================================== */ 1846+ 1847+/* ---------------------------------------------------------------------------------------------- */ 1848+/* General */ 1849+/* ---------------------------------------------------------------------------------------------- */ 1850+ 1851+/** 1852+ * Returns the handle of the current thread. 1853+ * 1854+ * @param thread Receives the handle of the current thread. 1855+ * 1856+ * @return A zyan status code. 1857+ */ 1858+ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread); 1859+ 1860+/** 1861+ * Returns the unique id of the current thread. 1862+ * 1863+ * @param thread_id Receives the unique id of the current thread. 1864+ * 1865+ * @return A zyan status code. 1866+ */ 1867+ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id); 1868+ 1869+/* ---------------------------------------------------------------------------------------------- */ 1870+/* Thread Local Storage (TLS) */ 1871+/* ---------------------------------------------------------------------------------------------- */ 1872+ 1873+/** 1874+ * Allocates a new Thread Local Storage (TLS) slot. 1875+ * 1876+ * @param index Receives the TLS slot index. 1877+ * @param destructor A pointer to a destructor callback which is invoked to finalize the data 1878+ * in the TLS slot or `ZYAN_NULL`, if not needed. 1879+ * 1880+ * The maximum available number of TLS slots is implementation specific and different on each 1881+ * platform: 1882+ * - Windows 1883+ * - A total amount of 128 slots per process are guaranteed 1884+ * - POSIX 1885+ * - A total amount of 128 slots per process are guaranteed 1886+ * - Some systems guarantee larger amounts like e.g. 1024 slots per process 1887+ * 1888+ * Note that the invocation rules for the destructor callback are implementation specific and 1889+ * different on each platform: 1890+ * - Windows 1891+ * - The callback is invoked when a thread exits 1892+ * - The callback is invoked when the process exits 1893+ * - The callback is invoked when the TLS slot is released 1894+ * - POSIX 1895+ * - The callback is invoked when a thread exits and the stored value is not null 1896+ * - The callback is NOT invoked when the process exits 1897+ * - The callback is NOT invoked when the TLS slot is released 1898+ * 1899+ * @return A zyan status code. 1900+ */ 1901+ZYCORE_EXPORT ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, 1902+ ZyanThreadTlsCallback destructor); 1903+ 1904+/** 1905+ * Releases a Thread Local Storage (TLS) slot. 1906+ * 1907+ * @param index The TLS slot index. 1908+ * 1909+ * @return A zyan status code. 1910+ */ 1911+ZYCORE_EXPORT ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index); 1912+ 1913+/** 1914+ * Returns the value inside the given Thread Local Storage (TLS) slot for the 1915+ * calling thread. 1916+ * 1917+ * @param index The TLS slot index. 1918+ * @param data Receives the value inside the given Thread Local Storage 1919+ * (TLS) slot for the calling thread. 1920+ * 1921+ * @return A zyan status code. 1922+ */ 1923+ZYCORE_EXPORT ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data); 1924+ 1925+/** 1926+ * Set the value of the given Thread Local Storage (TLS) slot for the calling thread. 1927+ * 1928+ * @param index The TLS slot index. 1929+ * @param data The value to store inside the given Thread Local Storage (TLS) slot for the 1930+ * calling thread 1931+ * 1932+ * @return A zyan status code. 1933+ */ 1934+ZYCORE_EXPORT ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data); 1935+ 1936+/* ---------------------------------------------------------------------------------------------- */ 1937+ 1938+/* ============================================================================================== */ 1939+ 1940+#ifdef __cplusplus 1941+} 1942+#endif 1943+ 1944+#endif /* ZYAN_NO_LIBC */ 1945+ 1946+#endif /* ZYCORE_API_THREAD_H */ 1947diff --git a/zycore/include/Zycore/Allocator.h b/zycore/include/Zycore/Allocator.h 1948new file mode 100644 1949index 0000000..ff80a2c 1950--- /dev/null 1951+++ b/zycore/include/Zycore/Allocator.h 1952@@ -0,0 +1,142 @@ 1953+/*************************************************************************************************** 1954+ 1955+ Zyan Core Library (Zycore-C) 1956+ 1957+ Original Author : Florian Bernd 1958+ 1959+ * Permission is hereby granted, free of charge, to any person obtaining a copy 1960+ * of this software and associated documentation files (the "Software"), to deal 1961+ * in the Software without restriction, including without limitation the rights 1962+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1963+ * copies of the Software, and to permit persons to whom the Software is 1964+ * furnished to do so, subject to the following conditions: 1965+ * 1966+ * The above copyright notice and this permission notice shall be included in all 1967+ * copies or substantial portions of the Software. 1968+ * 1969+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1970+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1971+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1972+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1973+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1974+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1975+ * SOFTWARE. 1976+ 1977+***************************************************************************************************/ 1978+ 1979+/** 1980+ * @file 1981+ * @brief 1982+ */ 1983+ 1984+#ifndef ZYCORE_ALLOCATOR_H 1985+#define ZYCORE_ALLOCATOR_H 1986+ 1987+#include <Zycore/Status.h> 1988+#include <Zycore/Types.h> 1989+ 1990+#ifdef __cplusplus 1991+extern "C" { 1992+#endif 1993+ 1994+/* ============================================================================================== */ 1995+/* Enums and types */ 1996+/* ============================================================================================== */ 1997+ 1998+struct ZyanAllocator_; 1999+ 2000+/** 2001+ * Defines the `ZyanAllocatorAllocate` function prototype. 2002+ * 2003+ * @param allocator A pointer to the `ZyanAllocator` instance. 2004+ * @param p Receives a pointer to the first memory block sufficient to hold an 2005+ * array of `n` elements with a size of `element_size`. 2006+ * @param element_size The size of a single element. 2007+ * @param n The number of elements to allocate storage for. 2008+ * 2009+ * @return A zyan status code. 2010+ * 2011+ * This prototype is used for the `allocate()` and `reallocate()` functions. 2012+ * 2013+ * The result of the `reallocate()` function is undefined, if `p` does not point to a memory block 2014+ * previously obtained by `(re-)allocate()`. 2015+ */ 2016+typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p, 2017+ ZyanUSize element_size, ZyanUSize n); 2018+ 2019+/** 2020+ * Defines the `ZyanAllocatorDeallocate` function prototype. 2021+ * 2022+ * @param allocator A pointer to the `ZyanAllocator` instance. 2023+ * @param p The pointer obtained from `(re-)allocate()`. 2024+ * @param element_size The size of a single element. 2025+ * @param n The number of elements earlier passed to `(re-)allocate()`. 2026+ * 2027+ * @return A zyan status code. 2028+ */ 2029+typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p, 2030+ ZyanUSize element_size, ZyanUSize n); 2031+ 2032+/** 2033+ * Defines the `ZyanAllocator` struct. 2034+ * 2035+ * This is the base class for all custom allocator implementations. 2036+ * 2037+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 2038+ * behavior. 2039+ */ 2040+typedef struct ZyanAllocator_ 2041+{ 2042+ /** 2043+ * The allocate function. 2044+ */ 2045+ ZyanAllocatorAllocate allocate; 2046+ /** 2047+ * The reallocate function. 2048+ */ 2049+ ZyanAllocatorAllocate reallocate; 2050+ /** 2051+ * The deallocate function. 2052+ */ 2053+ ZyanAllocatorDeallocate deallocate; 2054+} ZyanAllocator; 2055+ 2056+/* ============================================================================================== */ 2057+/* Exported functions */ 2058+/* ============================================================================================== */ 2059+ 2060+/** 2061+ * Initializes the given `ZyanAllocator` instance. 2062+ * 2063+ * @param allocator A pointer to the `ZyanAllocator` instance. 2064+ * @param allocate The allocate function. 2065+ * @param reallocate The reallocate function. 2066+ * @param deallocate The deallocate function. 2067+ * 2068+ * @return A zyan status code. 2069+ */ 2070+ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate, 2071+ ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate); 2072+ 2073+#ifndef ZYAN_NO_LIBC 2074+ 2075+/** 2076+ * Returns the default `ZyanAllocator` instance. 2077+ * 2078+ * @return A pointer to the default `ZyanAllocator` instance. 2079+ * 2080+ * The default allocator uses the default memory manager to allocate memory on the heap. 2081+ * 2082+ * You should in no case modify the returned allocator instance to avoid unexpected behavior. 2083+ */ 2084+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void); 2085+ 2086+#endif // ZYAN_NO_LIBC 2087+ 2088+/* ============================================================================================== */ 2089+ 2090+#ifdef __cplusplus 2091+} 2092+#endif 2093+ 2094+#endif /* ZYCORE_ALLOCATOR_H */ 2095diff --git a/zycore/include/Zycore/ArgParse.h b/zycore/include/Zycore/ArgParse.h 2096new file mode 100644 2097index 0000000..5d389cb 2098--- /dev/null 2099+++ b/zycore/include/Zycore/ArgParse.h 2100@@ -0,0 +1,173 @@ 2101+/*************************************************************************************************** 2102+ 2103+ Zyan Core Library (Zycore-C) 2104+ 2105+ Original Author : Joel Hoener 2106+ 2107+ * Permission is hereby granted, free of charge, to any person obtaining a copy 2108+ * of this software and associated documentation files (the "Software"), to deal 2109+ * in the Software without restriction, including without limitation the rights 2110+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 2111+ * copies of the Software, and to permit persons to whom the Software is 2112+ * furnished to do so, subject to the following conditions: 2113+ * 2114+ * The above copyright notice and this permission notice shall be included in all 2115+ * copies or substantial portions of the Software. 2116+ * 2117+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2118+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2119+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2120+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2121+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2122+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2123+ * SOFTWARE. 2124+ 2125+***************************************************************************************************/ 2126+ 2127+/** 2128+ * @file 2129+ * Implements command-line argument parsing. 2130+ */ 2131+ 2132+#ifndef ZYCORE_ARGPARSE_H 2133+#define ZYCORE_ARGPARSE_H 2134+ 2135+#include <Zycore/Types.h> 2136+#include <Zycore/Status.h> 2137+#include <Zycore/Vector.h> 2138+#include <Zycore/String.h> 2139+ 2140+#ifdef __cplusplus 2141+extern "C" { 2142+#endif 2143+ 2144+/* ============================================================================================== */ 2145+/* Structs and other types */ 2146+/* ============================================================================================== */ 2147+ 2148+/** 2149+ * Definition of a single argument. 2150+ */ 2151+typedef struct ZyanArgParseDefinition_ 2152+{ 2153+ /** 2154+ * The argument name, e.g. `--help`. 2155+ * 2156+ * Must start with either one or two dashes. Single dash arguments must consist of a single 2157+ * character, (e.g. `-n`), double-dash arguments can be of arbitrary length. 2158+ */ 2159+ const char* name; 2160+ /** 2161+ * Whether the argument is boolean or expects a value. 2162+ */ 2163+ ZyanBool boolean; 2164+ /** 2165+ * Whether this argument is required (error if missing). 2166+ */ 2167+ ZyanBool required; 2168+} ZyanArgParseDefinition; 2169+ 2170+/** 2171+ * Configuration for argument parsing. 2172+ */ 2173+typedef struct ZyanArgParseConfig_ 2174+{ 2175+ /** 2176+ * `argv` argument passed to `main` by LibC. 2177+ */ 2178+ const char** argv; 2179+ /** 2180+ * `argc` argument passed to `main` by LibC. 2181+ */ 2182+ ZyanUSize argc; 2183+ /** 2184+ * Minimum # of accepted unnamed / anonymous arguments. 2185+ */ 2186+ ZyanUSize min_unnamed_args; 2187+ /** 2188+ * Maximum # of accepted unnamed / anonymous arguments. 2189+ */ 2190+ ZyanUSize max_unnamed_args; 2191+ /** 2192+ * Argument definition array, or `ZYAN_NULL`. 2193+ * 2194+ * Expects a pointer to an array of `ZyanArgParseDefinition` instances. The array is 2195+ * terminated by setting the `.name` field of the last element to `ZYAN_NULL`. If no named 2196+ * arguments should be parsed, you can also set this to `ZYAN_NULL`. 2197+ */ 2198+ ZyanArgParseDefinition* args; 2199+} ZyanArgParseConfig; 2200+ 2201+/** 2202+ * Information about a parsed argument. 2203+ */ 2204+typedef struct ZyanArgParseArg_ 2205+{ 2206+ /** 2207+ * Corresponding argument definition, or `ZYAN_NULL` for unnamed args. 2208+ * 2209+ * This pointer is borrowed from the `cfg` pointer passed to `ZyanArgParse`. 2210+ */ 2211+ const ZyanArgParseDefinition* def; 2212+ /** 2213+ * Whether the argument has a value (is non-boolean). 2214+ */ 2215+ ZyanBool has_value; 2216+ /** 2217+ * If `has_value == true`, then the argument value. 2218+ * 2219+ * This is a view into the `argv` string array passed to `ZyanArgParse` via the `cfg` argument. 2220+ */ 2221+ ZyanStringView value; 2222+} ZyanArgParseArg; 2223+ 2224+/* ============================================================================================== */ 2225+/* Exported functions */ 2226+/* ============================================================================================== */ 2227+ 2228+#ifndef ZYAN_NO_LIBC 2229+ 2230+/** 2231+ * Parse arguments according to a `ZyanArgParseConfig` definition. 2232+ * 2233+ * @param cfg Argument parser config to use. 2234+ * @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is 2235+ * transferred to the user. Input is expected to be uninitialized. On error, 2236+ * the vector remains uninitialized. 2237+ * @param error_token On error, if it makes sense, receives the argument fragment causing the 2238+ * error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg` 2239+ * struct and doesn't have to be freed by the user. 2240+ * 2241+ * @return A `ZyanStatus` status determining whether the parsing succeeded. 2242+ */ 2243+ZYCORE_EXPORT ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed, 2244+ const char** error_token); 2245+ 2246+#endif 2247+ 2248+/** 2249+ * Parse arguments according to a `ZyanArgParseConfig` definition. 2250+ * 2251+ * This version allows specification of a custom memory allocator and thus supports no-libc. 2252+ * 2253+ * @param cfg Argument parser config to use. 2254+ * @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is 2255+ * transferred to the user. Input is expected to be uninitialized. On error, 2256+ * the vector remains uninitialized. 2257+ * @param error_token On error, if it makes sense, receives the argument fragment causing the 2258+ * error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg` 2259+ * struct and doesn't have to be freed by the user. 2260+ * @param allocator The `ZyanAllocator` to be used for allocating the output vector's data. 2261+ * 2262+ * @return A `ZyanStatus` status determining whether the parsing succeeded. 2263+ */ 2264+ZYCORE_EXPORT ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed, 2265+ const char** error_token, ZyanAllocator* allocator); 2266+ 2267+/* ============================================================================================== */ 2268+ 2269+#ifdef __cplusplus 2270+} 2271+#endif 2272+ 2273+#endif /* ZYCORE_ARGPARSE_H */ 2274diff --git a/zycore/include/Zycore/Atomic.h b/zycore/include/Zycore/Atomic.h 2275new file mode 100644 2276index 0000000..f5dcf27 2277--- /dev/null 2278+++ b/zycore/include/Zycore/Atomic.h 2279@@ -0,0 +1,236 @@ 2280+/*************************************************************************************************** 2281+ 2282+ Zyan Core Library (Zyan-C) 2283+ 2284+ Original Author : Florian Bernd 2285+ 2286+ * Permission is hereby granted, free of charge, to any person obtaining a copy 2287+ * of this software and associated documentation files (the "Software"), to deal 2288+ * in the Software without restriction, including without limitation the rights 2289+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 2290+ * copies of the Software, and to permit persons to whom the Software is 2291+ * furnished to do so, subject to the following conditions: 2292+ * 2293+ * The above copyright notice and this permission notice shall be included in all 2294+ * copies or substantial portions of the Software. 2295+ * 2296+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2297+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2298+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2299+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2300+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2301+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2302+ * SOFTWARE. 2303+ 2304+***************************************************************************************************/ 2305+ 2306+/** 2307+ * @file 2308+ * Cross compiler atomic intrinsics. 2309+ */ 2310+ 2311+#ifndef ZYCORE_ATOMIC_H 2312+#define ZYCORE_ATOMIC_H 2313+ 2314+#ifdef __cplusplus 2315+extern "C" { 2316+#endif 2317+ 2318+#include <Zycore/Defines.h> 2319+#include <Zycore/Types.h> 2320+ 2321+/* ============================================================================================== */ 2322+/* Enums and Types */ 2323+/* ============================================================================================== */ 2324+ 2325+/* 2326+ * Wraps a 32-bit value to provide atomic access. 2327+ */ 2328+typedef struct ZyanAtomic32_ 2329+{ 2330+ ZyanU32 volatile value; 2331+} ZyanAtomic32; 2332+ 2333+/* 2334+ * Wraps a 64-bit value to provide atomic access. 2335+ */ 2336+typedef struct ZyanAtomic64_ 2337+{ 2338+ ZyanU64 volatile value; 2339+} ZyanAtomic64; 2340+ 2341+/* 2342+ * Wraps a pointer-sized value to provide atomic access. 2343+ */ 2344+typedef struct ZyanAtomicPointer_ 2345+{ 2346+ ZyanVoidPointer volatile value; 2347+} ZyanAtomicPointer; 2348+ 2349+/* ============================================================================================== */ 2350+/* Macros */ 2351+/* ============================================================================================== */ 2352+ 2353+/* ---------------------------------------------------------------------------------------------- */ 2354+/* Pointer sized */ 2355+/* ---------------------------------------------------------------------------------------------- */ 2356+ 2357+/** 2358+ * @copydoc ZyanAtomicCompareExchange 2359+ */ 2360+#define ZYAN_ATOMIC_COMPARE_EXCHANGE(destination, comparand, value) \ 2361+ ZyanAtomicCompareExchange((ZyanAtomicPointer*)&(destination), (comparand), (value)) 2362+ 2363+/** 2364+ * @copydoc ZyanAtomicIncrement 2365+ */ 2366+#define ZYAN_ATOMIC_INCREMENT(destination) \ 2367+ ZyanAtomicIncrement((ZyanAtomicPointer*)&(destination)); 2368+ 2369+/** 2370+ * @copydoc ZyanAtomicDecrement 2371+ */ 2372+#define ZYAN_ATOMIC_DECREMENT(destination) \ 2373+ ZyanAtomicDecrement((ZyanAtomicPointer*)&(destination)); 2374+ 2375+/* ---------------------------------------------------------------------------------------------- */ 2376+/* 32-bit */ 2377+/* ---------------------------------------------------------------------------------------------- */ 2378+ 2379+/** 2380+ * @copydoc ZyanAtomicCompareExchange 2381+ */ 2382+#define ZYAN_ATOMIC_COMPARE_EXCHANGE32(destination, comparand, value) \ 2383+ ZyanAtomicCompareExchange32((ZyanAtomic32*)&(destination), (comparand), (value)) 2384+ 2385+/** 2386+ * @copydoc ZyanAtomicIncrement 2387+ */ 2388+#define ZYAN_ATOMIC_INCREMENT32(destination) \ 2389+ ZyanAtomicIncrement32((ZyanAtomic32*)&(destination)); 2390+ 2391+/** 2392+ * @copydoc ZyanAtomicDecrement 2393+ */ 2394+#define ZYAN_ATOMIC_DECREMENT32(destination) \ 2395+ ZyanAtomicDecrement32((ZyanAtomic32*)&(destination)); 2396+ 2397+/* ---------------------------------------------------------------------------------------------- */ 2398+/* 64-bit */ 2399+/* ---------------------------------------------------------------------------------------------- */ 2400+ 2401+/** 2402+ * @copydoc ZyanAtomicCompareExchange 2403+ */ 2404+#define ZYAN_ATOMIC_COMPARE_EXCHANGE64(destination, comparand, value) \ 2405+ ZyanAtomicCompareExchange64((ZyanAtomic64*)&(destination), (comparand), (value)) 2406+ 2407+/** 2408+ * @copydoc ZyanAtomicIncrement 2409+ */ 2410+#define ZYAN_ATOMIC_INCREMENT64(destination) \ 2411+ ZyanAtomicIncrement64((ZyanAtomic64*)&(destination)); 2412+ 2413+/** 2414+ * @copydoc ZyanAtomicDecrement 2415+ */ 2416+#define ZYAN_ATOMIC_DECREMENT64(destination) \ 2417+ ZyanAtomicDecrement64((ZyanAtomic64*)&(destination)); 2418+ 2419+/* ---------------------------------------------------------------------------------------------- */ 2420+ 2421+/* ============================================================================================== */ 2422+/* Functions */ 2423+/* ============================================================================================== */ 2424+ 2425+/* ---------------------------------------------------------------------------------------------- */ 2426+/* Pointer sized */ 2427+/* ---------------------------------------------------------------------------------------------- */ 2428+ 2429+/** 2430+ * Compares two values for equality and, if they are equal, replaces the first value. 2431+ * 2432+ * @param destination A pointer to the destination value. 2433+ * @param comparand The value to compare with. 2434+ * @param value The replacement value. 2435+ * 2436+ * @return The original value. 2437+ */ 2438+static ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination, 2439+ ZyanUPointer comparand, ZyanUPointer value); 2440+ 2441+/** 2442+ * Increments the given value and stores the result, as an atomic operation. 2443+ * 2444+ * @param destination A pointer to the destination value. 2445+ * 2446+ * @return The incremented value. 2447+*/ 2448+static ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination); 2449+ 2450+/** 2451+ * Decrements the given value and stores the result, as an atomic operation. 2452+ * 2453+ * @param destination A pointer to the destination value. 2454+ * 2455+ * @return The decremented value. 2456+*/ 2457+static ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination); 2458+ 2459+/* ---------------------------------------------------------------------------------------------- */ 2460+/* 32-bit */ 2461+/* ---------------------------------------------------------------------------------------------- */ 2462+ 2463+/** 2464+ * @copydoc ZyanAtomicCompareExchange 2465+ */ 2466+static ZyanU32 ZyanAtomicCompareExchange32(ZyanAtomic32* destination, 2467+ ZyanU32 comparand, ZyanU32 value); 2468+ 2469+/** 2470+ * @copydoc ZyanAtomicIncrement 2471+ */ 2472+static ZyanU32 ZyanAtomicIncrement32(ZyanAtomic32* destination); 2473+ 2474+/** 2475+ * @copydoc ZyanAtomicDecrement 2476+ */ 2477+static ZyanU32 ZyanAtomicDecrement32(ZyanAtomic32* destination); 2478+ 2479+/* ---------------------------------------------------------------------------------------------- */ 2480+/* 64-bit */ 2481+/* ---------------------------------------------------------------------------------------------- */ 2482+ 2483+/** 2484+ * @copydoc ZyanAtomicCompareExchange 2485+ */ 2486+static ZyanU64 ZyanAtomicCompareExchange64(ZyanAtomic64* destination, 2487+ ZyanU64 comparand, ZyanU64 value); 2488+ 2489+/** 2490+ * @copydoc ZyanAtomicIncrement 2491+ */ 2492+static ZyanU64 ZyanAtomicIncrement64(ZyanAtomic64* destination); 2493+ 2494+/** 2495+ * @copydoc ZyanAtomicDecrement 2496+ */ 2497+static ZyanU64 ZyanAtomicDecrement64(ZyanAtomic64* destination); 2498+ 2499+/* ---------------------------------------------------------------------------------------------- */ 2500+ 2501+/* ============================================================================================== */ 2502+ 2503+#if defined(ZYAN_CLANG) || defined(ZYAN_GCC) || defined(ZYAN_ICC) 2504+# include <Zycore/Internal/AtomicGNU.h> 2505+#elif defined(ZYAN_MSVC) 2506+# include <Zycore/Internal/AtomicMSVC.h> 2507+#else 2508+# error "Unsupported compiler detected" 2509+#endif 2510+ 2511+#ifdef __cplusplus 2512+} 2513+#endif 2514+ 2515+#endif /* ZYCORE_ATOMIC_H */ 2516diff --git a/zycore/include/Zycore/Bitset.h b/zycore/include/Zycore/Bitset.h 2517new file mode 100644 2518index 0000000..0404f87 2519--- /dev/null 2520+++ b/zycore/include/Zycore/Bitset.h 2521@@ -0,0 +1,483 @@ 2522+/*************************************************************************************************** 2523+ 2524+ Zyan Core Library (Zycore-C) 2525+ 2526+ Original Author : Florian Bernd 2527+ 2528+ * Permission is hereby granted, free of charge, to any person obtaining a copy 2529+ * of this software and associated documentation files (the "Software"), to deal 2530+ * in the Software without restriction, including without limitation the rights 2531+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 2532+ * copies of the Software, and to permit persons to whom the Software is 2533+ * furnished to do so, subject to the following conditions: 2534+ * 2535+ * The above copyright notice and this permission notice shall be included in all 2536+ * copies or substantial portions of the Software. 2537+ * 2538+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2539+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2540+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2541+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2542+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2543+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2544+ * SOFTWARE. 2545+ 2546+***************************************************************************************************/ 2547+ 2548+/** 2549+ * @file 2550+ * Implements the bitset class. 2551+ */ 2552+ 2553+#ifndef ZYCORE_BITSET_H 2554+#define ZYCORE_BITSET_H 2555+ 2556+#include <Zycore/Allocator.h> 2557+#include <Zycore/Status.h> 2558+#include <Zycore/Types.h> 2559+#include <Zycore/Vector.h> 2560+ 2561+#ifdef __cplusplus 2562+extern "C" { 2563+#endif 2564+ 2565+/* ============================================================================================== */ 2566+/* Enums and types */ 2567+/* ============================================================================================== */ 2568+ 2569+/** 2570+ * Defines the `ZyanVector` struct. 2571+ * 2572+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 2573+ * behavior. 2574+ */ 2575+typedef struct ZyanBitset_ 2576+{ 2577+ /** 2578+ * The bitset size. 2579+ */ 2580+ ZyanUSize size; 2581+ /** 2582+ * The bitset data. 2583+ */ 2584+ ZyanVector bits; 2585+} ZyanBitset; 2586+ 2587+/** 2588+ * Defines the `ZyanBitsetByteOperation` function prototype. 2589+ * 2590+ * @param v1 A pointer to the first byte. This value receives the result after performing the 2591+ * desired operation. 2592+ * @param v2 A pointer to the second byte. 2593+ * 2594+ * @return A zyan status code. 2595+ * 2596+ * This function is used to perform byte-wise operations on two `ZyanBitset` instances. 2597+ */ 2598+typedef ZyanStatus (*ZyanBitsetByteOperation)(ZyanU8* v1, const ZyanU8* v2); 2599+ 2600+/* ============================================================================================== */ 2601+/* Exported functions */ 2602+/* ============================================================================================== */ 2603+ 2604+/* ---------------------------------------------------------------------------------------------- */ 2605+/* Constructor and destructor */ 2606+/* ---------------------------------------------------------------------------------------------- */ 2607+ 2608+#ifndef ZYAN_NO_LIBC 2609+ 2610+/** 2611+ * Initializes the given `ZyanBitset` instance. 2612+ * 2613+ * @param bitset A pointer to the `ZyanBitset` instance. 2614+ * @param count The initial amount of bits. 2615+ * 2616+ * @return A zyan status code. 2617+ * 2618+ * The space for the bitset is dynamically allocated by the default allocator using the default 2619+ * growth factor and the default shrink threshold. 2620+ */ 2621+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count); 2622+ 2623+#endif // ZYAN_NO_LIBC 2624+ 2625+/** 2626+ * Initializes the given `ZyanBitset` instance and sets a custom `allocator` and memory 2627+ * allocation/deallocation parameters. 2628+ * 2629+ * @param bitset A pointer to the `ZyanBitset` instance. 2630+ * @param count The initial amount of bits. 2631+ * @param allocator A pointer to a `ZyanAllocator` instance. 2632+ * @param growth_factor The growth factor. 2633+ * @param shrink_threshold The shrink threshold. 2634+ * 2635+ * @return A zyan status code. 2636+ * 2637+ * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables 2638+ * dynamic shrinking. 2639+ */ 2640+ZYCORE_EXPORT ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count, 2641+ ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); 2642+ 2643+/** 2644+ * Initializes the given `ZyanBitset` instance and configures it to use a custom user 2645+ * defined buffer with a fixed size. 2646+ * 2647+ * @param bitset A pointer to the `ZyanBitset` instance. 2648+ * @param count The initial amount of bits. 2649+ * @param buffer A pointer to the buffer that is used as storage for the bits. 2650+ * @param capacity The maximum capacity (number of bytes) of the buffer. 2651+ * 2652+ * @return A zyan status code. 2653+ */ 2654+ZYCORE_EXPORT ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer, 2655+ ZyanUSize capacity); 2656+ 2657+/** 2658+ * Destroys the given `ZyanBitset` instance. 2659+ * 2660+ * @param bitset A pointer to the `ZyanBitset` instance. 2661+ * 2662+ * @return A zyan status code. 2663+ */ 2664+ZYCORE_EXPORT ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset); 2665+ 2666+/* ---------------------------------------------------------------------------------------------- */ 2667+/* Logical operations */ 2668+/* ---------------------------------------------------------------------------------------------- */ 2669+ 2670+/** 2671+ * Performs a byte-wise `operation` for every byte in the given `ZyanBitset` instances. 2672+ * 2673+ * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and 2674+ * as the destination. 2675+ * @param source A pointer to the `ZyanBitset` instance that is used as the second input. 2676+ * @param operation A pointer to the function that performs the desired operation. 2677+ * 2678+ * @return A zyan status code. 2679+ * 2680+ * The `operation` callback is invoked once for every byte in the smallest of the `ZyanBitset` 2681+ * instances. 2682+ */ 2683+ZYCORE_EXPORT ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination, 2684+ const ZyanBitset* source, ZyanBitsetByteOperation operation); 2685+ 2686+/** 2687+ * Performs a logical `AND` operation on the given `ZyanBitset` instances. 2688+ * 2689+ * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and 2690+ * as the destination. 2691+ * @param source A pointer to the `ZyanBitset` instance that is used as the second input. 2692+ * 2693+ * @return A zyan status code. 2694+ * 2695+ * If the destination bitmask contains more bits than the source one, the state of the remaining 2696+ * bits will be undefined. 2697+ */ 2698+ZYCORE_EXPORT ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source); 2699+ 2700+/** 2701+ * Performs a logical `OR` operation on the given `ZyanBitset` instances. 2702+ * 2703+ * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and 2704+ * as the destination. 2705+ * @param source A pointer to the `ZyanBitset` instance that is used as the second input. 2706+ * 2707+ * @return A zyan status code. 2708+ * 2709+ * If the destination bitmask contains more bits than the source one, the state of the remaining 2710+ * bits will be undefined. 2711+ */ 2712+ZYCORE_EXPORT ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source); 2713+ 2714+/** 2715+ * Performs a logical `XOR` operation on the given `ZyanBitset` instances. 2716+ * 2717+ * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and 2718+ * as the destination. 2719+ * @param source A pointer to the `ZyanBitset` instance that is used as the second input. 2720+ * 2721+ * @return A zyan status code. 2722+ * 2723+ * If the destination bitmask contains more bits than the source one, the state of the remaining 2724+ * bits will be undefined. 2725+ */ 2726+ZYCORE_EXPORT ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source); 2727+ 2728+/** 2729+ * Flips all bits of the given `ZyanBitset` instance. 2730+ * 2731+ * @param bitset A pointer to the `ZyanBitset` instance. 2732+ * 2733+ * @return A zyan status code. 2734+ */ 2735+ZYCORE_EXPORT ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset); 2736+ 2737+/* ---------------------------------------------------------------------------------------------- */ 2738+/* Bit access */ 2739+/* ---------------------------------------------------------------------------------------------- */ 2740+ 2741+/** 2742+ * Sets the bit at `index` of the given `ZyanBitset` instance to `1`. 2743+ * 2744+ * @param bitset A pointer to the `ZyanBitset` instance. 2745+ * @param index The bit index. 2746+ * 2747+ * @return A zyan status code. 2748+ */ 2749+ZYCORE_EXPORT ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index); 2750+ 2751+/** 2752+ * Sets the bit at `index` of the given `ZyanBitset` instance to `0`. 2753+ * 2754+ * @param bitset A pointer to the `ZyanBitset` instance. 2755+ * @param index The bit index. 2756+ * 2757+ * @return A zyan status code. 2758+ */ 2759+ZYCORE_EXPORT ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index); 2760+ 2761+/** 2762+ * Sets the bit at `index` of the given `ZyanBitset` instance to the specified `value`. 2763+ * 2764+ * @param bitset A pointer to the `ZyanBitset` instance. 2765+ * @param index The bit index. 2766+ * @param value The new value. 2767+ * 2768+ * @return A zyan status code. 2769+ */ 2770+ZYCORE_EXPORT ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value); 2771+ 2772+/** 2773+ * Toggles the bit at `index` of the given `ZyanBitset` instance. 2774+ * 2775+ * @param bitset A pointer to the `ZyanBitset` instance. 2776+ * @param index The bit index. 2777+ * 2778+ * @return A zyan status code. 2779+ */ 2780+ZYCORE_EXPORT ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index); 2781+ 2782+/** 2783+ * Returns the value of the bit at `index`. 2784+ * 2785+ * @param bitset A pointer to the `ZyanBitset` instance. 2786+ * @param index The bit index. 2787+ * 2788+ * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not, Another zyan 2789+ * status code, if an error occurred. 2790+ */ 2791+ZYCORE_EXPORT ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index); 2792+ 2793+/** 2794+ * Returns the value of the most significant bit. 2795+ * 2796+ * @param bitset A pointer to the `ZyanBitset` instance. 2797+ * 2798+ * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan 2799+ * status code, if an error occurred. 2800+ */ 2801+ZYCORE_EXPORT ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset); 2802+ 2803+/** 2804+ * Returns the value of the least significant bit. 2805+ * 2806+ * @param bitset A pointer to the `ZyanBitset` instance. 2807+ * 2808+ * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan 2809+ * status code, if an error occurred. 2810+ */ 2811+ZYCORE_EXPORT ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset); 2812+ 2813+/* ---------------------------------------------------------------------------------------------- */ 2814+ 2815+/** 2816+ * Sets all bits of the given `ZyanBitset` instance to `1`. 2817+ * 2818+ * @param bitset A pointer to the `ZyanBitset` instance. 2819+ * 2820+ * @return A zyan status code. 2821+ */ 2822+ZYCORE_EXPORT ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset); 2823+ 2824+/** 2825+ * Sets all bits of the given `ZyanBitset` instance to `0`. 2826+ * 2827+ * @param bitset A pointer to the `ZyanBitset` instance. 2828+ * 2829+ * @return A zyan status code. 2830+ */ 2831+ZYCORE_EXPORT ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset); 2832+ 2833+/* ---------------------------------------------------------------------------------------------- */ 2834+/* Size management */ 2835+/* ---------------------------------------------------------------------------------------------- */ 2836+ 2837+/** 2838+ * Adds a new bit at the end of the bitset. 2839+ * 2840+ * @param bitset A pointer to the `ZyanBitset` instance. 2841+ * @param value The value of the new bit. 2842+ * 2843+ * @return A zyan status code. 2844+ */ 2845+ZYCORE_EXPORT ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value); 2846+ 2847+/** 2848+ * Removes the last bit of the bitset. 2849+ * 2850+ * @param bitset A pointer to the `ZyanBitset` instance. 2851+ * 2852+ * @return A zyan status code. 2853+ */ 2854+ZYCORE_EXPORT ZyanStatus ZyanBitsetPop(ZyanBitset* bitset); 2855+ 2856+/** 2857+ * Deletes all bits of the given `ZyanBitset` instance. 2858+ * 2859+ * @param bitset A pointer to the `ZyanBitset` instance. 2860+ * 2861+ * @return A zyan status code. 2862+ */ 2863+ZYCORE_EXPORT ZyanStatus ZyanBitsetClear(ZyanBitset* bitset); 2864+ 2865+/* ---------------------------------------------------------------------------------------------- */ 2866+/* Memory management */ 2867+/* ---------------------------------------------------------------------------------------------- */ 2868+ 2869+/** 2870+ * Changes the capacity of the given `ZyanBitset` instance. 2871+ * 2872+ * @param bitset A pointer to the `ZyanBitset` instance. 2873+ * @param count The new capacity (number of bits). 2874+ * 2875+ * @return A zyan status code. 2876+ */ 2877+ZYCORE_EXPORT ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count); 2878+ 2879+/** 2880+ * Shrinks the capacity of the given bitset to match it's size. 2881+ * 2882+ * @param bitset A pointer to the `ZyanBitset` instance. 2883+ * 2884+ * @return A zyan status code. 2885+ */ 2886+ZYCORE_EXPORT ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset); 2887+ 2888+/* ---------------------------------------------------------------------------------------------- */ 2889+/* Information */ 2890+/* ---------------------------------------------------------------------------------------------- */ 2891+ 2892+/** 2893+ * Returns the current size of the bitset in bits. 2894+ * 2895+ * @param bitset A pointer to the `ZyanBitset` instance. 2896+ * @param size Receives the size of the bitset in bits. 2897+ * 2898+ * @return A zyan status code. 2899+ */ 2900+ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size); 2901+ 2902+/** 2903+ * Returns the current capacity of the bitset in bits. 2904+ * 2905+ * @param bitset A pointer to the `ZyanBitset` instance. 2906+ * @param capacity Receives the size of the bitset in bits. 2907+ * 2908+ * @return A zyan status code. 2909+ */ 2910+ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity); 2911+ 2912+/** 2913+ * Returns the current size of the bitset in bytes. 2914+ * 2915+ * @param bitset A pointer to the `ZyanBitset` instance. 2916+ * @param size Receives the size of the bitset in bytes. 2917+ * 2918+ * @return A zyan status code. 2919+ */ 2920+ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size); 2921+ 2922+/** 2923+ * Returns the current capacity of the bitset in bytes. 2924+ * 2925+ * @param bitset A pointer to the `ZyanBitset` instance. 2926+ * @param capacity Receives the size of the bitset in bytes. 2927+ * 2928+ * @return A zyan status code. 2929+ */ 2930+ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity); 2931+ 2932+/* ---------------------------------------------------------------------------------------------- */ 2933+ 2934+/** 2935+ * Returns the amount of bits set in the given bitset. 2936+ * 2937+ * @param bitset A pointer to the `ZyanBitset` instance. 2938+ * @param count Receives the amount of bits set in the given bitset. 2939+ * 2940+ * @return A zyan status code. 2941+ */ 2942+ZYCORE_EXPORT ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count); 2943+ 2944+/** 2945+ * Checks, if all bits of the given bitset are set. 2946+ * 2947+ * @param bitset A pointer to the `ZyanBitset` instance. 2948+ * 2949+ * @return `ZYAN_STATUS_TRUE`, if all bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan 2950+ * status code, if an error occurred. 2951+ */ 2952+ZYCORE_EXPORT ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset); 2953+ 2954+/** 2955+ * Checks, if at least one bit of the given bitset is set. 2956+ * 2957+ * @param bitset A pointer to the `ZyanBitset` instance. 2958+ * 2959+ * @return `ZYAN_STATUS_TRUE`, if at least one bit is set, `ZYAN_STATUS_FALSE`, if not. Another 2960+ * zyan status code, if an error occurred. 2961+ */ 2962+ZYCORE_EXPORT ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset); 2963+ 2964+/** 2965+ * Checks, if none bits of the given bitset are set. 2966+ * 2967+ * @param bitset A pointer to the `ZyanBitset` instance. 2968+ * 2969+ * @return `ZYAN_STATUS_TRUE`, if none bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan 2970+ * status code, if an error occurred. 2971+ */ 2972+ZYCORE_EXPORT ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset); 2973+ 2974+///* ---------------------------------------------------------------------------------------------- */ 2975+// 2976+///** 2977+// * Returns a 32-bit unsigned integer representation of the data. 2978+// * 2979+// * @param bitset A pointer to the `ZyanBitset` instance. 2980+// * @param value Receives the 32-bit unsigned integer representation of the data. 2981+// * 2982+// * @return A zyan status code. 2983+// */ 2984+//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value); 2985+// 2986+///** 2987+// * Returns a 64-bit unsigned integer representation of the data. 2988+// * 2989+// * @param bitset A pointer to the `ZyanBitset` instance. 2990+// * @param value Receives the 64-bit unsigned integer representation of the data. 2991+// * 2992+// * @return A zyan status code. 2993+// */ 2994+//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value); 2995+ 2996+/* ---------------------------------------------------------------------------------------------- */ 2997+ 2998+/* ============================================================================================== */ 2999+ 3000+#ifdef __cplusplus 3001+} 3002+#endif 3003+ 3004+#endif /* ZYCORE_BITSET_H */ 3005diff --git a/zycore/include/Zycore/Comparison.h b/zycore/include/Zycore/Comparison.h 3006new file mode 100644 3007index 0000000..6d8b518 3008--- /dev/null 3009+++ b/zycore/include/Zycore/Comparison.h 3010@@ -0,0 +1,316 @@ 3011+/*************************************************************************************************** 3012+ 3013+ Zyan Core Library (Zycore-C) 3014+ 3015+ Original Author : Florian Bernd 3016+ 3017+ * Permission is hereby granted, free of charge, to any person obtaining a copy 3018+ * of this software and associated documentation files (the "Software"), to deal 3019+ * in the Software without restriction, including without limitation the rights 3020+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 3021+ * copies of the Software, and to permit persons to whom the Software is 3022+ * furnished to do so, subject to the following conditions: 3023+ * 3024+ * The above copyright notice and this permission notice shall be included in all 3025+ * copies or substantial portions of the Software. 3026+ * 3027+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3028+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3029+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 3030+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3031+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 3032+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3033+ * SOFTWARE. 3034+ 3035+***************************************************************************************************/ 3036+ 3037+/** 3038+ * @file 3039+ * Defines prototypes of general-purpose comparison functions. 3040+ */ 3041+ 3042+#ifndef ZYCORE_COMPARISON_H 3043+#define ZYCORE_COMPARISON_H 3044+ 3045+#include <Zycore/Defines.h> 3046+#include <Zycore/Types.h> 3047+ 3048+#ifdef __cplusplus 3049+extern "C" { 3050+#endif 3051+ 3052+/* ============================================================================================== */ 3053+/* Enums and types */ 3054+/* ============================================================================================== */ 3055+ 3056+/** 3057+ * Defines the `ZyanEqualityComparison` function prototype. 3058+ * 3059+ * @param left A pointer to the first element. 3060+ * @param right A pointer to the second element. 3061+ * 3062+ * @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one 3063+ * or `ZYAN_FALSE`, if not. 3064+ */ 3065+typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right); 3066+ 3067+/** 3068+ * Defines the `ZyanComparison` function prototype. 3069+ * 3070+ * @param left A pointer to the first element. 3071+ * @param right A pointer to the second element. 3072+ * 3073+ * @return This function should return values in the following range: 3074+ * `left == right -> result == 0` 3075+ * `left < right -> result < 0` 3076+ * `left > right -> result > 0` 3077+ */ 3078+typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right); 3079+ 3080+/* ============================================================================================== */ 3081+/* Macros */ 3082+/* ============================================================================================== */ 3083+ 3084+/* ---------------------------------------------------------------------------------------------- */ 3085+/* Equality comparison functions */ 3086+/* ---------------------------------------------------------------------------------------------- */ 3087+ 3088+/** 3089+ * Declares a generic equality comparison function for an integral data-type. 3090+ * 3091+ * @param name The name of the function. 3092+ * @param type The name of the integral data-type. 3093+ */ 3094+#define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \ 3095+ ZyanBool name(const type* left, const type* right) \ 3096+ { \ 3097+ ZYAN_ASSERT(left); \ 3098+ ZYAN_ASSERT(right); \ 3099+ \ 3100+ return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \ 3101+ } 3102+ 3103+/** 3104+ * Declares a generic equality comparison function that compares a single integral 3105+ * data-type field of a struct. 3106+ * 3107+ * @param name The name of the function. 3108+ * @param type The name of the integral data-type. 3109+ * @param field_name The name of the struct field. 3110+ */ 3111+#define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \ 3112+ ZyanBool name(const type* left, const type* right) \ 3113+ { \ 3114+ ZYAN_ASSERT(left); \ 3115+ ZYAN_ASSERT(right); \ 3116+ \ 3117+ return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \ 3118+ } 3119+ 3120+/* ---------------------------------------------------------------------------------------------- */ 3121+/* Comparison functions */ 3122+/* ---------------------------------------------------------------------------------------------- */ 3123+ 3124+/** 3125+ * Declares a generic comparison function for an integral data-type. 3126+ * 3127+ * @param name The name of the function. 3128+ * @param type The name of the integral data-type. 3129+ */ 3130+#define ZYAN_DECLARE_COMPARISON(name, type) \ 3131+ ZyanI32 name(const type* left, const type* right) \ 3132+ { \ 3133+ ZYAN_ASSERT(left); \ 3134+ ZYAN_ASSERT(right); \ 3135+ \ 3136+ if (*left < *right) \ 3137+ { \ 3138+ return -1; \ 3139+ } \ 3140+ if (*left > *right) \ 3141+ { \ 3142+ return 1; \ 3143+ } \ 3144+ return 0; \ 3145+ } 3146+ 3147+/** 3148+ * Declares a generic comparison function that compares a single integral data-type field 3149+ * of a struct. 3150+ * 3151+ * @param name The name of the function. 3152+ * @param type The name of the integral data-type. 3153+ * @param field_name The name of the struct field. 3154+ */ 3155+#define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \ 3156+ ZyanI32 name(const type* left, const type* right) \ 3157+ { \ 3158+ ZYAN_ASSERT(left); \ 3159+ ZYAN_ASSERT(right); \ 3160+ \ 3161+ if (left->field_name < right->field_name) \ 3162+ { \ 3163+ return -1; \ 3164+ } \ 3165+ if (left->field_name > right->field_name) \ 3166+ { \ 3167+ return 1; \ 3168+ } \ 3169+ return 0; \ 3170+ } 3171+ 3172+ /* ---------------------------------------------------------------------------------------------- */ 3173+ 3174+/* ============================================================================================== */ 3175+/* Exported functions */ 3176+/* ============================================================================================== */ 3177+ 3178+/* ---------------------------------------------------------------------------------------------- */ 3179+/* Default equality comparison functions */ 3180+/* ---------------------------------------------------------------------------------------------- */ 3181+ 3182+/** 3183+ * Defines a default equality comparison function for pointer values. 3184+ * 3185+ * @param left A pointer to the first value. 3186+ * @param right A pointer to the second value. 3187+ * 3188+ * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if 3189+ * not. 3190+ */ 3191+ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const) 3192+ 3193+/** 3194+ * Defines a default equality comparison function for `ZyanBool` values. 3195+ * 3196+ * @param left A pointer to the first value. 3197+ * @param right A pointer to the second value. 3198+ * 3199+ * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if 3200+ * not. 3201+ */ 3202+ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool) 3203+ 3204+/** 3205+ * Defines a default equality comparison function for 8-bit numeric values. 3206+ * 3207+ * @param left A pointer to the first value. 3208+ * @param right A pointer to the second value. 3209+ * 3210+ * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if 3211+ * not. 3212+ */ 3213+ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8) 3214+ 3215+/** 3216+ * Defines a default equality comparison function for 16-bit numeric values. 3217+ * 3218+ * @param left A pointer to the first value. 3219+ * @param right A pointer to the second value. 3220+ * 3221+ * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if 3222+ * not. 3223+ */ 3224+ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16) 3225+ 3226+/** 3227+ * Defines a default equality comparison function for 32-bit numeric values. 3228+ * 3229+ * @param left A pointer to the first value. 3230+ * @param right A pointer to the second value. 3231+ * 3232+ * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if 3233+ * not. 3234+ */ 3235+ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32) 3236+ 3237+/** 3238+ * Defines a default equality comparison function for 64-bit numeric values. 3239+ * 3240+ * @param left A pointer to the first value. 3241+ * @param right A pointer to the second value. 3242+ * 3243+ * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if 3244+ * not. 3245+ */ 3246+ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64) 3247+ 3248+/* ---------------------------------------------------------------------------------------------- */ 3249+/* Default comparison functions */ 3250+/* ---------------------------------------------------------------------------------------------- */ 3251+ 3252+/** 3253+ * Defines a default comparison function for pointer values. 3254+ * 3255+ * @param left A pointer to the first value. 3256+ * @param right A pointer to the second value. 3257+ * 3258+ * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is 3259+ * less than the `right` one, or `1` if the `left` value is greater than the `right` one. 3260+ */ 3261+ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const) 3262+ 3263+/** 3264+ * Defines a default comparison function for `ZyanBool` values. 3265+ * 3266+ * @param left A pointer to the first value. 3267+ * @param right A pointer to the second value. 3268+ * 3269+ * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is 3270+ * less than the `right` one, or `1` if the `left` value is greater than the `right` one. 3271+ */ 3272+ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool) 3273+ 3274+/** 3275+ * Defines a default comparison function for 8-bit numeric values. 3276+ * 3277+ * @param left A pointer to the first value. 3278+ * @param right A pointer to the second value. 3279+ * 3280+ * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is 3281+ * less than the `right` one, or `1` if the `left` value is greater than the `right` one. 3282+ */ 3283+ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8) 3284+ 3285+/** 3286+ * Defines a default comparison function for 16-bit numeric values. 3287+ * 3288+ * @param left A pointer to the first value. 3289+ * @param right A pointer to the second value. 3290+ * 3291+ * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is 3292+ * less than the `right` one, or `1` if the `left` value is greater than the `right` one. 3293+ */ 3294+ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16) 3295+ 3296+/** 3297+ * Defines a default comparison function for 32-bit numeric values. 3298+ * 3299+ * @param left A pointer to the first value. 3300+ * @param right A pointer to the second value. 3301+ * 3302+ * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is 3303+ * less than the `right` one, or `1` if the `left` value is greater than the `right` one. 3304+ */ 3305+ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32) 3306+ 3307+/** 3308+ * Defines a default comparison function for 64-bit numeric values. 3309+ * 3310+ * @param left A pointer to the first value. 3311+ * @param right A pointer to the second value. 3312+ * 3313+ * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is 3314+ * less than the `right` one, or `1` if the `left` value is greater than the `right` one. 3315+ */ 3316+ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64) 3317+ 3318+/* ---------------------------------------------------------------------------------------------- */ 3319+ 3320+/* ============================================================================================== */ 3321+ 3322+#ifdef __cplusplus 3323+} 3324+#endif 3325+ 3326+#endif /* ZYCORE_COMPARISON_H */ 3327diff --git a/zycore/include/Zycore/Defines.h b/zycore/include/Zycore/Defines.h 3328new file mode 100644 3329index 0000000..d823d34 3330--- /dev/null 3331+++ b/zycore/include/Zycore/Defines.h 3332@@ -0,0 +1,521 @@ 3333+/*************************************************************************************************** 3334+ 3335+ Zyan Core Library (Zycore-C) 3336+ 3337+ Original Author : Florian Bernd, Joel Hoener 3338+ 3339+ * Permission is hereby granted, free of charge, to any person obtaining a copy 3340+ * of this software and associated documentation files (the "Software"), to deal 3341+ * in the Software without restriction, including without limitation the rights 3342+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 3343+ * copies of the Software, and to permit persons to whom the Software is 3344+ * furnished to do so, subject to the following conditions: 3345+ * 3346+ * The above copyright notice and this permission notice shall be included in all 3347+ * copies or substantial portions of the Software. 3348+ * 3349+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3350+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3351+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 3352+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3353+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 3354+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3355+ * SOFTWARE. 3356+ 3357+***************************************************************************************************/ 3358+ 3359+/** 3360+ * @file 3361+ * General helper and platform detection macros. 3362+ */ 3363+ 3364+#ifndef ZYCORE_DEFINES_H 3365+#define ZYCORE_DEFINES_H 3366+ 3367+/* ============================================================================================== */ 3368+/* Meta macros */ 3369+/* ============================================================================================== */ 3370+ 3371+/** 3372+ * Concatenates two values using the stringify operator (`##`). 3373+ * 3374+ * @param x The first value. 3375+ * @param y The second value. 3376+ * 3377+ * @return The combined string of the given values. 3378+ */ 3379+#define ZYAN_MACRO_CONCAT(x, y) x ## y 3380+ 3381+/** 3382+ * Concatenates two values using the stringify operator (`##`) and expands the value to 3383+ * be used in another macro. 3384+ * 3385+ * @param x The first value. 3386+ * @param y The second value. 3387+ * 3388+ * @return The combined string of the given values. 3389+ */ 3390+#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y) 3391+ 3392+/* ============================================================================================== */ 3393+/* Compiler detection */ 3394+/* ============================================================================================== */ 3395+ 3396+#if defined(__clang__) 3397+# define ZYAN_CLANG 3398+# define ZYAN_GNUC 3399+#elif defined(__ICC) || defined(__INTEL_COMPILER) 3400+# define ZYAN_ICC 3401+#elif defined(__GNUC__) || defined(__GNUG__) 3402+# define ZYAN_GCC 3403+# define ZYAN_GNUC 3404+#elif defined(_MSC_VER) 3405+# define ZYAN_MSVC 3406+#elif defined(__BORLANDC__) 3407+# define ZYAN_BORLAND 3408+#else 3409+# define ZYAN_UNKNOWN_COMPILER 3410+#endif 3411+ 3412+/* ============================================================================================== */ 3413+/* Platform detection */ 3414+/* ============================================================================================== */ 3415+ 3416+#if defined(_WIN32) 3417+# define ZYAN_WINDOWS 3418+#elif defined(__EMSCRIPTEN__) 3419+# define ZYAN_EMSCRIPTEN 3420+#elif defined(__wasi__) || defined(__WASI__) 3421+// via: https://reviews.llvm.org/D57155 3422+# define ZYAN_WASI 3423+#elif defined(__APPLE__) 3424+# define ZYAN_APPLE 3425+# define ZYAN_POSIX 3426+#elif defined(__linux) 3427+# define ZYAN_LINUX 3428+# define ZYAN_POSIX 3429+#elif defined(__FreeBSD__) 3430+# define ZYAN_FREEBSD 3431+# define ZYAN_POSIX 3432+#elif defined(sun) || defined(__sun) 3433+# define ZYAN_SOLARIS 3434+# define ZYAN_POSIX 3435+#elif defined(__unix) 3436+# define ZYAN_UNIX 3437+# define ZYAN_POSIX 3438+#elif defined(__posix) 3439+# define ZYAN_POSIX 3440+#else 3441+# define ZYAN_UNKNOWN_PLATFORM 3442+#endif 3443+ 3444+/* ============================================================================================== */ 3445+/* Kernel mode detection */ 3446+/* ============================================================================================== */ 3447+ 3448+#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \ 3449+ (defined(ZYAN_APPLE) && defined(KERNEL)) || \ 3450+ (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \ 3451+ (defined(__FreeBSD_kernel__)) 3452+# define ZYAN_KERNEL 3453+#else 3454+# define ZYAN_USER 3455+#endif 3456+ 3457+/* ============================================================================================== */ 3458+/* Architecture detection */ 3459+/* ============================================================================================== */ 3460+ 3461+#if defined(_M_AMD64) || defined(__x86_64__) 3462+# define ZYAN_X64 3463+#elif defined(_M_IX86) || defined(__i386__) 3464+# define ZYAN_X86 3465+#elif defined(_M_ARM64) || defined(__aarch64__) 3466+# define ZYAN_AARCH64 3467+#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) 3468+# define ZYAN_ARM 3469+#elif defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__) 3470+# define ZYAN_WASM 3471+#else 3472+# error "Unsupported architecture detected" 3473+#endif 3474+ 3475+/* ============================================================================================== */ 3476+/* Debug/Release detection */ 3477+/* ============================================================================================== */ 3478+ 3479+#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND) 3480+# ifdef _DEBUG 3481+# define ZYAN_DEBUG 3482+# else 3483+# define ZYAN_RELEASE 3484+# endif 3485+#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC) 3486+# ifdef NDEBUG 3487+# define ZYAN_RELEASE 3488+# else 3489+# define ZYAN_DEBUG 3490+# endif 3491+#else 3492+# define ZYAN_RELEASE 3493+#endif 3494+ 3495+/* ============================================================================================== */ 3496+/* Deprecation hint */ 3497+/* ============================================================================================== */ 3498+ 3499+#if defined(ZYAN_GCC) || defined(ZYAN_CLANG) 3500+# define ZYAN_DEPRECATED __attribute__((__deprecated__)) 3501+#elif defined(ZYAN_MSVC) 3502+# define ZYAN_DEPRECATED __declspec(deprecated) 3503+#else 3504+# define ZYAN_DEPRECATED 3505+#endif 3506+ 3507+/* ============================================================================================== */ 3508+/* Generic DLL import/export helpers */ 3509+/* ============================================================================================== */ 3510+ 3511+#if defined(ZYAN_MSVC) 3512+# define ZYAN_DLLEXPORT __declspec(dllexport) 3513+# define ZYAN_DLLIMPORT __declspec(dllimport) 3514+#else 3515+# define ZYAN_DLLEXPORT 3516+# define ZYAN_DLLIMPORT 3517+#endif 3518+ 3519+/* ============================================================================================== */ 3520+/* Zycore dll{export,import} */ 3521+/* ============================================================================================== */ 3522+ 3523+// This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To 3524+// simplify builds without CMake, we define these things manually instead of relying on CMake 3525+// to generate the header. 3526+// 3527+// For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds, 3528+// our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or 3529+// exported. If CMake isn't used, users can manually define these to fit their use-case. 3530+ 3531+// Backward compatibility: CMake would previously generate these variables names. However, because 3532+// they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For 3533+// backward compatibility for users that don't use CMake and previously manually defined these, we 3534+// translate the old defines here and print a warning. 3535+#if defined(ZYCORE_STATIC_DEFINE) 3536+# pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.") 3537+# define ZYCORE_STATIC_BUILD 3538+#endif 3539+#if defined(Zycore_EXPORTS) 3540+# pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.") 3541+# define ZYCORE_SHOULD_EXPORT 3542+#endif 3543+ 3544+/** 3545+ * Symbol is exported in shared library builds. 3546+ */ 3547+#if defined(ZYCORE_STATIC_BUILD) 3548+# define ZYCORE_EXPORT 3549+#else 3550+# if defined(ZYCORE_SHOULD_EXPORT) 3551+# define ZYCORE_EXPORT ZYAN_DLLEXPORT 3552+# else 3553+# define ZYCORE_EXPORT ZYAN_DLLIMPORT 3554+# endif 3555+#endif 3556+ 3557+/** 3558+ * Symbol is not exported and for internal use only. 3559+ */ 3560+#define ZYCORE_NO_EXPORT 3561+ 3562+/* ============================================================================================== */ 3563+/* Misc compatibility macros */ 3564+/* ============================================================================================== */ 3565+ 3566+#if defined(ZYAN_CLANG) 3567+# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what))) 3568+#else 3569+# define ZYAN_NO_SANITIZE(what) 3570+#endif 3571+ 3572+#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND) 3573+# define ZYAN_INLINE __inline 3574+#else 3575+# define ZYAN_INLINE static inline 3576+#endif 3577+ 3578+#if defined(ZYAN_MSVC) 3579+# define ZYAN_NOINLINE __declspec(noinline) 3580+#elif defined(ZYAN_GCC) || defined(ZYAN_CLANG) 3581+# define ZYAN_NOINLINE __attribute__((noinline)) 3582+#else 3583+# define ZYAN_NOINLINE 3584+#endif 3585+ 3586+/* ============================================================================================== */ 3587+/* Debugging and optimization macros */ 3588+/* ============================================================================================== */ 3589+ 3590+/** 3591+ * Runtime debug assertion. 3592+ */ 3593+#if defined(ZYAN_NO_LIBC) 3594+# define ZYAN_ASSERT(condition) (void)(condition) 3595+#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) 3596+# include <wdm.h> 3597+# define ZYAN_ASSERT(condition) NT_ASSERT(condition) 3598+#else 3599+# include <assert.h> 3600+# define ZYAN_ASSERT(condition) assert(condition) 3601+#endif 3602+ 3603+/** 3604+ * Compiler-time assertion. 3605+ */ 3606+#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus) 3607+# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x) 3608+#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \ 3609+ (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \ 3610+ (defined (_MSC_VER) && (_MSC_VER >= 1800)) 3611+# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x) 3612+#else 3613+# define ZYAN_STATIC_ASSERT(x) \ 3614+ typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1] 3615+#endif 3616+ 3617+/** 3618+ * Marks the current code path as unreachable. 3619+ */ 3620+#if defined(ZYAN_RELEASE) 3621+# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs. 3622+# if __has_builtin(__builtin_unreachable) 3623+# define ZYAN_UNREACHABLE __builtin_unreachable() 3624+# else 3625+# define ZYAN_UNREACHABLE for(;;) 3626+# endif 3627+# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4) 3628+# define ZYAN_UNREACHABLE __builtin_unreachable() 3629+# elif defined(ZYAN_ICC) 3630+# ifdef ZYAN_WINDOWS 3631+# include <stdlib.h> // "missing return statement" workaround 3632+# define ZYAN_UNREACHABLE __assume(0); (void)abort() 3633+# else 3634+# define ZYAN_UNREACHABLE __builtin_unreachable() 3635+# endif 3636+# elif defined(ZYAN_MSVC) 3637+# define ZYAN_UNREACHABLE __assume(0) 3638+# else 3639+# define ZYAN_UNREACHABLE for(;;) 3640+# endif 3641+#elif defined(ZYAN_NO_LIBC) 3642+# define ZYAN_UNREACHABLE for(;;) 3643+#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) 3644+# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} } 3645+#else 3646+# include <stdlib.h> 3647+# define ZYAN_UNREACHABLE { assert(0); abort(); } 3648+#endif 3649+ 3650+/* ============================================================================================== */ 3651+/* Utils */ 3652+/* ============================================================================================== */ 3653+ 3654+/* ---------------------------------------------------------------------------------------------- */ 3655+/* General purpose */ 3656+/* ---------------------------------------------------------------------------------------------- */ 3657+ 3658+/** 3659+ * Marks the specified parameter as unused. 3660+ * 3661+ * @param x The name of the unused parameter. 3662+ */ 3663+#define ZYAN_UNUSED(x) (void)(x) 3664+ 3665+/** 3666+ * Intentional fallthrough. 3667+ */ 3668+#if defined(ZYAN_GCC) && __GNUC__ >= 7 3669+# define ZYAN_FALLTHROUGH __attribute__((__fallthrough__)) 3670+#else 3671+# define ZYAN_FALLTHROUGH 3672+#endif 3673+ 3674+/** 3675+ * Declares a bitfield. 3676+ * 3677+ * @param x The size (in bits) of the bitfield. 3678+ */ 3679+#define ZYAN_BITFIELD(x) : x 3680+ 3681+/** 3682+ * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`). 3683+ */ 3684+#define ZYAN_REQUIRES_LIBC 3685+ 3686+/** 3687+ * Decorator for `printf`-style functions. 3688+ * 3689+ * @param format_index The 1-based index of the format string parameter. 3690+ * @param first_to_check The 1-based index of the format arguments parameter. 3691+ */ 3692+#if defined(__RESHARPER__) 3693+# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ 3694+ [[gnu::format(printf, format_index, first_to_check)]] 3695+#elif defined(ZYAN_GCC) 3696+# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ 3697+ __attribute__((format(printf, format_index, first_to_check))) 3698+#else 3699+# define ZYAN_PRINTF_ATTR(format_index, first_to_check) 3700+#endif 3701+ 3702+/** 3703+ * Decorator for `wprintf`-style functions. 3704+ * 3705+ * @param format_index The 1-based index of the format string parameter. 3706+ * @param first_to_check The 1-based index of the format arguments parameter. 3707+ */ 3708+#if defined(__RESHARPER__) 3709+# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \ 3710+ [[rscpp::format(wprintf, format_index, first_to_check)]] 3711+#else 3712+# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) 3713+#endif 3714+ 3715+/* ---------------------------------------------------------------------------------------------- */ 3716+/* Arrays */ 3717+/* ---------------------------------------------------------------------------------------------- */ 3718+ 3719+/** 3720+ * Returns the length (number of elements) of an array. 3721+ * 3722+ * @param a The name of the array. 3723+ * 3724+ * @return The number of elements of the given array. 3725+ */ 3726+#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) 3727+ 3728+/* ---------------------------------------------------------------------------------------------- */ 3729+/* Arithmetic */ 3730+/* ---------------------------------------------------------------------------------------------- */ 3731+ 3732+/** 3733+ * Returns the smaller value of `a` or `b`. 3734+ * 3735+ * @param a The first value. 3736+ * @param b The second value. 3737+ * 3738+ * @return The smaller value of `a` or `b`. 3739+ */ 3740+#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b)) 3741+ 3742+/** 3743+ * Returns the bigger value of `a` or `b`. 3744+ * 3745+ * @param a The first value. 3746+ * @param b The second value. 3747+ * 3748+ * @return The bigger value of `a` or `b`. 3749+ */ 3750+#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b)) 3751+ 3752+/** 3753+ * Returns the absolute value of `a`. 3754+ * 3755+ * @param a The value. 3756+ * 3757+ * @return The absolute value of `a`. 3758+ */ 3759+#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a)) 3760+ 3761+/** 3762+ * Checks, if the given value is a power of 2. 3763+ * 3764+ * @param x The value. 3765+ * 3766+ * @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not. 3767+ * 3768+ * Note that this macro always returns `ZYAN_TRUE` for `x == 0`. 3769+ */ 3770+#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) 3771+ 3772+/** 3773+ * Checks, if the given value is properly aligned. 3774+ * 3775+ * Note that this macro only works for powers of 2. 3776+ */ 3777+#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0) 3778+ 3779+/** 3780+ * Aligns the value to the nearest given alignment boundary (by rounding it up). 3781+ * 3782+ * @param x The value. 3783+ * @param align The desired alignment. 3784+ * 3785+ * @return The aligned value. 3786+ * 3787+ * Note that this macro only works for powers of 2. 3788+ */ 3789+#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) 3790+ 3791+/** 3792+ * Aligns the value to the nearest given alignment boundary (by rounding it down). 3793+ * 3794+ * @param x The value. 3795+ * @param align The desired alignment. 3796+ * 3797+ * @return The aligned value. 3798+ * 3799+ * Note that this macro only works for powers of 2. 3800+ */ 3801+#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1)) 3802+ 3803+/* ---------------------------------------------------------------------------------------------- */ 3804+/* Bit operations */ 3805+/* ---------------------------------------------------------------------------------------------- */ 3806+ 3807+/* 3808+ * Checks, if the bit at index `b` is required to present the ordinal value `n`. 3809+ * 3810+ * @param n The ordinal value. 3811+ * @param b The bit index. 3812+ * 3813+ * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or 3814+ * `ZYAN_FALSE`, if not. 3815+ * 3816+ * Note that this macro always returns `ZYAN_FALSE` for `n == 0`. 3817+ */ 3818+#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0) 3819+ 3820+/* 3821+ * Returns the number of bits required to represent the ordinal value `n`. 3822+ * 3823+ * @param n The ordinal value. 3824+ * 3825+ * @return The number of bits required to represent the ordinal value `n`. 3826+ * 3827+ * Note that this macro returns `0` for `n == 0`. 3828+ */ 3829+#define ZYAN_BITS_TO_REPRESENT(n) \ 3830+ ( \ 3831+ ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \ 3832+ ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \ 3833+ ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \ 3834+ ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \ 3835+ ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \ 3836+ ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \ 3837+ ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \ 3838+ ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \ 3839+ ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \ 3840+ ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \ 3841+ ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \ 3842+ ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \ 3843+ ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \ 3844+ ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \ 3845+ ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \ 3846+ ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \ 3847+ ) 3848+ 3849+/* ---------------------------------------------------------------------------------------------- */ 3850+ 3851+/* ============================================================================================== */ 3852+ 3853+#endif /* ZYCORE_DEFINES_H */ 3854diff --git a/zycore/include/Zycore/Format.h b/zycore/include/Zycore/Format.h 3855new file mode 100644 3856index 0000000..006ca31 3857--- /dev/null 3858+++ b/zycore/include/Zycore/Format.h 3859@@ -0,0 +1,285 @@ 3860+/*************************************************************************************************** 3861+ 3862+ Zyan Core Library (Zycore-C) 3863+ 3864+ Original Author : Florian Bernd 3865+ 3866+ * Permission is hereby granted, free of charge, to any person obtaining a copy 3867+ * of this software and associated documentation files (the "Software"), to deal 3868+ * in the Software without restriction, including without limitation the rights 3869+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 3870+ * copies of the Software, and to permit persons to whom the Software is 3871+ * furnished to do so, subject to the following conditions: 3872+ * 3873+ * The above copyright notice and this permission notice shall be included in all 3874+ * copies or substantial portions of the Software. 3875+ * 3876+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3877+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3878+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 3879+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3880+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 3881+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3882+ * SOFTWARE. 3883+ 3884+***************************************************************************************************/ 3885+ 3886+/** 3887+ * @file 3888+ * Provides helper functions for performant number to string conversion. 3889+ */ 3890+ 3891+#ifndef ZYCORE_FORMAT_H 3892+#define ZYCORE_FORMAT_H 3893+ 3894+#include <Zycore/Status.h> 3895+#include <Zycore/String.h> 3896+#include <Zycore/Types.h> 3897+ 3898+#ifdef __cplusplus 3899+extern "C" { 3900+#endif 3901+ 3902+/* ============================================================================================== */ 3903+/* Exported functions */ 3904+/* ============================================================================================== */ 3905+ 3906+/* ---------------------------------------------------------------------------------------------- */ 3907+/* Helpers */ 3908+/* ---------------------------------------------------------------------------------------------- */ 3909+ 3910+/** 3911+ * Get the absolute value of a 64 bit int. 3912+ * 3913+ * @param x The value to process. 3914+ * @return The absolute, unsigned value. 3915+ * 3916+ * This gracefully deals with the special case of `x` being `INT_MAX`. 3917+ */ 3918+ZYAN_INLINE ZyanU64 ZyanAbsI64(ZyanI64 x) 3919+{ 3920+ // INT_MIN special case. Can't use the value directly because GCC thinks 3921+ // it's too big for an INT64 literal, however is perfectly happy to accept 3922+ // this expression. This is also hit INT64_MIN is defined in `stdint.h`. 3923+ if (x == (-0x7fffffffffffffff - 1)) 3924+ { 3925+ return 0x8000000000000000u; 3926+ } 3927+ 3928+ return (ZyanU64)(x < 0 ? -x : x); 3929+} 3930+ 3931+/* ---------------------------------------------------------------------------------------------- */ 3932+/* Insertion */ 3933+/* ---------------------------------------------------------------------------------------------- */ 3934+ 3935+/** 3936+ * Inserts formatted text in the destination string at the given `index`. 3937+ * 3938+ * @param string The destination string. 3939+ * @param index The insert index. 3940+ * @param format The format string. 3941+ * @param ... The format arguments. 3942+ * 3943+ * @return A zyan status code. 3944+ * 3945+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 3946+ * `ZyanString` instance. 3947+ */ 3948+ZYAN_PRINTF_ATTR(3, 4) 3949+ZYCORE_EXPORT ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index, 3950+ const char* format, ...); 3951+ 3952+/* ---------------------------------------------------------------------------------------------- */ 3953+ 3954+/** 3955+ * Formats the given unsigned ordinal `value` to its decimal text-representation and 3956+ * inserts it to the `string`. 3957+ * 3958+ * @param string A pointer to the `ZyanString` instance. 3959+ * @param index The insert index. 3960+ * @param value The value. 3961+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 3962+ * less than the `padding_length`. 3963+ * 3964+ * @return A zyan status code. 3965+ * 3966+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 3967+ * `ZyanString` instance. 3968+ */ 3969+ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value, 3970+ ZyanU8 padding_length); 3971+ 3972+/** 3973+ * Formats the given signed ordinal `value` to its decimal text-representation and 3974+ * inserts it to the `string`. 3975+ * 3976+ * @param string A pointer to the `ZyanString` instance. 3977+ * @param index The insert index. 3978+ * @param value The value. 3979+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 3980+ * less than the `padding_length`. 3981+ * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. 3982+ * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. 3983+ * 3984+ * @return A zyan status code. 3985+ * 3986+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 3987+ * `ZyanString` instance. 3988+ */ 3989+ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value, 3990+ ZyanU8 padding_length, ZyanBool force_sign, const ZyanString* prefix); 3991+ 3992+/** 3993+ * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and 3994+ * inserts it to the `string`. 3995+ * 3996+ * @param string A pointer to the `ZyanString` instance. 3997+ * @param index The insert index. 3998+ * @param value The value. 3999+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 4000+ * less than the `padding_length`. 4001+ * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase 4002+ * ones ('a'-'f'). 4003+ * 4004+ * @return A zyan status code. 4005+ * 4006+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4007+ * `ZyanString` instance. 4008+ */ 4009+ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value, 4010+ ZyanU8 padding_length, ZyanBool uppercase); 4011+ 4012+/** 4013+ * Formats the given signed ordinal `value` to its hexadecimal text-representation and 4014+ * inserts it to the `string`. 4015+ * 4016+ * @param string A pointer to the `ZyanString` instance. 4017+ * @param index The insert index. 4018+ * @param value The value. 4019+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 4020+ * less than the `padding_length`. 4021+ * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase 4022+ * ones ('a'-'f'). 4023+ * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. 4024+ * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. 4025+ * 4026+ * @return A zyan status code. 4027+ * 4028+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4029+ * `ZyanString` instance. 4030+ */ 4031+ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value, 4032+ ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix); 4033+ 4034+/* ---------------------------------------------------------------------------------------------- */ 4035+/* Appending */ 4036+/* ---------------------------------------------------------------------------------------------- */ 4037+ 4038+#ifndef ZYAN_NO_LIBC 4039+ 4040+/** 4041+ * Appends formatted text to the destination string. 4042+ * 4043+ * @param string The destination string. 4044+ * @param format The format string. 4045+ * @param ... The format arguments. 4046+ * 4047+ * @return A zyan status code. 4048+ * 4049+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4050+ * `ZyanString` instance. 4051+ */ 4052+ZYAN_PRINTF_ATTR(2, 3) 4053+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringAppendFormat( 4054+ ZyanString* string, const char* format, ...); 4055+ 4056+#endif // ZYAN_NO_LIBC 4057+ 4058+/* ---------------------------------------------------------------------------------------------- */ 4059+ 4060+/** 4061+ * Formats the given unsigned ordinal `value` to its decimal text-representation and 4062+ * appends it to the `string`. 4063+ * 4064+ * @param string A pointer to the `ZyanString` instance. 4065+ * @param value The value. 4066+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 4067+ * less than the `padding_length`. 4068+ * 4069+ * @return A zyan status code. 4070+ * 4071+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4072+ * `ZyanString` instance. 4073+ */ 4074+ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value, 4075+ ZyanU8 padding_length); 4076+ 4077+/** 4078+ * Formats the given signed ordinal `value` to its decimal text-representation and 4079+ * appends it to the `string`. 4080+ * 4081+ * @param string A pointer to the `ZyanString` instance. 4082+ * @param value The value. 4083+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 4084+ * less than the `padding_length`. 4085+ * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. 4086+ * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. 4087+ * 4088+ * @return A zyan status code. 4089+ * 4090+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4091+ * `ZyanString` instance. 4092+ */ 4093+ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value, 4094+ ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix); 4095+ 4096+/** 4097+ * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and 4098+ * appends it to the `string`. 4099+ * 4100+ * @param string A pointer to the `ZyanString` instance. 4101+ * @param value The value. 4102+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 4103+ * less than the `padding_length`. 4104+ * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase 4105+ * ones ('a'-'f'). 4106+ * 4107+ * @return A zyan status code. 4108+ * 4109+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4110+ * `ZyanString` instance. 4111+ */ 4112+ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value, 4113+ ZyanU8 padding_length, ZyanBool uppercase); 4114+ 4115+/** 4116+ * Formats the given signed ordinal `value` to its hexadecimal text-representation and 4117+ * appends it to the `string`. 4118+ * 4119+ * @param string A pointer to the `ZyanString` instance. 4120+ * @param value The value. 4121+ * @param padding_length Padds the converted value with leading zeros, if the number of chars is 4122+ * less than the `padding_length`. 4123+ * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase 4124+ * ones ('a'-'f'). 4125+ * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. 4126+ * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. 4127+ * 4128+ * @return A zyan status code. 4129+ * 4130+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 4131+ * `ZyanString` instance. 4132+ */ 4133+ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value, 4134+ ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix); 4135+ 4136+/* ---------------------------------------------------------------------------------------------- */ 4137+ 4138+/* ============================================================================================== */ 4139+ 4140+#ifdef __cplusplus 4141+} 4142+#endif 4143+ 4144+#endif // ZYCORE_FORMAT_H 4145diff --git a/zycore/include/Zycore/Internal/AtomicGNU.h b/zycore/include/Zycore/Internal/AtomicGNU.h 4146new file mode 100644 4147index 0000000..ca6b360 4148--- /dev/null 4149+++ b/zycore/include/Zycore/Internal/AtomicGNU.h 4150@@ -0,0 +1,117 @@ 4151+/*************************************************************************************************** 4152+ 4153+ Zyan Core Library (Zyan-C) 4154+ 4155+ Original Author : Florian Bernd 4156+ 4157+ * Permission is hereby granted, free of charge, to any person obtaining a copy 4158+ * of this software and associated documentation files (the "Software"), to deal 4159+ * in the Software without restriction, including without limitation the rights 4160+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 4161+ * copies of the Software, and to permit persons to whom the Software is 4162+ * furnished to do so, subject to the following conditions: 4163+ * 4164+ * The above copyright notice and this permission notice shall be included in all 4165+ * copies or substantial portions of the Software. 4166+ * 4167+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4168+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4169+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4170+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4171+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4172+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4173+ * SOFTWARE. 4174+ 4175+***************************************************************************************************/ 4176+ 4177+#ifndef ZYCORE_ATOMIC_GNU_H 4178+#define ZYCORE_ATOMIC_GNU_H 4179+ 4180+#ifdef __cplusplus 4181+extern "C" { 4182+#endif 4183+ 4184+#include <Zycore/Defines.h> 4185+#include <Zycore/Types.h> 4186+ 4187+/* ============================================================================================== */ 4188+/* Functions */ 4189+/* ============================================================================================== */ 4190+ 4191+#if defined(ZYAN_CLANG) || defined(ZYAN_GCC) || defined(ZYAN_ICC) 4192+ 4193+/* ---------------------------------------------------------------------------------------------- */ 4194+/* Pointer sized */ 4195+/* ---------------------------------------------------------------------------------------------- */ 4196+ 4197+ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination, 4198+ ZyanUPointer comparand, ZyanUPointer value) 4199+{ 4200+ return (ZyanUPointer)(__sync_val_compare_and_swap( 4201+ &destination->value, (void*)comparand, (void*)value, &destination->value)); 4202+} 4203+ 4204+ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination) 4205+{ 4206+ return (ZyanUPointer)(__sync_fetch_and_add(&destination->value, (void*)1, 4207+ &destination->value)) + 1; 4208+} 4209+ 4210+ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination) 4211+{ 4212+ return (ZyanUPointer)(__sync_sub_and_fetch(&destination->value, (void*)1, &destination->value)); 4213+} 4214+ 4215+/* ---------------------------------------------------------------------------------------------- */ 4216+/* 32-bit */ 4217+/* ---------------------------------------------------------------------------------------------- */ 4218+ 4219+ZYAN_INLINE ZyanU32 ZyanAtomicCompareExchange32(ZyanAtomic32* destination, 4220+ ZyanU32 comparand, ZyanU32 value) 4221+{ 4222+ return (ZyanU32)(__sync_val_compare_and_swap(&destination->value, comparand, value, 4223+ &destination->value)); 4224+} 4225+ 4226+ZYAN_INLINE ZyanU32 ZyanAtomicIncrement32(ZyanAtomic32* destination) 4227+{ 4228+ return (ZyanU32)(__sync_fetch_and_add(&destination->value, 1, &destination->value)) + 1; 4229+} 4230+ 4231+ZYAN_INLINE ZyanU32 ZyanAtomicDecrement32(ZyanAtomic32* destination) 4232+{ 4233+ return (ZyanU32)(__sync_sub_and_fetch(&destination->value, 1, &destination->value)); 4234+} 4235+ 4236+/* ---------------------------------------------------------------------------------------------- */ 4237+/* 64-bit */ 4238+/* ---------------------------------------------------------------------------------------------- */ 4239+ 4240+ZYAN_INLINE ZyanU64 ZyanAtomicCompareExchange64(ZyanAtomic64* destination, 4241+ ZyanU64 comparand, ZyanU64 value) 4242+{ 4243+ return (ZyanU64)(__sync_val_compare_and_swap(&destination->value, comparand, value, 4244+ &destination->value)); 4245+} 4246+ 4247+ZYAN_INLINE ZyanU64 ZyanAtomicIncrement64(ZyanAtomic64* destination) 4248+{ 4249+ return (ZyanU64)(__sync_fetch_and_add(&destination->value, 1, &destination->value)) + 1; 4250+} 4251+ 4252+ZYAN_INLINE ZyanU64 ZyanAtomicDecrement64(ZyanAtomic64* destination) 4253+{ 4254+ return (ZyanU64)(__sync_sub_and_fetch(&destination->value, 1, &destination->value)); 4255+} 4256+ 4257+/* ---------------------------------------------------------------------------------------------- */ 4258+ 4259+#endif 4260+ 4261+/* ============================================================================================== */ 4262+ 4263+#ifdef __cplusplus 4264+} 4265+#endif 4266+ 4267+#endif /* ZYCORE_ATOMIC_GNU_H */ 4268diff --git a/zycore/include/Zycore/Internal/AtomicMSVC.h b/zycore/include/Zycore/Internal/AtomicMSVC.h 4269new file mode 100644 4270index 0000000..f4dc1e6 4271--- /dev/null 4272+++ b/zycore/include/Zycore/Internal/AtomicMSVC.h 4273@@ -0,0 +1,141 @@ 4274+/*************************************************************************************************** 4275+ 4276+ Zyan Core Library (Zyan-C) 4277+ 4278+ Original Author : Florian Bernd 4279+ 4280+ * Permission is hereby granted, free of charge, to any person obtaining a copy 4281+ * of this software and associated documentation files (the "Software"), to deal 4282+ * in the Software without restriction, including without limitation the rights 4283+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 4284+ * copies of the Software, and to permit persons to whom the Software is 4285+ * furnished to do so, subject to the following conditions: 4286+ * 4287+ * The above copyright notice and this permission notice shall be included in all 4288+ * copies or substantial portions of the Software. 4289+ * 4290+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4291+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4292+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4293+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4294+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4295+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4296+ * SOFTWARE. 4297+ 4298+***************************************************************************************************/ 4299+ 4300+#ifndef ZYCORE_ATOMIC_MSVC_H 4301+#define ZYCORE_ATOMIC_MSVC_H 4302+ 4303+#ifdef __cplusplus 4304+extern "C" { 4305+#endif 4306+ 4307+#include <Windows.h> 4308+ 4309+#include <Zycore/Defines.h> 4310+#include <Zycore/Types.h> 4311+ 4312+/* ============================================================================================== */ 4313+/* Functions */ 4314+/* ============================================================================================== */ 4315+ 4316+#if defined(ZYAN_MSVC) 4317+ 4318+/* ---------------------------------------------------------------------------------------------- */ 4319+/* Pointer sized */ 4320+/* ---------------------------------------------------------------------------------------------- */ 4321+ 4322+#if defined(ZYAN_X86) 4323+ 4324+static ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination, 4325+ ZyanUPointer comparand, ZyanUPointer value) 4326+{ 4327+ return (ZyanUPointer)ZyanAtomicCompareExchange32((ZyanAtomic32*)destination, comparand, value); 4328+} 4329+ 4330+static ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination) 4331+{ 4332+ return (ZyanUPointer)ZyanAtomicIncrement32((ZyanAtomic32*)destination); 4333+} 4334+ 4335+static ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination) 4336+{ 4337+ return (ZyanUPointer)ZyanAtomicDecrement32((ZyanAtomic32*)destination); 4338+} 4339+ 4340+#elif defined(ZYAN_X64) 4341+ 4342+static ZYAN_INLINE ZyanUPointer ZyanAtomicCompareExchange(ZyanAtomicPointer* destination, 4343+ ZyanUPointer comparand, ZyanUPointer value) 4344+{ 4345+ return (ZyanUPointer)ZyanAtomicCompareExchange64((ZyanAtomic64*)destination, comparand, value); 4346+} 4347+ 4348+static ZYAN_INLINE ZyanUPointer ZyanAtomicIncrement(ZyanAtomicPointer* destination) 4349+{ 4350+ return (ZyanUPointer)ZyanAtomicIncrement64((ZyanAtomic64*)destination); 4351+} 4352+ 4353+static ZYAN_INLINE ZyanUPointer ZyanAtomicDecrement(ZyanAtomicPointer* destination) 4354+{ 4355+ return (ZyanUPointer)ZyanAtomicDecrement64((ZyanAtomic64*)destination); 4356+} 4357+ 4358+#else 4359+# error "Unsupported architecture detected" 4360+#endif 4361+ 4362+/* ---------------------------------------------------------------------------------------------- */ 4363+/* 32-bit */ 4364+/* ---------------------------------------------------------------------------------------------- */ 4365+ 4366+static ZYAN_INLINE ZyanU32 ZyanAtomicCompareExchange32(ZyanAtomic32* destination, 4367+ ZyanU32 comparand, ZyanU32 value) 4368+{ 4369+ return (ZyanU32)(_InterlockedCompareExchange((volatile LONG*)&(destination->value), 4370+ (LONG)value, (LONG)comparand)); 4371+} 4372+ 4373+static ZYAN_INLINE ZyanU32 ZyanAtomicIncrement32(ZyanAtomic32* destination) 4374+{ 4375+ return (ZyanU32)(_InterlockedIncrement((volatile LONG*)&(destination->value))); 4376+} 4377+ 4378+static ZYAN_INLINE ZyanU32 ZyanAtomicDecrement32(ZyanAtomic32* destination) 4379+{ 4380+ return (ZyanU32)(_InterlockedDecrement((volatile LONG*)&(destination->value))); 4381+} 4382+ 4383+/* ---------------------------------------------------------------------------------------------- */ 4384+/* 64-bit */ 4385+/* ---------------------------------------------------------------------------------------------- */ 4386+ 4387+static ZYAN_INLINE ZyanU64 ZyanAtomicCompareExchange64(ZyanAtomic64* destination, 4388+ ZyanU64 comparand, ZyanU64 value) 4389+{ 4390+ return (ZyanU64)(_InterlockedCompareExchange64((volatile LONG64*)&(destination->value), 4391+ (LONG64)value, (LONG64)comparand)); 4392+} 4393+ 4394+static ZYAN_INLINE ZyanU64 ZyanAtomicIncrement64(ZyanAtomic64* destination) 4395+{ 4396+ return (ZyanU64)(_InterlockedIncrement64((volatile LONG64*)&(destination->value))); 4397+} 4398+ 4399+static ZYAN_INLINE ZyanU64 ZyanAtomicDecrement64(ZyanAtomic64* destination) 4400+{ 4401+ return (ZyanU64)(_InterlockedDecrement64((volatile LONG64*)&(destination->value))); 4402+} 4403+ 4404+/* ---------------------------------------------------------------------------------------------- */ 4405+ 4406+#endif 4407+ 4408+/* ============================================================================================== */ 4409+ 4410+#ifdef __cplusplus 4411+} 4412+#endif 4413+ 4414+#endif /* ZYCORE_ATOMIC_MSVC_H */ 4415diff --git a/zycore/include/Zycore/LibC.h b/zycore/include/Zycore/LibC.h 4416new file mode 100644 4417index 0000000..cb0b2f3 4418--- /dev/null 4419+++ b/zycore/include/Zycore/LibC.h 4420@@ -0,0 +1,511 @@ 4421+/*************************************************************************************************** 4422+ 4423+ Zyan Core Library (Zycore-C) 4424+ 4425+ Original Author : Florian Bernd, Joel Hoener 4426+ 4427+ * Permission is hereby granted, free of charge, to any person obtaining a copy 4428+ * of this software and associated documentation files (the "Software"), to deal 4429+ * in the Software without restriction, including without limitation the rights 4430+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 4431+ * copies of the Software, and to permit persons to whom the Software is 4432+ * furnished to do so, subject to the following conditions: 4433+ * 4434+ * The above copyright notice and this permission notice shall be included in all 4435+ * copies or substantial portions of the Software. 4436+ * 4437+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4438+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4439+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4440+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4441+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4442+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4443+ * SOFTWARE. 4444+ 4445+***************************************************************************************************/ 4446+ 4447+/** 4448+ * @file 4449+ * Provides a simple LibC abstraction and fallback routines. 4450+ */ 4451+ 4452+#ifndef ZYCORE_LIBC_H 4453+#define ZYCORE_LIBC_H 4454+ 4455+#ifndef ZYAN_CUSTOM_LIBC 4456+ 4457+// Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC 4458+// replacement functions 4459+ 4460+#ifndef ZYAN_NO_LIBC 4461+ 4462+/* ============================================================================================== */ 4463+/* LibC is available */ 4464+/* ============================================================================================== */ 4465+ 4466+/* ---------------------------------------------------------------------------------------------- */ 4467+/* errno.h */ 4468+/* ---------------------------------------------------------------------------------------------- */ 4469+ 4470+#include <errno.h> 4471+ 4472+#define ZYAN_ERRNO errno 4473+ 4474+/* ---------------------------------------------------------------------------------------------- */ 4475+/* stdarg.h */ 4476+/* ---------------------------------------------------------------------------------------------- */ 4477+ 4478+#include <stdarg.h> 4479+ 4480+/** 4481+ * Defines the `ZyanVAList` datatype. 4482+ */ 4483+typedef va_list ZyanVAList; 4484+ 4485+#define ZYAN_VA_START va_start 4486+#define ZYAN_VA_ARG va_arg 4487+#define ZYAN_VA_END va_end 4488+#define ZYAN_VA_COPY(dest, source) va_copy((dest), (source)) 4489+ 4490+/* ---------------------------------------------------------------------------------------------- */ 4491+/* stdio.h */ 4492+/* ---------------------------------------------------------------------------------------------- */ 4493+ 4494+#include <stdio.h> 4495+ 4496+#define ZYAN_FPUTS fputs 4497+#define ZYAN_FPUTC fputc 4498+#define ZYAN_FPRINTF fprintf 4499+#define ZYAN_PRINTF printf 4500+#define ZYAN_PUTC putc 4501+#define ZYAN_PUTS puts 4502+#define ZYAN_SCANF scanf 4503+#define ZYAN_SSCANF sscanf 4504+#define ZYAN_VSNPRINTF vsnprintf 4505+ 4506+/** 4507+ * Defines the `ZyanFile` datatype. 4508+ */ 4509+typedef FILE ZyanFile; 4510+ 4511+#define ZYAN_STDIN stdin 4512+#define ZYAN_STDOUT stdout 4513+#define ZYAN_STDERR stderr 4514+ 4515+/* ---------------------------------------------------------------------------------------------- */ 4516+/* stdlib.h */ 4517+/* ---------------------------------------------------------------------------------------------- */ 4518+ 4519+#include <stdlib.h> 4520+#define ZYAN_CALLOC calloc 4521+#define ZYAN_FREE free 4522+#define ZYAN_MALLOC malloc 4523+#define ZYAN_REALLOC realloc 4524+ 4525+/* ---------------------------------------------------------------------------------------------- */ 4526+/* string.h */ 4527+/* ---------------------------------------------------------------------------------------------- */ 4528+ 4529+#include <string.h> 4530+#define ZYAN_MEMCHR memchr 4531+#define ZYAN_MEMCMP memcmp 4532+#define ZYAN_MEMCPY memcpy 4533+#define ZYAN_MEMMOVE memmove 4534+#define ZYAN_MEMSET memset 4535+#define ZYAN_STRCAT strcat 4536+#define ZYAN_STRCHR strchr 4537+#define ZYAN_STRCMP strcmp 4538+#define ZYAN_STRCOLL strcoll 4539+#define ZYAN_STRCPY strcpy 4540+#define ZYAN_STRCSPN strcspn 4541+#define ZYAN_STRLEN strlen 4542+#define ZYAN_STRNCAT strncat 4543+#define ZYAN_STRNCMP strncmp 4544+#define ZYAN_STRNCPY strncpy 4545+#define ZYAN_STRPBRK strpbrk 4546+#define ZYAN_STRRCHR strrchr 4547+#define ZYAN_STRSPN strspn 4548+#define ZYAN_STRSTR strstr 4549+#define ZYAN_STRTOK strtok 4550+#define ZYAN_STRXFRM strxfrm 4551+ 4552+/* ---------------------------------------------------------------------------------------------- */ 4553+ 4554+#else // if ZYAN_NO_LIBC 4555+ 4556+/* ============================================================================================== */ 4557+/* No LibC available, use our own functions */ 4558+/* ============================================================================================== */ 4559+ 4560+#include <Zycore/Defines.h> 4561+#include <Zycore/Types.h> 4562+ 4563+/* 4564+ * These implementations are by no means optimized and will be outperformed by pretty much any 4565+ * libc implementation out there. We do not aim towards providing competetive implementations here, 4566+ * but towards providing a last resort fallback for environments without a working libc. 4567+ */ 4568+ 4569+/* ---------------------------------------------------------------------------------------------- */ 4570+/* stdarg.h */ 4571+/* ---------------------------------------------------------------------------------------------- */ 4572+ 4573+#if defined(ZYAN_MSVC) || defined(ZYAN_ICC) 4574+ 4575+/** 4576+ * Defines the `ZyanVAList` datatype. 4577+ */ 4578+typedef char* ZyanVAList; 4579+ 4580+# define ZYAN_VA_START __crt_va_start 4581+# define ZYAN_VA_ARG __crt_va_arg 4582+# define ZYAN_VA_END __crt_va_end 4583+# define ZYAN_VA_COPY(destination, source) ((destination) = (source)) 4584+ 4585+#elif defined(ZYAN_GNUC) 4586+ 4587+/** 4588+ * Defines the `ZyanVAList` datatype. 4589+ */ 4590+typedef __builtin_va_list ZyanVAList; 4591+ 4592+# define ZYAN_VA_START(v, l) __builtin_va_start(v, l) 4593+# define ZYAN_VA_END(v) __builtin_va_end(v) 4594+# define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l) 4595+# define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s) 4596+ 4597+#else 4598+# error "Unsupported compiler for no-libc mode." 4599+#endif 4600+ 4601+/* ---------------------------------------------------------------------------------------------- */ 4602+/* stdio.h */ 4603+/* ---------------------------------------------------------------------------------------------- */ 4604+ 4605+// ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count, 4606+// char const* const format, ZyanVAList args) 4607+// { 4608+// // We cant provide a fallback implementation for this function 4609+// ZYAN_UNUSED(buffer); 4610+// ZYAN_UNUSED(count); 4611+// ZYAN_UNUSED(format); 4612+// ZYAN_UNUSED(args); 4613+// return ZYAN_NULL; 4614+// } 4615+ 4616+/* ---------------------------------------------------------------------------------------------- */ 4617+/* stdlib.h */ 4618+/* ---------------------------------------------------------------------------------------------- */ 4619+ 4620+// ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size) 4621+// { 4622+// // We cant provide a fallback implementation for this function 4623+// ZYAN_UNUSED(nitems); 4624+// ZYAN_UNUSED(size); 4625+// return ZYAN_NULL; 4626+// } 4627+// 4628+// ZYAN_INLINE void ZYAN_FREE(void *p) 4629+// { 4630+// // We cant provide a fallback implementation for this function 4631+// ZYAN_UNUSED(p); 4632+// } 4633+// 4634+// ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n) 4635+// { 4636+// // We cant provide a fallback implementation for this function 4637+// ZYAN_UNUSED(n); 4638+// return ZYAN_NULL; 4639+// } 4640+// 4641+// ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n) 4642+// { 4643+// // We cant provide a fallback implementation for this function 4644+// ZYAN_UNUSED(p); 4645+// ZYAN_UNUSED(n); 4646+// return ZYAN_NULL; 4647+// } 4648+ 4649+/* ---------------------------------------------------------------------------------------------- */ 4650+/* string.h */ 4651+/* ---------------------------------------------------------------------------------------------- */ 4652+ 4653+ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n) 4654+{ 4655+ const ZyanU8* p = (ZyanU8*)str; 4656+ while (n--) 4657+ { 4658+ if (*p != (ZyanU8)c) 4659+ { 4660+ p++; 4661+ } else 4662+ { 4663+ return (void*)p; 4664+ } 4665+ } 4666+ return 0; 4667+} 4668+ 4669+ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n) 4670+{ 4671+ const ZyanU8* p1 = s1, *p2 = s2; 4672+ while (n--) 4673+ { 4674+ if (*p1 != *p2) 4675+ { 4676+ return *p1 - *p2; 4677+ } 4678+ p1++, p2++; 4679+ } 4680+ return 0; 4681+} 4682+ 4683+ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n) 4684+{ 4685+ volatile ZyanU8* dp = dst; 4686+ const ZyanU8* sp = src; 4687+ while (n--) 4688+ { 4689+ *dp++ = *sp++; 4690+ } 4691+ return dst; 4692+} 4693+ 4694+ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n) 4695+{ 4696+ volatile ZyanU8* pd = dst; 4697+ const ZyanU8* ps = src; 4698+ if (ps < pd) 4699+ { 4700+ for (pd += n, ps += n; n--;) 4701+ { 4702+ *--pd = *--ps; 4703+ } 4704+ } else 4705+ { 4706+ while (n--) 4707+ { 4708+ *pd++ = *ps++; 4709+ } 4710+ } 4711+ return dst; 4712+} 4713+ 4714+ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n) 4715+{ 4716+ volatile ZyanU8* p = dst; 4717+ while (n--) 4718+ { 4719+ *p++ = (unsigned char)val; 4720+ } 4721+ return dst; 4722+} 4723+ 4724+ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src) 4725+{ 4726+ char* ret = dest; 4727+ while (*dest) 4728+ { 4729+ dest++; 4730+ } 4731+ while ((*dest++ = *src++)); 4732+ return ret; 4733+} 4734+ 4735+ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c) 4736+{ 4737+ while (*s != (char)c) 4738+ { 4739+ if (!*s++) 4740+ { 4741+ return 0; 4742+ } 4743+ } 4744+ return (char*)s; 4745+} 4746+ 4747+ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2) 4748+{ 4749+ while (*s1 && (*s1 == *s2)) 4750+ { 4751+ s1++, s2++; 4752+ } 4753+ return *(const ZyanU8*)s1 - *(const ZyanU8*)s2; 4754+} 4755+ 4756+ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2) 4757+{ 4758+ // TODO: Implement 4759+ 4760+ ZYAN_UNUSED(s1); 4761+ ZYAN_UNUSED(s2); 4762+ 4763+ return 0; 4764+} 4765+ 4766+ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src) 4767+{ 4768+ char* ret = dest; 4769+ while ((*dest++ = *src++)); 4770+ return ret; 4771+} 4772+ 4773+ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2) 4774+{ 4775+ ZyanUSize ret = 0; 4776+ while (*s1) 4777+ { 4778+ if (ZYAN_STRCHR(s2, *s1)) 4779+ { 4780+ return ret; 4781+ } 4782+ s1++, ret++; 4783+ } 4784+ return ret; 4785+} 4786+ 4787+ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str) 4788+{ 4789+ const char* p = str; 4790+ while (*str) 4791+ { 4792+ ++str; 4793+ } 4794+ return str - p; 4795+} 4796+ 4797+ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n) 4798+{ 4799+ char* ret = dest; 4800+ while (*dest) 4801+ { 4802+ dest++; 4803+ } 4804+ while (n--) 4805+ { 4806+ if (!(*dest++ = *src++)) 4807+ { 4808+ return ret; 4809+ } 4810+ } 4811+ *dest = 0; 4812+ return ret; 4813+} 4814+ 4815+ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n) 4816+{ 4817+ while (n--) 4818+ { 4819+ if (*s1++ != *s2++) 4820+ { 4821+ return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1); 4822+ } 4823+ } 4824+ return 0; 4825+} 4826+ 4827+ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n) 4828+{ 4829+ char* ret = dest; 4830+ do 4831+ { 4832+ if (!n--) 4833+ { 4834+ return ret; 4835+ } 4836+ } while ((*dest++ = *src++)); 4837+ while (n--) 4838+ { 4839+ *dest++ = 0; 4840+ } 4841+ return ret; 4842+} 4843+ 4844+ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2) 4845+{ 4846+ while (*s1) 4847+ { 4848+ if(ZYAN_STRCHR(s2, *s1++)) 4849+ { 4850+ return (char*)--s1; 4851+ } 4852+ } 4853+ return 0; 4854+} 4855+ 4856+ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c) 4857+{ 4858+ char* ret = 0; 4859+ do 4860+ { 4861+ if (*s == (char)c) 4862+ { 4863+ ret = (char*)s; 4864+ } 4865+ } while (*s++); 4866+ return ret; 4867+} 4868+ 4869+ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2) 4870+{ 4871+ ZyanUSize ret = 0; 4872+ while (*s1 && ZYAN_STRCHR(s2, *s1++)) 4873+ { 4874+ ret++; 4875+ } 4876+ return ret; 4877+} 4878+ 4879+ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2) 4880+{ 4881+ const ZyanUSize n = ZYAN_STRLEN(s2); 4882+ while (*s1) 4883+ { 4884+ if (!ZYAN_MEMCMP(s1++, s2, n)) 4885+ { 4886+ return (char*)(s1 - 1); 4887+ } 4888+ } 4889+ return 0; 4890+} 4891+ 4892+ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim) 4893+{ 4894+ static char* p = 0; 4895+ if (str) 4896+ { 4897+ p = str; 4898+ } else 4899+ if (!p) 4900+ { 4901+ return 0; 4902+ } 4903+ str = p + ZYAN_STRSPN(p, delim); 4904+ p = str + ZYAN_STRCSPN(str, delim); 4905+ if (p == str) 4906+ { 4907+ return p = 0; 4908+ } 4909+ p = *p ? *p = 0, p + 1 : 0; 4910+ return str; 4911+} 4912+ 4913+ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n) 4914+{ 4915+ const ZyanUSize n2 = ZYAN_STRLEN(src); 4916+ if (n > n2) 4917+ { 4918+ ZYAN_STRCPY(dest, src); 4919+ } 4920+ return n2; 4921+} 4922+ 4923+/* ---------------------------------------------------------------------------------------------- */ 4924+ 4925+#endif 4926+ 4927+#endif 4928+ 4929+/* ============================================================================================== */ 4930+ 4931+#endif /* ZYCORE_LIBC_H */ 4932diff --git a/zycore/include/Zycore/List.h b/zycore/include/Zycore/List.h 4933new file mode 100644 4934index 0000000..86244b8 4935--- /dev/null 4936+++ b/zycore/include/Zycore/List.h 4937@@ -0,0 +1,573 @@ 4938+/*************************************************************************************************** 4939+ 4940+ Zyan Core Library (Zycore-C) 4941+ 4942+ Original Author : Florian Bernd 4943+ 4944+ * Permission is hereby granted, free of charge, to any person obtaining a copy 4945+ * of this software and associated documentation files (the "Software"), to deal 4946+ * in the Software without restriction, including without limitation the rights 4947+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 4948+ * copies of the Software, and to permit persons to whom the Software is 4949+ * furnished to do so, subject to the following conditions: 4950+ * 4951+ * The above copyright notice and this permission notice shall be included in all 4952+ * copies or substantial portions of the Software. 4953+ * 4954+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4955+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4956+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4957+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4958+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4959+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4960+ * SOFTWARE. 4961+ 4962+***************************************************************************************************/ 4963+ 4964+/** 4965+ * @file 4966+ * Implements a doubly linked list. 4967+ */ 4968+ 4969+#ifndef ZYCORE_LIST_H 4970+#define ZYCORE_LIST_H 4971+ 4972+#include <Zycore/Allocator.h> 4973+#include <Zycore/Object.h> 4974+#include <Zycore/Status.h> 4975+#include <Zycore/Types.h> 4976+ 4977+#ifdef __cplusplus 4978+extern "C" { 4979+#endif 4980+ 4981+/* ============================================================================================== */ 4982+/* Enums and types */ 4983+/* ============================================================================================== */ 4984+ 4985+/** 4986+ * Defines the `ZyanListNode` struct. 4987+ * 4988+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 4989+ * behavior. 4990+ */ 4991+typedef struct ZyanListNode_ 4992+{ 4993+ /** 4994+ * A pointer to the previous list node. 4995+ */ 4996+ struct ZyanListNode_* prev; 4997+ /** 4998+ * A pointer to the next list node. 4999+ */ 5000+ struct ZyanListNode_* next; 5001+} ZyanListNode; 5002+ 5003+/** 5004+ * Defines the `ZyanList` struct. 5005+ * 5006+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 5007+ * behavior. 5008+ */ 5009+typedef struct ZyanList_ 5010+{ 5011+ /** 5012+ * The memory allocator. 5013+ */ 5014+ ZyanAllocator* allocator; 5015+ /** 5016+ * The current number of elements in the list. 5017+ */ 5018+ ZyanUSize size; 5019+ /** 5020+ * The size of a single element in bytes. 5021+ */ 5022+ ZyanUSize element_size; 5023+ /** 5024+ * The element destructor callback. 5025+ */ 5026+ ZyanMemberProcedure destructor; 5027+ /** 5028+ * The head node. 5029+ */ 5030+ ZyanListNode* head; 5031+ /** 5032+ * The tail node. 5033+ */ 5034+ ZyanListNode* tail; 5035+ /** 5036+ * The data buffer. 5037+ * 5038+ * Only used for instances created by `ZyanListInitCustomBuffer`. 5039+ */ 5040+ void* buffer; 5041+ /** 5042+ * The data buffer capacity (number of bytes). 5043+ * 5044+ * Only used for instances created by `ZyanListInitCustomBuffer`. 5045+ */ 5046+ ZyanUSize capacity; 5047+ /** 5048+ * The first unused node. 5049+ * 5050+ * When removing a node, the first-unused value is updated to point at the removed node and the 5051+ * next node of the removed node will be updated to point at the old first-unused node. 5052+ * 5053+ * When appending the memory of the first unused-node is recycled to store the new node. The 5054+ * value of the first-unused node is then updated to point at the reused nodes next node. 5055+ * 5056+ * If the first-unused value is `ZYAN_NULL`, any new node will be "allocated" behind the tail 5057+ * node (if there is enough space left in the fixed size buffer). 5058+ * 5059+ * Only used for instances created by `ZyanListInitCustomBuffer`. 5060+ */ 5061+ ZyanListNode* first_unused; 5062+} ZyanList; 5063+ 5064+/* ============================================================================================== */ 5065+/* Macros */ 5066+/* ============================================================================================== */ 5067+ 5068+/* ---------------------------------------------------------------------------------------------- */ 5069+/* General */ 5070+/* ---------------------------------------------------------------------------------------------- */ 5071+ 5072+/** 5073+ * Defines an uninitialized `ZyanList` instance. 5074+ */ 5075+#define ZYAN_LIST_INITIALIZER \ 5076+ { \ 5077+ /* allocator */ ZYAN_NULL, \ 5078+ /* size */ 0, \ 5079+ /* element_size */ 0, \ 5080+ /* head */ ZYAN_NULL, \ 5081+ /* destructor */ ZYAN_NULL, \ 5082+ /* tail */ ZYAN_NULL, \ 5083+ /* buffer */ ZYAN_NULL, \ 5084+ /* capacity */ 0, \ 5085+ /* first_unused */ ZYAN_NULL \ 5086+ } 5087+ 5088+/* ---------------------------------------------------------------------------------------------- */ 5089+/* Helper macros */ 5090+/* ---------------------------------------------------------------------------------------------- */ 5091+ 5092+/** 5093+ * Returns the data value of the given `node`. 5094+ * 5095+ * @param type The desired value type. 5096+ * @param node A pointer to the `ZyanListNode` struct. 5097+ * 5098+ * @result The data value of the given `node`. 5099+ * 5100+ * Note that this function is unsafe and might dereference a null-pointer. 5101+ */ 5102+#ifdef __cplusplus 5103+#define ZYAN_LIST_GET(type, node) \ 5104+ (*reinterpret_cast<const type*>(ZyanListGetNodeData(node))) 5105+#else 5106+#define ZYAN_LIST_GET(type, node) \ 5107+ (*(const type*)ZyanListGetNodeData(node)) 5108+#endif 5109+ 5110+/* ---------------------------------------------------------------------------------------------- */ 5111+ 5112+/* ============================================================================================== */ 5113+/* Exported functions */ 5114+/* ============================================================================================== */ 5115+ 5116+/* ---------------------------------------------------------------------------------------------- */ 5117+/* Constructor and destructor */ 5118+/* ---------------------------------------------------------------------------------------------- */ 5119+ 5120+#ifndef ZYAN_NO_LIBC 5121+ 5122+/** 5123+ * Initializes the given `ZyanList` instance. 5124+ * 5125+ * @param list A pointer to the `ZyanList` instance. 5126+ * @param element_size The size of a single element in bytes. 5127+ * @param destructor A destructor callback that is invoked every time an item is deleted, or 5128+ * `ZYAN_NULL` if not needed. 5129+ * 5130+ * @return A zyan status code. 5131+ * 5132+ * The memory for the list elements is dynamically allocated by the default allocator. 5133+ * 5134+ * Finalization with `ZyanListDestroy` is required for all instances created by this function. 5135+ */ 5136+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size, 5137+ ZyanMemberProcedure destructor); 5138+ 5139+#endif // ZYAN_NO_LIBC 5140+ 5141+/** 5142+ * Initializes the given `ZyanList` instance and sets a custom `allocator`. 5143+ * 5144+ * @param list A pointer to the `ZyanList` instance. 5145+ * @param element_size The size of a single element in bytes. 5146+ * @param destructor A destructor callback that is invoked every time an item is deleted, or 5147+ * `ZYAN_NULL` if not needed. 5148+ * @param allocator A pointer to a `ZyanAllocator` instance. 5149+ * 5150+ * @return A zyan status code. 5151+ * 5152+ * Finalization with `ZyanListDestroy` is required for all instances created by this function. 5153+ */ 5154+ZYCORE_EXPORT ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size, 5155+ ZyanMemberProcedure destructor, ZyanAllocator* allocator); 5156+ 5157+/** 5158+ * Initializes the given `ZyanList` instance and configures it to use a custom user 5159+ * defined buffer with a fixed size. 5160+ * 5161+ * @param list A pointer to the `ZyanList` instance. 5162+ * @param element_size The size of a single element in bytes. 5163+ * @param destructor A destructor callback that is invoked every time an item is deleted, or 5164+ * `ZYAN_NULL` if not needed. 5165+ * @param buffer A pointer to the buffer that is used as storage for the elements. 5166+ * @param capacity The maximum capacity (number of bytes) of the buffer including the 5167+ * space required for the list-nodes. 5168+ * 5169+ * @return A zyan status code. 5170+ * 5171+ * The buffer capacity required to store `n` elements of type `T` is be calculated by: 5172+ * `size = n * sizeof(ZyanListNode) + n * sizeof(T)` 5173+ * 5174+ * Finalization is not required for instances created by this function. 5175+ */ 5176+ZYCORE_EXPORT ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size, 5177+ ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity); 5178+ 5179+/** 5180+ * Destroys the given `ZyanList` instance. 5181+ * 5182+ * @param list A pointer to the `ZyanList` instance. 5183+ * 5184+ * @return A zyan status code. 5185+ */ 5186+ZYCORE_EXPORT ZyanStatus ZyanListDestroy(ZyanList* list); 5187+ 5188+/* ---------------------------------------------------------------------------------------------- */ 5189+/* Duplication */ 5190+/* ---------------------------------------------------------------------------------------------- */ 5191+ 5192+#ifndef ZYAN_NO_LIBC 5193+ 5194+/** 5195+ * Initializes a new `ZyanList` instance by duplicating an existing list. 5196+ * 5197+ * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. 5198+ * @param source A pointer to the source list. 5199+ * 5200+ * @return A zyan status code. 5201+ * 5202+ * The memory for the list is dynamically allocated by the default allocator. 5203+ * 5204+ * Finalization with `ZyanListDestroy` is required for all instances created by this function. 5205+ */ 5206+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListDuplicate(ZyanList* destination, 5207+ const ZyanList* source); 5208+ 5209+#endif // ZYAN_NO_LIBC 5210+ 5211+/** 5212+ * Initializes a new `ZyanList` instance by duplicating an existing list and sets a 5213+ * custom `allocator`. 5214+ * 5215+ * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. 5216+ * @param source A pointer to the source list. 5217+ * @param allocator A pointer to a `ZyanAllocator` instance. 5218+ * 5219+ * @return A zyan status code. 5220+ 5221+ * Finalization with `ZyanListDestroy` is required for all instances created by this function. 5222+ */ 5223+ZYCORE_EXPORT ZyanStatus ZyanListDuplicateEx(ZyanList* destination, const ZyanList* source, 5224+ ZyanAllocator* allocator); 5225+ 5226+/** 5227+ * Initializes a new `ZyanList` instance by duplicating an existing list and 5228+ * configures it to use a custom user defined buffer with a fixed size. 5229+ * 5230+ * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. 5231+ * @param source A pointer to the source list. 5232+ * @param buffer A pointer to the buffer that is used as storage for the elements. 5233+ * @param capacity The maximum capacity (number of bytes) of the buffer including the 5234+ * space required for the list-nodes. 5235+ 5236+ * This function will fail, if the capacity of the buffer is not sufficient 5237+ * to store all elements of the source list. 5238+ * 5239+ * @return A zyan status code. 5240+ * 5241+ * The buffer capacity required to store `n` elements of type `T` is be calculated by: 5242+ * `size = n * sizeof(ZyanListNode) + n * sizeof(T)` 5243+ * 5244+ * Finalization is not required for instances created by this function. 5245+ */ 5246+ZYCORE_EXPORT ZyanStatus ZyanListDuplicateCustomBuffer(ZyanList* destination, 5247+ const ZyanList* source, void* buffer, ZyanUSize capacity); 5248+ 5249+/* ---------------------------------------------------------------------------------------------- */ 5250+/* Item access */ 5251+/* ---------------------------------------------------------------------------------------------- */ 5252+ 5253+/** 5254+ * Returns a pointer to the first `ZyanListNode` struct of the given list. 5255+ * 5256+ * @param list A pointer to the `ZyanList` instance. 5257+ * @param node Receives a pointer to the first `ZyanListNode` struct of the list. 5258+ * 5259+ * @return A zyan status code. 5260+ */ 5261+ZYCORE_EXPORT ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node); 5262+ 5263+/** 5264+ * Returns a pointer to the last `ZyanListNode` struct of the given list. 5265+ * 5266+ * @param list A pointer to the `ZyanList` instance. 5267+ * @param node Receives a pointer to the last `ZyanListNode` struct of the list. 5268+ * 5269+ * @return A zyan status code. 5270+ */ 5271+ZYCORE_EXPORT ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node); 5272+ 5273+/** 5274+ * Receives a pointer to the previous `ZyanListNode` struct linked to the passed one. 5275+ * 5276+ * @param node Receives a pointer to the previous `ZyanListNode` struct linked to the passed 5277+ * one. 5278+ * 5279+ * @return A zyan status code. 5280+ */ 5281+ZYCORE_EXPORT ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node); 5282+ 5283+/** 5284+ * Receives a pointer to the next `ZyanListNode` struct linked to the passed one. 5285+ * 5286+ * @param node Receives a pointer to the next `ZyanListNode` struct linked to the passed one. 5287+ * 5288+ * @return A zyan status code. 5289+ */ 5290+ZYCORE_EXPORT ZyanStatus ZyanListGetNextNode(const ZyanListNode** node); 5291+ 5292+/** 5293+ * Returns a constant pointer to the data of the given `node`. 5294+ * 5295+ * @param node A pointer to the `ZyanListNode` struct. 5296+ * 5297+ * @return A constant pointer to the the data of the given `node` or `ZYAN_NULL`, if an error 5298+ * occured. 5299+ * 5300+ * Take a look at `ZyanListGetNodeDataEx`, if you need a function that returns a zyan status code. 5301+ */ 5302+ZYCORE_EXPORT const void* ZyanListGetNodeData(const ZyanListNode* node); 5303+ 5304+/** 5305+ * Returns a constant pointer to the data of the given `node`.. 5306+ * 5307+ * @param node A pointer to the `ZyanListNode` struct. 5308+ * @param value Receives a constant pointer to the data of the given `node`. 5309+ * 5310+ * Take a look at `ZyanListGetNodeData`, if you need a function that directly returns a pointer. 5311+ * 5312+ * @return A zyan status code. 5313+ */ 5314+ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value); 5315+ 5316+/** 5317+ * Returns a mutable pointer to the data of the given `node`. 5318+ * 5319+ * @param node A pointer to the `ZyanListNode` struct. 5320+ * 5321+ * @return A mutable pointer to the the data of the given `node` or `ZYAN_NULL`, if an error 5322+ * occured. 5323+ * 5324+ * Take a look at `ZyanListGetPointerMutableEx` instead, if you need a function that returns a 5325+ * zyan status code. 5326+ */ 5327+ZYCORE_EXPORT void* ZyanListGetNodeDataMutable(const ZyanListNode* node); 5328+ 5329+/** 5330+ * Returns a mutable pointer to the data of the given `node`.. 5331+ * 5332+ * @param node A pointer to the `ZyanListNode` struct. 5333+ * @param value Receives a mutable pointer to the data of the given `node`. 5334+ * 5335+ * Take a look at `ZyanListGetNodeDataMutable`, if you need a function that directly returns a 5336+ * pointer. 5337+ * 5338+ * @return A zyan status code. 5339+ */ 5340+ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value); 5341+ 5342+/** 5343+ * Assigns a new data value to the given `node`. 5344+ * 5345+ * @param list A pointer to the `ZyanList` instance. 5346+ * @param node A pointer to the `ZyanListNode` struct. 5347+ * @param value The value to assign. 5348+ * 5349+ * @return A zyan status code. 5350+ */ 5351+ZYCORE_EXPORT ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node, 5352+ const void* value); 5353+ 5354+/* ---------------------------------------------------------------------------------------------- */ 5355+/* Insertion */ 5356+/* ---------------------------------------------------------------------------------------------- */ 5357+ 5358+/** 5359+ * Adds a new `item` to the end of the list. 5360+ * 5361+ * @param list A pointer to the `ZyanList` instance. 5362+ * @param item A pointer to the item to add. 5363+ * 5364+ * @return A zyan status code. 5365+ */ 5366+ZYCORE_EXPORT ZyanStatus ZyanListPushBack(ZyanList* list, const void* item); 5367+ 5368+/** 5369+ * Adds a new `item` to the beginning of the list. 5370+ * 5371+ * @param list A pointer to the `ZyanList` instance. 5372+ * @param item A pointer to the item to add. 5373+ * 5374+ * @return A zyan status code. 5375+ */ 5376+ZYCORE_EXPORT ZyanStatus ZyanListPushFront(ZyanList* list, const void* item); 5377+ 5378+/** 5379+ * Constructs an `item` in-place at the end of the list. 5380+ * 5381+ * @param list A pointer to the `ZyanList` instance. 5382+ * @param item Receives a pointer to the new item. 5383+ * @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in 5384+ * undefined state, if no constructor was passed. 5385+ * 5386+ * @return A zyan status code. 5387+ */ 5388+ZYCORE_EXPORT ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item, 5389+ ZyanMemberFunction constructor); 5390+ 5391+/** 5392+ * Constructs an `item` in-place at the beginning of the list. 5393+ * 5394+ * @param list A pointer to the `ZyanList` instance. 5395+ * @param item Receives a pointer to the new item. 5396+ * @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in 5397+ * undefined state, if no constructor was passed. 5398+ * 5399+ * @return A zyan status code. 5400+ */ 5401+ZYCORE_EXPORT ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item, 5402+ ZyanMemberFunction constructor); 5403+ 5404+/* ---------------------------------------------------------------------------------------------- */ 5405+/* Deletion */ 5406+/* ---------------------------------------------------------------------------------------------- */ 5407+ 5408+/** 5409+ * Removes the last element of the list. 5410+ * 5411+ * @param list A pointer to the `ZyanList` instance. 5412+ * 5413+ * @return A zyan status code. 5414+ */ 5415+ZYCORE_EXPORT ZyanStatus ZyanListPopBack(ZyanList* list); 5416+ 5417+/** 5418+ * Removes the firstelement of the list. 5419+ * 5420+ * @param list A pointer to the `ZyanList` instance. 5421+ * 5422+ * @return A zyan status code. 5423+ */ 5424+ZYCORE_EXPORT ZyanStatus ZyanListPopFront(ZyanList* list); 5425+ 5426+/** 5427+ * Removes the given `node` from the list. 5428+ * 5429+ * @param list A pointer to the `ZyanList` instance. 5430+ * @param node A pointer to the `ZyanListNode` struct. 5431+ * 5432+ * @return A zyan status code. 5433+ */ 5434+ZYCORE_EXPORT ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node); 5435+ 5436+/** 5437+ * Removes multiple nodes from the list. 5438+ * 5439+ * @param list A pointer to the `ZyanList` instance. 5440+ * @param first A pointer to the first node. 5441+ * @param last A pointer to the last node. 5442+ * 5443+ * @return A zyan status code. 5444+ */ 5445+ZYCORE_EXPORT ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first, 5446+ const ZyanListNode* last); 5447+ 5448+/** 5449+ * Erases all elements of the list. 5450+ * 5451+ * @param list A pointer to the `ZyanList` instance. 5452+ * 5453+ * @return A zyan status code. 5454+ */ 5455+ZYCORE_EXPORT ZyanStatus ZyanListClear(ZyanList* list); 5456+ 5457+/* ---------------------------------------------------------------------------------------------- */ 5458+/* Searching */ 5459+/* ---------------------------------------------------------------------------------------------- */ 5460+ 5461+// TODO: 5462+ 5463+/* ---------------------------------------------------------------------------------------------- */ 5464+/* Memory management */ 5465+/* ---------------------------------------------------------------------------------------------- */ 5466+ 5467+/** 5468+ * Resizes the given `ZyanList` instance. 5469+ * 5470+ * @param list A pointer to the `ZyanList` instance. 5471+ * @param size The new size of the list. 5472+ * 5473+ * @return A zyan status code. 5474+ */ 5475+ZYCORE_EXPORT ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size); 5476+ 5477+/** 5478+ * Resizes the given `ZyanList` instance. 5479+ * 5480+ * @param list A pointer to the `ZyanList` instance. 5481+ * @param size The new size of the list. 5482+ * @param initializer A pointer to a value to be used as initializer for new items. 5483+ * 5484+ * @return A zyan status code. 5485+ */ 5486+ZYCORE_EXPORT ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer); 5487+ 5488+/* ---------------------------------------------------------------------------------------------- */ 5489+/* Information */ 5490+/* ---------------------------------------------------------------------------------------------- */ 5491+ 5492+/** 5493+ * Returns the current size of the list. 5494+ * 5495+ * @param list A pointer to the `ZyanList` instance. 5496+ * @param size Receives the size of the list. 5497+ * 5498+ * @return A zyan status code. 5499+ */ 5500+ZYCORE_EXPORT ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size); 5501+ 5502+/* ---------------------------------------------------------------------------------------------- */ 5503+ 5504+/* ============================================================================================== */ 5505+ 5506+#ifdef __cplusplus 5507+} 5508+#endif 5509+ 5510+#endif /* ZYCORE_VECTOR_H */ 5511diff --git a/zycore/include/Zycore/Object.h b/zycore/include/Zycore/Object.h 5512new file mode 100644 5513index 0000000..d015cef 5514--- /dev/null 5515+++ b/zycore/include/Zycore/Object.h 5516@@ -0,0 +1,84 @@ 5517+/*************************************************************************************************** 5518+ 5519+ Zyan Core Library (Zycore-C) 5520+ 5521+ Original Author : Florian Bernd 5522+ 5523+ * Permission is hereby granted, free of charge, to any person obtaining a copy 5524+ * of this software and associated documentation files (the "Software"), to deal 5525+ * in the Software without restriction, including without limitation the rights 5526+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5527+ * copies of the Software, and to permit persons to whom the Software is 5528+ * furnished to do so, subject to the following conditions: 5529+ * 5530+ * The above copyright notice and this permission notice shall be included in all 5531+ * copies or substantial portions of the Software. 5532+ * 5533+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5534+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 5535+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 5536+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 5537+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 5538+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 5539+ * SOFTWARE. 5540+ 5541+***************************************************************************************************/ 5542+ 5543+/** 5544+ * @file 5545+ * Defines some generic object-related datatypes. 5546+ */ 5547+ 5548+#ifndef ZYCORE_OBJECT_H 5549+#define ZYCORE_OBJECT_H 5550+ 5551+#include <Zycore/Status.h> 5552+#include <Zycore/Types.h> 5553+ 5554+#ifdef __cplusplus 5555+extern "C" { 5556+#endif 5557+ 5558+/* ============================================================================================== */ 5559+/* Enums and types */ 5560+/* ============================================================================================== */ 5561+ 5562+/** 5563+ * Defines the `ZyanMemberProcedure` function prototype. 5564+ * 5565+ * @param object A pointer to the object. 5566+ */ 5567+typedef void (*ZyanMemberProcedure)(void* object); 5568+ 5569+/** 5570+ * Defines the `ZyanConstMemberProcedure` function prototype. 5571+ * 5572+ * @param object A pointer to the object. 5573+ */ 5574+typedef void (*ZyanConstMemberProcedure)(const void* object); 5575+ 5576+/** 5577+ * Defines the `ZyanMemberFunction` function prototype. 5578+ * 5579+ * @param object A pointer to the object. 5580+ * 5581+ * @return A zyan status code. 5582+ */ 5583+typedef ZyanStatus (*ZyanMemberFunction)(void* object); 5584+ 5585+/** 5586+ * Defines the `ZyanConstMemberFunction` function prototype. 5587+ * 5588+ * @param object A pointer to the object. 5589+ * 5590+ * @return A zyan status code. 5591+ */ 5592+typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object); 5593+ 5594+/* ============================================================================================== */ 5595+ 5596+#ifdef __cplusplus 5597+} 5598+#endif 5599+ 5600+#endif /* ZYCORE_OBJECT_H */ 5601diff --git a/zycore/include/Zycore/Status.h b/zycore/include/Zycore/Status.h 5602new file mode 100644 5603index 0000000..b0d7fdf 5604--- /dev/null 5605+++ b/zycore/include/Zycore/Status.h 5606@@ -0,0 +1,287 @@ 5607+/*************************************************************************************************** 5608+ 5609+ Zyan Core Library (Zyan-C) 5610+ 5611+ Original Author : Florian Bernd, Joel Hoener 5612+ 5613+ * Permission is hereby granted, free of charge, to any person obtaining a copy 5614+ * of this software and associated documentation files (the "Software"), to deal 5615+ * in the Software without restriction, including without limitation the rights 5616+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5617+ * copies of the Software, and to permit persons to whom the Software is 5618+ * furnished to do so, subject to the following conditions: 5619+ * 5620+ * The above copyright notice and this permission notice shall be included in all 5621+ * copies or substantial portions of the Software. 5622+ * 5623+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5624+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 5625+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 5626+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 5627+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 5628+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 5629+ * SOFTWARE. 5630+ 5631+***************************************************************************************************/ 5632+ 5633+/** 5634+ * @file 5635+ * Status code definitions and check macros. 5636+ */ 5637+ 5638+#ifndef ZYCORE_STATUS_H 5639+#define ZYCORE_STATUS_H 5640+ 5641+#ifdef __cplusplus 5642+extern "C" { 5643+#endif 5644+ 5645+#include <Zycore/Types.h> 5646+ 5647+/* ============================================================================================== */ 5648+/* Enums and types */ 5649+/* ============================================================================================== */ 5650+ 5651+/** 5652+ * Defines the `ZyanStatus` data type. 5653+ */ 5654+typedef ZyanU32 ZyanStatus; 5655+ 5656+/* ============================================================================================== */ 5657+/* Macros */ 5658+/* ============================================================================================== */ 5659+ 5660+/* ---------------------------------------------------------------------------------------------- */ 5661+/* Definition */ 5662+/* ---------------------------------------------------------------------------------------------- */ 5663+ 5664+/** 5665+ * Defines a zyan status code. 5666+ * 5667+ * @param error `1`, if the status code signals an error or `0`, if not. 5668+ * @param module The module id. 5669+ * @param code The actual code. 5670+ * 5671+ * @return The zyan status code. 5672+ */ 5673+#define ZYAN_MAKE_STATUS(error, module, code) \ 5674+ (ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu)) 5675+ 5676+/* ---------------------------------------------------------------------------------------------- */ 5677+/* Checks */ 5678+/* ---------------------------------------------------------------------------------------------- */ 5679+ 5680+/** 5681+ * Checks if a zyan operation was successful. 5682+ * 5683+ * @param status The zyan status-code to check. 5684+ * 5685+ * @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not. 5686+ */ 5687+#define ZYAN_SUCCESS(status) \ 5688+ (!((status) & 0x80000000u)) 5689+ 5690+/** 5691+ * Checks if a zyan operation failed. 5692+ * 5693+ * @param status The zyan status-code to check. 5694+ * 5695+ * @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not. 5696+ */ 5697+#define ZYAN_FAILED(status) \ 5698+ ((status) & 0x80000000u) 5699+ 5700+/** 5701+ * Checks if a zyan operation was successful and returns with the status-code, if not. 5702+ * 5703+ * @param status The zyan status-code to check. 5704+ */ 5705+#define ZYAN_CHECK(status) \ 5706+ do \ 5707+ { \ 5708+ const ZyanStatus status_047620348 = (status); \ 5709+ if (!ZYAN_SUCCESS(status_047620348)) \ 5710+ { \ 5711+ return status_047620348; \ 5712+ } \ 5713+ } while (0) 5714+ 5715+/* ---------------------------------------------------------------------------------------------- */ 5716+/* Information */ 5717+/* ---------------------------------------------------------------------------------------------- */ 5718+ 5719+ /** 5720+ * Returns the module id of a zyan status-code. 5721+ * 5722+ * @param status The zyan status-code. 5723+ * 5724+ * @return The module id of the zyan status-code. 5725+ */ 5726+#define ZYAN_STATUS_MODULE(status) \ 5727+ (((status) >> 20) & 0x7FFu) 5728+ 5729+ /** 5730+ * Returns the code of a zyan status-code. 5731+ * 5732+ * @param status The zyan status-code. 5733+ * 5734+ * @return The code of the zyan status-code. 5735+ */ 5736+#define ZYAN_STATUS_CODE(status) \ 5737+ ((status) & 0xFFFFFu) 5738+ 5739+/* ============================================================================================== */ 5740+/* Status codes */ 5741+/* ============================================================================================== */ 5742+ 5743+/* ---------------------------------------------------------------------------------------------- */ 5744+/* Module IDs */ 5745+/* ---------------------------------------------------------------------------------------------- */ 5746+ 5747+/** 5748+ * The zycore generic module id. 5749+ */ 5750+#define ZYAN_MODULE_ZYCORE 0x001u 5751+ 5752+/** 5753+ * The zycore arg-parse submodule id. 5754+ */ 5755+#define ZYAN_MODULE_ARGPARSE 0x003u 5756+ 5757+/** 5758+ * The base module id for user-defined status codes. 5759+ */ 5760+#define ZYAN_MODULE_USER 0x3FFu 5761+ 5762+/* ---------------------------------------------------------------------------------------------- */ 5763+/* Status codes (general purpose) */ 5764+/* ---------------------------------------------------------------------------------------------- */ 5765+ 5766+/** 5767+ * The operation completed successfully. 5768+ */ 5769+#define ZYAN_STATUS_SUCCESS \ 5770+ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u) 5771+ 5772+/** 5773+ * The operation failed with an generic error. 5774+ */ 5775+#define ZYAN_STATUS_FAILED \ 5776+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u) 5777+ 5778+/** 5779+ * The operation completed successfully and returned `ZYAN_TRUE`. 5780+ */ 5781+#define ZYAN_STATUS_TRUE \ 5782+ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u) 5783+ 5784+/** 5785+ * The operation completed successfully and returned `ZYAN_FALSE`. 5786+ */ 5787+#define ZYAN_STATUS_FALSE \ 5788+ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u) 5789+ 5790+/** 5791+ * An invalid argument was passed to a function. 5792+ */ 5793+#define ZYAN_STATUS_INVALID_ARGUMENT \ 5794+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u) 5795+ 5796+/** 5797+ * An attempt was made to perform an invalid operation. 5798+ */ 5799+#define ZYAN_STATUS_INVALID_OPERATION \ 5800+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u) 5801+ 5802+/** 5803+ * Insufficient privileges to perform the requested operation. 5804+ */ 5805+#define ZYAN_STATUS_ACCESS_DENIED \ 5806+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u) 5807+ 5808+/** 5809+ * The requested entity was not found. 5810+ */ 5811+#define ZYAN_STATUS_NOT_FOUND \ 5812+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u) 5813+ 5814+/** 5815+ * An index passed to a function was out of bounds. 5816+ */ 5817+#define ZYAN_STATUS_OUT_OF_RANGE \ 5818+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u) 5819+ 5820+/** 5821+ * A buffer passed to a function was too small to complete the requested operation. 5822+ */ 5823+#define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \ 5824+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u) 5825+ 5826+/** 5827+ * Insufficient memory to perform the operation. 5828+ */ 5829+#define ZYAN_STATUS_NOT_ENOUGH_MEMORY \ 5830+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au) 5831+ 5832+/** 5833+ * An unknown error occurred during a system function call. 5834+ */ 5835+#define ZYAN_STATUS_BAD_SYSTEMCALL \ 5836+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu) 5837+ 5838+/** 5839+ * The process ran out of resources while performing an operation. 5840+ */ 5841+#define ZYAN_STATUS_OUT_OF_RESOURCES \ 5842+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu) 5843+ 5844+/** 5845+ * A dependency library was not found or does have an unexpected version number or 5846+ * feature-set. 5847+ */ 5848+#define ZYAN_STATUS_MISSING_DEPENDENCY \ 5849+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du) 5850+ 5851+/* ---------------------------------------------------------------------------------------------- */ 5852+/* Status codes (arg parse) */ 5853+/* ---------------------------------------------------------------------------------------------- */ 5854+ 5855+/** 5856+ * Argument was not expected. 5857+ */ 5858+#define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \ 5859+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u) 5860+ 5861+/** 5862+ * Too few arguments were provided. 5863+ */ 5864+#define ZYAN_STATUS_TOO_FEW_ARGS \ 5865+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u) 5866+ 5867+/** 5868+ * Too many arguments were provided. 5869+ */ 5870+#define ZYAN_STATUS_TOO_MANY_ARGS \ 5871+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u) 5872+ 5873+/** 5874+ * An argument that expected a value misses its value. 5875+ */ 5876+#define ZYAN_STATUS_ARG_MISSES_VALUE \ 5877+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u) 5878+ 5879+/** 5880+* A required argument is missing. 5881+*/ 5882+#define ZYAN_STATUS_REQUIRED_ARG_MISSING \ 5883+ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u) 5884+ 5885+/* ---------------------------------------------------------------------------------------------- */ 5886+ 5887+/* ============================================================================================== */ 5888+ 5889+#ifdef __cplusplus 5890+} 5891+#endif 5892+ 5893+#endif /* ZYCORE_STATUS_H */ 5894diff --git a/zycore/include/Zycore/String.h b/zycore/include/Zycore/String.h 5895new file mode 100644 5896index 0000000..7bffaa6 5897--- /dev/null 5898+++ b/zycore/include/Zycore/String.h 5899@@ -0,0 +1,1011 @@ 5900+/*************************************************************************************************** 5901+ 5902+ Zyan Core Library (Zycore-C) 5903+ 5904+ Original Author : Florian Bernd 5905+ 5906+ * Permission is hereby granted, free of charge, to any person obtaining a copy 5907+ * of this software and associated documentation files (the "Software"), to deal 5908+ * in the Software without restriction, including without limitation the rights 5909+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5910+ * copies of the Software, and to permit persons to whom the Software is 5911+ * furnished to do so, subject to the following conditions: 5912+ * 5913+ * The above copyright notice and this permission notice shall be included in all 5914+ * copies or substantial portions of the Software. 5915+ * 5916+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5917+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 5918+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 5919+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 5920+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 5921+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 5922+ * SOFTWARE. 5923+ 5924+***************************************************************************************************/ 5925+ 5926+/** 5927+ * @file 5928+ * Implements a string type. 5929+ */ 5930+ 5931+#ifndef ZYCORE_STRING_H 5932+#define ZYCORE_STRING_H 5933+ 5934+#include <Zycore/Allocator.h> 5935+#include <Zycore/Status.h> 5936+#include <Zycore/Types.h> 5937+#include <Zycore/Vector.h> 5938+ 5939+#ifdef __cplusplus 5940+extern "C" { 5941+#endif 5942+ 5943+/* ============================================================================================== */ 5944+/* Constants */ 5945+/* ============================================================================================== */ 5946+ 5947+/** 5948+ * The initial minimum capacity (number of characters) for all dynamically allocated 5949+ * string instances - not including the terminating '\0'-character. 5950+ */ 5951+#define ZYAN_STRING_MIN_CAPACITY 32 5952+ 5953+/** 5954+ * The default growth factor for all string instances. 5955+ */ 5956+#define ZYAN_STRING_DEFAULT_GROWTH_FACTOR 2 5957+ 5958+/** 5959+ * The default shrink threshold for all string instances. 5960+ */ 5961+#define ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD 4 5962+ 5963+/* ============================================================================================== */ 5964+/* Enums and types */ 5965+/* ============================================================================================== */ 5966+ 5967+/* ---------------------------------------------------------------------------------------------- */ 5968+/* String flags */ 5969+/* ---------------------------------------------------------------------------------------------- */ 5970+ 5971+/** 5972+ * Defines the `ZyanStringFlags` data-type. 5973+ */ 5974+typedef ZyanU8 ZyanStringFlags; 5975+ 5976+/** 5977+ * The string uses a custom user-defined buffer with a fixed capacity. 5978+ */ 5979+#define ZYAN_STRING_HAS_FIXED_CAPACITY 0x01 // (1 << 0) 5980+ 5981+/* ---------------------------------------------------------------------------------------------- */ 5982+/* String */ 5983+/* ---------------------------------------------------------------------------------------------- */ 5984+ 5985+/** 5986+ * Defines the `ZyanString` struct. 5987+ * 5988+ * The `ZyanString` type is implemented as a size-prefixed string - which allows for a lot of 5989+ * performance optimizations. 5990+ * Nevertheless null-termination is guaranteed at all times to provide maximum compatibility with 5991+ * default C-style strings (use `ZyanStringGetData` to access the C-style string). 5992+ * 5993+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 5994+ * behavior. 5995+ */ 5996+typedef struct ZyanString_ 5997+{ 5998+ /** 5999+ * String flags. 6000+ */ 6001+ ZyanStringFlags flags; 6002+ /** 6003+ * The vector that contains the actual string. 6004+ */ 6005+ ZyanVector vector; 6006+} ZyanString; 6007+ 6008+/* ---------------------------------------------------------------------------------------------- */ 6009+/* View */ 6010+/* ---------------------------------------------------------------------------------------------- */ 6011+ 6012+/** 6013+ * Defines the `ZyanStringView` struct. 6014+ * 6015+ * The `ZyanStringView` type provides a view inside a string (`ZyanString` instances, null- 6016+ * terminated C-style strings, or even not-null-terminated custom strings). A view is immutable 6017+ * by design and can't be directly converted to a C-style string. 6018+ * 6019+ * Views might become invalid (e.g. pointing to invalid memory), if the underlying string gets 6020+ * destroyed or resized. 6021+ * 6022+ * The `ZYAN_STRING_TO_VIEW` macro can be used to cast a `ZyanString` to a `ZyanStringView` pointer 6023+ * without any runtime overhead. 6024+ * Casting a view to a normal string is not supported and will lead to unexpected behavior (use 6025+ * `ZyanStringDuplicate` to create a deep-copy instead). 6026+ * 6027+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 6028+ * behavior. 6029+ */ 6030+typedef struct ZyanStringView_ 6031+{ 6032+ /** 6033+ * The string data. 6034+ * 6035+ * The view internally re-uses the normal string struct to allow casts without any runtime 6036+ * overhead. 6037+ */ 6038+ ZyanString string; 6039+} ZyanStringView; 6040+ 6041+/* ---------------------------------------------------------------------------------------------- */ 6042+ 6043+/* ============================================================================================== */ 6044+/* Macros */ 6045+/* ============================================================================================== */ 6046+ 6047+/* ---------------------------------------------------------------------------------------------- */ 6048+/* General */ 6049+/* ---------------------------------------------------------------------------------------------- */ 6050+ 6051+/** 6052+ * Defines an uninitialized `ZyanString` instance. 6053+ */ 6054+#define ZYAN_STRING_INITIALIZER \ 6055+ { \ 6056+ /* flags */ 0, \ 6057+ /* vector */ ZYAN_VECTOR_INITIALIZER \ 6058+ } 6059+ 6060+/* ---------------------------------------------------------------------------------------------- */ 6061+/* Helper macros */ 6062+/* ---------------------------------------------------------------------------------------------- */ 6063+ 6064+/** 6065+ * Casts a `ZyanString` pointer to a constant `ZyanStringView` pointer. 6066+ */ 6067+#define ZYAN_STRING_TO_VIEW(string) (const ZyanStringView*)(string) 6068+ 6069+/** 6070+ * Defines a `ZyanStringView` struct that provides a view into a static C-style string. 6071+ * 6072+ * @param string The C-style string. 6073+ */ 6074+#define ZYAN_DEFINE_STRING_VIEW(string) \ 6075+ { \ 6076+ /* string */ \ 6077+ { \ 6078+ /* flags */ 0, \ 6079+ /* vector */ \ 6080+ { \ 6081+ /* allocator */ ZYAN_NULL, \ 6082+ /* growth_factor */ 1, \ 6083+ /* shrink_threshold */ 0, \ 6084+ /* size */ sizeof(string), \ 6085+ /* capacity */ sizeof(string), \ 6086+ /* element_size */ sizeof(char), \ 6087+ /* destructor */ ZYAN_NULL, \ 6088+ /* data */ (char*)(string) \ 6089+ } \ 6090+ } \ 6091+ } 6092+ 6093+/* ---------------------------------------------------------------------------------------------- */ 6094+ 6095+/* ============================================================================================== */ 6096+/* Exported functions */ 6097+/* ============================================================================================== */ 6098+ 6099+/* ---------------------------------------------------------------------------------------------- */ 6100+/* Constructor and destructor */ 6101+/* ---------------------------------------------------------------------------------------------- */ 6102+ 6103+#ifndef ZYAN_NO_LIBC 6104+ 6105+/** 6106+ * Initializes the given `ZyanString` instance. 6107+ * 6108+ * @param string A pointer to the `ZyanString` instance. 6109+ * @param capacity The initial capacity (number of characters). 6110+ * 6111+ * @return A zyan status code. 6112+ * 6113+ * The memory for the string is dynamically allocated by the default allocator using the default 6114+ * growth factor and the default shrink threshold. 6115+ * 6116+ * The allocated buffer will be at least one character larger than the given `capacity`, to reserve 6117+ * space for the terminating '\0'. 6118+ * 6119+ * Finalization with `ZyanStringDestroy` is required for all strings created by this function. 6120+ */ 6121+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringInit(ZyanString* string, ZyanUSize capacity); 6122+ 6123+#endif // ZYAN_NO_LIBC 6124+ 6125+/** 6126+ * Initializes the given `ZyanString` instance and sets a custom `allocator` and memory 6127+ * allocation/deallocation parameters. 6128+ * 6129+ * @param string A pointer to the `ZyanString` instance. 6130+ * @param capacity The initial capacity (number of characters). 6131+ * @param allocator A pointer to a `ZyanAllocator` instance. 6132+ * @param growth_factor The growth factor. 6133+ * @param shrink_threshold The shrink threshold. 6134+ * 6135+ * @return A zyan status code. 6136+ * 6137+ * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables 6138+ * dynamic shrinking. 6139+ * 6140+ * The allocated buffer will be at least one character larger than the given `capacity`, to reserve 6141+ * space for the terminating '\0'. 6142+ * 6143+ * Finalization with `ZyanStringDestroy` is required for all strings created by this function. 6144+ */ 6145+ZYCORE_EXPORT ZyanStatus ZyanStringInitEx(ZyanString* string, ZyanUSize capacity, 6146+ ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); 6147+ 6148+/** 6149+ * Initializes the given `ZyanString` instance and configures it to use a custom user 6150+ * defined buffer with a fixed size. 6151+ * 6152+ * @param string A pointer to the `ZyanString` instance. 6153+ * @param buffer A pointer to the buffer that is used as storage for the string. 6154+ * @param capacity The maximum capacity (number of characters) of the buffer, including 6155+ * the terminating '\0'. 6156+ * 6157+ * @return A zyan status code. 6158+ * 6159+ * Finalization is not required for strings created by this function. 6160+ */ 6161+ZYCORE_EXPORT ZyanStatus ZyanStringInitCustomBuffer(ZyanString* string, char* buffer, 6162+ ZyanUSize capacity); 6163+ 6164+/** 6165+ * Destroys the given `ZyanString` instance. 6166+ * 6167+ * @param string A pointer to the `ZyanString` instance. 6168+ * 6169+ * @return A zyan status code. 6170+ * 6171+ */ 6172+ZYCORE_EXPORT ZyanStatus ZyanStringDestroy(ZyanString* string); 6173+ 6174+/* ---------------------------------------------------------------------------------------------- */ 6175+/* Duplication */ 6176+/* ---------------------------------------------------------------------------------------------- */ 6177+ 6178+#ifndef ZYAN_NO_LIBC 6179+ 6180+/** 6181+ * Initializes a new `ZyanString` instance by duplicating an existing string. 6182+ * 6183+ * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. 6184+ * @param source A pointer to the source string. 6185+ * @param capacity The initial capacity (number of characters). 6186+ * 6187+ * This value is automatically adjusted to the size of the source string, if 6188+ * a smaller value was passed. 6189+ * 6190+ * @return A zyan status code. 6191+ * 6192+ * The behavior of this function is undefined, if `source` is a view into the `destination` 6193+ * string or `destination` points to an already initialized `ZyanString` instance. 6194+ * 6195+ * The memory for the string is dynamically allocated by the default allocator using the default 6196+ * growth factor and the default shrink threshold. 6197+ * 6198+ * The allocated buffer will be at least one character larger than the given `capacity`, to reserve 6199+ * space for the terminating '\0'. 6200+ * 6201+ * Finalization with `ZyanStringDestroy` is required for all strings created by this function. 6202+ */ 6203+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringDuplicate(ZyanString* destination, 6204+ const ZyanStringView* source, ZyanUSize capacity); 6205+ 6206+#endif // ZYAN_NO_LIBC 6207+ 6208+/** 6209+ * Initializes a new `ZyanString` instance by duplicating an existing string and sets a 6210+ * custom `allocator` and memory allocation/deallocation parameters. 6211+ * 6212+ * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. 6213+ * @param source A pointer to the source string. 6214+ * @param capacity The initial capacity (number of characters). 6215+ 6216+ * This value is automatically adjusted to the size of the source 6217+ * string, if a smaller value was passed. 6218+ * @param allocator A pointer to a `ZyanAllocator` instance. 6219+ * @param growth_factor The growth factor. 6220+ * @param shrink_threshold The shrink threshold. 6221+ * 6222+ * @return A zyan status code. 6223+ * 6224+ * The behavior of this function is undefined, if `source` is a view into the `destination` 6225+ * string or `destination` points to an already initialized `ZyanString` instance. 6226+ * 6227+ * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables 6228+ * dynamic shrinking. 6229+ * 6230+ * The allocated buffer will be at least one character larger than the given `capacity`, to reserve 6231+ * space for the terminating '\0'. 6232+ * 6233+ * Finalization with `ZyanStringDestroy` is required for all strings created by this function. 6234+ */ 6235+ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateEx(ZyanString* destination, 6236+ const ZyanStringView* source, ZyanUSize capacity, ZyanAllocator* allocator, 6237+ ZyanU8 growth_factor, ZyanU8 shrink_threshold); 6238+ 6239+/** 6240+ * Initializes a new `ZyanString` instance by duplicating an existing string and 6241+ * configures it to use a custom user defined buffer with a fixed size. 6242+ * 6243+ * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. 6244+ * @param source A pointer to the source string. 6245+ * @param buffer A pointer to the buffer that is used as storage for the string. 6246+ * @param capacity The maximum capacity (number of characters) of the buffer, including the 6247+ * terminating '\0'. 6248+ 6249+ * This function will fail, if the capacity of the buffer is less or equal to 6250+ * the size of the source string. 6251+ * 6252+ * @return A zyan status code. 6253+ * 6254+ * The behavior of this function is undefined, if `source` is a view into the `destination` 6255+ * string or `destination` points to an already initialized `ZyanString` instance. 6256+ * 6257+ * Finalization is not required for strings created by this function. 6258+ */ 6259+ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateCustomBuffer(ZyanString* destination, 6260+ const ZyanStringView* source, char* buffer, ZyanUSize capacity); 6261+ 6262+/* ---------------------------------------------------------------------------------------------- */ 6263+/* Concatenation */ 6264+/* ---------------------------------------------------------------------------------------------- */ 6265+ 6266+#ifndef ZYAN_NO_LIBC 6267+ 6268+/** 6269+ * Initializes a new `ZyanString` instance by concatenating two existing strings. 6270+ * 6271+ * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. 6272+ * 6273+ * This function will fail, if the destination `ZyanString` instance equals 6274+ * one of the source strings. 6275+ * @param s1 A pointer to the first source string. 6276+ * @param s2 A pointer to the second source string. 6277+ * @param capacity The initial capacity (number of characters). 6278+ 6279+ * This value is automatically adjusted to the combined size of the source 6280+ * strings, if a smaller value was passed. 6281+ * 6282+ * @return A zyan status code. 6283+ * 6284+ * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` 6285+ * string or `destination` points to an already initialized `ZyanString` instance. 6286+ * 6287+ * The memory for the string is dynamically allocated by the default allocator using the default 6288+ * growth factor and the default shrink threshold. 6289+ * 6290+ * The allocated buffer will be at least one character larger than the given `capacity`, to reserve 6291+ * space for the terminating '\0'. 6292+ * 6293+ * Finalization with `ZyanStringDestroy` is required for all strings created by this function. 6294+ */ 6295+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringConcat(ZyanString* destination, 6296+ const ZyanStringView* s1, const ZyanStringView* s2, ZyanUSize capacity); 6297+ 6298+#endif // ZYAN_NO_LIBC 6299+ 6300+/** 6301+ * Initializes a new `ZyanString` instance by concatenating two existing strings and sets 6302+ * a custom `allocator` and memory allocation/deallocation parameters. 6303+ * 6304+ * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. 6305+ * 6306+ * This function will fail, if the destination `ZyanString` instance 6307+ * equals one of the source strings. 6308+ * @param s1 A pointer to the first source string. 6309+ * @param s2 A pointer to the second source string. 6310+ * @param capacity The initial capacity (number of characters). 6311+ * 6312+ * This value is automatically adjusted to the combined size of the 6313+ * source strings, if a smaller value was passed. 6314+ * @param allocator A pointer to a `ZyanAllocator` instance. 6315+ * @param growth_factor The growth factor. 6316+ * @param shrink_threshold The shrink threshold. 6317+ * 6318+ * @return A zyan status code. 6319+ * 6320+ * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` 6321+ * string or `destination` points to an already initialized `ZyanString` instance. 6322+ * 6323+ * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables 6324+ * dynamic shrinking. 6325+ * 6326+ * The allocated buffer will be at least one character larger than the given `capacity`, to reserve 6327+ * space for the terminating '\0'. 6328+ * 6329+ * Finalization with `ZyanStringDestroy` is required for all strings created by this function. 6330+ */ 6331+ZYCORE_EXPORT ZyanStatus ZyanStringConcatEx(ZyanString* destination, const ZyanStringView* s1, 6332+ const ZyanStringView* s2, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, 6333+ ZyanU8 shrink_threshold); 6334+ 6335+/** 6336+ * Initializes a new `ZyanString` instance by concatenating two existing strings and 6337+ * configures it to use a custom user defined buffer with a fixed size. 6338+ * 6339+ * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. 6340+ * 6341+ * This function will fail, if the destination `ZyanString` instance equals 6342+ * one of the source strings. 6343+ * @param s1 A pointer to the first source string. 6344+ * @param s2 A pointer to the second source string. 6345+ * @param buffer A pointer to the buffer that is used as storage for the string. 6346+ * @param capacity The maximum capacity (number of characters) of the buffer. 6347+ * 6348+ * This function will fail, if the capacity of the buffer is less or equal to 6349+ * the combined size of the source strings. 6350+ * 6351+ * @return A zyan status code. 6352+ * 6353+ * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` 6354+ * string or `destination` points to an already initialized `ZyanString` instance. 6355+ * 6356+ * Finalization is not required for strings created by this function. 6357+ */ 6358+ZYCORE_EXPORT ZyanStatus ZyanStringConcatCustomBuffer(ZyanString* destination, 6359+ const ZyanStringView* s1, const ZyanStringView* s2, char* buffer, ZyanUSize capacity); 6360+ 6361+/* ---------------------------------------------------------------------------------------------- */ 6362+/* Views */ 6363+/* ---------------------------------------------------------------------------------------------- */ 6364+ 6365+/** 6366+ * Returns a view inside an existing view/string. 6367+ * 6368+ * @param view A pointer to the `ZyanStringView` instance. 6369+ * @param source A pointer to the source string. 6370+ * 6371+ * @return A zyan status code. 6372+ * 6373+ * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the 6374+ * `source` string. 6375+ */ 6376+ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideView(ZyanStringView* view, 6377+ const ZyanStringView* source); 6378+ 6379+/** 6380+ * Returns a view inside an existing view/string starting from the given `index`. 6381+ * 6382+ * @param view A pointer to the `ZyanStringView` instance. 6383+ * @param source A pointer to the source string. 6384+ * @param index The start index. 6385+ * @param count The number of characters. 6386+ * 6387+ * @return A zyan status code. 6388+ * 6389+ * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the 6390+ * `source` string. 6391+ */ 6392+ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideViewEx(ZyanStringView* view, 6393+ const ZyanStringView* source, ZyanUSize index, ZyanUSize count); 6394+ 6395+/** 6396+ * Returns a view inside a null-terminated C-style string. 6397+ * 6398+ * @param view A pointer to the `ZyanStringView` instance. 6399+ * @param string The C-style string. 6400+ * 6401+ * @return A zyan status code. 6402+ */ 6403+ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBuffer(ZyanStringView* view, const char* string); 6404+ 6405+/** 6406+ * Returns a view inside a character buffer with custom length. 6407+ * 6408+ * @param view A pointer to the `ZyanStringView` instance. 6409+ * @param buffer A pointer to the buffer containing the string characters. 6410+ * @param length The length of the string (number of characters). 6411+ * 6412+ * @return A zyan status code. 6413+ */ 6414+ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBufferEx(ZyanStringView* view, const char* buffer, 6415+ ZyanUSize length); 6416+ 6417+/** 6418+ * Returns the size (number of characters) of the view. 6419+ * 6420+ * @param view A pointer to the `ZyanStringView` instance. 6421+ * @param size Receives the size (number of characters) of the view. 6422+ * 6423+ * @return A zyan status code. 6424+ */ 6425+ZYCORE_EXPORT ZyanStatus ZyanStringViewGetSize(const ZyanStringView* view, ZyanUSize* size); 6426+ 6427+/** 6428+ * Returns the C-style string of the given `ZyanString` instance. 6429+ * 6430+ * @warning The string is not guaranteed to be null terminated! 6431+ * 6432+ * @param view A pointer to the `ZyanStringView` instance. 6433+ * @param buffer Receives a pointer to the C-style string. 6434+ * 6435+ * @return A zyan status code. 6436+ */ 6437+ZYCORE_EXPORT ZyanStatus ZyanStringViewGetData(const ZyanStringView* view, const char** buffer); 6438+ 6439+/* ---------------------------------------------------------------------------------------------- */ 6440+/* Character access */ 6441+/* ---------------------------------------------------------------------------------------------- */ 6442+ 6443+/** 6444+ * Returns the character at the given `index`. 6445+ * 6446+ * @param string A pointer to the `ZyanStringView` instance. 6447+ * @param index The character index. 6448+ * @param value Receives the desired character of the string. 6449+ * 6450+ * @return A zyan status code. 6451+ */ 6452+ZYCORE_EXPORT ZyanStatus ZyanStringGetChar(const ZyanStringView* string, ZyanUSize index, 6453+ char* value); 6454+ 6455+/** 6456+ * Returns a pointer to the character at the given `index`. 6457+ * 6458+ * @param string A pointer to the `ZyanString` instance. 6459+ * @param index The character index. 6460+ * @param value Receives a pointer to the desired character in the string. 6461+ * 6462+ * @return A zyan status code. 6463+ */ 6464+ZYCORE_EXPORT ZyanStatus ZyanStringGetCharMutable(ZyanString* string, ZyanUSize index, 6465+ char** value); 6466+ 6467+/** 6468+ * Assigns a new value to the character at the given `index`. 6469+ * 6470+ * @param string A pointer to the `ZyanString` instance. 6471+ * @param index The character index. 6472+ * @param value The character to assign. 6473+ * 6474+ * @return A zyan status code. 6475+ */ 6476+ZYCORE_EXPORT ZyanStatus ZyanStringSetChar(ZyanString* string, ZyanUSize index, char value); 6477+ 6478+/* ---------------------------------------------------------------------------------------------- */ 6479+/* Insertion */ 6480+/* ---------------------------------------------------------------------------------------------- */ 6481+ 6482+/** 6483+ * Inserts the content of the source string in the destination string at the given `index`. 6484+ * 6485+ * @param destination The destination string. 6486+ * @param index The insert index. 6487+ * @param source The source string. 6488+ * 6489+ * @return A zyan status code. 6490+ */ 6491+ZYCORE_EXPORT ZyanStatus ZyanStringInsert(ZyanString* destination, ZyanUSize index, 6492+ const ZyanStringView* source); 6493+ 6494+/** 6495+ * Inserts `count` characters of the source string in the destination string at the given 6496+ * `index`. 6497+ * 6498+ * @param destination The destination string. 6499+ * @param destination_index The insert index. 6500+ * @param source The source string. 6501+ * @param source_index The index of the first character to be inserted from the source 6502+ * string. 6503+ * @param count The number of chars to insert from the source string. 6504+ * 6505+ * @return A zyan status code. 6506+ */ 6507+ZYCORE_EXPORT ZyanStatus ZyanStringInsertEx(ZyanString* destination, ZyanUSize destination_index, 6508+ const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count); 6509+ 6510+/* ---------------------------------------------------------------------------------------------- */ 6511+/* Appending */ 6512+/* ---------------------------------------------------------------------------------------------- */ 6513+ 6514+/** 6515+ * Appends the content of the source string to the end of the destination string. 6516+ * 6517+ * @param destination The destination string. 6518+ * @param source The source string. 6519+ * 6520+ * @return A zyan status code. 6521+ */ 6522+ZYCORE_EXPORT ZyanStatus ZyanStringAppend(ZyanString* destination, const ZyanStringView* source); 6523+ 6524+/** 6525+ * Appends `count` characters of the source string to the end of the destination string. 6526+ * 6527+ * @param destination The destination string. 6528+ * @param source The source string. 6529+ * @param source_index The index of the first character to be appended from the source string. 6530+ * @param count The number of chars to append from the source string. 6531+ * 6532+ * @return A zyan status code. 6533+ */ 6534+ZYCORE_EXPORT ZyanStatus ZyanStringAppendEx(ZyanString* destination, const ZyanStringView* source, 6535+ ZyanUSize source_index, ZyanUSize count); 6536+ 6537+/* ---------------------------------------------------------------------------------------------- */ 6538+/* Deletion */ 6539+/* ---------------------------------------------------------------------------------------------- */ 6540+ 6541+/** 6542+ * Deletes characters from the given string, starting at `index`. 6543+ * 6544+ * @param string A pointer to the `ZyanString` instance. 6545+ * @param index The index of the first character to delete. 6546+ * @param count The number of characters to delete. 6547+ * 6548+ * @return A zyan status code. 6549+ */ 6550+ZYCORE_EXPORT ZyanStatus ZyanStringDelete(ZyanString* string, ZyanUSize index, ZyanUSize count); 6551+ 6552+/** 6553+ * Deletes all remaining characters from the given string, starting at `index`. 6554+ * 6555+ * @param string A pointer to the `ZyanString` instance. 6556+ * @param index The index of the first character to delete. 6557+ * 6558+ * @return A zyan status code. 6559+ */ 6560+ZYCORE_EXPORT ZyanStatus ZyanStringTruncate(ZyanString* string, ZyanUSize index); 6561+ 6562+/** 6563+ * Erases the given string. 6564+ * 6565+ * @param string A pointer to the `ZyanString` instance. 6566+ * 6567+ * @return A zyan status code. 6568+ */ 6569+ZYCORE_EXPORT ZyanStatus ZyanStringClear(ZyanString* string); 6570+ 6571+/* ---------------------------------------------------------------------------------------------- */ 6572+/* Searching */ 6573+/* ---------------------------------------------------------------------------------------------- */ 6574+ 6575+/** 6576+ * Searches for the first occurrence of `needle` in the given `haystack` starting from the 6577+ * left. 6578+ * 6579+ * @param haystack The string to search in. 6580+ * @param needle The sub-string to search for. 6581+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6582+ * `needle`. 6583+ * 6584+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6585+ * zyan status code, if an error occured. 6586+ * 6587+ * The `found_index` is set to `-1`, if the needle was not found. 6588+ */ 6589+ZYCORE_EXPORT ZyanStatus ZyanStringLPos(const ZyanStringView* haystack, 6590+ const ZyanStringView* needle, ZyanISize* found_index); 6591+ 6592+/** 6593+ * Searches for the first occurrence of `needle` in the given `haystack` starting from the 6594+ * left. 6595+ * 6596+ * @param haystack The string to search in. 6597+ * @param needle The sub-string to search for. 6598+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6599+ * `needle`. 6600+ * @param index The start index. 6601+ * @param count The maximum number of characters to iterate, beginning from the start 6602+ * `index`. 6603+ * 6604+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6605+ * zyan status code, if an error occured. 6606+ * 6607+ * The `found_index` is set to `-1`, if the needle was not found. 6608+ */ 6609+ZYCORE_EXPORT ZyanStatus ZyanStringLPosEx(const ZyanStringView* haystack, 6610+ const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); 6611+ 6612+/** 6613+ * Performs a case-insensitive search for the first occurrence of `needle` in the given 6614+ * `haystack` starting from the left. 6615+ * 6616+ * @param haystack The string to search in. 6617+ * @param needle The sub-string to search for. 6618+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6619+ * `needle`. 6620+ * 6621+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6622+ * zyan status code, if an error occured. 6623+ * 6624+ * The `found_index` is set to `-1`, if the needle was not found. 6625+ */ 6626+ZYCORE_EXPORT ZyanStatus ZyanStringLPosI(const ZyanStringView* haystack, 6627+ const ZyanStringView* needle, ZyanISize* found_index); 6628+ 6629+/** 6630+ * Performs a case-insensitive search for the first occurrence of `needle` in the given 6631+ * `haystack` starting from the left. 6632+ * 6633+ * @param haystack The string to search in. 6634+ * @param needle The sub-string to search for. 6635+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6636+ * `needle`. 6637+ * @param index The start index. 6638+ * @param count The maximum number of characters to iterate, beginning from the start 6639+ * `index`. 6640+ * 6641+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6642+ * zyan status code, if an error occurred. 6643+ * 6644+ * The `found_index` is set to `-1`, if the needle was not found. 6645+ */ 6646+ZYCORE_EXPORT ZyanStatus ZyanStringLPosIEx(const ZyanStringView* haystack, 6647+ const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); 6648+ 6649+/** 6650+ * Searches for the first occurrence of `needle` in the given `haystack` starting from the 6651+ * right. 6652+ * 6653+ * @param haystack The string to search in. 6654+ * @param needle The sub-string to search for. 6655+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6656+ * `needle`. 6657+ * 6658+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6659+ * zyan status code, if an error occurred. 6660+ * 6661+ * The `found_index` is set to `-1`, if the needle was not found. 6662+ */ 6663+ZYCORE_EXPORT ZyanStatus ZyanStringRPos(const ZyanStringView* haystack, 6664+ const ZyanStringView* needle, ZyanISize* found_index); 6665+ 6666+/** 6667+ * Searches for the first occurrence of `needle` in the given `haystack` starting from the 6668+ * right. 6669+ * 6670+ * @param haystack The string to search in. 6671+ * @param needle The sub-string to search for. 6672+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6673+ * `needle`. 6674+ * @param index The start index. 6675+ * @param count The maximum number of characters to iterate, beginning from the start 6676+ * `index`. 6677+ * 6678+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6679+ * zyan status code, if an error occurred. 6680+ * 6681+ * The `found_index` is set to `-1`, if the needle was not found. 6682+ */ 6683+ZYCORE_EXPORT ZyanStatus ZyanStringRPosEx(const ZyanStringView* haystack, 6684+ const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); 6685+ 6686+/** 6687+ * Performs a case-insensitive search for the first occurrence of `needle` in the given 6688+ * `haystack` starting from the right. 6689+ * 6690+ * @param haystack The string to search in. 6691+ * @param needle The sub-string to search for. 6692+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6693+ * `needle`. 6694+ * 6695+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6696+ * zyan status code, if an error occurred. 6697+ * 6698+ * The `found_index` is set to `-1`, if the needle was not found. 6699+ */ 6700+ZYCORE_EXPORT ZyanStatus ZyanStringRPosI(const ZyanStringView* haystack, 6701+ const ZyanStringView* needle, ZyanISize* found_index); 6702+ 6703+/** 6704+ * Performs a case-insensitive search for the first occurrence of `needle` in the given 6705+ * `haystack` starting from the right. 6706+ * 6707+ * @param haystack The string to search in. 6708+ * @param needle The sub-string to search for. 6709+ * @param found_index A pointer to a variable that receives the index of the first occurrence of 6710+ * `needle`. 6711+ * @param index The start index. 6712+ * @param count The maximum number of characters to iterate, beginning from the start 6713+ * `index`. 6714+ * 6715+ * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another 6716+ * zyan status code, if an error occurred. 6717+ * 6718+ * The `found_index` is set to `-1`, if the needle was not found. 6719+ */ 6720+ZYCORE_EXPORT ZyanStatus ZyanStringRPosIEx(const ZyanStringView* haystack, 6721+ const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); 6722+ 6723+/* ---------------------------------------------------------------------------------------------- */ 6724+/* Comparing */ 6725+/* ---------------------------------------------------------------------------------------------- */ 6726+ 6727+/** 6728+ * Compares two strings. 6729+ * 6730+ * @param s1 The first string 6731+ * @param s2 The second string. 6732+ * @param result Receives the comparison result. 6733+ * 6734+ * Values: 6735+ * - `result < 0` -> The first character that does not match has a lower value 6736+ * in `s1` than in `s2`. 6737+ * - `result == 0` -> The contents of both strings are equal. 6738+ * - `result > 0` -> The first character that does not match has a greater value 6739+ * in `s1` than in `s2`. 6740+ * 6741+ * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another 6742+ * zyan status code, if an error occurred. 6743+ */ 6744+ZYCORE_EXPORT ZyanStatus ZyanStringCompare(const ZyanStringView* s1, const ZyanStringView* s2, 6745+ ZyanI32* result); 6746+ 6747+/** 6748+ * Performs a case-insensitive comparison of two strings. 6749+ * 6750+ * @param s1 The first string 6751+ * @param s2 The second string. 6752+ * @param result Receives the comparison result. 6753+ * 6754+ * Values: 6755+ * - `result < 0` -> The first character that does not match has a lower value 6756+ * in `s1` than in `s2`. 6757+ * - `result == 0` -> The contents of both strings are equal. 6758+ * - `result > 0` -> The first character that does not match has a greater value 6759+ * in `s1` than in `s2`. 6760+ * 6761+ * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another 6762+ * zyan status code, if an error occurred. 6763+ */ 6764+ZYCORE_EXPORT ZyanStatus ZyanStringCompareI(const ZyanStringView* s1, const ZyanStringView* s2, 6765+ ZyanI32* result); 6766+ 6767+/* ---------------------------------------------------------------------------------------------- */ 6768+/* Case conversion */ 6769+/* ---------------------------------------------------------------------------------------------- */ 6770+ 6771+/** 6772+ * Converts the given string to lowercase letters. 6773+ * 6774+ * @param string A pointer to the `ZyanString` instance. 6775+ * 6776+ * @return A zyan status code. 6777+ * 6778+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6779+ * `ZyanString` instance. 6780+ */ 6781+ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCase(ZyanString* string); 6782+ 6783+/** 6784+ * Converts `count` characters of the given string to lowercase letters. 6785+ * 6786+ * @param string A pointer to the `ZyanString` instance. 6787+ * @param index The start index. 6788+ * @param count The number of characters to convert, beginning from the start `index`. 6789+ * 6790+ * @return A zyan status code. 6791+ * 6792+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6793+ * `ZyanString` instance. 6794+ */ 6795+ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCaseEx(ZyanString* string, ZyanUSize index, 6796+ ZyanUSize count); 6797+ 6798+/** 6799+ * Converts the given string to uppercase letters. 6800+ * 6801+ * @param string A pointer to the `ZyanString` instance. 6802+ * 6803+ * @return A zyan status code. 6804+ * 6805+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6806+ * `ZyanString` instance. 6807+ */ 6808+ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCase(ZyanString* string); 6809+ 6810+/** 6811+ * Converts `count` characters of the given string to uppercase letters. 6812+ * 6813+ * @param string A pointer to the `ZyanString` instance. 6814+ * @param index The start index. 6815+ * @param count The number of characters to convert, beginning from the start `index`. 6816+ * 6817+ * @return A zyan status code. 6818+ * 6819+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6820+ * `ZyanString` instance. 6821+ */ 6822+ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCaseEx(ZyanString* string, ZyanUSize index, 6823+ ZyanUSize count); 6824+ 6825+/* ---------------------------------------------------------------------------------------------- */ 6826+/* Memory management */ 6827+/* ---------------------------------------------------------------------------------------------- */ 6828+ 6829+/** 6830+ * Resizes the given `ZyanString` instance. 6831+ * 6832+ * @param string A pointer to the `ZyanString` instance. 6833+ * @param size The new size of the string. 6834+ * 6835+ * @return A zyan status code. 6836+ * 6837+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6838+ * `ZyanString` instance. 6839+ */ 6840+ZYCORE_EXPORT ZyanStatus ZyanStringResize(ZyanString* string, ZyanUSize size); 6841+ 6842+/** 6843+ * Changes the capacity of the given `ZyanString` instance. 6844+ * 6845+ * @param string A pointer to the `ZyanString` instance. 6846+ * @param capacity The new minimum capacity of the string. 6847+ * 6848+ * @return A zyan status code. 6849+ * 6850+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6851+ * `ZyanString` instance. 6852+ */ 6853+ZYCORE_EXPORT ZyanStatus ZyanStringReserve(ZyanString* string, ZyanUSize capacity); 6854+ 6855+/** 6856+ * Shrinks the capacity of the given string to match it's size. 6857+ * 6858+ * @param string A pointer to the `ZyanString` instance. 6859+ * 6860+ * @return A zyan status code. 6861+ * 6862+ * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified 6863+ * `ZyanString` instance. 6864+ */ 6865+ZYCORE_EXPORT ZyanStatus ZyanStringShrinkToFit(ZyanString* string); 6866+ 6867+/* ---------------------------------------------------------------------------------------------- */ 6868+/* Information */ 6869+/* ---------------------------------------------------------------------------------------------- */ 6870+ 6871+/** 6872+ * Returns the current capacity of the string. 6873+ * 6874+ * @param string A pointer to the `ZyanString` instance. 6875+ * @param capacity Receives the size of the string. 6876+ * 6877+ * @return A zyan status code. 6878+ */ 6879+ZYCORE_EXPORT ZyanStatus ZyanStringGetCapacity(const ZyanString* string, ZyanUSize* capacity); 6880+ 6881+/** 6882+ * Returns the current size (number of characters) of the string (excluding the 6883+ * terminating zero character). 6884+ * 6885+ * @param string A pointer to the `ZyanString` instance. 6886+ * @param size Receives the size (number of characters) of the string. 6887+ * 6888+ * @return A zyan status code. 6889+ */ 6890+ZYCORE_EXPORT ZyanStatus ZyanStringGetSize(const ZyanString* string, ZyanUSize* size); 6891+ 6892+/** 6893+ * Returns the C-style string of the given `ZyanString` instance. 6894+ * 6895+ * @param string A pointer to the `ZyanString` instance. 6896+ * @param value Receives a pointer to the C-style string. 6897+ * 6898+ * @return A zyan status code. 6899+ */ 6900+ZYCORE_EXPORT ZyanStatus ZyanStringGetData(const ZyanString* string, const char** value); 6901+ 6902+/* ---------------------------------------------------------------------------------------------- */ 6903+ 6904+/* ============================================================================================== */ 6905+ 6906+#ifdef __cplusplus 6907+} 6908+#endif 6909+ 6910+#endif // ZYCORE_STRING_H 6911diff --git a/zycore/include/Zycore/Types.h b/zycore/include/Zycore/Types.h 6912new file mode 100644 6913index 0000000..07b9ae2 6914--- /dev/null 6915+++ b/zycore/include/Zycore/Types.h 6916@@ -0,0 +1,236 @@ 6917+/*************************************************************************************************** 6918+ 6919+ Zyan Core Library (Zyan-C) 6920+ 6921+ Original Author : Florian Bernd, Joel Hoener 6922+ 6923+ * Permission is hereby granted, free of charge, to any person obtaining a copy 6924+ * of this software and associated documentation files (the "Software"), to deal 6925+ * in the Software without restriction, including without limitation the rights 6926+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6927+ * copies of the Software, and to permit persons to whom the Software is 6928+ * furnished to do so, subject to the following conditions: 6929+ * 6930+ * The above copyright notice and this permission notice shall be included in all 6931+ * copies or substantial portions of the Software. 6932+ * 6933+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6934+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6935+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 6936+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 6937+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 6938+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 6939+ * SOFTWARE. 6940+ 6941+***************************************************************************************************/ 6942+ 6943+/** 6944+ * @file 6945+ * Includes and defines some default data types. 6946+ */ 6947+ 6948+#ifndef ZYCORE_TYPES_H 6949+#define ZYCORE_TYPES_H 6950+ 6951+#include <Zycore/Defines.h> 6952+ 6953+/* ============================================================================================== */ 6954+/* Integer types */ 6955+/* ============================================================================================== */ 6956+ 6957+#if defined(ZYAN_NO_LIBC) || \ 6958+ (defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h. 6959+ // No LibC mode, use compiler built-in types / macros. 6960+# if defined(ZYAN_MSVC) || defined(ZYAN_ICC) 6961+ typedef unsigned __int8 ZyanU8; 6962+ typedef unsigned __int16 ZyanU16; 6963+ typedef unsigned __int32 ZyanU32; 6964+ typedef unsigned __int64 ZyanU64; 6965+ typedef signed __int8 ZyanI8; 6966+ typedef signed __int16 ZyanI16; 6967+ typedef signed __int32 ZyanI32; 6968+ typedef signed __int64 ZyanI64; 6969+# if _WIN64 6970+ typedef ZyanU64 ZyanUSize; 6971+ typedef ZyanI64 ZyanISize; 6972+ typedef ZyanU64 ZyanUPointer; 6973+ typedef ZyanI64 ZyanIPointer; 6974+# else 6975+ typedef ZyanU32 ZyanUSize; 6976+ typedef ZyanI32 ZyanISize; 6977+ typedef ZyanU32 ZyanUPointer; 6978+ typedef ZyanI32 ZyanIPointer; 6979+# endif 6980+# elif defined(ZYAN_GNUC) 6981+ typedef __UINT8_TYPE__ ZyanU8; 6982+ typedef __UINT16_TYPE__ ZyanU16; 6983+ typedef __UINT32_TYPE__ ZyanU32; 6984+ typedef __UINT64_TYPE__ ZyanU64; 6985+ typedef __INT8_TYPE__ ZyanI8; 6986+ typedef __INT16_TYPE__ ZyanI16; 6987+ typedef __INT32_TYPE__ ZyanI32; 6988+ typedef __INT64_TYPE__ ZyanI64; 6989+ typedef __SIZE_TYPE__ ZyanUSize; 6990+ typedef __PTRDIFF_TYPE__ ZyanISize; 6991+ typedef __UINTPTR_TYPE__ ZyanUPointer; 6992+ typedef __INTPTR_TYPE__ ZyanIPointer; 6993+# else 6994+# error "Unsupported compiler for no-libc mode." 6995+# endif 6996+ 6997+# if defined(ZYAN_MSVC) 6998+# define ZYAN_INT8_MIN (-127i8 - 1) 6999+# define ZYAN_INT16_MIN (-32767i16 - 1) 7000+# define ZYAN_INT32_MIN (-2147483647i32 - 1) 7001+# define ZYAN_INT64_MIN (-9223372036854775807i64 - 1) 7002+# define ZYAN_INT8_MAX 127i8 7003+# define ZYAN_INT16_MAX 32767i16 7004+# define ZYAN_INT32_MAX 2147483647i32 7005+# define ZYAN_INT64_MAX 9223372036854775807i64 7006+# define ZYAN_UINT8_MAX 0xffui8 7007+# define ZYAN_UINT16_MAX 0xffffui16 7008+# define ZYAN_UINT32_MAX 0xffffffffui32 7009+# define ZYAN_UINT64_MAX 0xffffffffffffffffui64 7010+# else 7011+# define ZYAN_INT8_MAX __INT8_MAX__ 7012+# define ZYAN_INT8_MIN (-ZYAN_INT8_MAX - 1) 7013+# define ZYAN_INT16_MAX __INT16_MAX__ 7014+# define ZYAN_INT16_MIN (-ZYAN_INT16_MAX - 1) 7015+# define ZYAN_INT32_MAX __INT32_MAX__ 7016+# define ZYAN_INT32_MIN (-ZYAN_INT32_MAX - 1) 7017+# define ZYAN_INT64_MAX __INT64_MAX__ 7018+# define ZYAN_INT64_MIN (-ZYAN_INT64_MAX - 1) 7019+# define ZYAN_UINT8_MAX __UINT8_MAX__ 7020+# define ZYAN_UINT16_MAX __UINT16_MAX__ 7021+# define ZYAN_UINT32_MAX __UINT32_MAX__ 7022+# define ZYAN_UINT64_MAX __UINT64_MAX__ 7023+# endif 7024+#else 7025+ // If is LibC present, we use stdint types. 7026+# include <stdint.h> 7027+# include <stddef.h> 7028+ typedef uint8_t ZyanU8; 7029+ typedef uint16_t ZyanU16; 7030+ typedef uint32_t ZyanU32; 7031+ typedef uint64_t ZyanU64; 7032+ typedef int8_t ZyanI8; 7033+ typedef int16_t ZyanI16; 7034+ typedef int32_t ZyanI32; 7035+ typedef int64_t ZyanI64; 7036+ typedef size_t ZyanUSize; 7037+ typedef ptrdiff_t ZyanISize; 7038+ typedef uintptr_t ZyanUPointer; 7039+ typedef intptr_t ZyanIPointer; 7040+ 7041+# define ZYAN_INT8_MIN INT8_MIN 7042+# define ZYAN_INT16_MIN INT16_MIN 7043+# define ZYAN_INT32_MIN INT32_MIN 7044+# define ZYAN_INT64_MIN INT64_MIN 7045+# define ZYAN_INT8_MAX INT8_MAX 7046+# define ZYAN_INT16_MAX INT16_MAX 7047+# define ZYAN_INT32_MAX INT32_MAX 7048+# define ZYAN_INT64_MAX INT64_MAX 7049+# define ZYAN_UINT8_MAX UINT8_MAX 7050+# define ZYAN_UINT16_MAX UINT16_MAX 7051+# define ZYAN_UINT32_MAX UINT32_MAX 7052+# define ZYAN_UINT64_MAX UINT64_MAX 7053+#endif 7054+ 7055+// Verify size assumptions. 7056+ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 ); 7057+ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 ); 7058+ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 ); 7059+ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 ); 7060+ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 ); 7061+ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 ); 7062+ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 ); 7063+ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 ); 7064+ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect! 7065+ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect! 7066+ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*)); 7067+ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*)); 7068+ 7069+// Verify signedness assumptions (relies on size checks above). 7070+ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1)); 7071+ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1)); 7072+ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1)); 7073+ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1)); 7074+ 7075+/* ============================================================================================== */ 7076+/* Pointer */ 7077+/* ============================================================================================== */ 7078+ 7079+/** 7080+ * Defines the `ZyanVoidPointer` data-type. 7081+ */ 7082+typedef void* ZyanVoidPointer; 7083+ 7084+/** 7085+ * Defines the `ZyanConstVoidPointer` data-type. 7086+ */ 7087+typedef const void* ZyanConstVoidPointer; 7088+ 7089+#define ZYAN_NULL ((void*)0) 7090+ 7091+/* ============================================================================================== */ 7092+/* Logic types */ 7093+/* ============================================================================================== */ 7094+ 7095+/* ---------------------------------------------------------------------------------------------- */ 7096+/* Boolean */ 7097+/* ---------------------------------------------------------------------------------------------- */ 7098+ 7099+#define ZYAN_FALSE 0 7100+#define ZYAN_TRUE 1 7101+ 7102+/** 7103+ * Defines the `ZyanBool` data-type. 7104+ * 7105+ * Represents a default boolean data-type where `0` is interpreted as `false` and all other values 7106+ * as `true`. 7107+ */ 7108+typedef ZyanU8 ZyanBool; 7109+ 7110+/* ---------------------------------------------------------------------------------------------- */ 7111+/* Ternary */ 7112+/* ---------------------------------------------------------------------------------------------- */ 7113+ 7114+/** 7115+ * Defines the `ZyanTernary` data-type. 7116+ * 7117+ * The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`, 7118+ * `false` and an indeterminate third value. 7119+ */ 7120+typedef ZyanI8 ZyanTernary; 7121+ 7122+#define ZYAN_TERNARY_FALSE (-1) 7123+#define ZYAN_TERNARY_UNKNOWN 0x00 7124+#define ZYAN_TERNARY_TRUE 0x01 7125+ 7126+/* ============================================================================================== */ 7127+/* String types */ 7128+/* ============================================================================================== */ 7129+ 7130+/* ---------------------------------------------------------------------------------------------- */ 7131+/* C-style strings */ 7132+/* ---------------------------------------------------------------------------------------------- */ 7133+ 7134+/** 7135+ * Defines the `ZyanCharPointer` data-type. 7136+ * 7137+ * This type is most often used to represent null-terminated strings aka. C-style strings. 7138+ */ 7139+typedef char* ZyanCharPointer; 7140+ 7141+/** 7142+ * Defines the `ZyanConstCharPointer` data-type. 7143+ * 7144+ * This type is most often used to represent null-terminated strings aka. C-style strings. 7145+ */ 7146+typedef const char* ZyanConstCharPointer; 7147+ 7148+/* ---------------------------------------------------------------------------------------------- */ 7149+ 7150+/* ============================================================================================== */ 7151+ 7152+#endif /* ZYCORE_TYPES_H */ 7153diff --git a/zycore/include/Zycore/Vector.h b/zycore/include/Zycore/Vector.h 7154new file mode 100644 7155index 0000000..3bf7cbc 7156--- /dev/null 7157+++ b/zycore/include/Zycore/Vector.h 7158@@ -0,0 +1,722 @@ 7159+/*************************************************************************************************** 7160+ 7161+ Zyan Core Library (Zycore-C) 7162+ 7163+ Original Author : Florian Bernd 7164+ 7165+ * Permission is hereby granted, free of charge, to any person obtaining a copy 7166+ * of this software and associated documentation files (the "Software"), to deal 7167+ * in the Software without restriction, including without limitation the rights 7168+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7169+ * copies of the Software, and to permit persons to whom the Software is 7170+ * furnished to do so, subject to the following conditions: 7171+ * 7172+ * The above copyright notice and this permission notice shall be included in all 7173+ * copies or substantial portions of the Software. 7174+ * 7175+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 7176+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7177+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 7178+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 7179+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 7180+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 7181+ * SOFTWARE. 7182+ 7183+***************************************************************************************************/ 7184+ 7185+/** 7186+ * @file 7187+ * Implements the vector container class. 7188+ */ 7189+ 7190+#ifndef ZYCORE_VECTOR_H 7191+#define ZYCORE_VECTOR_H 7192+ 7193+#include <Zycore/Allocator.h> 7194+#include <Zycore/Comparison.h> 7195+#include <Zycore/Object.h> 7196+#include <Zycore/Status.h> 7197+#include <Zycore/Types.h> 7198+ 7199+#ifdef __cplusplus 7200+extern "C" { 7201+#endif 7202+ 7203+/* ============================================================================================== */ 7204+/* Constants */ 7205+/* ============================================================================================== */ 7206+ 7207+/** 7208+ * The initial minimum capacity (number of elements) for all dynamically allocated vector 7209+ * instances. 7210+ */ 7211+#define ZYAN_VECTOR_MIN_CAPACITY 1 7212+ 7213+/** 7214+ * The default growth factor for all vector instances. 7215+ */ 7216+#define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2 7217+ 7218+/** 7219+ * The default shrink threshold for all vector instances. 7220+ */ 7221+#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 4 7222+ 7223+/* ============================================================================================== */ 7224+/* Enums and types */ 7225+/* ============================================================================================== */ 7226+ 7227+/** 7228+ * Defines the `ZyanVector` struct. 7229+ * 7230+ * All fields in this struct should be considered as "private". Any changes may lead to unexpected 7231+ * behavior. 7232+ */ 7233+typedef struct ZyanVector_ 7234+{ 7235+ /** 7236+ * The memory allocator. 7237+ */ 7238+ ZyanAllocator* allocator; 7239+ /** 7240+ * The growth factor. 7241+ */ 7242+ ZyanU8 growth_factor; 7243+ /** 7244+ * The shrink threshold. 7245+ */ 7246+ ZyanU8 shrink_threshold; 7247+ /** 7248+ * The current number of elements in the vector. 7249+ */ 7250+ ZyanUSize size; 7251+ /** 7252+ * The maximum capacity (number of elements). 7253+ */ 7254+ ZyanUSize capacity; 7255+ /** 7256+ * The size of a single element in bytes. 7257+ */ 7258+ ZyanUSize element_size; 7259+ /** 7260+ * The element destructor callback. 7261+ */ 7262+ ZyanMemberProcedure destructor; 7263+ /** 7264+ * The data pointer. 7265+ */ 7266+ void* data; 7267+} ZyanVector; 7268+ 7269+/* ============================================================================================== */ 7270+/* Macros */ 7271+/* ============================================================================================== */ 7272+ 7273+/* ---------------------------------------------------------------------------------------------- */ 7274+/* General */ 7275+/* ---------------------------------------------------------------------------------------------- */ 7276+ 7277+/** 7278+ * Defines an uninitialized `ZyanVector` instance. 7279+ */ 7280+#define ZYAN_VECTOR_INITIALIZER \ 7281+ { \ 7282+ /* allocator */ ZYAN_NULL, \ 7283+ /* growth_factor */ 0, \ 7284+ /* shrink_threshold */ 0, \ 7285+ /* size */ 0, \ 7286+ /* capacity */ 0, \ 7287+ /* element_size */ 0, \ 7288+ /* destructor */ ZYAN_NULL, \ 7289+ /* data */ ZYAN_NULL \ 7290+ } 7291+ 7292+/* ---------------------------------------------------------------------------------------------- */ 7293+/* Helper macros */ 7294+/* ---------------------------------------------------------------------------------------------- */ 7295+ 7296+/** 7297+ * Returns the value of the element at the given `index`. 7298+ * 7299+ * @param type The desired value type. 7300+ * @param vector A pointer to the `ZyanVector` instance. 7301+ * @param index The element index. 7302+ * 7303+ * @result The value of the desired element in the vector. 7304+ * 7305+ * Note that this function is unsafe and might dereference a null-pointer. 7306+ */ 7307+#ifdef __cplusplus 7308+#define ZYAN_VECTOR_GET(type, vector, index) \ 7309+ (*reinterpret_cast<const type*>(ZyanVectorGet(vector, index))) 7310+#else 7311+#define ZYAN_VECTOR_GET(type, vector, index) \ 7312+ (*(const type*)ZyanVectorGet(vector, index)) 7313+#endif 7314+ 7315+/** 7316+ * Loops through all elements of the vector. 7317+ * 7318+ * @param type The desired value type. 7319+ * @param vector A pointer to the `ZyanVector` instance. 7320+ * @param item_name The name of the iterator item. 7321+ * @param body The body to execute for each item in the vector. 7322+ */ 7323+#define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \ 7324+ { \ 7325+ const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ 7326+ for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ 7327+ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ 7328+ ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ 7329+ ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ 7330+ { \ 7331+ const type item_name = ZYAN_VECTOR_GET(type, vector, \ 7332+ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ 7333+ body \ 7334+ } \ 7335+ } 7336+ 7337+/** 7338+ * Loops through all elements of the vector. 7339+ * 7340+ * @param type The desired value type. 7341+ * @param vector A pointer to the `ZyanVector` instance. 7342+ * @param item_name The name of the iterator item. 7343+ * @param body The body to execute for each item in the vector. 7344+ */ 7345+#define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \ 7346+ { \ 7347+ const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ 7348+ for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ 7349+ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ 7350+ ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ 7351+ ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ 7352+ { \ 7353+ type* const item_name = ZyanVectorGetMutable(vector, \ 7354+ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ 7355+ body \ 7356+ } \ 7357+ } 7358+ 7359+/* ---------------------------------------------------------------------------------------------- */ 7360+ 7361+/* ============================================================================================== */ 7362+/* Exported functions */ 7363+/* ============================================================================================== */ 7364+ 7365+/* ---------------------------------------------------------------------------------------------- */ 7366+/* Constructor and destructor */ 7367+/* ---------------------------------------------------------------------------------------------- */ 7368+ 7369+#ifndef ZYAN_NO_LIBC 7370+ 7371+/** 7372+ * Initializes the given `ZyanVector` instance. 7373+ * 7374+ * @param vector A pointer to the `ZyanVector` instance. 7375+ * @param element_size The size of a single element in bytes. 7376+ * @param capacity The initial capacity (number of elements). 7377+ * @param destructor A destructor callback that is invoked every time an item is deleted, or 7378+ * `ZYAN_NULL` if not needed. 7379+ * 7380+ * @return A zyan status code. 7381+ * 7382+ * The memory for the vector elements is dynamically allocated by the default allocator using the 7383+ * default growth factor and the default shrink threshold. 7384+ * 7385+ * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. 7386+ */ 7387+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector, 7388+ ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor); 7389+ 7390+#endif // ZYAN_NO_LIBC 7391+ 7392+/** 7393+ * Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory 7394+ * allocation/deallocation parameters. 7395+ * 7396+ * @param vector A pointer to the `ZyanVector` instance. 7397+ * @param element_size The size of a single element in bytes. 7398+ * @param capacity The initial capacity (number of elements). 7399+ * @param destructor A destructor callback that is invoked every time an item is deleted, 7400+ * or `ZYAN_NULL` if not needed. 7401+ * @param allocator A pointer to a `ZyanAllocator` instance. 7402+ * @param growth_factor The growth factor. 7403+ * @param shrink_threshold The shrink threshold. 7404+ * 7405+ * @return A zyan status code. 7406+ * 7407+ * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables 7408+ * dynamic shrinking. 7409+ * 7410+ * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. 7411+ */ 7412+ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size, 7413+ ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator, 7414+ ZyanU8 growth_factor, ZyanU8 shrink_threshold); 7415+ 7416+/** 7417+ * Initializes the given `ZyanVector` instance and configures it to use a custom user 7418+ * defined buffer with a fixed size. 7419+ * 7420+ * @param vector A pointer to the `ZyanVector` instance. 7421+ * @param element_size The size of a single element in bytes. 7422+ * @param buffer A pointer to the buffer that is used as storage for the elements. 7423+ * @param capacity The maximum capacity (number of elements) of the buffer. 7424+ * @param destructor A destructor callback that is invoked every time an item is deleted, or 7425+ * `ZYAN_NULL` if not needed. 7426+ * 7427+ * @return A zyan status code. 7428+ * 7429+ * Finalization is not required for instances created by this function. 7430+ */ 7431+ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size, 7432+ void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor); 7433+ 7434+/** 7435+ * Destroys the given `ZyanVector` instance. 7436+ * 7437+ * @param vector A pointer to the `ZyanVector` instance.. 7438+ * 7439+ * @return A zyan status code. 7440+ */ 7441+ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector); 7442+ 7443+/* ---------------------------------------------------------------------------------------------- */ 7444+/* Duplication */ 7445+/* ---------------------------------------------------------------------------------------------- */ 7446+ 7447+#ifndef ZYAN_NO_LIBC 7448+ 7449+/** 7450+ * Initializes a new `ZyanVector` instance by duplicating an existing vector. 7451+ * 7452+ * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. 7453+ * @param source A pointer to the source vector. 7454+ * @param capacity The initial capacity (number of elements). 7455+ * 7456+ * This value is automatically adjusted to the size of the source vector, if 7457+ * a smaller value was passed. 7458+ * 7459+ * @return A zyan status code. 7460+ * 7461+ * The memory for the vector is dynamically allocated by the default allocator using the default 7462+ * growth factor and the default shrink threshold. 7463+ * 7464+ * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. 7465+ */ 7466+ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination, 7467+ const ZyanVector* source, ZyanUSize capacity); 7468+ 7469+#endif // ZYAN_NO_LIBC 7470+ 7471+/** 7472+ * Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a 7473+ * custom `allocator` and memory allocation/deallocation parameters. 7474+ * 7475+ * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. 7476+ * @param source A pointer to the source vector. 7477+ * @param capacity The initial capacity (number of elements). 7478+ 7479+ * This value is automatically adjusted to the size of the source 7480+ * vector, if a smaller value was passed. 7481+ * @param allocator A pointer to a `ZyanAllocator` instance. 7482+ * @param growth_factor The growth factor. 7483+ * @param shrink_threshold The shrink threshold. 7484+ * 7485+ * @return A zyan status code. 7486+ * 7487+ * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables 7488+ * dynamic shrinking. 7489+ * 7490+ * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. 7491+ */ 7492+ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source, 7493+ ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); 7494+ 7495+/** 7496+ * Initializes a new `ZyanVector` instance by duplicating an existing vector and 7497+ * configures it to use a custom user defined buffer with a fixed size. 7498+ * 7499+ * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. 7500+ * @param source A pointer to the source vector. 7501+ * @param buffer A pointer to the buffer that is used as storage for the elements. 7502+ * @param capacity The maximum capacity (number of elements) of the buffer. 7503+ 7504+ * This function will fail, if the capacity of the buffer is less than the 7505+ * size of the source vector. 7506+ * 7507+ * @return A zyan status code. 7508+ * 7509+ * Finalization is not required for instances created by this function. 7510+ */ 7511+ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination, 7512+ const ZyanVector* source, void* buffer, ZyanUSize capacity); 7513+ 7514+/* ---------------------------------------------------------------------------------------------- */ 7515+/* Element access */ 7516+/* ---------------------------------------------------------------------------------------------- */ 7517+ 7518+/** 7519+ * Returns a constant pointer to the element at the given `index`. 7520+ * 7521+ * @param vector A pointer to the `ZyanVector` instance. 7522+ * @param index The element index. 7523+ * 7524+ * @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error 7525+ * occurred. 7526+ * 7527+ * Note that the returned pointer might get invalid when the vector is resized by either a manual 7528+ * call to the memory-management functions or implicitly by inserting or removing elements. 7529+ * 7530+ * Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status 7531+ * code. 7532+ */ 7533+ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index); 7534+ 7535+/** 7536+ * Returns a mutable pointer to the element at the given `index`. 7537+ * 7538+ * @param vector A pointer to the `ZyanVector` instance. 7539+ * @param index The element index. 7540+ * 7541+ * @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error 7542+ * occurred. 7543+ * 7544+ * Note that the returned pointer might get invalid when the vector is resized by either a manual 7545+ * call to the memory-management functions or implicitly by inserting or removing elements. 7546+ * 7547+ * Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a 7548+ * zyan status code. 7549+ */ 7550+ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index); 7551+ 7552+/** 7553+ * Returns a constant pointer to the element at the given `index`. 7554+ * 7555+ * @param vector A pointer to the `ZyanVector` instance. 7556+ * @param index The element index. 7557+ * @param value Receives a constant pointer to the desired element in the vector. 7558+ * 7559+ * Note that the returned pointer might get invalid when the vector is resized by either a manual 7560+ * call to the memory-management functions or implicitly by inserting or removing elements. 7561+ * 7562+ * @return A zyan status code. 7563+ */ 7564+ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index, 7565+ const void** value); 7566+ 7567+/** 7568+ * Returns a mutable pointer to the element at the given `index`. 7569+ * 7570+ * @param vector A pointer to the `ZyanVector` instance. 7571+ * @param index The element index. 7572+ * @param value Receives a mutable pointer to the desired element in the vector. 7573+ * 7574+ * Note that the returned pointer might get invalid when the vector is resized by either a manual 7575+ * call to the memory-management functions or implicitly by inserting or removing elements. 7576+ * 7577+ * @return A zyan status code. 7578+ */ 7579+ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index, 7580+ void** value); 7581+ 7582+/** 7583+ * Assigns a new value to the element at the given `index`. 7584+ * 7585+ * @param vector A pointer to the `ZyanVector` instance. 7586+ * @param index The value index. 7587+ * @param value The value to assign. 7588+ * 7589+ * @return A zyan status code. 7590+ */ 7591+ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index, 7592+ const void* value); 7593+ 7594+/* ---------------------------------------------------------------------------------------------- */ 7595+/* Insertion */ 7596+/* ---------------------------------------------------------------------------------------------- */ 7597+ 7598+/** 7599+ * Adds a new `element` to the end of the vector. 7600+ * 7601+ * @param vector A pointer to the `ZyanVector` instance. 7602+ * @param element A pointer to the element to add. 7603+ * 7604+ * @return A zyan status code. 7605+ */ 7606+ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element); 7607+ 7608+/** 7609+ * Inserts an `element` at the given `index` of the vector. 7610+ * 7611+ * @param vector A pointer to the `ZyanVector` instance. 7612+ * @param index The insert index. 7613+ * @param element A pointer to the element to insert. 7614+ * 7615+ * @return A zyan status code. 7616+ */ 7617+ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index, 7618+ const void* element); 7619+ 7620+/** 7621+ * Inserts multiple `elements` at the given `index` of the vector. 7622+ * 7623+ * @param vector A pointer to the `ZyanVector` instance. 7624+ * @param index The insert index. 7625+ * @param elements A pointer to the first element. 7626+ * @param count The number of elements to insert. 7627+ * 7628+ * @return A zyan status code. 7629+ */ 7630+ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index, 7631+ const void* elements, ZyanUSize count); 7632+ 7633+/** 7634+ * Constructs an `element` in-place at the end of the vector. 7635+ * 7636+ * @param vector A pointer to the `ZyanVector` instance. 7637+ * @param element Receives a pointer to the new element. 7638+ * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in 7639+ * undefined state, if no constructor was passed. 7640+ * 7641+ * @return A zyan status code. 7642+ */ 7643+ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element, 7644+ ZyanMemberFunction constructor); 7645+ 7646+/** 7647+ * Constructs an `element` in-place and inserts it at the given `index` of the vector. 7648+ * 7649+ * @param vector A pointer to the `ZyanVector` instance. 7650+ * @param index The insert index. 7651+ * @param element Receives a pointer to the new element. 7652+ * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in 7653+ * undefined state, if no constructor was passed. 7654+ * 7655+ * @return A zyan status code. 7656+ */ 7657+ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index, 7658+ void** element, ZyanMemberFunction constructor); 7659+ 7660+/* ---------------------------------------------------------------------------------------------- */ 7661+/* Utils */ 7662+/* ---------------------------------------------------------------------------------------------- */ 7663+ 7664+/** 7665+ * Swaps the element at `index_first` with the element at `index_second`. 7666+ * 7667+ * @param vector A pointer to the `ZyanVector` instance. 7668+ * @param index_first The index of the first element. 7669+ * @param index_second The index of the second element. 7670+ * 7671+ * @return A zyan status code. 7672+ * 7673+ * This function requires the vector to have spare capacity for one temporary element. Call 7674+ * `ZyanVectorReserve` before this function to increase capacity, if needed. 7675+ */ 7676+ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first, 7677+ ZyanUSize index_second); 7678+ 7679+/* ---------------------------------------------------------------------------------------------- */ 7680+/* Deletion */ 7681+/* ---------------------------------------------------------------------------------------------- */ 7682+ 7683+/** 7684+ * Deletes the element at the given `index` of the vector. 7685+ * 7686+ * @param vector A pointer to the `ZyanVector` instance. 7687+ * @param index The element index. 7688+ * 7689+ * @return A zyan status code. 7690+ */ 7691+ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index); 7692+ 7693+/** 7694+ * Deletes multiple elements from the given vector, starting at `index`. 7695+ * 7696+ * @param vector A pointer to the `ZyanVector` instance. 7697+ * @param index The index of the first element to delete. 7698+ * @param count The number of elements to delete. 7699+ * 7700+ * @return A zyan status code. 7701+ */ 7702+ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index, 7703+ ZyanUSize count); 7704+ 7705+/** 7706+ * Removes the last element of the vector. 7707+ * 7708+ * @param vector A pointer to the `ZyanVector` instance. 7709+ * 7710+ * @return A zyan status code. 7711+ */ 7712+ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector); 7713+ 7714+/** 7715+ * Erases all elements of the given vector. 7716+ * 7717+ * @param vector A pointer to the `ZyanVector` instance. 7718+ * 7719+ * @return A zyan status code. 7720+ */ 7721+ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector); 7722+ 7723+/* ---------------------------------------------------------------------------------------------- */ 7724+/* Searching */ 7725+/* ---------------------------------------------------------------------------------------------- */ 7726+ 7727+/** 7728+ * Sequentially searches for the first occurrence of `element` in the given vector. 7729+ * 7730+ * @param vector A pointer to the `ZyanVector` instance. 7731+ * @param element A pointer to the element to search for. 7732+ * @param found_index A pointer to a variable that receives the index of the found element. 7733+ * @param comparison The comparison function to use. 7734+ * 7735+ * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic 7736+ * zyan status code if an error occurred. 7737+ * 7738+ * The `found_index` is set to `-1`, if the element was not found. 7739+ */ 7740+ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element, 7741+ ZyanISize* found_index, ZyanEqualityComparison comparison); 7742+ 7743+/** 7744+ * Sequentially searches for the first occurrence of `element` in the given vector. 7745+ * 7746+ * @param vector A pointer to the `ZyanVector` instance. 7747+ * @param element A pointer to the element to search for. 7748+ * @param found_index A pointer to a variable that receives the index of the found element. 7749+ * @param comparison The comparison function to use. 7750+ * @param index The start index. 7751+ * @param count The maximum number of elements to iterate, beginning from the start `index`. 7752+ * 7753+ * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic 7754+ * zyan status code if an error occurred. 7755+ * 7756+ * The `found_index` is set to `-1`, if the element was not found. 7757+ */ 7758+ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element, 7759+ ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count); 7760+ 7761+/** 7762+ * Searches for the first occurrence of `element` in the given vector using a binary- 7763+ * search algorithm. 7764+ * 7765+ * @param vector A pointer to the `ZyanVector` instance. 7766+ * @param element A pointer to the element to search for. 7767+ * @param found_index A pointer to a variable that receives the index of the found element. 7768+ * @param comparison The comparison function to use. 7769+ * 7770+ * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic 7771+ * zyan status code if an error occurred. 7772+ * 7773+ * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` 7774+ * contains the index of the first entry larger than `element`. 7775+ * 7776+ * This function requires all elements in the vector to be strictly ordered (sorted). 7777+ */ 7778+ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element, 7779+ ZyanUSize* found_index, ZyanComparison comparison); 7780+ 7781+/** 7782+ * Searches for the first occurrence of `element` in the given vector using a binary- 7783+ * search algorithm. 7784+ * 7785+ * @param vector A pointer to the `ZyanVector` instance. 7786+ * @param element A pointer to the element to search for. 7787+ * @param found_index A pointer to a variable that receives the index of the found element. 7788+ * @param comparison The comparison function to use. 7789+ * @param index The start index. 7790+ * @param count The maximum number of elements to iterate, beginning from the start `index`. 7791+ * 7792+ * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic 7793+ * zyan status code if an error occurred. 7794+ * 7795+ * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` 7796+ * contains the index of the first entry larger than `element`. 7797+ * 7798+ * This function requires all elements in the vector to be strictly ordered (sorted). 7799+ */ 7800+ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element, 7801+ ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count); 7802+ 7803+/* ---------------------------------------------------------------------------------------------- */ 7804+/* Memory management */ 7805+/* ---------------------------------------------------------------------------------------------- */ 7806+ 7807+/** 7808+ * Resizes the given `ZyanVector` instance. 7809+ * 7810+ * @param vector A pointer to the `ZyanVector` instance. 7811+ * @param size The new size of the vector. 7812+ * 7813+ * @return A zyan status code. 7814+ */ 7815+ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size); 7816+ 7817+/** 7818+ * Resizes the given `ZyanVector` instance. 7819+ * 7820+ * @param vector A pointer to the `ZyanVector` instance. 7821+ * @param size The new size of the vector. 7822+ * @param initializer A pointer to a value to be used as initializer for new items. 7823+ * 7824+ * @return A zyan status code. 7825+ */ 7826+ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size, 7827+ const void* initializer); 7828+ 7829+/** 7830+ * Changes the capacity of the given `ZyanVector` instance. 7831+ * 7832+ * @param vector A pointer to the `ZyanVector` instance. 7833+ * @param capacity The new minimum capacity of the vector. 7834+ * 7835+ * @return A zyan status code. 7836+ */ 7837+ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity); 7838+ 7839+/** 7840+ * Shrinks the capacity of the given vector to match it's size. 7841+ * 7842+ * @param vector A pointer to the `ZyanVector` instance. 7843+ * 7844+ * @return A zyan status code. 7845+ */ 7846+ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector); 7847+ 7848+/* ---------------------------------------------------------------------------------------------- */ 7849+/* Information */ 7850+/* ---------------------------------------------------------------------------------------------- */ 7851+ 7852+/** 7853+ * Returns the current capacity of the vector. 7854+ * 7855+ * @param vector A pointer to the `ZyanVector` instance. 7856+ * @param capacity Receives the size of the vector. 7857+ * 7858+ * @return A zyan status code. 7859+ */ 7860+ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity); 7861+ 7862+/** 7863+ * Returns the current size of the vector. 7864+ * 7865+ * @param vector A pointer to the `ZyanVector` instance. 7866+ * @param size Receives the size of the vector. 7867+ * 7868+ * @return A zyan status code. 7869+ */ 7870+ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size); 7871+ 7872+/* ---------------------------------------------------------------------------------------------- */ 7873+ 7874+/* ============================================================================================== */ 7875+ 7876+#ifdef __cplusplus 7877+} 7878+#endif 7879+ 7880+#endif /* ZYCORE_VECTOR_H */ 7881diff --git a/zycore/include/Zycore/Zycore.h b/zycore/include/Zycore/Zycore.h 7882new file mode 100644 7883index 0000000..f4f6bc6 7884--- /dev/null 7885+++ b/zycore/include/Zycore/Zycore.h 7886@@ -0,0 +1,110 @@ 7887+/*************************************************************************************************** 7888+ 7889+ Zyan Core Library (Zycore-C) 7890+ 7891+ Original Author : Florian Bernd 7892+ 7893+ * Permission is hereby granted, free of charge, to any person obtaining a copy 7894+ * of this software and associated documentation files (the "Software"), to deal 7895+ * in the Software without restriction, including without limitation the rights 7896+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7897+ * copies of the Software, and to permit persons to whom the Software is 7898+ * furnished to do so, subject to the following conditions: 7899+ * 7900+ * The above copyright notice and this permission notice shall be included in all 7901+ * copies or substantial portions of the Software. 7902+ * 7903+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 7904+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7905+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 7906+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 7907+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 7908+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 7909+ * SOFTWARE. 7910+ 7911+***************************************************************************************************/ 7912+ 7913+/** 7914+ * @file 7915+ * Master include file, including everything else. 7916+ */ 7917+ 7918+#ifndef ZYCORE_H 7919+#define ZYCORE_H 7920+ 7921+#include <Zycore/Types.h> 7922+ 7923+// TODO: 7924+ 7925+#ifdef __cplusplus 7926+extern "C" { 7927+#endif 7928+ 7929+/* ============================================================================================== */ 7930+/* Macros */ 7931+/* ============================================================================================== */ 7932+ 7933+/* ---------------------------------------------------------------------------------------------- */ 7934+/* Constants */ 7935+/* ---------------------------------------------------------------------------------------------- */ 7936+ 7937+/** 7938+ * A macro that defines the zycore version. 7939+ */ 7940+#define ZYCORE_VERSION (ZyanU64)0x0001000100000000 7941+ 7942+/* ---------------------------------------------------------------------------------------------- */ 7943+/* Helper macros */ 7944+/* ---------------------------------------------------------------------------------------------- */ 7945+ 7946+/** 7947+ * Extracts the major-part of the zycore version. 7948+ * 7949+ * @param version The zycore version value 7950+ */ 7951+#define ZYCORE_VERSION_MAJOR(version) (ZyanU16)((version & 0xFFFF000000000000) >> 48) 7952+ 7953+/** 7954+ * Extracts the minor-part of the zycore version. 7955+ * 7956+ * @param version The zycore version value 7957+ */ 7958+#define ZYCORE_VERSION_MINOR(version) (ZyanU16)((version & 0x0000FFFF00000000) >> 32) 7959+ 7960+/** 7961+ * Extracts the patch-part of the zycore version. 7962+ * 7963+ * @param version The zycore version value 7964+ */ 7965+#define ZYCORE_VERSION_PATCH(version) (ZyanU16)((version & 0x00000000FFFF0000) >> 16) 7966+ 7967+/** 7968+ * Extracts the build-part of the zycore version. 7969+ * 7970+ * @param version The zycore version value 7971+ */ 7972+#define ZYCORE_VERSION_BUILD(version) (ZyanU16)(version & 0x000000000000FFFF) 7973+ 7974+/* ---------------------------------------------------------------------------------------------- */ 7975+ 7976+/* ============================================================================================== */ 7977+/* Exported functions */ 7978+/* ============================================================================================== */ 7979+ 7980+/** 7981+ * Returns the zycore version. 7982+ * 7983+ * @return The zycore version. 7984+ * 7985+ * Use the macros provided in this file to extract the major, minor, patch and build part from the 7986+ * returned version value. 7987+ */ 7988+ZYCORE_EXPORT ZyanU64 ZycoreGetVersion(void); 7989+ 7990+/* ============================================================================================== */ 7991+ 7992+#ifdef __cplusplus 7993+} 7994+#endif 7995+ 7996+#endif /* ZYCORE_H */ 7997diff --git a/zycore/src/API/Memory.c b/zycore/src/API/Memory.c 7998new file mode 100644 7999index 0000000..fda1e5a 8000--- /dev/null 8001+++ b/zycore/src/API/Memory.c 8002@@ -0,0 +1,132 @@ 8003+/*************************************************************************************************** 8004+ 8005+ Zyan Core Library (Zycore-C) 8006+ 8007+ Original Author : Florian Bernd 8008+ 8009+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8010+ * of this software and associated documentation files (the "Software"), to deal 8011+ * in the Software without restriction, including without limitation the rights 8012+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8013+ * copies of the Software, and to permit persons to whom the Software is 8014+ * furnished to do so, subject to the following conditions: 8015+ * 8016+ * The above copyright notice and this permission notice shall be included in all 8017+ * copies or substantial portions of the Software. 8018+ * 8019+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8020+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8021+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8022+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8023+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 8024+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8025+ * SOFTWARE. 8026+ 8027+***************************************************************************************************/ 8028+ 8029+#include <Zycore/API/Memory.h> 8030+ 8031+#ifndef ZYAN_NO_LIBC 8032+ 8033+#if defined(ZYAN_WINDOWS) 8034+ 8035+#elif defined(ZYAN_POSIX) 8036+# include <unistd.h> 8037+#else 8038+# error "Unsupported platform detected" 8039+#endif 8040+ 8041+/* ============================================================================================== */ 8042+/* Exported functions */ 8043+/* ============================================================================================== */ 8044+ 8045+/* ---------------------------------------------------------------------------------------------- */ 8046+/* General */ 8047+/* ---------------------------------------------------------------------------------------------- */ 8048+ 8049+ZyanU32 ZyanMemoryGetSystemPageSize() 8050+{ 8051+#if defined(ZYAN_WINDOWS) 8052+ 8053+ SYSTEM_INFO system_info; 8054+ GetSystemInfo(&system_info); 8055+ 8056+ return system_info.dwPageSize; 8057+ 8058+#elif defined(ZYAN_POSIX) 8059+ 8060+ return sysconf(_SC_PAGE_SIZE); 8061+ 8062+#endif 8063+} 8064+ 8065+ZyanU32 ZyanMemoryGetSystemAllocationGranularity() 8066+{ 8067+#if defined(ZYAN_WINDOWS) 8068+ 8069+ SYSTEM_INFO system_info; 8070+ GetSystemInfo(&system_info); 8071+ 8072+ return system_info.dwAllocationGranularity; 8073+ 8074+#elif defined(ZYAN_POSIX) 8075+ 8076+ return sysconf(_SC_PAGE_SIZE); 8077+ 8078+#endif 8079+} 8080+ 8081+/* ---------------------------------------------------------------------------------------------- */ 8082+/* Memory management */ 8083+/* ---------------------------------------------------------------------------------------------- */ 8084+ 8085+ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size, 8086+ ZyanMemoryPageProtection protection) 8087+{ 8088+#if defined(ZYAN_WINDOWS) 8089+ 8090+ DWORD old; 8091+ if (!VirtualProtect(address, size, protection, &old)) 8092+ { 8093+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8094+ } 8095+ 8096+#elif defined(ZYAN_POSIX) 8097+ 8098+ if (mprotect(address, size, protection)) 8099+ { 8100+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8101+ } 8102+ 8103+#endif 8104+ 8105+ return ZYAN_STATUS_SUCCESS; 8106+} 8107+ 8108+ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size) 8109+{ 8110+#if defined(ZYAN_WINDOWS) 8111+ 8112+ ZYAN_UNUSED(size); 8113+ if (!VirtualFree(address, 0, MEM_RELEASE)) 8114+ { 8115+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8116+ } 8117+ 8118+#elif defined(ZYAN_POSIX) 8119+ 8120+ if (munmap(address, size)) 8121+ { 8122+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8123+ } 8124+ 8125+#endif 8126+ 8127+ return ZYAN_STATUS_SUCCESS; 8128+} 8129+ 8130+/* ---------------------------------------------------------------------------------------------- */ 8131+ 8132+/* ============================================================================================== */ 8133+ 8134+#endif /* ZYAN_NO_LIBC */ 8135diff --git a/zycore/src/API/Process.c b/zycore/src/API/Process.c 8136new file mode 100644 8137index 0000000..63e8e8f 8138--- /dev/null 8139+++ b/zycore/src/API/Process.c 8140@@ -0,0 +1,76 @@ 8141+/*************************************************************************************************** 8142+ 8143+ Zyan Core Library (Zycore-C) 8144+ 8145+ Original Author : Florian Bernd 8146+ 8147+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8148+ * of this software and associated documentation files (the "Software"), to deal 8149+ * in the Software without restriction, including without limitation the rights 8150+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8151+ * copies of the Software, and to permit persons to whom the Software is 8152+ * furnished to do so, subject to the following conditions: 8153+ * 8154+ * The above copyright notice and this permission notice shall be included in all 8155+ * copies or substantial portions of the Software. 8156+ * 8157+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8158+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8159+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8160+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8161+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 8162+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8163+ * SOFTWARE. 8164+ 8165+***************************************************************************************************/ 8166+ 8167+#include <Zycore/Defines.h> 8168+#if defined(ZYAN_WINDOWS) 8169+#if defined(ZYAN_KERNEL) 8170+# include <wdm.h> 8171+#else 8172+# include <windows.h> 8173+#endif 8174+#elif defined(ZYAN_POSIX) 8175+# include <sys/mman.h> 8176+#else 8177+# error "Unsupported platform detected" 8178+#endif 8179+#include <Zycore/API/Process.h> 8180+ 8181+#ifndef ZYAN_NO_LIBC 8182+ 8183+/* ============================================================================================== */ 8184+/* Exported functions */ 8185+/* ============================================================================================== */ 8186+ 8187+/* ---------------------------------------------------------------------------------------------- */ 8188+/* General */ 8189+/* ---------------------------------------------------------------------------------------------- */ 8190+ 8191+ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size) 8192+{ 8193+#if defined(ZYAN_WINDOWS) 8194+ 8195+ if (!FlushInstructionCache(GetCurrentProcess(), address, size)) 8196+ { 8197+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8198+ } 8199+ 8200+#elif defined(ZYAN_POSIX) 8201+ 8202+ if (msync(address, size, MS_SYNC | MS_INVALIDATE)) 8203+ { 8204+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8205+ } 8206+ 8207+#endif 8208+ 8209+ return ZYAN_STATUS_SUCCESS; 8210+} 8211+ 8212+/* ---------------------------------------------------------------------------------------------- */ 8213+ 8214+/* ============================================================================================== */ 8215+ 8216+#endif /* ZYAN_NO_LIBC */ 8217diff --git a/zycore/src/API/Synchronization.c b/zycore/src/API/Synchronization.c 8218new file mode 100644 8219index 0000000..48080bb 8220--- /dev/null 8221+++ b/zycore/src/API/Synchronization.c 8222@@ -0,0 +1,204 @@ 8223+/*************************************************************************************************** 8224+ 8225+ Zyan Core Library (Zycore-C) 8226+ 8227+ Original Author : Florian Bernd 8228+ 8229+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8230+ * of this software and associated documentation files (the "Software"), to deal 8231+ * in the Software without restriction, including without limitation the rights 8232+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8233+ * copies of the Software, and to permit persons to whom the Software is 8234+ * furnished to do so, subject to the following conditions: 8235+ * 8236+ * The above copyright notice and this permission notice shall be included in all 8237+ * copies or substantial portions of the Software. 8238+ * 8239+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8240+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8241+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8242+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8243+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 8244+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8245+ * SOFTWARE. 8246+ 8247+***************************************************************************************************/ 8248+ 8249+#include <Zycore/API/Synchronization.h> 8250+ 8251+#ifndef ZYAN_NO_LIBC 8252+ 8253+/* ============================================================================================== */ 8254+/* Internal functions */ 8255+/* ============================================================================================== */ 8256+ 8257+/* ---------------------------------------------------------------------------------------------- */ 8258+/* */ 8259+/* ---------------------------------------------------------------------------------------------- */ 8260+ 8261+ 8262+ 8263+/* ---------------------------------------------------------------------------------------------- */ 8264+ 8265+/* ============================================================================================== */ 8266+/* Exported functions */ 8267+/* ============================================================================================== */ 8268+ 8269+#if defined(ZYAN_POSIX) 8270+ 8271+#include <errno.h> 8272+ 8273+/* ---------------------------------------------------------------------------------------------- */ 8274+/* Critical Section */ 8275+/* ---------------------------------------------------------------------------------------------- */ 8276+ 8277+ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section) 8278+{ 8279+ pthread_mutexattr_t attribute; 8280+ 8281+ int error = pthread_mutexattr_init(&attribute); 8282+ if (error != 0) 8283+ { 8284+ if (error == ENOMEM) 8285+ { 8286+ return ZYAN_STATUS_NOT_ENOUGH_MEMORY; 8287+ } 8288+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8289+ } 8290+ pthread_mutexattr_settype(&attribute, PTHREAD_MUTEX_RECURSIVE); 8291+ 8292+ error = pthread_mutex_init(critical_section, &attribute); 8293+ pthread_mutexattr_destroy(&attribute); 8294+ if (error != 0) 8295+ { 8296+ if (error == EAGAIN) 8297+ { 8298+ return ZYAN_STATUS_OUT_OF_RESOURCES; 8299+ } 8300+ if (error == ENOMEM) 8301+ { 8302+ return ZYAN_STATUS_NOT_ENOUGH_MEMORY; 8303+ } 8304+ if (error == EPERM) 8305+ { 8306+ return ZYAN_STATUS_ACCESS_DENIED; 8307+ } 8308+ if ((error == EBUSY) || (error == EINVAL)) 8309+ { 8310+ return ZYAN_STATUS_INVALID_ARGUMENT; 8311+ } 8312+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8313+ } 8314+ 8315+ return ZYAN_STATUS_SUCCESS; 8316+} 8317+ 8318+ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section) 8319+{ 8320+ const int error = pthread_mutex_lock(critical_section); 8321+ if (error != 0) 8322+ { 8323+ if (error == EINVAL) 8324+ { 8325+ return ZYAN_STATUS_INVALID_ARGUMENT; 8326+ } 8327+ if (error == EAGAIN) 8328+ { 8329+ return ZYAN_STATUS_INVALID_OPERATION; 8330+ } 8331+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8332+ } 8333+ 8334+ return ZYAN_STATUS_SUCCESS; 8335+} 8336+ 8337+ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section) 8338+{ 8339+ // No fine grained error handling for this one 8340+ return pthread_mutex_trylock(critical_section) ? ZYAN_FALSE : ZYAN_TRUE; 8341+} 8342+ 8343+ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section) 8344+{ 8345+ const int error = pthread_mutex_unlock(critical_section); 8346+ if (error != 0) 8347+ { 8348+ if (error == EINVAL) 8349+ { 8350+ return ZYAN_STATUS_INVALID_ARGUMENT; 8351+ } 8352+ if (error == EPERM) 8353+ { 8354+ return ZYAN_STATUS_INVALID_OPERATION; 8355+ } 8356+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8357+ } 8358+ 8359+ return ZYAN_STATUS_SUCCESS; 8360+} 8361+ 8362+ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section) 8363+{ 8364+ const int error = pthread_mutex_destroy(critical_section); 8365+ if (error != 0) 8366+ { 8367+ if ((error == EBUSY) || (error == EINVAL)) 8368+ { 8369+ return ZYAN_STATUS_INVALID_ARGUMENT; 8370+ } 8371+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8372+ } 8373+ 8374+ return ZYAN_STATUS_SUCCESS; 8375+} 8376+ 8377+/* ---------------------------------------------------------------------------------------------- */ 8378+ 8379+#elif defined(ZYAN_WINDOWS) 8380+ 8381+/* ---------------------------------------------------------------------------------------------- */ 8382+/* General */ 8383+/* ---------------------------------------------------------------------------------------------- */ 8384+ 8385+ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section) 8386+{ 8387+ InitializeCriticalSection(critical_section); 8388+ 8389+ return ZYAN_STATUS_SUCCESS; 8390+} 8391+ 8392+ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section) 8393+{ 8394+ EnterCriticalSection(critical_section); 8395+ 8396+ return ZYAN_STATUS_SUCCESS; 8397+} 8398+ 8399+ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section) 8400+{ 8401+ return TryEnterCriticalSection(critical_section) ? ZYAN_TRUE : ZYAN_FALSE; 8402+} 8403+ 8404+ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section) 8405+{ 8406+ LeaveCriticalSection(critical_section); 8407+ 8408+ return ZYAN_STATUS_SUCCESS; 8409+} 8410+ 8411+ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section) 8412+{ 8413+ DeleteCriticalSection(critical_section); 8414+ 8415+ return ZYAN_STATUS_SUCCESS; 8416+} 8417+ 8418+/* ---------------------------------------------------------------------------------------------- */ 8419+ 8420+#else 8421+# error "Unsupported platform detected" 8422+#endif 8423+ 8424+/* ============================================================================================== */ 8425+ 8426+#endif /* ZYAN_NO_LIBC */ 8427diff --git a/zycore/src/API/Terminal.c b/zycore/src/API/Terminal.c 8428new file mode 100644 8429index 0000000..382bd78 8430--- /dev/null 8431+++ b/zycore/src/API/Terminal.c 8432@@ -0,0 +1,160 @@ 8433+/*************************************************************************************************** 8434+ 8435+ Zyan Core Library (Zycore-C) 8436+ 8437+ Original Author : Florian Bernd 8438+ 8439+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8440+ * of this software and associated documentation files (the "Software"), to deal 8441+ * in the Software without restriction, including without limitation the rights 8442+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8443+ * copies of the Software, and to permit persons to whom the Software is 8444+ * furnished to do so, subject to the following conditions: 8445+ * 8446+ * The above copyright notice and this permission notice shall be included in all 8447+ * copies or substantial portions of the Software. 8448+ * 8449+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8450+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8451+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8452+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8453+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 8454+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8455+ * SOFTWARE. 8456+ 8457+***************************************************************************************************/ 8458+ 8459+#include <Zycore/API/Terminal.h> 8460+ 8461+#ifndef ZYAN_NO_LIBC 8462+ 8463+#if defined(ZYAN_POSIX) 8464+# include <unistd.h> 8465+#elif defined(ZYAN_WINDOWS) 8466+# include <windows.h> 8467+# include <io.h> 8468+#else 8469+# error "Unsupported platform detected" 8470+#endif 8471+ 8472+// Provide fallback for old SDK versions 8473+#ifdef ZYAN_WINDOWS 8474+# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING 8475+# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 8476+# endif 8477+#endif 8478+ 8479+/* ============================================================================================== */ 8480+/* Exported functions */ 8481+/* ============================================================================================== */ 8482+ 8483+ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream) 8484+{ 8485+ if ((stream != ZYAN_STDSTREAM_OUT) && (stream != ZYAN_STDSTREAM_ERR)) 8486+ { 8487+ return ZYAN_STATUS_INVALID_ARGUMENT; 8488+ } 8489+ 8490+#ifdef ZYAN_WINDOWS 8491+ // Get file descriptor 8492+ int file; 8493+ switch (stream) 8494+ { 8495+ case ZYAN_STDSTREAM_OUT: 8496+ file = _fileno(ZYAN_STDOUT); 8497+ break; 8498+ case ZYAN_STDSTREAM_ERR: 8499+ file = _fileno(ZYAN_STDERR); 8500+ break; 8501+ default: 8502+ ZYAN_UNREACHABLE; 8503+ } 8504+ if (file < 0) 8505+ { 8506+ return ZYAN_STATUS_INVALID_ARGUMENT; 8507+ } 8508+ 8509+ HANDLE const handle = (HANDLE)_get_osfhandle(file); 8510+ if (handle == INVALID_HANDLE_VALUE) 8511+ { 8512+ return ZYAN_STATUS_INVALID_ARGUMENT; 8513+ } 8514+ 8515+ DWORD mode; 8516+ if (!GetConsoleMode(handle, &mode)) 8517+ { 8518+ // The given standard stream is not bound to a terminal 8519+ return ZYAN_STATUS_INVALID_ARGUMENT; 8520+ } 8521+ 8522+ mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; 8523+ if (!SetConsoleMode(handle, mode)) 8524+ { 8525+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8526+ } 8527+#endif 8528+ 8529+ return ZYAN_STATUS_SUCCESS; 8530+} 8531+ 8532+ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream) 8533+{ 8534+ // Get file descriptor 8535+ int file; 8536+#ifdef ZYAN_WINDOWS 8537+ switch (stream) 8538+ { 8539+ case ZYAN_STDSTREAM_IN: 8540+ file = _fileno(ZYAN_STDIN); 8541+ break; 8542+ case ZYAN_STDSTREAM_OUT: 8543+ file = _fileno(ZYAN_STDOUT); 8544+ break; 8545+ case ZYAN_STDSTREAM_ERR: 8546+ file = _fileno(ZYAN_STDERR); 8547+ break; 8548+ default: 8549+ ZYAN_UNREACHABLE; 8550+ } 8551+ if (file < 0) 8552+ { 8553+ return ZYAN_STATUS_INVALID_ARGUMENT; 8554+ } 8555+#else 8556+ switch (stream) 8557+ { 8558+ case ZYAN_STDSTREAM_IN: 8559+ file = STDIN_FILENO; 8560+ break; 8561+ case ZYAN_STDSTREAM_OUT: 8562+ file = STDOUT_FILENO; 8563+ break; 8564+ case ZYAN_STDSTREAM_ERR: 8565+ file = STDERR_FILENO; 8566+ break; 8567+ default: 8568+ ZYAN_UNREACHABLE; 8569+ } 8570+#endif 8571+ 8572+#ifdef ZYAN_WINDOWS 8573+ if (_isatty(file)) 8574+#else 8575+ if ( isatty(file)) 8576+#endif 8577+ { 8578+ return ZYAN_STATUS_TRUE; 8579+ } 8580+ if (ZYAN_ERRNO == EBADF) 8581+ { 8582+ // Invalid file descriptor 8583+ return ZYAN_STATUS_INVALID_ARGUMENT; 8584+ } 8585+ //ZYAN_ASSERT((errno == EINVAL) || (errno == ENOTTY)); 8586+ 8587+ return ZYAN_STATUS_FALSE; 8588+} 8589+ 8590+/* ============================================================================================== */ 8591+ 8592+#endif /* ZYAN_NO_LIBC */ 8593diff --git a/zycore/src/API/Thread.c b/zycore/src/API/Thread.c 8594new file mode 100644 8595index 0000000..0cc3d8c 8596--- /dev/null 8597+++ b/zycore/src/API/Thread.c 8598@@ -0,0 +1,244 @@ 8599+/*************************************************************************************************** 8600+ 8601+ Zyan Core Library (Zycore-C) 8602+ 8603+ Original Author : Florian Bernd 8604+ 8605+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8606+ * of this software and associated documentation files (the "Software"), to deal 8607+ * in the Software without restriction, including without limitation the rights 8608+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8609+ * copies of the Software, and to permit persons to whom the Software is 8610+ * furnished to do so, subject to the following conditions: 8611+ * 8612+ * The above copyright notice and this permission notice shall be included in all 8613+ * copies or substantial portions of the Software. 8614+ * 8615+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8616+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8617+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8618+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8619+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 8620+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8621+ * SOFTWARE. 8622+ 8623+***************************************************************************************************/ 8624+ 8625+#include <Zycore/API/Thread.h> 8626+ 8627+#ifndef ZYAN_NO_LIBC 8628+ 8629+/* ============================================================================================== */ 8630+/* Internal functions */ 8631+/* ============================================================================================== */ 8632+ 8633+/* ---------------------------------------------------------------------------------------------- */ 8634+/* Legacy Windows import declarations */ 8635+/* ---------------------------------------------------------------------------------------------- */ 8636+ 8637+#if defined(ZYAN_WINDOWS) && defined(_WIN32_WINNT) && \ 8638+ (_WIN32_WINNT >= 0x0501) && (_WIN32_WINNT < 0x0600) 8639+ 8640+/** 8641+ * The Windows SDK conditionally declares the following prototypes: the target OS must be Vista 8642+ * (0x0600) or above. MSDN states the same incorrect minimum requirement for the Fls* functions. 8643+ * 8644+ * However, these functions exist and work perfectly fine on XP (SP3) and Server 2003. 8645+ * Preserve backward compatibility with these OSes by declaring the prototypes here if needed. 8646+ */ 8647+ 8648+#ifndef FLS_OUT_OF_INDEXES 8649+#define FLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF) 8650+#endif 8651+ 8652+WINBASEAPI 8653+DWORD 8654+WINAPI 8655+FlsAlloc( 8656+ _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback 8657+ ); 8658+ 8659+WINBASEAPI 8660+PVOID 8661+WINAPI 8662+FlsGetValue( 8663+ _In_ DWORD dwFlsIndex 8664+ ); 8665+ 8666+WINBASEAPI 8667+BOOL 8668+WINAPI 8669+FlsSetValue( 8670+ _In_ DWORD dwFlsIndex, 8671+ _In_opt_ PVOID lpFlsData 8672+ ); 8673+ 8674+WINBASEAPI 8675+BOOL 8676+WINAPI 8677+FlsFree( 8678+ _In_ DWORD dwFlsIndex 8679+ ); 8680+ 8681+#endif /* (_WIN32_WINNT >= 0x0501) && (_WIN32_WINNT < 0x0600)*/ 8682+ 8683+ 8684+ 8685+/* ---------------------------------------------------------------------------------------------- */ 8686+ 8687+/* ============================================================================================== */ 8688+/* Exported functions */ 8689+/* ============================================================================================== */ 8690+ 8691+#if defined(ZYAN_POSIX) 8692+ 8693+#include <errno.h> 8694+ 8695+/* ---------------------------------------------------------------------------------------------- */ 8696+/* General */ 8697+/* ---------------------------------------------------------------------------------------------- */ 8698+ 8699+ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread) 8700+{ 8701+ *thread = pthread_self(); 8702+ 8703+ return ZYAN_STATUS_SUCCESS; 8704+} 8705+ 8706+ZYAN_STATIC_ASSERT(sizeof(ZyanThreadId) <= sizeof(ZyanU64)); 8707+ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id) 8708+{ 8709+ // TODO: Use `pthread_getthreadid_np` on platforms where it is available 8710+ 8711+ pthread_t ptid = pthread_self(); 8712+ *thread_id = *(ZyanThreadId*)ptid; 8713+ 8714+ return ZYAN_STATUS_SUCCESS; 8715+} 8716+ 8717+/* ---------------------------------------------------------------------------------------------- */ 8718+/* Thread Local Storage */ 8719+/* ---------------------------------------------------------------------------------------------- */ 8720+ 8721+ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, ZyanThreadTlsCallback destructor) 8722+{ 8723+ ZyanThreadTlsIndex value; 8724+ const int error = pthread_key_create(&value, destructor); 8725+ if (error != 0) 8726+ { 8727+ if (error == EAGAIN) 8728+ { 8729+ return ZYAN_STATUS_OUT_OF_RESOURCES; 8730+ } 8731+ if (error == ENOMEM) 8732+ { 8733+ return ZYAN_STATUS_NOT_ENOUGH_MEMORY; 8734+ } 8735+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8736+ } 8737+ 8738+ *index = value; 8739+ return ZYAN_STATUS_SUCCESS; 8740+} 8741+ 8742+ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index) 8743+{ 8744+ return !pthread_key_delete(index) ? ZYAN_STATUS_SUCCESS : ZYAN_STATUS_BAD_SYSTEMCALL; 8745+} 8746+ 8747+ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data) 8748+{ 8749+ *data = pthread_getspecific(index); 8750+ 8751+ return ZYAN_STATUS_SUCCESS; 8752+} 8753+ 8754+ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data) 8755+{ 8756+ const int error = pthread_setspecific(index, data); 8757+ if (error != 0) 8758+ { 8759+ if (error == EINVAL) 8760+ { 8761+ return ZYAN_STATUS_INVALID_ARGUMENT; 8762+ } 8763+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8764+ } 8765+ 8766+ return ZYAN_STATUS_SUCCESS; 8767+} 8768+ 8769+/* ---------------------------------------------------------------------------------------------- */ 8770+ 8771+#elif defined(ZYAN_WINDOWS) 8772+ 8773+/* ---------------------------------------------------------------------------------------------- */ 8774+/* General */ 8775+/* ---------------------------------------------------------------------------------------------- */ 8776+ 8777+ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread) 8778+{ 8779+ *thread = GetCurrentThread(); 8780+ 8781+ return ZYAN_STATUS_SUCCESS; 8782+} 8783+ 8784+ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id) 8785+{ 8786+ *thread_id = GetCurrentThreadId(); 8787+ 8788+ return ZYAN_STATUS_SUCCESS; 8789+} 8790+ 8791+/* ---------------------------------------------------------------------------------------------- */ 8792+/* Thread Local Storage (TLS) */ 8793+/* ---------------------------------------------------------------------------------------------- */ 8794+ 8795+ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, ZyanThreadTlsCallback destructor) 8796+{ 8797+ const ZyanThreadTlsIndex value = FlsAlloc(destructor); 8798+ if (value == FLS_OUT_OF_INDEXES) 8799+ { 8800+ return ZYAN_STATUS_OUT_OF_RESOURCES; 8801+ } 8802+ 8803+ *index = value; 8804+ return ZYAN_STATUS_SUCCESS; 8805+} 8806+ 8807+ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index) 8808+{ 8809+ return FlsFree(index) ? ZYAN_STATUS_SUCCESS : ZYAN_STATUS_BAD_SYSTEMCALL; 8810+} 8811+ 8812+ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data) 8813+{ 8814+ *data = FlsGetValue(index); 8815+ 8816+ return ZYAN_STATUS_SUCCESS; 8817+} 8818+ 8819+ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data) 8820+{ 8821+ if (!FlsSetValue(index, data)) 8822+ { 8823+ const DWORD error = GetLastError(); 8824+ if (error == ERROR_INVALID_PARAMETER) 8825+ { 8826+ return ZYAN_STATUS_INVALID_ARGUMENT; 8827+ } 8828+ return ZYAN_STATUS_BAD_SYSTEMCALL; 8829+ } 8830+ 8831+ return ZYAN_STATUS_SUCCESS; 8832+} 8833+ 8834+/* ---------------------------------------------------------------------------------------------- */ 8835+ 8836+#else 8837+# error "Unsupported platform detected" 8838+#endif 8839+ 8840+/* ============================================================================================== */ 8841+ 8842+#endif /* ZYAN_NO_LIBC */ 8843diff --git a/zycore/src/Allocator.c b/zycore/src/Allocator.c 8844new file mode 100644 8845index 0000000..5fadf64 8846--- /dev/null 8847+++ b/zycore/src/Allocator.c 8848@@ -0,0 +1,134 @@ 8849+/*************************************************************************************************** 8850+ 8851+ Zyan Core Library (Zycore-C) 8852+ 8853+ Original Author : Florian Bernd 8854+ 8855+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8856+ * of this software and associated documentation files (the "Software"), to deal 8857+ * in the Software without restriction, including without limitation the rights 8858+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8859+ * copies of the Software, and to permit persons to whom the Software is 8860+ * furnished to do so, subject to the following conditions: 8861+ * 8862+ * The above copyright notice and this permission notice shall be included in all 8863+ * copies or substantial portions of the Software. 8864+ * 8865+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8866+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8867+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8868+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8869+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 8870+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8871+ * SOFTWARE. 8872+ 8873+***************************************************************************************************/ 8874+ 8875+#include <Zycore/Allocator.h> 8876+#include <Zycore/LibC.h> 8877+ 8878+/* ============================================================================================== */ 8879+/* Internal functions */ 8880+/* ============================================================================================== */ 8881+ 8882+/* ---------------------------------------------------------------------------------------------- */ 8883+/* Default allocator */ 8884+/* ---------------------------------------------------------------------------------------------- */ 8885+ 8886+#ifndef ZYAN_NO_LIBC 8887+ 8888+static ZyanStatus ZyanAllocatorDefaultAllocate(ZyanAllocator* allocator, void** p, 8889+ ZyanUSize element_size, ZyanUSize n) 8890+{ 8891+ ZYAN_ASSERT(allocator); 8892+ ZYAN_ASSERT(p); 8893+ ZYAN_ASSERT(element_size); 8894+ ZYAN_ASSERT(n); 8895+ 8896+ ZYAN_UNUSED(allocator); 8897+ 8898+ *p = ZYAN_MALLOC(element_size * n); 8899+ if (!*p) 8900+ { 8901+ return ZYAN_STATUS_NOT_ENOUGH_MEMORY; 8902+ } 8903+ 8904+ return ZYAN_STATUS_SUCCESS; 8905+} 8906+ 8907+static ZyanStatus ZyanAllocatorDefaultReallocate(ZyanAllocator* allocator, void** p, 8908+ ZyanUSize element_size, ZyanUSize n) 8909+{ 8910+ ZYAN_ASSERT(allocator); 8911+ ZYAN_ASSERT(p); 8912+ ZYAN_ASSERT(element_size); 8913+ ZYAN_ASSERT(n); 8914+ 8915+ ZYAN_UNUSED(allocator); 8916+ 8917+ void* const x = ZYAN_REALLOC(*p, element_size * n); 8918+ if (!x) 8919+ { 8920+ return ZYAN_STATUS_NOT_ENOUGH_MEMORY; 8921+ } 8922+ *p = x; 8923+ 8924+ return ZYAN_STATUS_SUCCESS; 8925+} 8926+ 8927+static ZyanStatus ZyanAllocatorDefaultDeallocate(ZyanAllocator* allocator, void* p, 8928+ ZyanUSize element_size, ZyanUSize n) 8929+{ 8930+ ZYAN_ASSERT(allocator); 8931+ ZYAN_ASSERT(p); 8932+ ZYAN_ASSERT(element_size); 8933+ ZYAN_ASSERT(n); 8934+ 8935+ ZYAN_UNUSED(allocator); 8936+ ZYAN_UNUSED(element_size); 8937+ ZYAN_UNUSED(n); 8938+ 8939+ ZYAN_FREE(p); 8940+ 8941+ return ZYAN_STATUS_SUCCESS; 8942+} 8943+ 8944+#endif // ZYAN_NO_LIBC 8945+ 8946+/* ---------------------------------------------------------------------------------------------- */ 8947+ 8948+/* ============================================================================================== */ 8949+/* Exported functions */ 8950+/* ============================================================================================== */ 8951+ 8952+ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate, 8953+ ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate) 8954+{ 8955+ if (!allocator || !allocate || !reallocate || !deallocate) 8956+ { 8957+ return ZYAN_STATUS_INVALID_ARGUMENT; 8958+ } 8959+ 8960+ allocator->allocate = allocate; 8961+ allocator->reallocate = reallocate; 8962+ allocator->deallocate = deallocate; 8963+ 8964+ return ZYAN_STATUS_SUCCESS; 8965+} 8966+ 8967+#ifndef ZYAN_NO_LIBC 8968+ 8969+ZyanAllocator* ZyanAllocatorDefault(void) 8970+{ 8971+ static ZyanAllocator allocator = 8972+ { 8973+ &ZyanAllocatorDefaultAllocate, 8974+ &ZyanAllocatorDefaultReallocate, 8975+ &ZyanAllocatorDefaultDeallocate 8976+ }; 8977+ return &allocator; 8978+} 8979+ 8980+#endif 8981+ 8982+/* ============================================================================================== */ 8983diff --git a/zycore/src/ArgParse.c b/zycore/src/ArgParse.c 8984new file mode 100644 8985index 0000000..109cfc8 8986--- /dev/null 8987+++ b/zycore/src/ArgParse.c 8988@@ -0,0 +1,279 @@ 8989+/*************************************************************************************************** 8990+ 8991+ Zyan Core Library (Zycore-C) 8992+ 8993+ Original Author : Joel Hoener 8994+ 8995+ * Permission is hereby granted, free of charge, to any person obtaining a copy 8996+ * of this software and associated documentation files (the "Software"), to deal 8997+ * in the Software without restriction, including without limitation the rights 8998+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8999+ * copies of the Software, and to permit persons to whom the Software is 9000+ * furnished to do so, subject to the following conditions: 9001+ * 9002+ * The above copyright notice and this permission notice shall be included in all 9003+ * copies or substantial portions of the Software. 9004+ * 9005+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 9006+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9007+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 9008+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9009+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 9010+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 9011+ * SOFTWARE. 9012+ 9013+***************************************************************************************************/ 9014+ 9015+#include <Zycore/ArgParse.h> 9016+#include <Zycore/LibC.h> 9017+ 9018+/* ============================================================================================== */ 9019+/* Exported functions */ 9020+/* ============================================================================================== */ 9021+ 9022+#ifndef ZYAN_NO_LIBC 9023+ 9024+ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed, 9025+ const char** error_token) 9026+{ 9027+ return ZyanArgParseEx(cfg, parsed, error_token, ZyanAllocatorDefault()); 9028+} 9029+ 9030+#endif 9031+ 9032+ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed, 9033+ const char** error_token, ZyanAllocator* allocator) 9034+{ 9035+# define ZYAN_ERR_TOK(tok) if (error_token) { *error_token = tok; } 9036+ 9037+ ZYAN_ASSERT(cfg); 9038+ ZYAN_ASSERT(parsed); 9039+ 9040+ // TODO: Once we have a decent hash map impl, refactor this to use it. The majority of for 9041+ // loops through the argument list could be avoided. 9042+ 9043+ if (cfg->min_unnamed_args > cfg->max_unnamed_args) 9044+ { 9045+ return ZYAN_STATUS_INVALID_ARGUMENT; 9046+ } 9047+ 9048+ // Check argument syntax. 9049+ for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def) 9050+ { 9051+ // TODO: Duplicate check 9052+ 9053+ if (!def->name) 9054+ { 9055+ return ZYAN_STATUS_INVALID_ARGUMENT; 9056+ } 9057+ 9058+ ZyanUSize arg_len = ZYAN_STRLEN(def->name); 9059+ if (arg_len < 2 || def->name[0] != '-') 9060+ { 9061+ return ZYAN_STATUS_INVALID_ARGUMENT; 9062+ } 9063+ 9064+ // Single dash arguments only accept a single char name. 9065+ if (def->name[1] != '-' && arg_len != 2) 9066+ { 9067+ return ZYAN_STATUS_INVALID_ARGUMENT; 9068+ } 9069+ } 9070+ 9071+ // Initialize output vector. 9072+ ZYAN_CHECK(ZyanVectorInitEx(parsed, sizeof(ZyanArgParseArg), cfg->argc, ZYAN_NULL, allocator, 9073+ ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD)); 9074+ 9075+ ZyanStatus err; 9076+ ZyanBool accept_dash_args = ZYAN_TRUE; 9077+ ZyanUSize num_unnamed_args = 0; 9078+ for (ZyanUSize i = 1; i < cfg->argc; ++i) 9079+ { 9080+ const char* cur_arg = cfg->argv[i]; 9081+ ZyanUSize arg_len = ZYAN_STRLEN(cfg->argv[i]); 9082+ 9083+ // Double-dash argument? 9084+ if (accept_dash_args && arg_len >= 2 && ZYAN_MEMCMP(cur_arg, "--", 2) == 0) 9085+ { 9086+ // GNU style end of argument parsing. 9087+ if (arg_len == 2) 9088+ { 9089+ accept_dash_args = ZYAN_FALSE; 9090+ } 9091+ // Regular double-dash argument. 9092+ else 9093+ { 9094+ // Allocate parsed argument struct. 9095+ ZyanArgParseArg* parsed_arg; 9096+ ZYAN_CHECK(ZyanVectorEmplace(parsed, (void**)&parsed_arg, ZYAN_NULL)); 9097+ ZYAN_MEMSET(parsed_arg, 0, sizeof(*parsed_arg)); 9098+ 9099+ // Find corresponding argument definition. 9100+ for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def) 9101+ { 9102+ if (ZYAN_STRCMP(def->name, cur_arg) == 0) 9103+ { 9104+ parsed_arg->def = def; 9105+ break; 9106+ } 9107+ } 9108+ 9109+ // Search exhausted & argument not found. RIP. 9110+ if (!parsed_arg->def) 9111+ { 9112+ err = ZYAN_STATUS_ARG_NOT_UNDERSTOOD; 9113+ ZYAN_ERR_TOK(cur_arg); 9114+ goto failure; 9115+ } 9116+ 9117+ // Does the argument expect a value? If yes, consume next token. 9118+ if (!parsed_arg->def->boolean) 9119+ { 9120+ if (i == cfg->argc - 1) 9121+ { 9122+ err = ZYAN_STATUS_ARG_MISSES_VALUE; 9123+ ZYAN_ERR_TOK(cur_arg); 9124+ goto failure; 9125+ } 9126+ parsed_arg->has_value = ZYAN_TRUE; 9127+ ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, cfg->argv[++i])); 9128+ } 9129+ } 9130+ 9131+ // Continue parsing at next token. 9132+ continue; 9133+ } 9134+ 9135+ // Single-dash argument? 9136+ // TODO: How to deal with just dashes? Current code treats it as unnamed arg. 9137+ if (accept_dash_args && arg_len > 1 && cur_arg[0] == '-') 9138+ { 9139+ // Iterate argument token chars until there are either no more chars left 9140+ // or we encounter a non-boolean argument, in which case we consume the 9141+ // remaining chars as its value. 9142+ for (const char* read_ptr = cur_arg + 1; *read_ptr; ++read_ptr) 9143+ { 9144+ // Allocate parsed argument struct. 9145+ ZyanArgParseArg* parsed_arg; 9146+ ZYAN_CHECK(ZyanVectorEmplace(parsed, (void**)&parsed_arg, ZYAN_NULL)); 9147+ ZYAN_MEMSET(parsed_arg, 0, sizeof(*parsed_arg)); 9148+ 9149+ // Find corresponding argument definition. 9150+ for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def) 9151+ { 9152+ if (ZYAN_STRLEN(def->name) == 2 && 9153+ def->name[0] == '-' && 9154+ def->name[1] == *read_ptr) 9155+ { 9156+ parsed_arg->def = def; 9157+ break; 9158+ } 9159+ } 9160+ 9161+ // Search exhausted, no match found? 9162+ if (!parsed_arg->def) 9163+ { 9164+ err = ZYAN_STATUS_ARG_NOT_UNDERSTOOD; 9165+ ZYAN_ERR_TOK(cur_arg); 9166+ goto failure; 9167+ } 9168+ 9169+ // Requires value? 9170+ if (!parsed_arg->def->boolean) 9171+ { 9172+ // If there are chars left, consume them (e.g. `-n1000`). 9173+ if (read_ptr[1]) 9174+ { 9175+ parsed_arg->has_value = ZYAN_TRUE; 9176+ ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, read_ptr + 1)); 9177+ } 9178+ // If not, consume next token (e.g. `-n 1000`). 9179+ else 9180+ { 9181+ if (i == cfg->argc - 1) 9182+ { 9183+ err = ZYAN_STATUS_ARG_MISSES_VALUE; 9184+ ZYAN_ERR_TOK(cur_arg) 9185+ goto failure; 9186+ } 9187+ 9188+ parsed_arg->has_value = ZYAN_TRUE; 9189+ ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, cfg->argv[++i])); 9190+ } 9191+ 9192+ // Either way, continue with next argument. 9193+ goto continue_main_loop; 9194+ } 9195+ } 9196+ } 9197+ 9198+ // Still here? We're looking at an unnamed argument. 9199+ ++num_unnamed_args; 9200+ if (num_unnamed_args > cfg->max_unnamed_args) 9201+ { 9202+ err = ZYAN_STATUS_TOO_MANY_ARGS; 9203+ ZYAN_ERR_TOK(cur_arg); 9204+ goto failure; 9205+ } 9206+ 9207+ // Allocate parsed argument struct. 9208+ ZyanArgParseArg* parsed_arg; 9209+ ZYAN_CHECK(ZyanVectorEmplace(parsed, (void**)&parsed_arg, ZYAN_NULL)); 9210+ ZYAN_MEMSET(parsed_arg, 0, sizeof(*parsed_arg)); 9211+ parsed_arg->has_value = ZYAN_TRUE; 9212+ ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, cur_arg)); 9213+ 9214+ continue_main_loop:; 9215+ } 9216+ 9217+ // All tokens processed. Do we have enough unnamed arguments? 9218+ if (num_unnamed_args < cfg->min_unnamed_args) 9219+ { 9220+ err = ZYAN_STATUS_TOO_FEW_ARGS; 9221+ // No sensible error token for this error type. 9222+ goto failure; 9223+ } 9224+ 9225+ // Check whether all required arguments are present. 9226+ ZyanUSize num_parsed_args; 9227+ ZYAN_CHECK(ZyanVectorGetSize(parsed, &num_parsed_args)); 9228+ for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def) 9229+ { 9230+ if (!def->required) continue; 9231+ 9232+ ZyanBool arg_found = ZYAN_FALSE; 9233+ for (ZyanUSize i = 0; i < num_parsed_args; ++i) 9234+ { 9235+ const ZyanArgParseArg* arg = ZYAN_NULL; 9236+ ZYAN_CHECK(ZyanVectorGetPointer(parsed, i, (const void**)&arg)); 9237+ 9238+ // Skip unnamed args. 9239+ if (!arg->def) continue; 9240+ 9241+ if (arg->def == def) 9242+ { 9243+ arg_found = ZYAN_TRUE; 9244+ break; 9245+ } 9246+ } 9247+ 9248+ if (!arg_found) 9249+ { 9250+ err = ZYAN_STATUS_REQUIRED_ARG_MISSING; 9251+ ZYAN_ERR_TOK(def->name); 9252+ goto failure; 9253+ } 9254+ } 9255+ 9256+ // Yay! 9257+ ZYAN_ERR_TOK(ZYAN_NULL); 9258+ return ZYAN_STATUS_SUCCESS; 9259+ 9260+failure: 9261+ ZYAN_CHECK(ZyanVectorDestroy(parsed)); 9262+ return err; 9263+ 9264+# undef ZYAN_ERR_TOK 9265+} 9266+ 9267+/* ============================================================================================== */ 9268diff --git a/zycore/src/Bitset.c b/zycore/src/Bitset.c 9269new file mode 100644 9270index 0000000..b1c733d 9271--- /dev/null 9272+++ b/zycore/src/Bitset.c 9273@@ -0,0 +1,670 @@ 9274+/*************************************************************************************************** 9275+ 9276+ Zyan Core Library (Zycore-C) 9277+ 9278+ Original Author : Florian Bernd 9279+ 9280+ * Permission is hereby granted, free of charge, to any person obtaining a copy 9281+ * of this software and associated documentation files (the "Software"), to deal 9282+ * in the Software without restriction, including without limitation the rights 9283+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9284+ * copies of the Software, and to permit persons to whom the Software is 9285+ * furnished to do so, subject to the following conditions: 9286+ * 9287+ * The above copyright notice and this permission notice shall be included in all 9288+ * copies or substantial portions of the Software. 9289+ * 9290+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 9291+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9292+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 9293+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9294+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 9295+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 9296+ * SOFTWARE. 9297+ 9298+***************************************************************************************************/ 9299+ 9300+#include <Zycore/Bitset.h> 9301+#include <Zycore/LibC.h> 9302+ 9303+/* ============================================================================================== */ 9304+/* Internal constants */ 9305+/* ============================================================================================== */ 9306+ 9307+#define ZYAN_BITSET_GROWTH_FACTOR 2 9308+#define ZYAN_BITSET_SHRINK_THRESHOLD 2 9309+ 9310+/* ============================================================================================== */ 9311+/* Internal macros */ 9312+/* ============================================================================================== */ 9313+ 9314+/** 9315+ * Computes the smallest integer value not less than `x`. 9316+ * 9317+ * @param x The value. 9318+ * 9319+ * @return The smallest integer value not less than `x`. 9320+ */ 9321+#define ZYAN_BITSET_CEIL(x) \ 9322+ (((x) == ((ZyanU32)(x))) ? (ZyanU32)(x) : ((ZyanU32)(x)) + 1) 9323+ 9324+/** 9325+ * Converts bits to bytes. 9326+ * 9327+ * @param x The value in bits. 9328+ * 9329+ * @return The amount of bytes needed to fit `x` bits. 9330+ */ 9331+#define ZYAN_BITSET_BITS_TO_BYTES(x) \ 9332+ ZYAN_BITSET_CEIL((x) / 8) 9333+ 9334+/** 9335+ * Returns the offset of the given bit. 9336+ * 9337+ * @param index The bit index. 9338+ * 9339+ * @return The offset of the given bit. 9340+ */ 9341+#define ZYAN_BITSET_BIT_OFFSET(index) \ 9342+ (7 - ((index) % 8)) 9343+ 9344+/* ============================================================================================== */ 9345+/* Internal functions */ 9346+/* ============================================================================================== */ 9347+ 9348+/* ---------------------------------------------------------------------------------------------- */ 9349+/* Helper functions */ 9350+/* ---------------------------------------------------------------------------------------------- */ 9351+ 9352+/** 9353+ * Initializes the given `vector` with `count` "zero"-bytes. 9354+ * 9355+ * @param vector A pointer to the `ZyanVector` instance. 9356+ * @param count The number of bytes. 9357+ * 9358+ * @return A zyan status code. 9359+ */ 9360+static ZyanStatus ZyanBitsetInitVectorElements(ZyanVector* vector, ZyanUSize count) 9361+{ 9362+ ZYAN_ASSERT(vector); 9363+ 9364+ static const ZyanU8 zero = 0; 9365+ for (ZyanUSize i = 0; i < count; ++i) 9366+ { 9367+ ZYAN_CHECK(ZyanVectorPushBack(vector, &zero)); 9368+ } 9369+ 9370+ return ZYAN_STATUS_SUCCESS; 9371+} 9372+ 9373+/* ---------------------------------------------------------------------------------------------- */ 9374+/* Byte operations */ 9375+/* ---------------------------------------------------------------------------------------------- */ 9376+ 9377+static ZyanStatus ZyanBitsetOperationAND(ZyanU8* b1, const ZyanU8* b2) 9378+{ 9379+ *b1 &= *b2; 9380+ return ZYAN_STATUS_SUCCESS; 9381+} 9382+ 9383+static ZyanStatus ZyanBitsetOperationOR (ZyanU8* b1, const ZyanU8* b2) 9384+{ 9385+ *b1 |= *b2; 9386+ return ZYAN_STATUS_SUCCESS; 9387+} 9388+ 9389+static ZyanStatus ZyanBitsetOperationXOR(ZyanU8* b1, const ZyanU8* b2) 9390+{ 9391+ *b1 ^= *b2; 9392+ return ZYAN_STATUS_SUCCESS; 9393+} 9394+ 9395+/* ---------------------------------------------------------------------------------------------- */ 9396+ 9397+/* ============================================================================================== */ 9398+/* Exported functions */ 9399+/* ============================================================================================== */ 9400+ 9401+/* ---------------------------------------------------------------------------------------------- */ 9402+/* Constructor and destructor */ 9403+/* ---------------------------------------------------------------------------------------------- */ 9404+ 9405+#ifndef ZYAN_NO_LIBC 9406+ 9407+ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count) 9408+{ 9409+ return ZyanBitsetInitEx(bitset, count, ZyanAllocatorDefault(), ZYAN_BITSET_GROWTH_FACTOR, 9410+ ZYAN_BITSET_SHRINK_THRESHOLD); 9411+} 9412+ 9413+#endif // ZYAN_NO_LIBC 9414+ 9415+ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count, ZyanAllocator* allocator, 9416+ ZyanU8 growth_factor, ZyanU8 shrink_threshold) 9417+{ 9418+ if (!bitset) 9419+ { 9420+ return ZYAN_STATUS_INVALID_ARGUMENT; 9421+ } 9422+ 9423+ const ZyanU32 bytes = ZYAN_BITSET_BITS_TO_BYTES(count); 9424+ 9425+ bitset->size = count; 9426+ ZYAN_CHECK(ZyanVectorInitEx(&bitset->bits, sizeof(ZyanU8), bytes, ZYAN_NULL, allocator, 9427+ growth_factor, shrink_threshold)); 9428+ ZYAN_CHECK(ZyanBitsetInitVectorElements(&bitset->bits, bytes)); 9429+ 9430+ return ZYAN_STATUS_SUCCESS; 9431+} 9432+ 9433+ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer, 9434+ ZyanUSize capacity) 9435+{ 9436+ if (!bitset) 9437+ { 9438+ return ZYAN_STATUS_INVALID_ARGUMENT; 9439+ } 9440+ 9441+ const ZyanU32 bytes = ZYAN_BITSET_BITS_TO_BYTES(count); 9442+ if (capacity < bytes) 9443+ { 9444+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 9445+ } 9446+ 9447+ bitset->size = count; 9448+ ZYAN_CHECK(ZyanVectorInitCustomBuffer(&bitset->bits, sizeof(ZyanU8), buffer, capacity, 9449+ ZYAN_NULL)); 9450+ ZYAN_CHECK(ZyanBitsetInitVectorElements(&bitset->bits, bytes)); 9451+ 9452+ return ZYAN_STATUS_SUCCESS; 9453+} 9454+ 9455+ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset) 9456+{ 9457+ if (!bitset) 9458+ { 9459+ return ZYAN_STATUS_INVALID_ARGUMENT; 9460+ } 9461+ 9462+ return ZyanVectorDestroy(&bitset->bits); 9463+} 9464+ 9465+/* ---------------------------------------------------------------------------------------------- */ 9466+/* Logical operations */ 9467+/* ---------------------------------------------------------------------------------------------- */ 9468+ 9469+ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination, const ZyanBitset* source, 9470+ ZyanBitsetByteOperation operation) 9471+{ 9472+ if (!destination || !source || !operation) 9473+ { 9474+ return ZYAN_STATUS_INVALID_ARGUMENT; 9475+ } 9476+ 9477+ ZyanUSize s1; 9478+ ZyanUSize s2; 9479+ ZYAN_CHECK(ZyanVectorGetSize(&destination->bits, &s1)); 9480+ ZYAN_CHECK(ZyanVectorGetSize(&source->bits, &s2)); 9481+ 9482+ const ZyanUSize min = ZYAN_MIN(s1, s2); 9483+ for (ZyanUSize i = 0; i < min; ++i) 9484+ { 9485+ ZyanU8* v1; 9486+ const ZyanU8* v2; 9487+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&destination->bits, i, (void**)&v1)); 9488+ ZYAN_CHECK(ZyanVectorGetPointer(&source->bits, i, (const void**)&v2)); 9489+ 9490+ ZYAN_ASSERT(v1); 9491+ ZYAN_ASSERT(v2); 9492+ 9493+ ZYAN_CHECK(operation(v1, v2)); 9494+ } 9495+ 9496+ return ZYAN_STATUS_SUCCESS; 9497+} 9498+ 9499+ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source) 9500+{ 9501+ return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationAND); 9502+} 9503+ 9504+ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source) 9505+{ 9506+ return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationOR ); 9507+} 9508+ 9509+ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source) 9510+{ 9511+ return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationXOR); 9512+} 9513+ 9514+ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset) 9515+{ 9516+ if (!bitset) 9517+ { 9518+ return ZYAN_STATUS_INVALID_ARGUMENT; 9519+ } 9520+ 9521+ ZyanUSize size; 9522+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9523+ for (ZyanUSize i = 0; i < size; ++i) 9524+ { 9525+ ZyanU8* value; 9526+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value)); 9527+ *value = ~(*value); 9528+ } 9529+ 9530+ return ZYAN_STATUS_SUCCESS; 9531+} 9532+ 9533+/* ---------------------------------------------------------------------------------------------- */ 9534+/* Bit access */ 9535+/* ---------------------------------------------------------------------------------------------- */ 9536+ 9537+ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index) 9538+{ 9539+ if (!bitset) 9540+ { 9541+ return ZYAN_STATUS_INVALID_ARGUMENT; 9542+ } 9543+ if (index >= bitset->size) 9544+ { 9545+ return ZYAN_STATUS_OUT_OF_RANGE; 9546+ } 9547+ 9548+ ZyanU8* value; 9549+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value)); 9550+ 9551+ *value |= (1 << ZYAN_BITSET_BIT_OFFSET(index)); 9552+ 9553+ return ZYAN_STATUS_SUCCESS; 9554+} 9555+ 9556+ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index) 9557+{ 9558+ if (!bitset) 9559+ { 9560+ return ZYAN_STATUS_INVALID_ARGUMENT; 9561+ } 9562+ if (index >= bitset->size) 9563+ { 9564+ return ZYAN_STATUS_OUT_OF_RANGE; 9565+ } 9566+ 9567+ ZyanU8* value; 9568+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value)); 9569+ *value &= ~(1 << ZYAN_BITSET_BIT_OFFSET(index)); 9570+ 9571+ return ZYAN_STATUS_SUCCESS; 9572+} 9573+ 9574+ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value) 9575+{ 9576+ if (value) 9577+ { 9578+ return ZyanBitsetSet(bitset, index); 9579+ } 9580+ return ZyanBitsetReset(bitset, index); 9581+} 9582+ 9583+ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index) 9584+{ 9585+ if (!bitset) 9586+ { 9587+ return ZYAN_STATUS_INVALID_ARGUMENT; 9588+ } 9589+ if (index >= bitset->size) 9590+ { 9591+ return ZYAN_STATUS_OUT_OF_RANGE; 9592+ } 9593+ 9594+ ZyanU8* value; 9595+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value)); 9596+ *value ^= (1 << ZYAN_BITSET_BIT_OFFSET(index)); 9597+ 9598+ return ZYAN_STATUS_SUCCESS; 9599+} 9600+ 9601+ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index) 9602+{ 9603+ if (!bitset) 9604+ { 9605+ return ZYAN_STATUS_INVALID_ARGUMENT; 9606+ } 9607+ if (index >= bitset->size) 9608+ { 9609+ return ZYAN_STATUS_OUT_OF_RANGE; 9610+ } 9611+ 9612+ const ZyanU8* value; 9613+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, index / 8, (const void**)&value)); 9614+ if ((*value & (1 << ZYAN_BITSET_BIT_OFFSET(index))) == 0) 9615+ { 9616+ return ZYAN_STATUS_FALSE; 9617+ } 9618+ return ZYAN_STATUS_TRUE; 9619+} 9620+ 9621+ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset) 9622+{ 9623+ if (!bitset) 9624+ { 9625+ return ZYAN_STATUS_INVALID_ARGUMENT; 9626+ } 9627+ 9628+ return ZyanBitsetTest(bitset, bitset->size - 1); 9629+} 9630+ 9631+ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset) 9632+{ 9633+ return ZyanBitsetTest(bitset, 0); 9634+} 9635+ 9636+/* ---------------------------------------------------------------------------------------------- */ 9637+ 9638+ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset) 9639+{ 9640+ if (!bitset) 9641+ { 9642+ return ZYAN_STATUS_INVALID_ARGUMENT; 9643+ } 9644+ 9645+ ZyanUSize size; 9646+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9647+ for (ZyanUSize i = 0; i < size; ++i) 9648+ { 9649+ ZyanU8* value; 9650+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value)); 9651+ *value = 0xFF; 9652+ } 9653+ 9654+ return ZYAN_STATUS_SUCCESS; 9655+} 9656+ 9657+ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset) 9658+{ 9659+ if (!bitset) 9660+ { 9661+ return ZYAN_STATUS_INVALID_ARGUMENT; 9662+ } 9663+ 9664+ ZyanUSize size; 9665+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9666+ for (ZyanUSize i = 0; i < size; ++i) 9667+ { 9668+ ZyanU8* value; 9669+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value)); 9670+ *value = 0x00; 9671+ } 9672+ 9673+ return ZYAN_STATUS_SUCCESS; 9674+} 9675+ 9676+/* ---------------------------------------------------------------------------------------------- */ 9677+/* Size management */ 9678+/* ---------------------------------------------------------------------------------------------- */ 9679+ 9680+ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value) 9681+{ 9682+ if (!bitset) 9683+ { 9684+ return ZYAN_STATUS_INVALID_ARGUMENT; 9685+ } 9686+ 9687+ if ((bitset->size++ % 8) == 0) 9688+ { 9689+ static const ZyanU8 zero = 0; 9690+ ZYAN_CHECK(ZyanVectorPushBack(&bitset->bits, &zero)); 9691+ } 9692+ 9693+ return ZyanBitsetAssign(bitset, bitset->size - 1, value); 9694+} 9695+ 9696+ZyanStatus ZyanBitsetPop(ZyanBitset* bitset) 9697+{ 9698+ if (!bitset) 9699+ { 9700+ return ZYAN_STATUS_INVALID_ARGUMENT; 9701+ } 9702+ 9703+ if ((--bitset->size % 8) == 0) 9704+ { 9705+ return ZyanVectorPopBack(&bitset->bits); 9706+ } 9707+ 9708+ return ZYAN_STATUS_SUCCESS; 9709+} 9710+ 9711+ZyanStatus ZyanBitsetClear(ZyanBitset* bitset) 9712+{ 9713+ if (!bitset) 9714+ { 9715+ return ZYAN_STATUS_INVALID_ARGUMENT; 9716+ } 9717+ 9718+ bitset->size = 0; 9719+ return ZyanVectorClear(&bitset->bits); 9720+} 9721+ 9722+/* ---------------------------------------------------------------------------------------------- */ 9723+/* Memory management */ 9724+/* ---------------------------------------------------------------------------------------------- */ 9725+ 9726+ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count) 9727+{ 9728+ return ZyanVectorReserve(&bitset->bits, ZYAN_BITSET_BITS_TO_BYTES(count)); 9729+} 9730+ 9731+ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset) 9732+{ 9733+ return ZyanVectorShrinkToFit(&bitset->bits); 9734+} 9735+ 9736+/* ---------------------------------------------------------------------------------------------- */ 9737+/* Information */ 9738+/* ---------------------------------------------------------------------------------------------- */ 9739+ 9740+ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size) 9741+{ 9742+ if (!bitset) 9743+ { 9744+ return ZYAN_STATUS_INVALID_ARGUMENT; 9745+ } 9746+ 9747+ *size = bitset->size; 9748+ 9749+ return ZYAN_STATUS_SUCCESS; 9750+} 9751+ 9752+ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity) 9753+{ 9754+ ZYAN_CHECK(ZyanBitsetGetCapacityBytes(bitset, capacity)); 9755+ *capacity *= 8; 9756+ 9757+ return ZYAN_STATUS_SUCCESS; 9758+} 9759+ 9760+ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size) 9761+{ 9762+ if (!bitset) 9763+ { 9764+ return ZYAN_STATUS_INVALID_ARGUMENT; 9765+ } 9766+ 9767+ return ZyanVectorGetSize(&bitset->bits, size); 9768+} 9769+ 9770+ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity) 9771+{ 9772+ if (!bitset) 9773+ { 9774+ return ZYAN_STATUS_INVALID_ARGUMENT; 9775+ } 9776+ 9777+ return ZyanVectorGetCapacity(&bitset->bits, capacity); 9778+} 9779+ 9780+/* ---------------------------------------------------------------------------------------------- */ 9781+ 9782+ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count) 9783+{ 9784+ if (!bitset || !count) 9785+ { 9786+ return ZYAN_STATUS_INVALID_ARGUMENT; 9787+ } 9788+ 9789+ *count = 0; 9790+ 9791+ ZyanUSize size; 9792+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9793+ for (ZyanUSize i = 0; i < size; ++i) 9794+ { 9795+ ZyanU8* value; 9796+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value)); 9797+ 9798+ ZyanU8 popcnt = *value; 9799+ popcnt = (popcnt & 0x55) + ((popcnt >> 1) & 0x55); 9800+ popcnt = (popcnt & 0x33) + ((popcnt >> 2) & 0x33); 9801+ popcnt = (popcnt & 0x0F) + ((popcnt >> 4) & 0x0F); 9802+ 9803+ *count += popcnt; 9804+ } 9805+ 9806+ *count = ZYAN_MIN(*count, bitset->size); 9807+ 9808+ return ZYAN_STATUS_SUCCESS; 9809+} 9810+ 9811+ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset) 9812+{ 9813+ if (!bitset) 9814+ { 9815+ return ZYAN_STATUS_INVALID_ARGUMENT; 9816+ } 9817+ 9818+ ZyanUSize size; 9819+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9820+ for (ZyanUSize i = 0; i < size; ++i) 9821+ { 9822+ ZyanU8* value; 9823+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value)); 9824+ if (i < (size - 1)) 9825+ { 9826+ if (*value != 0xFF) 9827+ { 9828+ return ZYAN_STATUS_FALSE; 9829+ } 9830+ } else 9831+ { 9832+ const ZyanU8 mask = ~(8 - (bitset->size % 8)); 9833+ if ((*value & mask) != mask) 9834+ { 9835+ return ZYAN_STATUS_FALSE; 9836+ } 9837+ } 9838+ } 9839+ 9840+ return ZYAN_STATUS_TRUE; 9841+} 9842+ 9843+ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset) 9844+{ 9845+ if (!bitset) 9846+ { 9847+ return ZYAN_STATUS_INVALID_ARGUMENT; 9848+ } 9849+ 9850+ ZyanUSize size; 9851+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9852+ for (ZyanUSize i = 0; i < size; ++i) 9853+ { 9854+ ZyanU8* value; 9855+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value)); 9856+ if (i < (size - 1)) 9857+ { 9858+ if (*value != 0x00) 9859+ { 9860+ return ZYAN_STATUS_TRUE; 9861+ } 9862+ } else 9863+ { 9864+ const ZyanU8 mask = ~(8 - (bitset->size % 8)); 9865+ if ((*value & mask) != 0x00) 9866+ { 9867+ return ZYAN_STATUS_TRUE; 9868+ } 9869+ } 9870+ } 9871+ 9872+ return ZYAN_STATUS_FALSE; 9873+} 9874+ 9875+ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset) 9876+{ 9877+ if (!bitset) 9878+ { 9879+ return ZYAN_STATUS_INVALID_ARGUMENT; 9880+ } 9881+ 9882+ ZyanUSize size; 9883+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size)); 9884+ for (ZyanUSize i = 0; i < size; ++i) 9885+ { 9886+ ZyanU8* value; 9887+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value)); 9888+ if (i < (size - 1)) 9889+ { 9890+ if (*value != 0x00) 9891+ { 9892+ return ZYAN_STATUS_FALSE; 9893+ } 9894+ } else 9895+ { 9896+ const ZyanU8 mask = ~(8 - (bitset->size % 8)); 9897+ if ((*value & mask) != 0x00) 9898+ { 9899+ return ZYAN_STATUS_FALSE; 9900+ } 9901+ } 9902+ } 9903+ 9904+ return ZYAN_STATUS_TRUE; 9905+} 9906+ 9907+/* ---------------------------------------------------------------------------------------------- */ 9908+ 9909+//ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value) 9910+//{ 9911+// if (!bitset) 9912+// { 9913+// return ZYAN_STATUS_INVALID_ARGUMENT; 9914+// } 9915+// if (bitset->size > 32) 9916+// { 9917+// return ZYAN_STATUS_INVALID_OPERATION; 9918+// } 9919+// 9920+// // TODO: 9921+// 9922+// return ZYAN_STATUS_SUCCESS; 9923+//} 9924+// 9925+//ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value) 9926+//{ 9927+// if (!bitset) 9928+// { 9929+// return ZYAN_STATUS_INVALID_ARGUMENT; 9930+// } 9931+// if (bitset->size > 64) 9932+// { 9933+// return ZYAN_STATUS_INVALID_OPERATION; 9934+// } 9935+// 9936+// // TODO: 9937+// 9938+// return ZYAN_STATUS_SUCCESS; 9939+//} 9940+ 9941+/* ---------------------------------------------------------------------------------------------- */ 9942+ 9943+/* ============================================================================================== */ 9944diff --git a/zycore/src/Format.c b/zycore/src/Format.c 9945new file mode 100644 9946index 0000000..4529f88 9947--- /dev/null 9948+++ b/zycore/src/Format.c 9949@@ -0,0 +1,507 @@ 9950+/*************************************************************************************************** 9951+ 9952+ Zyan Core Library (Zycore-C) 9953+ 9954+ Original Author : Florian Bernd 9955+ 9956+ * Permission is hereby granted, free of charge, to any person obtaining a copy 9957+ * of this software and associated documentation files (the "Software"), to deal 9958+ * in the Software without restriction, including without limitation the rights 9959+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9960+ * copies of the Software, and to permit persons to whom the Software is 9961+ * furnished to do so, subject to the following conditions: 9962+ * 9963+ * The above copyright notice and this permission notice shall be included in all 9964+ * copies or substantial portions of the Software. 9965+ * 9966+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 9967+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9968+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 9969+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 9970+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 9971+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 9972+ * SOFTWARE. 9973+ 9974+***************************************************************************************************/ 9975+ 9976+#include <Zycore/Format.h> 9977+#include <Zycore/LibC.h> 9978+ 9979+/* ============================================================================================== */ 9980+/* Constants */ 9981+/* ============================================================================================== */ 9982+ 9983+/* ---------------------------------------------------------------------------------------------- */ 9984+/* Defines */ 9985+/* ---------------------------------------------------------------------------------------------- */ 9986+ 9987+#define ZYCORE_MAXCHARS_DEC_32 10 9988+#define ZYCORE_MAXCHARS_DEC_64 20 9989+#define ZYCORE_MAXCHARS_HEX_32 8 9990+#define ZYCORE_MAXCHARS_HEX_64 16 9991+ 9992+/* ---------------------------------------------------------------------------------------------- */ 9993+/* Lookup Tables */ 9994+/* ---------------------------------------------------------------------------------------------- */ 9995+ 9996+static const char* const DECIMAL_LOOKUP = 9997+ "00010203040506070809" 9998+ "10111213141516171819" 9999+ "20212223242526272829" 10000+ "30313233343536373839" 10001+ "40414243444546474849" 10002+ "50515253545556575859" 10003+ "60616263646566676869" 10004+ "70717273747576777879" 10005+ "80818283848586878889" 10006+ "90919293949596979899"; 10007+ 10008+/* ---------------------------------------------------------------------------------------------- */ 10009+/* Static strings */ 10010+/* ---------------------------------------------------------------------------------------------- */ 10011+ 10012+static const ZyanStringView STR_ADD = ZYAN_DEFINE_STRING_VIEW("+"); 10013+static const ZyanStringView STR_SUB = ZYAN_DEFINE_STRING_VIEW("-"); 10014+ 10015+/* ---------------------------------------------------------------------------------------------- */ 10016+ 10017+/* ============================================================================================== */ 10018+/* Internal macros */ 10019+/* ============================================================================================== */ 10020+ 10021+/** 10022+ * Writes a terminating '\0' character at the end of the string data. 10023+ */ 10024+#define ZYCORE_STRING_NULLTERMINATE(string) \ 10025+ *(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0'; 10026+ 10027+/* ============================================================================================== */ 10028+/* Internal functions */ 10029+/* ============================================================================================== */ 10030+ 10031+/* ---------------------------------------------------------------------------------------------- */ 10032+/* Decimal */ 10033+/* ---------------------------------------------------------------------------------------------- */ 10034+ 10035+#if defined(ZYAN_X86) || defined(ZYAN_ARM) || defined(ZYAN_EMSCRIPTEN) || defined(ZYAN_WASM) 10036+ZyanStatus ZyanStringAppendDecU32(ZyanString* string, ZyanU32 value, ZyanU8 padding_length) 10037+{ 10038+ if (!string) 10039+ { 10040+ return ZYAN_STATUS_INVALID_ARGUMENT; 10041+ } 10042+ 10043+ char buffer[ZYCORE_MAXCHARS_DEC_32]; 10044+ char *buffer_end = &buffer[ZYCORE_MAXCHARS_DEC_32]; 10045+ char *buffer_write_pointer = buffer_end; 10046+ while (value >= 100) 10047+ { 10048+ const ZyanU32 value_old = value; 10049+ buffer_write_pointer -= 2; 10050+ value /= 100; 10051+ ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[(value_old - (value * 100)) * 2], 2); 10052+ } 10053+ buffer_write_pointer -= 2; 10054+ ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[value * 2], 2); 10055+ 10056+ const ZyanUSize offset_odd = (ZyanUSize)(value < 10); 10057+ const ZyanUSize length_number = buffer_end - buffer_write_pointer - offset_odd; 10058+ const ZyanUSize length_total = ZYAN_MAX(length_number, padding_length); 10059+ const ZyanUSize length_target = string->vector.size; 10060+ 10061+ if (string->vector.size + length_total > string->vector.capacity) 10062+ { 10063+ ZYAN_CHECK(ZyanStringResize(string, string->vector.size + length_total - 1)); 10064+ } 10065+ 10066+ ZyanUSize offset_write = 0; 10067+ if (padding_length > length_number) 10068+ { 10069+ offset_write = padding_length - length_number; 10070+ ZYAN_MEMSET((char*)string->vector.data + length_target - 1, '0', offset_write); 10071+ } 10072+ 10073+ ZYAN_MEMCPY((char*)string->vector.data + length_target + offset_write - 1, 10074+ buffer_write_pointer + offset_odd, length_number); 10075+ string->vector.size = length_target + length_total; 10076+ ZYCORE_STRING_NULLTERMINATE(string); 10077+ 10078+ return ZYAN_STATUS_SUCCESS; 10079+} 10080+#endif 10081+ 10082+ZyanStatus ZyanStringAppendDecU64(ZyanString* string, ZyanU64 value, ZyanU8 padding_length) 10083+{ 10084+ if (!string) 10085+ { 10086+ return ZYAN_STATUS_INVALID_ARGUMENT; 10087+ } 10088+ 10089+ char buffer[ZYCORE_MAXCHARS_DEC_64]; 10090+ char *buffer_end = &buffer[ZYCORE_MAXCHARS_DEC_64]; 10091+ char *buffer_write_pointer = buffer_end; 10092+ while (value >= 100) 10093+ { 10094+ const ZyanU64 value_old = value; 10095+ buffer_write_pointer -= 2; 10096+ value /= 100; 10097+ ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[(value_old - (value * 100)) * 2], 2); 10098+ } 10099+ buffer_write_pointer -= 2; 10100+ ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[value * 2], 2); 10101+ 10102+ const ZyanUSize offset_odd = (ZyanUSize)(value < 10); 10103+ const ZyanUSize length_number = buffer_end - buffer_write_pointer - offset_odd; 10104+ const ZyanUSize length_total = ZYAN_MAX(length_number, padding_length); 10105+ const ZyanUSize length_target = string->vector.size; 10106+ 10107+ if (string->vector.size + length_total > string->vector.capacity) 10108+ { 10109+ ZYAN_CHECK(ZyanStringResize(string, string->vector.size + length_total - 1)); 10110+ } 10111+ 10112+ ZyanUSize offset_write = 0; 10113+ if (padding_length > length_number) 10114+ { 10115+ offset_write = padding_length - length_number; 10116+ ZYAN_MEMSET((char*)string->vector.data + length_target - 1, '0', offset_write); 10117+ } 10118+ 10119+ ZYAN_MEMCPY((char*)string->vector.data + length_target + offset_write - 1, 10120+ buffer_write_pointer + offset_odd, length_number); 10121+ string->vector.size = length_target + length_total; 10122+ ZYCORE_STRING_NULLTERMINATE(string); 10123+ 10124+ return ZYAN_STATUS_SUCCESS; 10125+} 10126+ 10127+/* ---------------------------------------------------------------------------------------------- */ 10128+/* Hexadecimal */ 10129+/* ---------------------------------------------------------------------------------------------- */ 10130+ 10131+#if defined(ZYAN_X86) || defined(ZYAN_ARM) || defined(ZYAN_EMSCRIPTEN) || defined(ZYAN_WASM) 10132+ZyanStatus ZyanStringAppendHexU32(ZyanString* string, ZyanU32 value, ZyanU8 padding_length, 10133+ ZyanBool uppercase) 10134+{ 10135+ if (!string) 10136+ { 10137+ return ZYAN_STATUS_INVALID_ARGUMENT; 10138+ } 10139+ 10140+ const ZyanUSize len = string->vector.size; 10141+ ZyanUSize remaining = string->vector.capacity - string->vector.size; 10142+ 10143+ if (remaining < (ZyanUSize)padding_length) 10144+ { 10145+ ZYAN_CHECK(ZyanStringResize(string, len + padding_length - 1)); 10146+ remaining = padding_length; 10147+ } 10148+ 10149+ if (!value) 10150+ { 10151+ const ZyanU8 n = (padding_length ? padding_length : 1); 10152+ 10153+ if (remaining < (ZyanUSize)n) 10154+ { 10155+ ZYAN_CHECK(ZyanStringResize(string, string->vector.size + n - 1)); 10156+ } 10157+ 10158+ ZYAN_MEMSET((char*)string->vector.data + len - 1, '0', n); 10159+ string->vector.size = len + n; 10160+ ZYCORE_STRING_NULLTERMINATE(string); 10161+ 10162+ return ZYAN_STATUS_SUCCESS; 10163+ } 10164+ 10165+ ZyanU8 n = 0; 10166+ char* buffer = ZYAN_NULL; 10167+ for (ZyanI8 i = ZYCORE_MAXCHARS_HEX_32 - 1; i >= 0; --i) 10168+ { 10169+ const ZyanU8 v = (value >> i * 4) & 0x0F; 10170+ if (!n) 10171+ { 10172+ if (!v) 10173+ { 10174+ continue; 10175+ } 10176+ if (remaining <= (ZyanU8)i) 10177+ { 10178+ ZYAN_CHECK(ZyanStringResize(string, string->vector.size + i)); 10179+ } 10180+ buffer = (char*)string->vector.data + len - 1; 10181+ if (padding_length > i) 10182+ { 10183+ n = padding_length - i - 1; 10184+ ZYAN_MEMSET(buffer, '0', n); 10185+ } 10186+ } 10187+ ZYAN_ASSERT(buffer); 10188+ if (uppercase) 10189+ { 10190+ buffer[n++] = "0123456789ABCDEF"[v]; 10191+ } else 10192+ { 10193+ buffer[n++] = "0123456789abcdef"[v]; 10194+ } 10195+ } 10196+ string->vector.size = len + n; 10197+ ZYCORE_STRING_NULLTERMINATE(string); 10198+ 10199+ return ZYAN_STATUS_SUCCESS; 10200+} 10201+#endif 10202+ 10203+ZyanStatus ZyanStringAppendHexU64(ZyanString* string, ZyanU64 value, ZyanU8 padding_length, 10204+ ZyanBool uppercase) 10205+{ 10206+ if (!string) 10207+ { 10208+ return ZYAN_STATUS_INVALID_ARGUMENT; 10209+ } 10210+ 10211+ const ZyanUSize len = string->vector.size; 10212+ ZyanUSize remaining = string->vector.capacity - string->vector.size; 10213+ 10214+ if (remaining < (ZyanUSize)padding_length) 10215+ { 10216+ ZYAN_CHECK(ZyanStringResize(string, len + padding_length - 1)); 10217+ remaining = padding_length; 10218+ } 10219+ 10220+ if (!value) 10221+ { 10222+ const ZyanU8 n = (padding_length ? padding_length : 1); 10223+ 10224+ if (remaining < (ZyanUSize)n) 10225+ { 10226+ ZYAN_CHECK(ZyanStringResize(string, string->vector.size + n - 1)); 10227+ } 10228+ 10229+ ZYAN_MEMSET((char*)string->vector.data + len - 1, '0', n); 10230+ string->vector.size = len + n; 10231+ ZYCORE_STRING_NULLTERMINATE(string); 10232+ 10233+ return ZYAN_STATUS_SUCCESS; 10234+ } 10235+ 10236+ ZyanU8 n = 0; 10237+ char* buffer = ZYAN_NULL; 10238+ for (ZyanI8 i = ((value & 0xFFFFFFFF00000000) ? 10239+ ZYCORE_MAXCHARS_HEX_64 : ZYCORE_MAXCHARS_HEX_32) - 1; i >= 0; --i) 10240+ { 10241+ const ZyanU8 v = (value >> i * 4) & 0x0F; 10242+ if (!n) 10243+ { 10244+ if (!v) 10245+ { 10246+ continue; 10247+ } 10248+ if (remaining <= (ZyanU8)i) 10249+ { 10250+ ZYAN_CHECK(ZyanStringResize(string, string->vector.size + i)); 10251+ } 10252+ buffer = (char*)string->vector.data + len - 1; 10253+ if (padding_length > i) 10254+ { 10255+ n = padding_length - i - 1; 10256+ ZYAN_MEMSET(buffer, '0', n); 10257+ } 10258+ } 10259+ ZYAN_ASSERT(buffer); 10260+ if (uppercase) 10261+ { 10262+ buffer[n++] = "0123456789ABCDEF"[v]; 10263+ } else 10264+ { 10265+ buffer[n++] = "0123456789abcdef"[v]; 10266+ } 10267+ } 10268+ string->vector.size = len + n; 10269+ ZYCORE_STRING_NULLTERMINATE(string); 10270+ 10271+ return ZYAN_STATUS_SUCCESS; 10272+} 10273+ 10274+/* ---------------------------------------------------------------------------------------------- */ 10275+ 10276+/* ============================================================================================== */ 10277+/* Exported functions */ 10278+/* ============================================================================================== */ 10279+ 10280+/* ---------------------------------------------------------------------------------------------- */ 10281+/* Insertion */ 10282+/* ---------------------------------------------------------------------------------------------- */ 10283+ 10284+//ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index, const char* format, ...) 10285+//{ 10286+// 10287+//} 10288+// 10289+///* ---------------------------------------------------------------------------------------------- */ 10290+// 10291+//ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value, 10292+// ZyanUSize padding_length) 10293+//{ 10294+// 10295+//} 10296+// 10297+//ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value, 10298+// ZyanUSize padding_length, ZyanBool force_sign, const ZyanString* prefix) 10299+//{ 10300+// 10301+//} 10302+// 10303+//ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value, 10304+// ZyanUSize padding_length, ZyanBool uppercase) 10305+//{ 10306+// 10307+//} 10308+// 10309+//ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value, 10310+// ZyanUSize padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix) 10311+//{ 10312+// 10313+//} 10314+ 10315+/* ---------------------------------------------------------------------------------------------- */ 10316+/* Appending */ 10317+/* ---------------------------------------------------------------------------------------------- */ 10318+ 10319+#ifndef ZYAN_NO_LIBC 10320+ 10321+ZyanStatus ZyanStringAppendFormat(ZyanString* string, const char* format, ...) 10322+{ 10323+ if (!string || !format) 10324+ { 10325+ return ZYAN_STATUS_INVALID_ARGUMENT; 10326+ } 10327+ 10328+ ZyanVAList arglist; 10329+ ZYAN_VA_START(arglist, format); 10330+ 10331+ const ZyanUSize len = string->vector.size; 10332+ 10333+ ZyanI32 w = ZYAN_VSNPRINTF((char*)string->vector.data + len - 1, 10334+ string->vector.capacity - len + 1, format, arglist); 10335+ if (w < 0) 10336+ { 10337+ ZYAN_VA_END(arglist); 10338+ return ZYAN_STATUS_FAILED; 10339+ } 10340+ if (w <= (ZyanI32)(string->vector.capacity - len)) 10341+ { 10342+ string->vector.size = len + w; 10343+ 10344+ ZYAN_VA_END(arglist); 10345+ return ZYAN_STATUS_SUCCESS; 10346+ } 10347+ 10348+ // The remaining capacity was not sufficent to fit the formatted string. Trying to resize .. 10349+ const ZyanStatus status = ZyanStringResize(string, string->vector.size + w - 1); 10350+ if (!ZYAN_SUCCESS(status)) 10351+ { 10352+ ZYAN_VA_END(arglist); 10353+ return status; 10354+ } 10355+ 10356+ w = ZYAN_VSNPRINTF((char*)string->vector.data + len - 1, 10357+ string->vector.capacity - string->vector.size + 1, format, arglist); 10358+ if (w < 0) 10359+ { 10360+ ZYAN_VA_END(arglist); 10361+ return ZYAN_STATUS_FAILED; 10362+ } 10363+ ZYAN_ASSERT(w <= (ZyanI32)(string->vector.capacity - string->vector.size)); 10364+ 10365+ ZYAN_VA_END(arglist); 10366+ return ZYAN_STATUS_SUCCESS; 10367+} 10368+ 10369+#endif // ZYAN_NO_LIBC 10370+ 10371+/* ---------------------------------------------------------------------------------------------- */ 10372+ 10373+ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length) 10374+{ 10375+#if defined(ZYAN_X64) || defined(ZYAN_AARCH64) 10376+ return ZyanStringAppendDecU64(string, value, padding_length); 10377+#else 10378+ // Working with 64-bit values is slow on non 64-bit systems 10379+ if (value & 0xFFFFFFFF00000000) 10380+ { 10381+ return ZyanStringAppendDecU64(string, value, padding_length); 10382+ } 10383+ return ZyanStringAppendDecU32(string, (ZyanU32)value, padding_length); 10384+#endif 10385+} 10386+ 10387+ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value, ZyanU8 padding_length, 10388+ ZyanBool force_sign, const ZyanStringView* prefix) 10389+{ 10390+ if (value < 0) 10391+ { 10392+ ZYAN_CHECK(ZyanStringAppend(string, &STR_SUB)); 10393+ if (prefix) 10394+ { 10395+ ZYAN_CHECK(ZyanStringAppend(string, prefix)); 10396+ } 10397+ return ZyanStringAppendDecU(string, ZyanAbsI64(value), padding_length); 10398+ } 10399+ 10400+ if (force_sign) 10401+ { 10402+ ZYAN_ASSERT(value >= 0); 10403+ ZYAN_CHECK(ZyanStringAppend(string, &STR_ADD)); 10404+ } 10405+ 10406+ if (prefix) 10407+ { 10408+ ZYAN_CHECK(ZyanStringAppend(string, prefix)); 10409+ } 10410+ return ZyanStringAppendDecU(string, value, padding_length); 10411+} 10412+ 10413+ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length, 10414+ ZyanBool uppercase) 10415+{ 10416+#if defined(ZYAN_X64) || defined(ZYAN_AARCH64) 10417+ return ZyanStringAppendHexU64(string, value, padding_length, uppercase); 10418+#else 10419+ // Working with 64-bit values is slow on non 64-bit systems 10420+ if (value & 0xFFFFFFFF00000000) 10421+ { 10422+ return ZyanStringAppendHexU64(string, value, padding_length, uppercase); 10423+ } 10424+ return ZyanStringAppendHexU32(string, (ZyanU32)value, padding_length, uppercase); 10425+#endif 10426+} 10427+ 10428+ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value, ZyanU8 padding_length, 10429+ ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix) 10430+{ 10431+ if (value < 0) 10432+ { 10433+ ZYAN_CHECK(ZyanStringAppend(string, &STR_SUB)); 10434+ if (prefix) 10435+ { 10436+ ZYAN_CHECK(ZyanStringAppend(string, prefix)); 10437+ } 10438+ return ZyanStringAppendHexU(string, ZyanAbsI64(value), padding_length, uppercase); 10439+ } 10440+ 10441+ if (force_sign) 10442+ { 10443+ ZYAN_ASSERT(value >= 0); 10444+ ZYAN_CHECK(ZyanStringAppend(string, &STR_ADD)); 10445+ } 10446+ 10447+ if (prefix) 10448+ { 10449+ ZYAN_CHECK(ZyanStringAppend(string, prefix)); 10450+ } 10451+ return ZyanStringAppendHexU(string, value, padding_length, uppercase); 10452+} 10453+ 10454+/* ---------------------------------------------------------------------------------------------- */ 10455+ 10456+/* ============================================================================================== */ 10457diff --git a/zycore/src/List.c b/zycore/src/List.c 10458new file mode 100644 10459index 0000000..e233da8 10460--- /dev/null 10461+++ b/zycore/src/List.c 10462@@ -0,0 +1,673 @@ 10463+/*************************************************************************************************** 10464+ 10465+ Zyan Core Library (Zycore-C) 10466+ 10467+ Original Author : Florian Bernd 10468+ 10469+ * Permission is hereby granted, free of charge, to any person obtaining a copy 10470+ * of this software and associated documentation files (the "Software"), to deal 10471+ * in the Software without restriction, including without limitation the rights 10472+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10473+ * copies of the Software, and to permit persons to whom the Software is 10474+ * furnished to do so, subject to the following conditions: 10475+ * 10476+ * The above copyright notice and this permission notice shall be included in all 10477+ * copies or substantial portions of the Software. 10478+ * 10479+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10480+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10481+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10482+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 10483+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10484+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 10485+ * SOFTWARE. 10486+ 10487+***************************************************************************************************/ 10488+ 10489+#include <Zycore/LibC.h> 10490+#include <Zycore/List.h> 10491+ 10492+/* ============================================================================================== */ 10493+/* Internal macros */ 10494+/* ============================================================================================== */ 10495+ 10496+/** 10497+ * Returns a pointer to the data of the given `node`. 10498+ * 10499+ * @param node A pointer to the `ZyanNodeData` struct. 10500+ * 10501+ * @return A pointer to the data of the given `node`. 10502+ */ 10503+#define ZYCORE_LIST_GET_NODE_DATA(node) \ 10504+ ((void*)(node + 1)) 10505+ 10506+/* ============================================================================================== */ 10507+/* Internal functions */ 10508+/* ============================================================================================== */ 10509+ 10510+/* ---------------------------------------------------------------------------------------------- */ 10511+/* Helper functions */ 10512+/* ---------------------------------------------------------------------------------------------- */ 10513+ 10514+/** 10515+ * Allocates memory for a new list node. 10516+ * 10517+ * @param list A pointer to the `ZyanList` instance. 10518+ * @param node Receives a pointer to the new `ZyanListNode` struct. 10519+ * 10520+ * @return A zyan status code. 10521+ */ 10522+static ZyanStatus ZyanListAllocateNode(ZyanList* list, ZyanListNode** node) 10523+{ 10524+ ZYAN_ASSERT(list); 10525+ ZYAN_ASSERT(node); 10526+ 10527+ const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL); 10528+ if (is_dynamic) 10529+ { 10530+ ZYAN_ASSERT(list->allocator->allocate); 10531+ ZYAN_CHECK(list->allocator->allocate(list->allocator, (void**)node, 10532+ sizeof(ZyanListNode) + list->element_size, 1)); 10533+ } else 10534+ { 10535+ if (list->first_unused) 10536+ { 10537+ *node = list->first_unused; 10538+ list->first_unused = (*node)->next; 10539+ } else 10540+ { 10541+ const ZyanUSize size = list->size * (sizeof(ZyanListNode) + list->element_size); 10542+ if (size + (sizeof(ZyanListNode) + list->element_size) > list->capacity) 10543+ { 10544+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 10545+ } 10546+ 10547+ *node = (ZyanListNode*)((ZyanU8*)list->buffer + size); 10548+ } 10549+ } 10550+ 10551+ return ZYAN_STATUS_SUCCESS; 10552+} 10553+ 10554+/** 10555+ * Frees memory of a node. 10556+ * 10557+ * @param list A pointer to the `ZyanList` instance. 10558+ * @param node A pointer to the `ZyanListNode` struct. 10559+ * 10560+ * @return A zyan status code. 10561+ */ 10562+static ZyanStatus ZyanListDeallocateNode(ZyanList* list, ZyanListNode* node) 10563+{ 10564+ ZYAN_ASSERT(list); 10565+ ZYAN_ASSERT(node); 10566+ 10567+ const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL); 10568+ if (is_dynamic) 10569+ { 10570+ ZYAN_ASSERT(list->allocator->deallocate); 10571+ ZYAN_CHECK(list->allocator->deallocate(list->allocator, (void*)node, 10572+ sizeof(ZyanListNode) + list->element_size, 1)); 10573+ } else 10574+ { 10575+ node->next = list->first_unused; 10576+ list->first_unused = node; 10577+ } 10578+ 10579+ return ZYAN_STATUS_SUCCESS; 10580+} 10581+ 10582+/* ---------------------------------------------------------------------------------------------- */ 10583+ 10584+/* ============================================================================================== */ 10585+/* Exported functions */ 10586+/* ============================================================================================== */ 10587+ 10588+/* ---------------------------------------------------------------------------------------------- */ 10589+/* Constructor and destructor */ 10590+/* ---------------------------------------------------------------------------------------------- */ 10591+ 10592+#ifndef ZYAN_NO_LIBC 10593+ 10594+ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size, 10595+ ZyanMemberProcedure destructor) 10596+{ 10597+ return ZyanListInitEx(list, element_size, destructor, ZyanAllocatorDefault()); 10598+} 10599+ 10600+#endif // ZYAN_NO_LIBC 10601+ 10602+ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size, ZyanMemberProcedure destructor, 10603+ ZyanAllocator* allocator) 10604+{ 10605+ if (!list || !element_size || !allocator) 10606+ { 10607+ return ZYAN_STATUS_INVALID_ARGUMENT; 10608+ } 10609+ 10610+ list->allocator = allocator; 10611+ list->size = 0; 10612+ list->element_size = element_size; 10613+ list->destructor = destructor; 10614+ list->head = ZYAN_NULL; 10615+ list->tail = ZYAN_NULL; 10616+ list->buffer = ZYAN_NULL; 10617+ list->capacity = 0; 10618+ list->first_unused = ZYAN_NULL; 10619+ 10620+ return ZYAN_STATUS_SUCCESS; 10621+} 10622+ 10623+ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size, 10624+ ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity) 10625+{ 10626+ if (!list || !element_size || !buffer || !capacity) 10627+ { 10628+ return ZYAN_STATUS_INVALID_ARGUMENT; 10629+ } 10630+ 10631+ list->allocator = ZYAN_NULL; 10632+ list->size = 0; 10633+ list->element_size = element_size; 10634+ list->destructor = destructor; 10635+ list->head = ZYAN_NULL; 10636+ list->tail = ZYAN_NULL; 10637+ list->buffer = buffer; 10638+ list->capacity = capacity; 10639+ list->first_unused = ZYAN_NULL; 10640+ 10641+ return ZYAN_STATUS_SUCCESS; 10642+} 10643+ 10644+ZyanStatus ZyanListDestroy(ZyanList* list) 10645+{ 10646+ if (!list) 10647+ { 10648+ return ZYAN_STATUS_INVALID_ARGUMENT; 10649+ } 10650+ 10651+ ZYAN_ASSERT(list->element_size); 10652+ 10653+ const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL); 10654+ ZyanListNode* node = (is_dynamic || list->destructor) ? list->head : ZYAN_NULL; 10655+ while (node) 10656+ { 10657+ if (list->destructor) 10658+ { 10659+ list->destructor(ZYCORE_LIST_GET_NODE_DATA(node)); 10660+ } 10661+ 10662+ ZyanListNode* const next = node->next; 10663+ 10664+ if (is_dynamic) 10665+ { 10666+ ZYAN_CHECK(list->allocator->deallocate(list->allocator, node, 10667+ sizeof(ZyanListNode) + list->element_size, 1)); 10668+ } 10669+ 10670+ node = next; 10671+ } 10672+ 10673+ return ZYAN_STATUS_SUCCESS; 10674+} 10675+ 10676+/* ---------------------------------------------------------------------------------------------- */ 10677+/* Duplication */ 10678+/* ---------------------------------------------------------------------------------------------- */ 10679+ 10680+ 10681+ 10682+/* ---------------------------------------------------------------------------------------------- */ 10683+/* Item access */ 10684+/* ---------------------------------------------------------------------------------------------- */ 10685+ 10686+ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node) 10687+{ 10688+ if (!list) 10689+ { 10690+ return ZYAN_STATUS_INVALID_ARGUMENT; 10691+ } 10692+ 10693+ *node = list->head; 10694+ 10695+ return ZYAN_STATUS_SUCCESS; 10696+} 10697+ 10698+ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node) 10699+{ 10700+ if (!list) 10701+ { 10702+ return ZYAN_STATUS_INVALID_ARGUMENT; 10703+ } 10704+ 10705+ *node = list->tail; 10706+ 10707+ return ZYAN_STATUS_SUCCESS; 10708+} 10709+ 10710+ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node) 10711+{ 10712+ if (!node || !*node) 10713+ { 10714+ return ZYAN_STATUS_INVALID_ARGUMENT; 10715+ } 10716+ 10717+ *node = (*node)->prev; 10718+ 10719+ return ZYAN_STATUS_SUCCESS; 10720+} 10721+ 10722+ZyanStatus ZyanListGetNextNode(const ZyanListNode** node) 10723+{ 10724+ if (!node || !*node) 10725+ { 10726+ return ZYAN_STATUS_INVALID_ARGUMENT; 10727+ } 10728+ 10729+ *node = (*node)->next; 10730+ 10731+ return ZYAN_STATUS_SUCCESS; 10732+} 10733+ 10734+const void* ZyanListGetNodeData(const ZyanListNode* node) 10735+{ 10736+ if (!node) 10737+ { 10738+ return ZYAN_NULL; 10739+ } 10740+ 10741+ return (const void*)ZYCORE_LIST_GET_NODE_DATA(node); 10742+} 10743+ 10744+ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value) 10745+{ 10746+ if (!node) 10747+ { 10748+ return ZYAN_STATUS_INVALID_ARGUMENT; 10749+ } 10750+ 10751+ *value = (const void*)ZYCORE_LIST_GET_NODE_DATA(node); 10752+ 10753+ return ZYAN_STATUS_SUCCESS; 10754+} 10755+ 10756+void* ZyanListGetNodeDataMutable(const ZyanListNode* node) 10757+{ 10758+ if (!node) 10759+ { 10760+ return ZYAN_NULL; 10761+ } 10762+ 10763+ return ZYCORE_LIST_GET_NODE_DATA(node); 10764+} 10765+ 10766+ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value) 10767+{ 10768+ if (!node) 10769+ { 10770+ return ZYAN_STATUS_INVALID_ARGUMENT; 10771+ } 10772+ 10773+ *value = ZYCORE_LIST_GET_NODE_DATA(node); 10774+ 10775+ return ZYAN_STATUS_SUCCESS; 10776+} 10777+ 10778+ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node, const void* value) 10779+{ 10780+ if (!list || !node || !value) 10781+ { 10782+ return ZYAN_STATUS_INVALID_ARGUMENT; 10783+ } 10784+ 10785+ if (list->destructor) 10786+ { 10787+ list->destructor(ZYCORE_LIST_GET_NODE_DATA(node)); 10788+ } 10789+ 10790+ ZYAN_ASSERT(list->element_size); 10791+ ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), value, list->element_size); 10792+ 10793+ return ZYAN_STATUS_SUCCESS; 10794+} 10795+ 10796+/* ---------------------------------------------------------------------------------------------- */ 10797+/* Insertion */ 10798+/* ---------------------------------------------------------------------------------------------- */ 10799+ 10800+ZyanStatus ZyanListPushBack(ZyanList* list, const void* item) 10801+{ 10802+ if (!list || !item) 10803+ { 10804+ return ZYAN_STATUS_INVALID_ARGUMENT; 10805+ } 10806+ 10807+ ZyanListNode* node; 10808+ ZYAN_CHECK(ZyanListAllocateNode(list, &node)); 10809+ node->prev = list->tail; 10810+ node->next = ZYAN_NULL; 10811+ 10812+ ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), item, list->element_size); 10813+ 10814+ if (!list->head) 10815+ { 10816+ list->head = node; 10817+ list->tail = node; 10818+ } else 10819+ { 10820+ list->tail->next = node; 10821+ list->tail = node; 10822+ } 10823+ ++list->size; 10824+ 10825+ return ZYAN_STATUS_SUCCESS; 10826+} 10827+ 10828+ZyanStatus ZyanListPushFront(ZyanList* list, const void* item) 10829+{ 10830+ if (!list || !item) 10831+ { 10832+ return ZYAN_STATUS_INVALID_ARGUMENT; 10833+ } 10834+ 10835+ ZyanListNode* node; 10836+ ZYAN_CHECK(ZyanListAllocateNode(list, &node)); 10837+ node->prev = ZYAN_NULL; 10838+ node->next = list->head; 10839+ 10840+ ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), item, list->element_size); 10841+ 10842+ if (!list->head) 10843+ { 10844+ list->head = node; 10845+ list->tail = node; 10846+ } else 10847+ { 10848+ list->head->prev= node; 10849+ list->head = node; 10850+ } 10851+ ++list->size; 10852+ 10853+ return ZYAN_STATUS_SUCCESS; 10854+} 10855+ 10856+ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item, ZyanMemberFunction constructor) 10857+{ 10858+ if (!list || !item) 10859+ { 10860+ return ZYAN_STATUS_INVALID_ARGUMENT; 10861+ } 10862+ 10863+ ZyanListNode* node; 10864+ ZYAN_CHECK(ZyanListAllocateNode(list, &node)); 10865+ node->prev = list->tail; 10866+ node->next = ZYAN_NULL; 10867+ 10868+ *item = ZYCORE_LIST_GET_NODE_DATA(node); 10869+ if (constructor) 10870+ { 10871+ constructor(*item); 10872+ } 10873+ 10874+ if (!list->head) 10875+ { 10876+ list->head = node; 10877+ list->tail = node; 10878+ } else 10879+ { 10880+ list->tail->next = node; 10881+ list->tail = node; 10882+ } 10883+ ++list->size; 10884+ 10885+ return ZYAN_STATUS_SUCCESS; 10886+} 10887+ 10888+ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item, ZyanMemberFunction constructor) 10889+{ 10890+ if (!list || !item) 10891+ { 10892+ return ZYAN_STATUS_INVALID_ARGUMENT; 10893+ } 10894+ 10895+ ZyanListNode* node; 10896+ ZYAN_CHECK(ZyanListAllocateNode(list, &node)); 10897+ node->prev = ZYAN_NULL; 10898+ node->next = list->head; 10899+ 10900+ *item = ZYCORE_LIST_GET_NODE_DATA(node); 10901+ if (constructor) 10902+ { 10903+ constructor(*item); 10904+ } 10905+ 10906+ if (!list->head) 10907+ { 10908+ list->head = node; 10909+ list->tail = node; 10910+ } else 10911+ { 10912+ list->head->prev= node; 10913+ list->head = node; 10914+ } 10915+ ++list->size; 10916+ 10917+ return ZYAN_STATUS_SUCCESS; 10918+} 10919+ 10920+/* ---------------------------------------------------------------------------------------------- */ 10921+/* Deletion */ 10922+/* ---------------------------------------------------------------------------------------------- */ 10923+ 10924+ZyanStatus ZyanListPopBack(ZyanList* list) 10925+{ 10926+ if (!list) 10927+ { 10928+ return ZYAN_STATUS_INVALID_ARGUMENT; 10929+ } 10930+ if (!list->tail) 10931+ { 10932+ return ZYAN_STATUS_INVALID_OPERATION; 10933+ } 10934+ 10935+ ZyanListNode* const node = list->tail; 10936+ 10937+ if (list->destructor) 10938+ { 10939+ list->destructor(ZYCORE_LIST_GET_NODE_DATA(node)); 10940+ } 10941+ 10942+ list->tail = node->prev; 10943+ if (list->tail) 10944+ { 10945+ list->tail->next = ZYAN_NULL; 10946+ } 10947+ if (list->head == node) 10948+ { 10949+ list->head = list->tail; 10950+ } 10951+ --list->size; 10952+ 10953+ return ZyanListDeallocateNode(list, node); 10954+} 10955+ 10956+ZyanStatus ZyanListPopFront(ZyanList* list) 10957+{ 10958+ if (!list) 10959+ { 10960+ return ZYAN_STATUS_INVALID_ARGUMENT; 10961+ } 10962+ if (!list->head) 10963+ { 10964+ return ZYAN_STATUS_INVALID_OPERATION; 10965+ } 10966+ 10967+ ZyanListNode* const node = list->head; 10968+ 10969+ if (list->destructor) 10970+ { 10971+ list->destructor(ZYCORE_LIST_GET_NODE_DATA(node)); 10972+ } 10973+ 10974+ list->head = node->next; 10975+ if (list->head) 10976+ { 10977+ list->head->prev = ZYAN_NULL; 10978+ } 10979+ if (list->tail == node) 10980+ { 10981+ list->tail = list->head; 10982+ } 10983+ --list->size; 10984+ 10985+ return ZyanListDeallocateNode(list, node); 10986+} 10987+ 10988+ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node) 10989+{ 10990+ ZYAN_UNUSED(list); 10991+ ZYAN_UNUSED(node); 10992+ return ZYAN_STATUS_SUCCESS; 10993+} 10994+ 10995+ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first, const ZyanListNode* last) 10996+{ 10997+ ZYAN_UNUSED(list); 10998+ ZYAN_UNUSED(first); 10999+ ZYAN_UNUSED(last); 11000+ return ZYAN_STATUS_SUCCESS; 11001+} 11002+ 11003+ZyanStatus ZyanListClear(ZyanList* list) 11004+{ 11005+ return ZyanListResizeEx(list, 0, ZYAN_NULL); 11006+} 11007+ 11008+/* ---------------------------------------------------------------------------------------------- */ 11009+/* Searching */ 11010+/* ---------------------------------------------------------------------------------------------- */ 11011+ 11012+ 11013+ 11014+/* ---------------------------------------------------------------------------------------------- */ 11015+/* Memory management */ 11016+/* ---------------------------------------------------------------------------------------------- */ 11017+ 11018+ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size) 11019+{ 11020+ return ZyanListResizeEx(list, size, ZYAN_NULL); 11021+} 11022+ 11023+ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer) 11024+{ 11025+ if (!list) 11026+ { 11027+ return ZYAN_STATUS_INVALID_ARGUMENT; 11028+ } 11029+ if (size == list->size) 11030+ { 11031+ return ZYAN_STATUS_SUCCESS; 11032+ } 11033+ 11034+ if (size == 0) 11035+ { 11036+ const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL); 11037+ ZyanListNode* node = (is_dynamic || list->destructor) ? list->head : ZYAN_NULL; 11038+ while (node) 11039+ { 11040+ if (list->destructor) 11041+ { 11042+ list->destructor(ZYCORE_LIST_GET_NODE_DATA(node)); 11043+ } 11044+ 11045+ ZyanListNode* const next = node->next; 11046+ 11047+ if (is_dynamic) 11048+ { 11049+ ZYAN_CHECK(list->allocator->deallocate(list->allocator, node, 11050+ sizeof(ZyanListNode) + list->element_size, 1)); 11051+ } 11052+ 11053+ node = next; 11054+ } 11055+ 11056+ list->size = 0; 11057+ list->head = 0; 11058+ list->tail = 0; 11059+ list->first_unused = ZYAN_NULL; 11060+ 11061+ return ZYAN_STATUS_SUCCESS; 11062+ } 11063+ 11064+ if (size > list->size) 11065+ { 11066+ ZyanListNode* node; 11067+ for (ZyanUSize i = list->size; i < size; ++i) 11068+ { 11069+ ZYAN_CHECK(ZyanListAllocateNode(list, &node)); 11070+ node->prev = list->tail; 11071+ node->next = ZYAN_NULL; 11072+ 11073+ if (initializer) 11074+ { 11075+ ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), initializer, list->element_size); 11076+ } 11077+ 11078+ if (!list->head) 11079+ { 11080+ list->head = node; 11081+ list->tail = node; 11082+ } else 11083+ { 11084+ list->tail->next = node; 11085+ list->tail = node; 11086+ } 11087+ 11088+ // `ZyanListAllocateNode` needs the list size 11089+ ++list->size; 11090+ } 11091+ } else 11092+ { 11093+ for (ZyanUSize i = size; i < list->size; ++i) 11094+ { 11095+ ZyanListNode* const node = list->tail; 11096+ 11097+ if (list->destructor) 11098+ { 11099+ list->destructor(ZYCORE_LIST_GET_NODE_DATA(node)); 11100+ } 11101+ 11102+ list->tail = node->prev; 11103+ if (list->tail) 11104+ { 11105+ list->tail->next = ZYAN_NULL; 11106+ } 11107+ 11108+ ZYAN_CHECK(ZyanListDeallocateNode(list, node)); 11109+ } 11110+ 11111+ list->size = size; 11112+ } 11113+ 11114+ return ZYAN_STATUS_SUCCESS; 11115+} 11116+ 11117+/* ---------------------------------------------------------------------------------------------- */ 11118+/* Information */ 11119+/* ---------------------------------------------------------------------------------------------- */ 11120+ 11121+ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size) 11122+{ 11123+ if (!list) 11124+ { 11125+ return ZYAN_STATUS_INVALID_ARGUMENT; 11126+ } 11127+ 11128+ *size = list->size; 11129+ 11130+ return ZYAN_STATUS_SUCCESS; 11131+} 11132+ 11133+/* ---------------------------------------------------------------------------------------------- */ 11134+ 11135+/* ============================================================================================== */ 11136diff --git a/zycore/src/String.c b/zycore/src/String.c 11137new file mode 100644 11138index 0000000..9dce43f 11139--- /dev/null 11140+++ b/zycore/src/String.c 11141@@ -0,0 +1,1098 @@ 11142+/*************************************************************************************************** 11143+ 11144+ Zyan Core Library (Zycore-C) 11145+ 11146+ Original Author : Florian Bernd 11147+ 11148+ * Permission is hereby granted, free of charge, to any person obtaining a copy 11149+ * of this software and associated documentation files (the "Software"), to deal 11150+ * in the Software without restriction, including without limitation the rights 11151+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11152+ * copies of the Software, and to permit persons to whom the Software is 11153+ * furnished to do so, subject to the following conditions: 11154+ * 11155+ * The above copyright notice and this permission notice shall be included in all 11156+ * copies or substantial portions of the Software. 11157+ * 11158+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11159+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11160+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 11161+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11162+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 11163+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11164+ * SOFTWARE. 11165+ 11166+***************************************************************************************************/ 11167+ 11168+#include <Zycore/String.h> 11169+#include <Zycore/LibC.h> 11170+ 11171+/* ============================================================================================== */ 11172+/* Internal macros */ 11173+/* ============================================================================================== */ 11174+ 11175+/** 11176+ * Writes a terminating '\0' character at the end of the string data. 11177+ */ 11178+#define ZYCORE_STRING_NULLTERMINATE(string) \ 11179+ *(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0'; 11180+ 11181+/** 11182+ * Checks for a terminating '\0' character at the end of the string data. 11183+ */ 11184+#define ZYCORE_STRING_ASSERT_NULLTERMINATION(string) \ 11185+ ZYAN_ASSERT(*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) == '\0'); 11186+ 11187+/* ============================================================================================== */ 11188+/* Exported functions */ 11189+/* ============================================================================================== */ 11190+ 11191+/* ---------------------------------------------------------------------------------------------- */ 11192+/* Constructor and destructor */ 11193+/* ---------------------------------------------------------------------------------------------- */ 11194+ 11195+#ifndef ZYAN_NO_LIBC 11196+ 11197+ZyanStatus ZyanStringInit(ZyanString* string, ZyanUSize capacity) 11198+{ 11199+ return ZyanStringInitEx(string, capacity, ZyanAllocatorDefault(), 11200+ ZYAN_STRING_DEFAULT_GROWTH_FACTOR, ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD); 11201+} 11202+ 11203+#endif // ZYAN_NO_LIBC 11204+ 11205+ZyanStatus ZyanStringInitEx(ZyanString* string, ZyanUSize capacity, ZyanAllocator* allocator, 11206+ ZyanU8 growth_factor, ZyanU8 shrink_threshold) 11207+{ 11208+ if (!string) 11209+ { 11210+ return ZYAN_STATUS_INVALID_ARGUMENT; 11211+ } 11212+ 11213+ string->flags = 0; 11214+ capacity = ZYAN_MAX(ZYAN_STRING_MIN_CAPACITY, capacity) + 1; 11215+ ZYAN_CHECK(ZyanVectorInitEx(&string->vector, sizeof(char), capacity, ZYAN_NULL, allocator, 11216+ growth_factor, shrink_threshold)); 11217+ ZYAN_ASSERT(string->vector.capacity >= capacity); 11218+ // Some of the string code relies on `sizeof(char) == 1` 11219+ ZYAN_ASSERT(string->vector.element_size == 1); 11220+ 11221+ *(char*)string->vector.data = '\0'; 11222+ ++string->vector.size; 11223+ 11224+ return ZYAN_STATUS_SUCCESS; 11225+} 11226+ 11227+ZyanStatus ZyanStringInitCustomBuffer(ZyanString* string, char* buffer, ZyanUSize capacity) 11228+{ 11229+ if (!string || !capacity) 11230+ { 11231+ return ZYAN_STATUS_INVALID_ARGUMENT; 11232+ } 11233+ 11234+ string->flags = ZYAN_STRING_HAS_FIXED_CAPACITY; 11235+ ZYAN_CHECK(ZyanVectorInitCustomBuffer(&string->vector, sizeof(char), (void*)buffer, capacity, 11236+ ZYAN_NULL)); 11237+ ZYAN_ASSERT(string->vector.capacity == capacity); 11238+ // Some of the string code relies on `sizeof(char) == 1` 11239+ ZYAN_ASSERT(string->vector.element_size == 1); 11240+ 11241+ *(char*)string->vector.data = '\0'; 11242+ ++string->vector.size; 11243+ 11244+ return ZYAN_STATUS_SUCCESS; 11245+} 11246+ 11247+ZyanStatus ZyanStringDestroy(ZyanString* string) 11248+{ 11249+ if (!string) 11250+ { 11251+ return ZYAN_STATUS_INVALID_ARGUMENT; 11252+ } 11253+ if (string->flags & ZYAN_STRING_HAS_FIXED_CAPACITY) 11254+ { 11255+ return ZYAN_STATUS_SUCCESS; 11256+ } 11257+ 11258+ return ZyanVectorDestroy(&string->vector); 11259+} 11260+ 11261+/* ---------------------------------------------------------------------------------------------- */ 11262+/* Duplication */ 11263+/* ---------------------------------------------------------------------------------------------- */ 11264+ 11265+#ifndef ZYAN_NO_LIBC 11266+ 11267+ZyanStatus ZyanStringDuplicate(ZyanString* destination, const ZyanStringView* source, 11268+ ZyanUSize capacity) 11269+{ 11270+ return ZyanStringDuplicateEx(destination, source, capacity, ZyanAllocatorDefault(), 11271+ ZYAN_STRING_DEFAULT_GROWTH_FACTOR, ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD); 11272+} 11273+ 11274+#endif // ZYAN_NO_LIBC 11275+ 11276+ZyanStatus ZyanStringDuplicateEx(ZyanString* destination, const ZyanStringView* source, 11277+ ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold) 11278+{ 11279+ if (!source || !source->string.vector.size) 11280+ { 11281+ return ZYAN_STATUS_INVALID_ARGUMENT; 11282+ } 11283+ 11284+ const ZyanUSize len = source->string.vector.size; 11285+ capacity = ZYAN_MAX(capacity, len - 1); 11286+ ZYAN_CHECK(ZyanStringInitEx(destination, capacity, allocator, growth_factor, shrink_threshold)); 11287+ ZYAN_ASSERT(destination->vector.capacity >= len); 11288+ 11289+ ZYAN_MEMCPY(destination->vector.data, source->string.vector.data, 11290+ source->string.vector.size - 1); 11291+ destination->vector.size = len; 11292+ ZYCORE_STRING_NULLTERMINATE(destination); 11293+ 11294+ return ZYAN_STATUS_SUCCESS; 11295+} 11296+ 11297+ZyanStatus ZyanStringDuplicateCustomBuffer(ZyanString* destination, const ZyanStringView* source, 11298+ char* buffer, ZyanUSize capacity) 11299+{ 11300+ if (!source || !source->string.vector.size) 11301+ { 11302+ return ZYAN_STATUS_INVALID_ARGUMENT; 11303+ } 11304+ 11305+ const ZyanUSize len = source->string.vector.size; 11306+ if (capacity < len) 11307+ { 11308+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 11309+ } 11310+ 11311+ ZYAN_CHECK(ZyanStringInitCustomBuffer(destination, buffer, capacity)); 11312+ ZYAN_ASSERT(destination->vector.capacity >= len); 11313+ 11314+ ZYAN_MEMCPY(destination->vector.data, source->string.vector.data, 11315+ source->string.vector.size - 1); 11316+ destination->vector.size = len; 11317+ ZYCORE_STRING_NULLTERMINATE(destination); 11318+ 11319+ return ZYAN_STATUS_SUCCESS; 11320+} 11321+ 11322+/* ---------------------------------------------------------------------------------------------- */ 11323+/* Concatenation */ 11324+/* ---------------------------------------------------------------------------------------------- */ 11325+ 11326+#ifndef ZYAN_NO_LIBC 11327+ 11328+ZyanStatus ZyanStringConcat(ZyanString* destination, const ZyanStringView* s1, 11329+ const ZyanStringView* s2, ZyanUSize capacity) 11330+{ 11331+ return ZyanStringConcatEx(destination, s1, s2, capacity, ZyanAllocatorDefault(), 11332+ ZYAN_STRING_DEFAULT_GROWTH_FACTOR, ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD); 11333+} 11334+ 11335+#endif // ZYAN_NO_LIBC 11336+ 11337+ZyanStatus ZyanStringConcatEx(ZyanString* destination, const ZyanStringView* s1, 11338+ const ZyanStringView* s2, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, 11339+ ZyanU8 shrink_threshold) 11340+{ 11341+ if (!s1 || !s2 || !s1->string.vector.size || !s2->string.vector.size) 11342+ { 11343+ return ZYAN_STATUS_INVALID_ARGUMENT; 11344+ } 11345+ 11346+ const ZyanUSize len = s1->string.vector.size + s2->string.vector.size - 1; 11347+ capacity = ZYAN_MAX(capacity, len - 1); 11348+ ZYAN_CHECK(ZyanStringInitEx(destination, capacity, allocator, growth_factor, shrink_threshold)); 11349+ ZYAN_ASSERT(destination->vector.capacity >= len); 11350+ 11351+ ZYAN_MEMCPY(destination->vector.data, s1->string.vector.data, s1->string.vector.size - 1); 11352+ ZYAN_MEMCPY((char*)destination->vector.data + s1->string.vector.size - 1, 11353+ s2->string.vector.data, s2->string.vector.size - 1); 11354+ destination->vector.size = len; 11355+ ZYCORE_STRING_NULLTERMINATE(destination); 11356+ 11357+ return ZYAN_STATUS_SUCCESS; 11358+} 11359+ 11360+ZyanStatus ZyanStringConcatCustomBuffer(ZyanString* destination, const ZyanStringView* s1, 11361+ const ZyanStringView* s2, char* buffer, ZyanUSize capacity) 11362+{ 11363+ if (!s1 || !s2 || !s1->string.vector.size || !s2->string.vector.size) 11364+ { 11365+ return ZYAN_STATUS_INVALID_ARGUMENT; 11366+ } 11367+ 11368+ const ZyanUSize len = s1->string.vector.size + s2->string.vector.size - 1; 11369+ if (capacity < len) 11370+ { 11371+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 11372+ } 11373+ 11374+ ZYAN_CHECK(ZyanStringInitCustomBuffer(destination, buffer, capacity)); 11375+ ZYAN_ASSERT(destination->vector.capacity >= len); 11376+ 11377+ ZYAN_MEMCPY(destination->vector.data, s1->string.vector.data, s1->string.vector.size - 1); 11378+ ZYAN_MEMCPY((char*)destination->vector.data + s1->string.vector.size - 1, 11379+ s2->string.vector.data, s2->string.vector.size - 1); 11380+ destination->vector.size = len; 11381+ ZYCORE_STRING_NULLTERMINATE(destination); 11382+ 11383+ return ZYAN_STATUS_SUCCESS; 11384+} 11385+ 11386+/* ---------------------------------------------------------------------------------------------- */ 11387+/* Views */ 11388+/* ---------------------------------------------------------------------------------------------- */ 11389+ 11390+ZyanStatus ZyanStringViewInsideView(ZyanStringView* view, const ZyanStringView* source) 11391+{ 11392+ if (!view || !source) 11393+ { 11394+ return ZYAN_STATUS_INVALID_ARGUMENT; 11395+ } 11396+ 11397+ view->string.vector.data = source->string.vector.data; 11398+ view->string.vector.size = source->string.vector.size; 11399+ 11400+ return ZYAN_STATUS_SUCCESS; 11401+} 11402+ 11403+ZyanStatus ZyanStringViewInsideViewEx(ZyanStringView* view, const ZyanStringView* source, 11404+ ZyanUSize index, ZyanUSize count) 11405+{ 11406+ if (!view || !source) 11407+ { 11408+ return ZYAN_STATUS_INVALID_ARGUMENT; 11409+ } 11410+ 11411+ if (index + count >= source->string.vector.size) 11412+ { 11413+ return ZYAN_STATUS_OUT_OF_RANGE; 11414+ } 11415+ 11416+ view->string.vector.data = (void*)((char*)source->string.vector.data + index); 11417+ view->string.vector.size = count; 11418+ 11419+ return ZYAN_STATUS_SUCCESS; 11420+} 11421+ 11422+ZyanStatus ZyanStringViewInsideBuffer(ZyanStringView* view, const char* string) 11423+{ 11424+ if (!view || !string) 11425+ { 11426+ return ZYAN_STATUS_INVALID_ARGUMENT; 11427+ } 11428+ 11429+ view->string.vector.data = (void*)string; 11430+ view->string.vector.size = ZYAN_STRLEN(string) + 1; 11431+ 11432+ return ZYAN_STATUS_SUCCESS; 11433+} 11434+ 11435+ZyanStatus ZyanStringViewInsideBufferEx(ZyanStringView* view, const char* buffer, ZyanUSize length) 11436+{ 11437+ if (!view || !buffer || !length) 11438+ { 11439+ return ZYAN_STATUS_INVALID_ARGUMENT; 11440+ } 11441+ 11442+ view->string.vector.data = (void*)buffer; 11443+ view->string.vector.size = length + 1; 11444+ 11445+ return ZYAN_STATUS_SUCCESS; 11446+} 11447+ 11448+ZyanStatus ZyanStringViewGetSize(const ZyanStringView* view, ZyanUSize* size) 11449+{ 11450+ if (!view || !size) 11451+ { 11452+ return ZYAN_STATUS_INVALID_ARGUMENT; 11453+ } 11454+ 11455+ ZYAN_ASSERT(view->string.vector.size >= 1); 11456+ *size = view->string.vector.size - 1; 11457+ 11458+ return ZYAN_STATUS_SUCCESS; 11459+} 11460+ 11461+ZYCORE_EXPORT ZyanStatus ZyanStringViewGetData(const ZyanStringView* view, const char** buffer) 11462+{ 11463+ if (!view || !buffer) 11464+ { 11465+ return ZYAN_STATUS_INVALID_ARGUMENT; 11466+ } 11467+ 11468+ *buffer = view->string.vector.data; 11469+ 11470+ return ZYAN_STATUS_SUCCESS; 11471+} 11472+ 11473+/* ---------------------------------------------------------------------------------------------- */ 11474+/* Character access */ 11475+/* ---------------------------------------------------------------------------------------------- */ 11476+ 11477+ZyanStatus ZyanStringGetChar(const ZyanStringView* string, ZyanUSize index, char* value) 11478+{ 11479+ if (!string || !value) 11480+ { 11481+ return ZYAN_STATUS_INVALID_ARGUMENT; 11482+ } 11483+ 11484+ // Don't allow direct access to the terminating '\0' character 11485+ if (index + 1 >= string->string.vector.size) 11486+ { 11487+ return ZYAN_STATUS_OUT_OF_RANGE; 11488+ } 11489+ 11490+ const char* chr; 11491+ ZYAN_CHECK(ZyanVectorGetPointer(&string->string.vector, index, (const void**)&chr)); 11492+ *value = *chr; 11493+ 11494+ return ZYAN_STATUS_SUCCESS; 11495+} 11496+ 11497+ZyanStatus ZyanStringGetCharMutable(ZyanString* string, ZyanUSize index, char** value) 11498+{ 11499+ if (!string) 11500+ { 11501+ return ZYAN_STATUS_INVALID_ARGUMENT; 11502+ } 11503+ 11504+ // Don't allow direct access to the terminating '\0' character 11505+ if (index + 1 >= string->vector.size) 11506+ { 11507+ return ZYAN_STATUS_OUT_OF_RANGE; 11508+ } 11509+ 11510+ return ZyanVectorGetPointerMutable(&string->vector, index, (void**)value); 11511+} 11512+ 11513+ZyanStatus ZyanStringSetChar(ZyanString* string, ZyanUSize index, char value) 11514+{ 11515+ if (!string) 11516+ { 11517+ return ZYAN_STATUS_INVALID_ARGUMENT; 11518+ } 11519+ 11520+ // Don't allow direct access to the terminating '\0' character 11521+ if (index + 1 >= string->vector.size) 11522+ { 11523+ return ZYAN_STATUS_OUT_OF_RANGE; 11524+ } 11525+ 11526+ return ZyanVectorSet(&string->vector, index, (void*)&value); 11527+} 11528+ 11529+/* ---------------------------------------------------------------------------------------------- */ 11530+/* Insertion */ 11531+/* ---------------------------------------------------------------------------------------------- */ 11532+ 11533+ZyanStatus ZyanStringInsert(ZyanString* destination, ZyanUSize index, const ZyanStringView* source) 11534+{ 11535+ if (!destination || !source || !source->string.vector.size) 11536+ { 11537+ return ZYAN_STATUS_INVALID_ARGUMENT; 11538+ } 11539+ 11540+ if (index == destination->vector.size) 11541+ { 11542+ return ZyanStringAppend(destination, source); 11543+ } 11544+ 11545+ // Don't allow insertion after the terminating '\0' character 11546+ if (index >= destination->vector.size) 11547+ { 11548+ return ZYAN_STATUS_OUT_OF_RANGE; 11549+ } 11550+ 11551+ ZYAN_CHECK(ZyanVectorInsertRange(&destination->vector, index, source->string.vector.data, 11552+ source->string.vector.size - 1)); 11553+ ZYCORE_STRING_ASSERT_NULLTERMINATION(destination); 11554+ 11555+ return ZYAN_STATUS_SUCCESS; 11556+} 11557+ 11558+ZyanStatus ZyanStringInsertEx(ZyanString* destination, ZyanUSize destination_index, 11559+ const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count) 11560+{ 11561+ if (!destination || !source || !source->string.vector.size) 11562+ { 11563+ return ZYAN_STATUS_INVALID_ARGUMENT; 11564+ } 11565+ 11566+ if (destination_index == destination->vector.size) 11567+ { 11568+ return ZyanStringAppendEx(destination, source, source_index, count); 11569+ } 11570+ 11571+ // Don't allow insertion after the terminating '\0' character 11572+ if (destination_index >= destination->vector.size) 11573+ { 11574+ return ZYAN_STATUS_OUT_OF_RANGE; 11575+ } 11576+ 11577+ // Don't allow access to the terminating '\0' character 11578+ if (source_index + count >= source->string.vector.size) 11579+ { 11580+ return ZYAN_STATUS_OUT_OF_RANGE; 11581+ } 11582+ 11583+ ZYAN_CHECK(ZyanVectorInsertRange(&destination->vector, destination_index, 11584+ (char*)source->string.vector.data + source_index, count)); 11585+ ZYCORE_STRING_ASSERT_NULLTERMINATION(destination); 11586+ 11587+ return ZYAN_STATUS_SUCCESS; 11588+} 11589+ 11590+/* ---------------------------------------------------------------------------------------------- */ 11591+/* Appending */ 11592+/* ---------------------------------------------------------------------------------------------- */ 11593+ 11594+ZyanStatus ZyanStringAppend(ZyanString* destination, const ZyanStringView* source) 11595+{ 11596+ if (!destination || !source || !source->string.vector.size) 11597+ { 11598+ return ZYAN_STATUS_INVALID_ARGUMENT; 11599+ } 11600+ 11601+ const ZyanUSize len = destination->vector.size; 11602+ ZYAN_CHECK(ZyanVectorResize(&destination->vector, len + source->string.vector.size - 1)); 11603+ ZYAN_MEMCPY((char*)destination->vector.data + len - 1, source->string.vector.data, 11604+ source->string.vector.size - 1); 11605+ ZYCORE_STRING_NULLTERMINATE(destination); 11606+ 11607+ return ZYAN_STATUS_SUCCESS; 11608+} 11609+ 11610+ZyanStatus ZyanStringAppendEx(ZyanString* destination, const ZyanStringView* source, 11611+ ZyanUSize source_index, ZyanUSize count) 11612+{ 11613+ if (!destination || !source || !source->string.vector.size) 11614+ { 11615+ return ZYAN_STATUS_INVALID_ARGUMENT; 11616+ } 11617+ 11618+ // Don't allow access to the terminating '\0' character 11619+ if (source_index + count >= source->string.vector.size) 11620+ { 11621+ return ZYAN_STATUS_OUT_OF_RANGE; 11622+ } 11623+ 11624+ const ZyanUSize len = destination->vector.size; 11625+ ZYAN_CHECK(ZyanVectorResize(&destination->vector, len + count)); 11626+ ZYAN_MEMCPY((char*)destination->vector.data + len - 1, 11627+ (const char*)source->string.vector.data + source_index, count); 11628+ ZYCORE_STRING_NULLTERMINATE(destination); 11629+ 11630+ return ZYAN_STATUS_SUCCESS; 11631+} 11632+ 11633+/* ---------------------------------------------------------------------------------------------- */ 11634+/* Deletion */ 11635+/* ---------------------------------------------------------------------------------------------- */ 11636+ 11637+ZyanStatus ZyanStringDelete(ZyanString* string, ZyanUSize index, ZyanUSize count) 11638+{ 11639+ if (!string) 11640+ { 11641+ return ZYAN_STATUS_INVALID_ARGUMENT; 11642+ } 11643+ 11644+ // Don't allow removal of the terminating '\0' character 11645+ if (index + count >= string->vector.size) 11646+ { 11647+ return ZYAN_STATUS_OUT_OF_RANGE; 11648+ } 11649+ 11650+ ZYAN_CHECK(ZyanVectorDeleteRange(&string->vector, index, count)); 11651+ ZYCORE_STRING_NULLTERMINATE(string); 11652+ 11653+ return ZYAN_STATUS_SUCCESS; 11654+} 11655+ 11656+ZyanStatus ZyanStringTruncate(ZyanString* string, ZyanUSize index) 11657+{ 11658+ if (!string) 11659+ { 11660+ return ZYAN_STATUS_INVALID_ARGUMENT; 11661+ } 11662+ 11663+ // Don't allow removal of the terminating '\0' character 11664+ if (index >= string->vector.size) 11665+ { 11666+ return ZYAN_STATUS_OUT_OF_RANGE; 11667+ } 11668+ 11669+ ZYAN_CHECK(ZyanVectorDeleteRange(&string->vector, index, string->vector.size - index - 1)); 11670+ ZYCORE_STRING_NULLTERMINATE(string); 11671+ 11672+ return ZYAN_STATUS_SUCCESS; 11673+} 11674+ 11675+ZyanStatus ZyanStringClear(ZyanString* string) 11676+{ 11677+ if (!string) 11678+ { 11679+ return ZYAN_STATUS_INVALID_ARGUMENT; 11680+ } 11681+ 11682+ ZYAN_CHECK(ZyanVectorClear(&string->vector)); 11683+ // `ZyanVector` guarantees a minimum capacity of 1 element/character 11684+ ZYAN_ASSERT(string->vector.capacity >= 1); 11685+ 11686+ *(char*)string->vector.data = '\0'; 11687+ string->vector.size++; 11688+ 11689+ return ZYAN_STATUS_SUCCESS; 11690+} 11691+ 11692+/* ---------------------------------------------------------------------------------------------- */ 11693+/* Searching */ 11694+/* ---------------------------------------------------------------------------------------------- */ 11695+ 11696+ZyanStatus ZyanStringLPos(const ZyanStringView* haystack, const ZyanStringView* needle, 11697+ ZyanISize* found_index) 11698+{ 11699+ if (!haystack) 11700+ { 11701+ return ZYAN_STATUS_INVALID_ARGUMENT; 11702+ } 11703+ 11704+ return ZyanStringLPosEx(haystack, needle, found_index, 0, haystack->string.vector.size - 1); 11705+} 11706+ 11707+ZyanStatus ZyanStringLPosEx(const ZyanStringView* haystack, const ZyanStringView* needle, 11708+ ZyanISize* found_index, ZyanUSize index, ZyanUSize count) 11709+{ 11710+ if (!haystack || !needle || !found_index) 11711+ { 11712+ return ZYAN_STATUS_INVALID_ARGUMENT; 11713+ } 11714+ 11715+ // Don't allow access to the terminating '\0' character 11716+ if (index + count >= haystack->string.vector.size) 11717+ { 11718+ return ZYAN_STATUS_OUT_OF_RANGE; 11719+ } 11720+ 11721+ if ((haystack->string.vector.size == 1) || (needle->string.vector.size == 1) || 11722+ (haystack->string.vector.size < needle->string.vector.size)) 11723+ { 11724+ *found_index = -1; 11725+ return ZYAN_STATUS_FALSE; 11726+ } 11727+ 11728+ const char* s = (const char*)haystack->string.vector.data + index; 11729+ const char* b = (const char*)needle->string.vector.data; 11730+ for (; s + 1 < (const char*)haystack->string.vector.data + haystack->string.vector.size; ++s) 11731+ { 11732+ if (*s != *b) 11733+ { 11734+ continue; 11735+ } 11736+ const char* a = s; 11737+ for (;;) 11738+ { 11739+ if ((ZyanUSize)(a - (const char*)haystack->string.vector.data) > index + count) 11740+ { 11741+ *found_index = -1; 11742+ return ZYAN_STATUS_FALSE; 11743+ } 11744+ if (*b == 0) 11745+ { 11746+ *found_index = (ZyanISize)(s - (const char*)haystack->string.vector.data); 11747+ return ZYAN_STATUS_TRUE; 11748+ } 11749+ if (*a++ != *b++) 11750+ { 11751+ break; 11752+ } 11753+ } 11754+ b = (char*)needle->string.vector.data; 11755+ } 11756+ 11757+ *found_index = -1; 11758+ return ZYAN_STATUS_FALSE; 11759+} 11760+ 11761+ZyanStatus ZyanStringLPosI(const ZyanStringView* haystack, const ZyanStringView* needle, 11762+ ZyanISize* found_index) 11763+{ 11764+ if (!haystack) 11765+ { 11766+ return ZYAN_STATUS_INVALID_ARGUMENT; 11767+ } 11768+ 11769+ return ZyanStringLPosIEx(haystack, needle, found_index, 0, haystack->string.vector.size - 1); 11770+} 11771+ 11772+ZyanStatus ZyanStringLPosIEx(const ZyanStringView* haystack, const ZyanStringView* needle, 11773+ ZyanISize* found_index, ZyanUSize index, ZyanUSize count) 11774+{ 11775+ // This solution assumes that characters are represented using ASCII representation, i.e., 11776+ // codes for 'a', 'b', 'c', .. 'z' are 97, 98, 99, .. 122 respectively. And codes for 'A', 11777+ // 'B', 'C', .. 'Z' are 65, 66, .. 95 respectively. 11778+ 11779+ if (!haystack || !needle || !found_index) 11780+ { 11781+ return ZYAN_STATUS_INVALID_ARGUMENT; 11782+ } 11783+ 11784+ // Don't allow access to the terminating '\0' character 11785+ if (index + count >= haystack->string.vector.size) 11786+ { 11787+ return ZYAN_STATUS_OUT_OF_RANGE; 11788+ } 11789+ 11790+ if ((haystack->string.vector.size == 1) || (needle->string.vector.size == 1) || 11791+ (haystack->string.vector.size < needle->string.vector.size)) 11792+ { 11793+ *found_index = -1; 11794+ return ZYAN_STATUS_FALSE; 11795+ } 11796+ 11797+ const char* s = (const char*)haystack->string.vector.data + index; 11798+ const char* b = (const char*)needle->string.vector.data; 11799+ for (; s + 1 < (const char*)haystack->string.vector.data + haystack->string.vector.size; ++s) 11800+ { 11801+ if ((*s != *b) && ((*s ^ 32) != *b)) 11802+ { 11803+ continue; 11804+ } 11805+ const char* a = s; 11806+ for (;;) 11807+ { 11808+ if ((ZyanUSize)(a - (const char*)haystack->string.vector.data) > index + count) 11809+ { 11810+ *found_index = -1; 11811+ return ZYAN_STATUS_FALSE; 11812+ } 11813+ if (*b == 0) 11814+ { 11815+ *found_index = (ZyanISize)(s - (const char*)haystack->string.vector.data); 11816+ return ZYAN_STATUS_TRUE; 11817+ } 11818+ const char c1 = *a++; 11819+ const char c2 = *b++; 11820+ if ((c1 != c2) && ((c1 ^ 32) != c2)) 11821+ { 11822+ break; 11823+ } 11824+ } 11825+ b = (char*)needle->string.vector.data; 11826+ } 11827+ 11828+ *found_index = -1; 11829+ return ZYAN_STATUS_FALSE; 11830+} 11831+ 11832+ZyanStatus ZyanStringRPos(const ZyanStringView* haystack, const ZyanStringView* needle, 11833+ ZyanISize* found_index) 11834+{ 11835+ if (!haystack) 11836+ { 11837+ return ZYAN_STATUS_INVALID_ARGUMENT; 11838+ } 11839+ 11840+ return ZyanStringRPosEx(haystack, needle, found_index, haystack->string.vector.size - 1, 11841+ haystack->string.vector.size - 1); 11842+} 11843+ 11844+ZyanStatus ZyanStringRPosEx(const ZyanStringView* haystack, const ZyanStringView* needle, 11845+ ZyanISize* found_index, ZyanUSize index, ZyanUSize count) 11846+{ 11847+ if (!haystack || !needle || !found_index) 11848+ { 11849+ return ZYAN_STATUS_INVALID_ARGUMENT; 11850+ } 11851+ 11852+ // Don't allow access to the terminating '\0' character 11853+ if ((index >= haystack->string.vector.size) || (count > index)) 11854+ { 11855+ return ZYAN_STATUS_OUT_OF_RANGE; 11856+ } 11857+ 11858+ if (!index || !count || 11859+ (haystack->string.vector.size == 1) || (needle->string.vector.size == 1) || 11860+ (haystack->string.vector.size < needle->string.vector.size)) 11861+ { 11862+ *found_index = -1; 11863+ return ZYAN_STATUS_FALSE; 11864+ } 11865+ 11866+ const char* s = (const char*)haystack->string.vector.data + index - 1; 11867+ const char* b = (const char*)needle->string.vector.data + needle->string.vector.size - 2; 11868+ for (; s >= (const char*)haystack->string.vector.data; --s) 11869+ { 11870+ if (*s != *b) 11871+ { 11872+ continue; 11873+ } 11874+ const char* a = s; 11875+ for (;;) 11876+ { 11877+ if (b < (const char*)needle->string.vector.data) 11878+ { 11879+ *found_index = (ZyanISize)(a - (const char*)haystack->string.vector.data + 1); 11880+ return ZYAN_STATUS_TRUE; 11881+ } 11882+ if (a < (const char*)haystack->string.vector.data + index - count) 11883+ { 11884+ *found_index = -1; 11885+ return ZYAN_STATUS_FALSE; 11886+ } 11887+ if (*a-- != *b--) 11888+ { 11889+ break; 11890+ } 11891+ } 11892+ b = (char*)needle->string.vector.data + needle->string.vector.size - 2; 11893+ } 11894+ 11895+ *found_index = -1; 11896+ return ZYAN_STATUS_FALSE; 11897+} 11898+ 11899+ZyanStatus ZyanStringRPosI(const ZyanStringView* haystack, const ZyanStringView* needle, 11900+ ZyanISize* found_index) 11901+{ 11902+ if (!haystack) 11903+ { 11904+ return ZYAN_STATUS_INVALID_ARGUMENT; 11905+ } 11906+ 11907+ return ZyanStringRPosIEx(haystack, needle, found_index, haystack->string.vector.size - 1, 11908+ haystack->string.vector.size - 1); 11909+} 11910+ 11911+ZyanStatus ZyanStringRPosIEx(const ZyanStringView* haystack, const ZyanStringView* needle, 11912+ ZyanISize* found_index, ZyanUSize index, ZyanUSize count) 11913+{ 11914+ // This solution assumes that characters are represented using ASCII representation, i.e., 11915+ // codes for 'a', 'b', 'c', .. 'z' are 97, 98, 99, .. 122 respectively. And codes for 'A', 11916+ // 'B', 'C', .. 'Z' are 65, 66, .. 95 respectively. 11917+ 11918+ if (!haystack || !needle || !found_index) 11919+ { 11920+ return ZYAN_STATUS_INVALID_ARGUMENT; 11921+ } 11922+ 11923+ // Don't allow access to the terminating '\0' character 11924+ if ((index >= haystack->string.vector.size) || (count > index)) 11925+ { 11926+ return ZYAN_STATUS_OUT_OF_RANGE; 11927+ } 11928+ 11929+ if (!index || !count || 11930+ (haystack->string.vector.size == 1) || (needle->string.vector.size == 1) || 11931+ (haystack->string.vector.size < needle->string.vector.size)) 11932+ { 11933+ *found_index = -1; 11934+ return ZYAN_STATUS_FALSE; 11935+ } 11936+ 11937+ const char* s = (const char*)haystack->string.vector.data + index - 1; 11938+ const char* b = (const char*)needle->string.vector.data + needle->string.vector.size - 2; 11939+ for (; s >= (const char*)haystack->string.vector.data; --s) 11940+ { 11941+ if ((*s != *b) && ((*s ^ 32) != *b)) 11942+ { 11943+ continue; 11944+ } 11945+ const char* a = s; 11946+ for (;;) 11947+ { 11948+ if (b < (const char*)needle->string.vector.data) 11949+ { 11950+ *found_index = (ZyanISize)(a - (const char*)haystack->string.vector.data + 1); 11951+ return ZYAN_STATUS_TRUE; 11952+ } 11953+ if (a < (const char*)haystack->string.vector.data + index - count) 11954+ { 11955+ *found_index = -1; 11956+ return ZYAN_STATUS_FALSE; 11957+ } 11958+ const char c1 = *a--; 11959+ const char c2 = *b--; 11960+ if ((c1 != c2) && ((c1 ^ 32) != c2)) 11961+ { 11962+ break; 11963+ } 11964+ } 11965+ b = (char*)needle->string.vector.data + needle->string.vector.size - 2; 11966+ } 11967+ 11968+ *found_index = -1; 11969+ return ZYAN_STATUS_FALSE; 11970+} 11971+ 11972+/* ---------------------------------------------------------------------------------------------- */ 11973+/* Comparing */ 11974+/* ---------------------------------------------------------------------------------------------- */ 11975+ 11976+ZyanStatus ZyanStringCompare(const ZyanStringView* s1, const ZyanStringView* s2, ZyanI32* result) 11977+{ 11978+ if (!s1 || !s2) 11979+ { 11980+ return ZYAN_STATUS_INVALID_ARGUMENT; 11981+ } 11982+ 11983+ if (s1->string.vector.size < s2->string.vector.size) 11984+ { 11985+ *result = -1; 11986+ return ZYAN_STATUS_FALSE; 11987+ } 11988+ if (s1->string.vector.size > s2->string.vector.size) 11989+ { 11990+ *result = 1; 11991+ return ZYAN_STATUS_FALSE; 11992+ } 11993+ 11994+ const char* const a = (char*)s1->string.vector.data; 11995+ const char* const b = (char*)s2->string.vector.data; 11996+ ZyanUSize i; 11997+ for (i = 0; (i + 1 < s1->string.vector.size) && (i + 1 < s2->string.vector.size); ++i) 11998+ { 11999+ if (a[i] == b[i]) 12000+ { 12001+ continue; 12002+ } 12003+ break; 12004+ } 12005+ 12006+ if (a[i] == b[i]) 12007+ { 12008+ *result = 0; 12009+ return ZYAN_STATUS_TRUE; 12010+ } 12011+ 12012+ if ((a[i] | 32) < (b[i] | 32)) 12013+ { 12014+ *result = -1; 12015+ return ZYAN_STATUS_FALSE; 12016+ } 12017+ 12018+ *result = 1; 12019+ return ZYAN_STATUS_FALSE; 12020+} 12021+ 12022+ZyanStatus ZyanStringCompareI(const ZyanStringView* s1, const ZyanStringView* s2, ZyanI32* result) 12023+{ 12024+ // This solution assumes that characters are represented using ASCII representation, i.e., 12025+ // codes for 'a', 'b', 'c', .. 'z' are 97, 98, 99, .. 122 respectively. And codes for 'A', 12026+ // 'B', 'C', .. 'Z' are 65, 66, .. 95 respectively. 12027+ 12028+ if (!s1 || !s2) 12029+ { 12030+ return ZYAN_STATUS_INVALID_ARGUMENT; 12031+ } 12032+ 12033+ if (s1->string.vector.size < s2->string.vector.size) 12034+ { 12035+ *result = -1; 12036+ return ZYAN_STATUS_FALSE; 12037+ } 12038+ if (s1->string.vector.size > s2->string.vector.size) 12039+ { 12040+ *result = 1; 12041+ return ZYAN_STATUS_FALSE; 12042+ } 12043+ 12044+ const char* const a = (char*)s1->string.vector.data; 12045+ const char* const b = (char*)s2->string.vector.data; 12046+ ZyanUSize i; 12047+ for (i = 0; (i + 1 < s1->string.vector.size) && (i + 1 < s2->string.vector.size); ++i) 12048+ { 12049+ if ((a[i] == b[i]) || ((a[i] ^ 32) == b[i])) 12050+ { 12051+ continue; 12052+ } 12053+ break; 12054+ } 12055+ 12056+ if (a[i] == b[i]) 12057+ { 12058+ *result = 0; 12059+ return ZYAN_STATUS_TRUE; 12060+ } 12061+ 12062+ if ((a[i] | 32) < (b[i] | 32)) 12063+ { 12064+ *result = -1; 12065+ return ZYAN_STATUS_FALSE; 12066+ } 12067+ 12068+ *result = 1; 12069+ return ZYAN_STATUS_FALSE; 12070+} 12071+ 12072+/* ---------------------------------------------------------------------------------------------- */ 12073+/* Case conversion */ 12074+/* ---------------------------------------------------------------------------------------------- */ 12075+ 12076+ZyanStatus ZyanStringToLowerCase(ZyanString* string) 12077+{ 12078+ if (!string) 12079+ { 12080+ return ZYAN_STATUS_INVALID_ARGUMENT; 12081+ } 12082+ 12083+ return ZyanStringToLowerCaseEx(string, 0, string->vector.size - 1); 12084+} 12085+ 12086+ZyanStatus ZyanStringToLowerCaseEx(ZyanString* string, ZyanUSize index, ZyanUSize count) 12087+{ 12088+ // This solution assumes that characters are represented using ASCII representation, i.e., 12089+ // codes for 'a', 'b', 'c', .. 'z' are 97, 98, 99, .. 122 respectively. And codes for 'A', 12090+ // 'B', 'C', .. 'Z' are 65, 66, .. 95 respectively. 12091+ 12092+ if (!string) 12093+ { 12094+ return ZYAN_STATUS_INVALID_ARGUMENT; 12095+ } 12096+ 12097+ // Don't allow access to the terminating '\0' character 12098+ if (index + count >= string->vector.size) 12099+ { 12100+ return ZYAN_STATUS_OUT_OF_RANGE; 12101+ } 12102+ 12103+ char* s = (char*)string->vector.data + index; 12104+ for (ZyanUSize i = index; i < index + count; ++i) 12105+ { 12106+ const char c = *s; 12107+ if ((c >= 'A') && (c <= 'Z')) 12108+ { 12109+ *s = c | 32; 12110+ } 12111+ ++s; 12112+ } 12113+ 12114+ return ZYAN_STATUS_SUCCESS; 12115+} 12116+ 12117+ZyanStatus ZyanStringToUpperCase(ZyanString* string) 12118+{ 12119+ if (!string) 12120+ { 12121+ return ZYAN_STATUS_INVALID_ARGUMENT; 12122+ } 12123+ 12124+ return ZyanStringToUpperCaseEx(string, 0, string->vector.size - 1); 12125+} 12126+ 12127+ZyanStatus ZyanStringToUpperCaseEx(ZyanString* string, ZyanUSize index, ZyanUSize count) 12128+{ 12129+ // This solution assumes that characters are represented using ASCII representation, i.e., 12130+ // codes for 'a', 'b', 'c', .. 'z' are 97, 98, 99, .. 122 respectively. And codes for 'A', 12131+ // 'B', 'C', .. 'Z' are 65, 66, .. 95 respectively. 12132+ 12133+ if (!string) 12134+ { 12135+ return ZYAN_STATUS_INVALID_ARGUMENT; 12136+ } 12137+ 12138+ // Don't allow access to the terminating '\0' character 12139+ if (index + count >= string->vector.size) 12140+ { 12141+ return ZYAN_STATUS_OUT_OF_RANGE; 12142+ } 12143+ 12144+ char* s = (char*)string->vector.data + index; 12145+ for (ZyanUSize i = index; i < index + count; ++i) 12146+ { 12147+ const char c = *s; 12148+ if ((c >= 'a') && (c <= 'z')) 12149+ { 12150+ *s = c & ~32; 12151+ } 12152+ ++s; 12153+ } 12154+ 12155+ return ZYAN_STATUS_SUCCESS; 12156+} 12157+ 12158+/* ---------------------------------------------------------------------------------------------- */ 12159+/* Memory management */ 12160+/* ---------------------------------------------------------------------------------------------- */ 12161+ 12162+ZyanStatus ZyanStringResize(ZyanString* string, ZyanUSize size) 12163+{ 12164+ if (!string) 12165+ { 12166+ return ZYAN_STATUS_INVALID_ARGUMENT; 12167+ } 12168+ 12169+ ZYAN_CHECK(ZyanVectorResize(&string->vector, size + 1)); 12170+ ZYCORE_STRING_NULLTERMINATE(string); 12171+ 12172+ return ZYAN_STATUS_SUCCESS; 12173+} 12174+ 12175+ZyanStatus ZyanStringReserve(ZyanString* string, ZyanUSize capacity) 12176+{ 12177+ if (!string) 12178+ { 12179+ return ZYAN_STATUS_INVALID_ARGUMENT; 12180+ } 12181+ 12182+ return ZyanVectorReserve(&string->vector, capacity); 12183+} 12184+ 12185+ZyanStatus ZyanStringShrinkToFit(ZyanString* string) 12186+{ 12187+ if (!string) 12188+ { 12189+ return ZYAN_STATUS_INVALID_ARGUMENT; 12190+ } 12191+ 12192+ return ZyanVectorShrinkToFit(&string->vector); 12193+} 12194+ 12195+/* ---------------------------------------------------------------------------------------------- */ 12196+/* Information */ 12197+/* ---------------------------------------------------------------------------------------------- */ 12198+ 12199+ZyanStatus ZyanStringGetCapacity(const ZyanString* string, ZyanUSize* capacity) 12200+{ 12201+ if (!string) 12202+ { 12203+ return ZYAN_STATUS_INVALID_ARGUMENT; 12204+ } 12205+ 12206+ ZYAN_ASSERT(string->vector.capacity >= 1); 12207+ *capacity = string->vector.capacity - 1; 12208+ 12209+ return ZYAN_STATUS_SUCCESS; 12210+} 12211+ 12212+ZyanStatus ZyanStringGetSize(const ZyanString* string, ZyanUSize* size) 12213+{ 12214+ if (!string) 12215+ { 12216+ return ZYAN_STATUS_INVALID_ARGUMENT; 12217+ } 12218+ 12219+ ZYAN_ASSERT(string->vector.size >= 1); 12220+ *size = string->vector.size - 1; 12221+ 12222+ return ZYAN_STATUS_SUCCESS; 12223+} 12224+ 12225+ZyanStatus ZyanStringGetData(const ZyanString* string, const char** value) 12226+{ 12227+ if (!string) 12228+ { 12229+ return ZYAN_STATUS_INVALID_ARGUMENT; 12230+ } 12231+ 12232+ *value = string->vector.data; 12233+ 12234+ return ZYAN_STATUS_SUCCESS; 12235+} 12236+ 12237+/* ---------------------------------------------------------------------------------------------- */ 12238+ 12239+/* ============================================================================================== */ 12240diff --git a/zycore/src/Vector.c b/zycore/src/Vector.c 12241new file mode 100644 12242index 0000000..f92c9de 12243--- /dev/null 12244+++ b/zycore/src/Vector.c 12245@@ -0,0 +1,846 @@ 12246+/*************************************************************************************************** 12247+ 12248+ Zyan Core Library (Zycore-C) 12249+ 12250+ Original Author : Florian Bernd 12251+ 12252+ * Permission is hereby granted, free of charge, to any person obtaining a copy 12253+ * of this software and associated documentation files (the "Software"), to deal 12254+ * in the Software without restriction, including without limitation the rights 12255+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12256+ * copies of the Software, and to permit persons to whom the Software is 12257+ * furnished to do so, subject to the following conditions: 12258+ * 12259+ * The above copyright notice and this permission notice shall be included in all 12260+ * copies or substantial portions of the Software. 12261+ * 12262+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12263+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12264+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 12265+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 12266+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12267+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 12268+ * SOFTWARE. 12269+ 12270+***************************************************************************************************/ 12271+ 12272+#include <Zycore/LibC.h> 12273+#include <Zycore/Vector.h> 12274+ 12275+/* ============================================================================================== */ 12276+/* Internal macros */ 12277+/* ============================================================================================== */ 12278+ 12279+/** 12280+ * Checks, if the passed vector should grow. 12281+ * 12282+ * @param size The desired size of the vector. 12283+ * @param capacity The current capacity of the vector. 12284+ * 12285+ * @return `ZYAN_TRUE`, if the vector should grow or `ZYAN_FALSE`, if not. 12286+ */ 12287+#define ZYCORE_VECTOR_SHOULD_GROW(size, capacity) \ 12288+ ((size) > (capacity)) 12289+ 12290+/** 12291+ * Checks, if the passed vector should shrink. 12292+ * 12293+ * @param size The desired size of the vector. 12294+ * @param capacity The current capacity of the vector. 12295+ * @param threshold The shrink threshold. 12296+ * 12297+ * @return `ZYAN_TRUE`, if the vector should shrink or `ZYAN_FALSE`, if not. 12298+ */ 12299+#define ZYCORE_VECTOR_SHOULD_SHRINK(size, capacity, threshold) \ 12300+ (((threshold) != 0) && ((size) * (threshold) < (capacity))) 12301+ 12302+/** 12303+ * Returns the offset of the element at the given `index`. 12304+ * 12305+ * @param vector A pointer to the `ZyanVector` instance. 12306+ * @param index The element index. 12307+ * 12308+ * @return The offset of the element at the given `index`. 12309+ */ 12310+#define ZYCORE_VECTOR_OFFSET(vector, index) \ 12311+ ((void*)((ZyanU8*)(vector)->data + ((index) * (vector)->element_size))) 12312+ 12313+/* ============================================================================================== */ 12314+/* Internal functions */ 12315+/* ============================================================================================== */ 12316+ 12317+/* ---------------------------------------------------------------------------------------------- */ 12318+/* Helper functions */ 12319+/* ---------------------------------------------------------------------------------------------- */ 12320+ 12321+/** 12322+ * Reallocates the internal buffer of the vector. 12323+ * 12324+ * @param vector A pointer to the `ZyanVector` instance. 12325+ * @param capacity The new capacity. 12326+ * 12327+ * @return A zyan status code. 12328+ */ 12329+static ZyanStatus ZyanVectorReallocate(ZyanVector* vector, ZyanUSize capacity) 12330+{ 12331+ ZYAN_ASSERT(vector); 12332+ ZYAN_ASSERT(vector->capacity >= ZYAN_VECTOR_MIN_CAPACITY); 12333+ ZYAN_ASSERT(vector->element_size); 12334+ ZYAN_ASSERT(vector->data); 12335+ 12336+ if (!vector->allocator) 12337+ { 12338+ if (vector->capacity < capacity) 12339+ { 12340+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 12341+ } 12342+ return ZYAN_STATUS_SUCCESS; 12343+ } 12344+ 12345+ ZYAN_ASSERT(vector->allocator); 12346+ ZYAN_ASSERT(vector->allocator->reallocate); 12347+ 12348+ if (capacity < ZYAN_VECTOR_MIN_CAPACITY) 12349+ { 12350+ if (vector->capacity > ZYAN_VECTOR_MIN_CAPACITY) 12351+ { 12352+ capacity = ZYAN_VECTOR_MIN_CAPACITY; 12353+ } else 12354+ { 12355+ return ZYAN_STATUS_SUCCESS; 12356+ } 12357+ } 12358+ 12359+ vector->capacity = capacity; 12360+ ZYAN_CHECK(vector->allocator->reallocate(vector->allocator, &vector->data, 12361+ vector->element_size, vector->capacity)); 12362+ 12363+ return ZYAN_STATUS_SUCCESS; 12364+} 12365+ 12366+/** 12367+ * Shifts all elements starting at the specified `index` by the amount of `count` to the left. 12368+ * 12369+ * @param vector A pointer to the `ZyanVector` instance. 12370+ * @param index The start index. 12371+ * @param count The amount of shift operations. 12372+ * 12373+ * @return A zyan status code. 12374+ */ 12375+static ZyanStatus ZyanVectorShiftLeft(ZyanVector* vector, ZyanUSize index, ZyanUSize count) 12376+{ 12377+ ZYAN_ASSERT(vector); 12378+ ZYAN_ASSERT(vector->element_size); 12379+ ZYAN_ASSERT(vector->data); 12380+ ZYAN_ASSERT(count > 0); 12381+ //ZYAN_ASSERT((ZyanISize)count - (ZyanISize)index + 1 >= 0); 12382+ 12383+ const void* const source = ZYCORE_VECTOR_OFFSET(vector, index + count); 12384+ void* const dest = ZYCORE_VECTOR_OFFSET(vector, index); 12385+ const ZyanUSize size = (vector->size - index - count) * vector->element_size; 12386+ ZYAN_MEMMOVE(dest, source, size); 12387+ 12388+ return ZYAN_STATUS_SUCCESS; 12389+} 12390+ 12391+/** 12392+ * Shifts all elements starting at the specified `index` by the amount of `count` to the right. 12393+ * 12394+ * @param vector A pointer to the `ZyanVector` instance. 12395+ * @param index The start index. 12396+ * @param count The amount of shift operations. 12397+ * 12398+ * @return A zyan status code. 12399+ */ 12400+static ZyanStatus ZyanVectorShiftRight(ZyanVector* vector, ZyanUSize index, ZyanUSize count) 12401+{ 12402+ ZYAN_ASSERT(vector); 12403+ ZYAN_ASSERT(vector->element_size); 12404+ ZYAN_ASSERT(vector->data); 12405+ ZYAN_ASSERT(count > 0); 12406+ ZYAN_ASSERT(vector->size + count <= vector->capacity); 12407+ 12408+ const void* const source = ZYCORE_VECTOR_OFFSET(vector, index); 12409+ void* const dest = ZYCORE_VECTOR_OFFSET(vector, index + count); 12410+ const ZyanUSize size = (vector->size - index) * vector->element_size; 12411+ ZYAN_MEMMOVE(dest, source, size); 12412+ 12413+ return ZYAN_STATUS_SUCCESS; 12414+} 12415+ 12416+/* ---------------------------------------------------------------------------------------------- */ 12417+ 12418+/* ============================================================================================== */ 12419+/* Exported functions */ 12420+/* ============================================================================================== */ 12421+ 12422+/* ---------------------------------------------------------------------------------------------- */ 12423+/* Constructor and destructor */ 12424+/* ---------------------------------------------------------------------------------------------- */ 12425+ 12426+#ifndef ZYAN_NO_LIBC 12427+ 12428+ZyanStatus ZyanVectorInit(ZyanVector* vector, ZyanUSize element_size, ZyanUSize capacity, 12429+ ZyanMemberProcedure destructor) 12430+{ 12431+ return ZyanVectorInitEx(vector, element_size, capacity, destructor, ZyanAllocatorDefault(), 12432+ ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD); 12433+} 12434+ 12435+#endif // ZYAN_NO_LIBC 12436+ 12437+ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size, ZyanUSize capacity, 12438+ ZyanMemberProcedure destructor, ZyanAllocator* allocator, ZyanU8 growth_factor, 12439+ ZyanU8 shrink_threshold) 12440+{ 12441+ if (!vector || !element_size || !allocator || (growth_factor < 1)) 12442+ { 12443+ return ZYAN_STATUS_INVALID_ARGUMENT; 12444+ } 12445+ 12446+ ZYAN_ASSERT(allocator->allocate); 12447+ 12448+ vector->allocator = allocator; 12449+ vector->growth_factor = growth_factor; 12450+ vector->shrink_threshold = shrink_threshold; 12451+ vector->size = 0; 12452+ vector->capacity = ZYAN_MAX(ZYAN_VECTOR_MIN_CAPACITY, capacity); 12453+ vector->element_size = element_size; 12454+ vector->destructor = destructor; 12455+ vector->data = ZYAN_NULL; 12456+ 12457+ return allocator->allocate(vector->allocator, &vector->data, vector->element_size, 12458+ vector->capacity); 12459+} 12460+ 12461+ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size, 12462+ void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor) 12463+{ 12464+ if (!vector || !element_size || !buffer || !capacity) 12465+ { 12466+ return ZYAN_STATUS_INVALID_ARGUMENT; 12467+ } 12468+ 12469+ vector->allocator = ZYAN_NULL; 12470+ vector->growth_factor = 1; 12471+ vector->shrink_threshold = 0; 12472+ vector->size = 0; 12473+ vector->capacity = capacity; 12474+ vector->element_size = element_size; 12475+ vector->destructor = destructor; 12476+ vector->data = buffer; 12477+ 12478+ return ZYAN_STATUS_SUCCESS; 12479+} 12480+ 12481+ZyanStatus ZyanVectorDestroy(ZyanVector* vector) 12482+{ 12483+ if (!vector) 12484+ { 12485+ return ZYAN_STATUS_INVALID_ARGUMENT; 12486+ } 12487+ 12488+ ZYAN_ASSERT(vector->element_size); 12489+ ZYAN_ASSERT(vector->data); 12490+ 12491+ if (vector->destructor) 12492+ { 12493+ for (ZyanUSize i = 0; i < vector->size; ++i) 12494+ { 12495+ vector->destructor(ZYCORE_VECTOR_OFFSET(vector, i)); 12496+ } 12497+ } 12498+ 12499+ if (vector->allocator && vector->capacity) 12500+ { 12501+ ZYAN_ASSERT(vector->allocator->deallocate); 12502+ ZYAN_CHECK(vector->allocator->deallocate(vector->allocator, vector->data, 12503+ vector->element_size, vector->capacity)); 12504+ } 12505+ 12506+ vector->data = ZYAN_NULL; 12507+ return ZYAN_STATUS_SUCCESS; 12508+} 12509+ 12510+/* ---------------------------------------------------------------------------------------------- */ 12511+/* Duplication */ 12512+/* ---------------------------------------------------------------------------------------------- */ 12513+ 12514+#ifndef ZYAN_NO_LIBC 12515+ 12516+ZyanStatus ZyanVectorDuplicate(ZyanVector* destination, const ZyanVector* source, 12517+ ZyanUSize capacity) 12518+{ 12519+ return ZyanVectorDuplicateEx(destination, source, capacity, ZyanAllocatorDefault(), 12520+ ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD); 12521+} 12522+ 12523+#endif // ZYAN_NO_LIBC 12524+ 12525+ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source, 12526+ ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold) 12527+{ 12528+ if (!source) 12529+ { 12530+ return ZYAN_STATUS_INVALID_ARGUMENT; 12531+ } 12532+ 12533+ const ZyanUSize len = source->size; 12534+ 12535+ capacity = ZYAN_MAX(capacity, len); 12536+ ZYAN_CHECK(ZyanVectorInitEx(destination, source->element_size, capacity, source->destructor, 12537+ allocator, growth_factor, shrink_threshold)); 12538+ ZYAN_ASSERT(destination->capacity >= len); 12539+ 12540+ ZYAN_MEMCPY(destination->data, source->data, len * source->element_size); 12541+ destination->size = len; 12542+ 12543+ return ZYAN_STATUS_SUCCESS; 12544+} 12545+ 12546+ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination, const ZyanVector* source, 12547+ void* buffer, ZyanUSize capacity) 12548+{ 12549+ if (!source) 12550+ { 12551+ return ZYAN_STATUS_INVALID_ARGUMENT; 12552+ } 12553+ 12554+ const ZyanUSize len = source->size; 12555+ 12556+ if (capacity < len) 12557+ { 12558+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 12559+ } 12560+ 12561+ ZYAN_CHECK(ZyanVectorInitCustomBuffer(destination, source->element_size, buffer, capacity, 12562+ source->destructor)); 12563+ ZYAN_ASSERT(destination->capacity >= len); 12564+ 12565+ ZYAN_MEMCPY(destination->data, source->data, len * source->element_size); 12566+ destination->size = len; 12567+ 12568+ return ZYAN_STATUS_SUCCESS; 12569+} 12570+ 12571+/* ---------------------------------------------------------------------------------------------- */ 12572+/* Element access */ 12573+/* ---------------------------------------------------------------------------------------------- */ 12574+ 12575+const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index) 12576+{ 12577+ if (!vector || (index >= vector->size)) 12578+ { 12579+ return ZYAN_NULL; 12580+ } 12581+ 12582+ ZYAN_ASSERT(vector->element_size); 12583+ ZYAN_ASSERT(vector->data); 12584+ 12585+ return ZYCORE_VECTOR_OFFSET(vector, index); 12586+} 12587+ 12588+void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index) 12589+{ 12590+ if (!vector || (index >= vector->size)) 12591+ { 12592+ return ZYAN_NULL; 12593+ } 12594+ 12595+ ZYAN_ASSERT(vector->element_size); 12596+ ZYAN_ASSERT(vector->data); 12597+ 12598+ return ZYCORE_VECTOR_OFFSET(vector, index); 12599+} 12600+ 12601+ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index, const void** value) 12602+{ 12603+ if (!vector || !value) 12604+ { 12605+ return ZYAN_STATUS_INVALID_ARGUMENT; 12606+ } 12607+ if (index >= vector->size) 12608+ { 12609+ return ZYAN_STATUS_OUT_OF_RANGE; 12610+ } 12611+ 12612+ ZYAN_ASSERT(vector->element_size); 12613+ ZYAN_ASSERT(vector->data); 12614+ 12615+ *value = (const void*)ZYCORE_VECTOR_OFFSET(vector, index); 12616+ 12617+ return ZYAN_STATUS_SUCCESS; 12618+} 12619+ 12620+ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index, void** value) 12621+{ 12622+ if (!vector || !value) 12623+ { 12624+ return ZYAN_STATUS_INVALID_ARGUMENT; 12625+ } 12626+ if (index >= vector->size) 12627+ { 12628+ return ZYAN_STATUS_OUT_OF_RANGE; 12629+ } 12630+ 12631+ ZYAN_ASSERT(vector->element_size); 12632+ ZYAN_ASSERT(vector->data); 12633+ 12634+ *value = ZYCORE_VECTOR_OFFSET(vector, index); 12635+ 12636+ return ZYAN_STATUS_SUCCESS; 12637+} 12638+ 12639+ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index, const void* value) 12640+{ 12641+ if (!vector || !value) 12642+ { 12643+ return ZYAN_STATUS_INVALID_ARGUMENT; 12644+ } 12645+ if (index >= vector->size) 12646+ { 12647+ return ZYAN_STATUS_OUT_OF_RANGE; 12648+ } 12649+ 12650+ ZYAN_ASSERT(vector->element_size); 12651+ ZYAN_ASSERT(vector->data); 12652+ 12653+ void* const offset = ZYCORE_VECTOR_OFFSET(vector, index); 12654+ if (vector->destructor) 12655+ { 12656+ vector->destructor(offset); 12657+ } 12658+ ZYAN_MEMCPY(offset, value, vector->element_size); 12659+ 12660+ return ZYAN_STATUS_SUCCESS; 12661+} 12662+ 12663+/* ---------------------------------------------------------------------------------------------- */ 12664+/* Insertion */ 12665+/* ---------------------------------------------------------------------------------------------- */ 12666+ 12667+ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element) 12668+{ 12669+ if (!vector || !element) 12670+ { 12671+ return ZYAN_STATUS_INVALID_ARGUMENT; 12672+ } 12673+ 12674+ ZYAN_ASSERT(vector->element_size); 12675+ ZYAN_ASSERT(vector->data); 12676+ 12677+ if (ZYCORE_VECTOR_SHOULD_GROW(vector->size + 1, vector->capacity)) 12678+ { 12679+ ZYAN_CHECK(ZyanVectorReallocate(vector, 12680+ ZYAN_MAX(1, (ZyanUSize)((vector->size + 1) * vector->growth_factor)))); 12681+ } 12682+ 12683+ void* const offset = ZYCORE_VECTOR_OFFSET(vector, vector->size); 12684+ ZYAN_MEMCPY(offset, element, vector->element_size); 12685+ 12686+ ++vector->size; 12687+ 12688+ return ZYAN_STATUS_SUCCESS; 12689+} 12690+ 12691+ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index, const void* element) 12692+{ 12693+ return ZyanVectorInsertRange(vector, index, element, 1); 12694+} 12695+ 12696+ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index, const void* elements, 12697+ ZyanUSize count) 12698+{ 12699+ if (!vector || !elements || !count) 12700+ { 12701+ return ZYAN_STATUS_INVALID_ARGUMENT; 12702+ } 12703+ if (index > vector->size) 12704+ { 12705+ return ZYAN_STATUS_OUT_OF_RANGE; 12706+ } 12707+ 12708+ ZYAN_ASSERT(vector->element_size); 12709+ ZYAN_ASSERT(vector->data); 12710+ 12711+ if (ZYCORE_VECTOR_SHOULD_GROW(vector->size + count, vector->capacity)) 12712+ { 12713+ ZYAN_CHECK(ZyanVectorReallocate(vector, 12714+ ZYAN_MAX(1, (ZyanUSize)((vector->size + count) * vector->growth_factor)))); 12715+ } 12716+ 12717+ if (index < vector->size) 12718+ { 12719+ ZYAN_CHECK(ZyanVectorShiftRight(vector, index, count)); 12720+ } 12721+ 12722+ void* const offset = ZYCORE_VECTOR_OFFSET(vector, index); 12723+ ZYAN_MEMCPY(offset, elements, count * vector->element_size); 12724+ vector->size += count; 12725+ 12726+ return ZYAN_STATUS_SUCCESS; 12727+} 12728+ 12729+ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element, ZyanMemberFunction constructor) 12730+{ 12731+ if (!vector) 12732+ { 12733+ return ZYAN_STATUS_INVALID_ARGUMENT; 12734+ } 12735+ 12736+ return ZyanVectorEmplaceEx(vector, vector->size, element, constructor); 12737+} 12738+ 12739+ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index, void** element, 12740+ ZyanMemberFunction constructor) 12741+{ 12742+ if (!vector) 12743+ { 12744+ return ZYAN_STATUS_INVALID_ARGUMENT; 12745+ } 12746+ if (index > vector->size) 12747+ { 12748+ return ZYAN_STATUS_OUT_OF_RANGE; 12749+ } 12750+ 12751+ ZYAN_ASSERT(vector->element_size); 12752+ ZYAN_ASSERT(vector->data); 12753+ 12754+ if (ZYCORE_VECTOR_SHOULD_GROW(vector->size + 1, vector->capacity)) 12755+ { 12756+ ZYAN_CHECK(ZyanVectorReallocate(vector, 12757+ ZYAN_MAX(1, (ZyanUSize)((vector->size + 1) * vector->growth_factor)))); 12758+ } 12759+ 12760+ if (index < vector->size) 12761+ { 12762+ ZYAN_CHECK(ZyanVectorShiftRight(vector, index, 1)); 12763+ } 12764+ 12765+ *element = ZYCORE_VECTOR_OFFSET(vector, index); 12766+ if (constructor) 12767+ { 12768+ ZYAN_CHECK(constructor(*element)); 12769+ } 12770+ 12771+ ++vector->size; 12772+ 12773+ return ZYAN_STATUS_SUCCESS; 12774+} 12775+ 12776+/* ---------------------------------------------------------------------------------------------- */ 12777+/* Utils */ 12778+/* ---------------------------------------------------------------------------------------------- */ 12779+ 12780+ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first, ZyanUSize index_second) 12781+{ 12782+ if (!vector) 12783+ { 12784+ return ZYAN_STATUS_INVALID_ARGUMENT; 12785+ } 12786+ if ((index_first >= vector->size) || (index_second >= vector->size)) 12787+ { 12788+ return ZYAN_STATUS_OUT_OF_RANGE; 12789+ } 12790+ 12791+ if (vector->size == vector->capacity) 12792+ { 12793+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 12794+ } 12795+ 12796+ ZYAN_ASSERT(vector->element_size); 12797+ ZYAN_ASSERT(vector->data); 12798+ 12799+ ZyanU64* const t = ZYCORE_VECTOR_OFFSET(vector, vector->size); 12800+ ZyanU64* const a = ZYCORE_VECTOR_OFFSET(vector, index_first); 12801+ ZyanU64* const b = ZYCORE_VECTOR_OFFSET(vector, index_second); 12802+ ZYAN_MEMCPY(t, a, vector->element_size); 12803+ ZYAN_MEMCPY(a, b, vector->element_size); 12804+ ZYAN_MEMCPY(b, t, vector->element_size); 12805+ 12806+ return ZYAN_STATUS_SUCCESS; 12807+} 12808+ 12809+/* ---------------------------------------------------------------------------------------------- */ 12810+/* Deletion */ 12811+/* ---------------------------------------------------------------------------------------------- */ 12812+ 12813+ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index) 12814+{ 12815+ return ZyanVectorDeleteRange(vector, index, 1); 12816+} 12817+ 12818+ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index, ZyanUSize count) 12819+{ 12820+ if (!vector || !count) 12821+ { 12822+ return ZYAN_STATUS_INVALID_ARGUMENT; 12823+ } 12824+ if (index + count > vector->size) 12825+ { 12826+ return ZYAN_STATUS_OUT_OF_RANGE; 12827+ } 12828+ 12829+ if (vector->destructor) 12830+ { 12831+ for (ZyanUSize i = index; i < index + count; ++i) 12832+ { 12833+ vector->destructor(ZYCORE_VECTOR_OFFSET(vector, i)); 12834+ } 12835+ } 12836+ 12837+ if (index + count < vector->size) 12838+ { 12839+ ZYAN_CHECK(ZyanVectorShiftLeft(vector, index, count)); 12840+ } 12841+ 12842+ vector->size -= count; 12843+ if (ZYCORE_VECTOR_SHOULD_SHRINK(vector->size, vector->capacity, vector->shrink_threshold)) 12844+ { 12845+ return ZyanVectorReallocate(vector, 12846+ ZYAN_MAX(1, (ZyanUSize)(vector->size * vector->growth_factor))); 12847+ } 12848+ 12849+ return ZYAN_STATUS_SUCCESS; 12850+} 12851+ 12852+ZyanStatus ZyanVectorPopBack(ZyanVector* vector) 12853+{ 12854+ if (!vector) 12855+ { 12856+ return ZYAN_STATUS_INVALID_ARGUMENT; 12857+ } 12858+ if (vector->size == 0) 12859+ { 12860+ return ZYAN_STATUS_OUT_OF_RANGE; 12861+ } 12862+ 12863+ if (vector->destructor) 12864+ { 12865+ vector->destructor(ZYCORE_VECTOR_OFFSET(vector, vector->size - 1)); 12866+ } 12867+ 12868+ --vector->size; 12869+ if (ZYCORE_VECTOR_SHOULD_SHRINK(vector->size, vector->capacity, vector->shrink_threshold)) 12870+ { 12871+ return ZyanVectorReallocate(vector, 12872+ ZYAN_MAX(1, (ZyanUSize)(vector->size * vector->growth_factor))); 12873+ } 12874+ 12875+ return ZYAN_STATUS_SUCCESS; 12876+} 12877+ 12878+ZyanStatus ZyanVectorClear(ZyanVector* vector) 12879+{ 12880+ return ZyanVectorResizeEx(vector, 0, ZYAN_NULL); 12881+} 12882+ 12883+/* ---------------------------------------------------------------------------------------------- */ 12884+/* Searching */ 12885+/* ---------------------------------------------------------------------------------------------- */ 12886+ 12887+ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element, ZyanISize* found_index, 12888+ ZyanEqualityComparison comparison) 12889+{ 12890+ if (!vector) 12891+ { 12892+ return ZYAN_STATUS_INVALID_ARGUMENT; 12893+ } 12894+ 12895+ return ZyanVectorFindEx(vector, element, found_index, comparison, 0, vector->size); 12896+} 12897+ 12898+ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element, ZyanISize* found_index, 12899+ ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count) 12900+{ 12901+ if (!vector) 12902+ { 12903+ return ZYAN_STATUS_INVALID_ARGUMENT; 12904+ } 12905+ if ((index + count > vector->size) || (index == vector->size)) 12906+ { 12907+ return ZYAN_STATUS_OUT_OF_RANGE; 12908+ } 12909+ 12910+ if (!count) 12911+ { 12912+ *found_index = -1; 12913+ return ZYAN_STATUS_FALSE; 12914+ } 12915+ 12916+ ZYAN_ASSERT(vector->element_size); 12917+ ZYAN_ASSERT(vector->data); 12918+ 12919+ for (ZyanUSize i = index; i < index + count; ++i) 12920+ { 12921+ if (comparison(ZYCORE_VECTOR_OFFSET(vector, i), element)) 12922+ { 12923+ *found_index = i; 12924+ return ZYAN_STATUS_TRUE; 12925+ } 12926+ } 12927+ 12928+ *found_index = -1; 12929+ return ZYAN_STATUS_FALSE; 12930+} 12931+ 12932+ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element, 12933+ ZyanUSize* found_index, ZyanComparison comparison) 12934+{ 12935+ if (!vector) 12936+ { 12937+ return ZYAN_STATUS_INVALID_ARGUMENT; 12938+ } 12939+ 12940+ return ZyanVectorBinarySearchEx(vector, element, found_index, comparison, 0, vector->size); 12941+} 12942+ 12943+ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element, 12944+ ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count) 12945+{ 12946+ if (!vector) 12947+ { 12948+ return ZYAN_STATUS_INVALID_ARGUMENT; 12949+ } 12950+ if (((index >= vector->size) && (count > 0)) || (index + count > vector->size)) 12951+ { 12952+ return ZYAN_STATUS_OUT_OF_RANGE; 12953+ } 12954+ 12955+ if (!count) 12956+ { 12957+ *found_index = index; 12958+ return ZYAN_STATUS_FALSE; 12959+ } 12960+ 12961+ ZYAN_ASSERT(vector->element_size); 12962+ ZYAN_ASSERT(vector->data); 12963+ 12964+ ZyanStatus status = ZYAN_STATUS_FALSE; 12965+ ZyanISize l = index; 12966+ ZyanISize h = index + count - 1; 12967+ while (l <= h) 12968+ { 12969+ const ZyanUSize mid = l + ((h - l) >> 1); 12970+ const ZyanI32 cmp = comparison(ZYCORE_VECTOR_OFFSET(vector, mid), element); 12971+ if (cmp < 0) 12972+ { 12973+ l = mid + 1; 12974+ } else 12975+ { 12976+ h = mid - 1; 12977+ if (cmp == 0) 12978+ { 12979+ status = ZYAN_STATUS_TRUE; 12980+ } 12981+ } 12982+ } 12983+ 12984+ *found_index = l; 12985+ return status; 12986+} 12987+ 12988+/* ---------------------------------------------------------------------------------------------- */ 12989+/* Memory management */ 12990+/* ---------------------------------------------------------------------------------------------- */ 12991+ 12992+ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size) 12993+{ 12994+ return ZyanVectorResizeEx(vector, size, ZYAN_NULL); 12995+} 12996+ 12997+ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size, const void* initializer) 12998+{ 12999+ if (!vector) 13000+ { 13001+ return ZYAN_STATUS_INVALID_ARGUMENT; 13002+ } 13003+ if (size == vector->size) 13004+ { 13005+ return ZYAN_STATUS_SUCCESS; 13006+ } 13007+ 13008+ if (vector->destructor && (size < vector->size)) 13009+ { 13010+ for (ZyanUSize i = size; i < vector->size; ++i) 13011+ { 13012+ vector->destructor(ZYCORE_VECTOR_OFFSET(vector, i)); 13013+ } 13014+ } 13015+ 13016+ if (ZYCORE_VECTOR_SHOULD_GROW(size, vector->capacity) || 13017+ ZYCORE_VECTOR_SHOULD_SHRINK(size, vector->capacity, vector->shrink_threshold)) 13018+ { 13019+ ZYAN_ASSERT(vector->growth_factor >= 1); 13020+ ZYAN_CHECK(ZyanVectorReallocate(vector, (ZyanUSize)(size * vector->growth_factor))); 13021+ } 13022+ 13023+ if (initializer && (size > vector->size)) 13024+ { 13025+ for (ZyanUSize i = vector->size; i < size; ++i) 13026+ { 13027+ ZYAN_MEMCPY(ZYCORE_VECTOR_OFFSET(vector, i), initializer, vector->element_size); 13028+ } 13029+ } 13030+ 13031+ vector->size = size; 13032+ 13033+ return ZYAN_STATUS_SUCCESS; 13034+} 13035+ 13036+ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity) 13037+{ 13038+ if (!vector) 13039+ { 13040+ return ZYAN_STATUS_INVALID_ARGUMENT; 13041+ } 13042+ 13043+ if (capacity > vector->capacity) 13044+ { 13045+ ZYAN_CHECK(ZyanVectorReallocate(vector, capacity)); 13046+ } 13047+ 13048+ return ZYAN_STATUS_SUCCESS; 13049+} 13050+ 13051+ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector) 13052+{ 13053+ if (!vector) 13054+ { 13055+ return ZYAN_STATUS_INVALID_ARGUMENT; 13056+ } 13057+ 13058+ return ZyanVectorReallocate(vector, vector->size); 13059+} 13060+ 13061+/* ---------------------------------------------------------------------------------------------- */ 13062+/* Information */ 13063+/* ---------------------------------------------------------------------------------------------- */ 13064+ 13065+ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity) 13066+{ 13067+ if (!vector) 13068+ { 13069+ return ZYAN_STATUS_INVALID_ARGUMENT; 13070+ } 13071+ 13072+ *capacity = vector->capacity; 13073+ 13074+ return ZYAN_STATUS_SUCCESS; 13075+} 13076+ 13077+ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size) 13078+{ 13079+ if (!vector) 13080+ { 13081+ return ZYAN_STATUS_INVALID_ARGUMENT; 13082+ } 13083+ 13084+ *size = vector->size; 13085+ 13086+ return ZYAN_STATUS_SUCCESS; 13087+} 13088+ 13089+/* ---------------------------------------------------------------------------------------------- */ 13090+ 13091+/* ============================================================================================== */ 13092diff --git a/zycore/src/Zycore.c b/zycore/src/Zycore.c 13093new file mode 100644 13094index 0000000..9bbb200 13095--- /dev/null 13096+++ b/zycore/src/Zycore.c 13097@@ -0,0 +1,38 @@ 13098+/*************************************************************************************************** 13099+ 13100+ Zyan Core Library (Zycore-C) 13101+ 13102+ Original Author : Florian Bernd 13103+ 13104+ * Permission is hereby granted, free of charge, to any person obtaining a copy 13105+ * of this software and associated documentation files (the "Software"), to deal 13106+ * in the Software without restriction, including without limitation the rights 13107+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13108+ * copies of the Software, and to permit persons to whom the Software is 13109+ * furnished to do so, subject to the following conditions: 13110+ * 13111+ * The above copyright notice and this permission notice shall be included in all 13112+ * copies or substantial portions of the Software. 13113+ * 13114+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13115+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13116+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13117+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13118+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 13119+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 13120+ * SOFTWARE. 13121+ 13122+***************************************************************************************************/ 13123+ 13124+#include <Zycore/Zycore.h> 13125+ 13126+/* ============================================================================================== */ 13127+/* Exported functions */ 13128+/* ============================================================================================== */ 13129+ 13130+ZyanU64 ZycoreGetVersion(void) 13131+{ 13132+ return ZYCORE_VERSION; 13133+} 13134+ 13135+/* ============================================================================================== */ 13136-- 131372.17.1 13138 13139