• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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