parent
e6d175cb03
commit
0b422476e1
@ -1,13 +1,13 @@
|
||||
#include "Theodosius.h"
|
||||
#include <Windows.h>
|
||||
|
||||
void UsermodeNoObfuscation()
|
||||
{
|
||||
for (auto idx = 0u; idx < 5; ++idx)
|
||||
MessageBoxA(0, "Demo", "Hello From Non-Obfuscated Routine!", 0);
|
||||
MessageBoxA(0, "Demo", "Hello From Non-Obfuscated Routine!", 0);
|
||||
}
|
||||
|
||||
MutateRoutine
|
||||
void UsermodeMutateDemo()
|
||||
THEO_MUTATE(LLVM_BCF LLVM_SUB void UsermodeMutateDemo()
|
||||
{
|
||||
MessageBoxA(0, "Demo", "Hello From Mutated Routine!", 0);
|
||||
}
|
||||
for (auto idx = 0u; idx < 5; ++idx)
|
||||
MessageBoxA(0, "Demo", "Hello From Mutated Routine!", 0);
|
||||
})
|
@ -1,41 +1,36 @@
|
||||
#include "Theodosius.h"
|
||||
#include "Types.h"
|
||||
inline int a = 10; // c++17 tests (c++1z...)
|
||||
|
||||
// this routine is not obfuscated...
|
||||
void PrintCR3()
|
||||
THEO_OBFUSCATE(void PrintCR3()
|
||||
{
|
||||
ULONG_PTR Cr3Value =
|
||||
*reinterpret_cast<ULONG_PTR*>(
|
||||
IoGetCurrentProcess() + CR3_OFFSET);
|
||||
|
||||
DbgPrint("> Current CR3 = 0x%p\n", Cr3Value);
|
||||
}
|
||||
|
||||
ObfuscateRoutine
|
||||
void LoopDemo(bool* result)
|
||||
{
|
||||
// JCC's work! :)
|
||||
for (auto idx = 0u; idx < 10; ++idx)
|
||||
DbgPrint("> Loop Demo: %d\n", idx);
|
||||
|
||||
*result = true;
|
||||
}
|
||||
|
||||
MutateRoutine extern "C" void DrvEntry()
|
||||
{
|
||||
DbgPrint("> Hello World!\n");
|
||||
|
||||
// non-exported symbols being resolved by jit linker...
|
||||
DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable);
|
||||
DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener);
|
||||
|
||||
// example of referencing itself...
|
||||
DbgPrint("> DrvEntry = 0x%p\n", &DrvEntry);
|
||||
DbgPrint("> PrintCR3 = 0x%p\n", &PrintCR3);
|
||||
})
|
||||
|
||||
THEO_OBFUSCATE(LLVM_BCF void LoopDemo(unsigned* result)
|
||||
{
|
||||
// JCC's work! :)
|
||||
for (auto idx = 0u; idx < 10; ++idx)
|
||||
// addresses to variables on the stack work! :)
|
||||
*result = idx;
|
||||
})
|
||||
|
||||
THEO_MUTATE(LLVM_BCF LLVM_SUB extern "C" void DrvEntry()
|
||||
{
|
||||
// example of calling other obfuscated/non obfuscated routines...
|
||||
PrintCR3();
|
||||
|
||||
bool result = false;
|
||||
unsigned result = 0u;
|
||||
LoopDemo(&result);
|
||||
DbgPrint("> result = %d\n", result);
|
||||
}
|
||||
})
|
@ -1,3 +1,43 @@
|
||||
#pragma once
|
||||
#define ObfuscateRoutine __declspec(code_seg(".theo"), noinline)
|
||||
#define MutateRoutine __declspec(code_seg(".theo1"), noinline)
|
||||
#define WINUSERAPI
|
||||
#define _KERNEL32_
|
||||
#define _ACRTIMP
|
||||
#define NTKERNELAPI
|
||||
|
||||
#define THEO_OBFUSCATE(...) \
|
||||
_Pragma("code_seg(\".theo\")") \
|
||||
__VA_ARGS__ \
|
||||
_Pragma("code_seg()")
|
||||
|
||||
#define THEO_MUTATE(...) \
|
||||
_Pragma("code_seg(\".theo1\")") \
|
||||
__VA_ARGS__ \
|
||||
_Pragma("code_seg()")
|
||||
|
||||
#define LLVM_BCF __attribute((__annotate__(("bcf"))))
|
||||
#define LLVM_SUB __attribute((__annotate__(("sub"))))
|
||||
#define LLVM_FLA __attribute((__annotate__(("fla"))))
|
||||
|
||||
#define CR3_OFFSET 0x28
|
||||
#define NT_SUCCESS(x) ((x) >= 0)
|
||||
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
||||
|
||||
using NTSTATUS = unsigned long;
|
||||
using PVOID = void*;
|
||||
|
||||
using HANDLE = unsigned long;
|
||||
using UCHAR = unsigned char;
|
||||
using USHORT = unsigned short;
|
||||
using ULONG = unsigned long;
|
||||
using PULONG = unsigned long*;
|
||||
typedef unsigned long long ULONG_PTR;
|
||||
|
||||
// this is a demo of resolving non-exported symbols...
|
||||
// win32kfull.sys export example...
|
||||
extern "C" void NtUserRegisterShellPTPListener();
|
||||
extern "C" void* PiDDBCacheTable;
|
||||
|
||||
extern "C" unsigned char* IoGetCurrentProcess();
|
||||
extern "C" unsigned long DbgPrint(const char* format, ...);
|
||||
extern "C" PVOID ExAllocatePool(ULONG, ULONG);
|
||||
extern "C" void ExFreePool(PVOID);
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#define NT_SUCCESS(x) ((x) >= 0)
|
||||
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
||||
#define CR3_OFFSET 0x28
|
||||
|
||||
using NTSTATUS = unsigned long;
|
||||
using PVOID = void*;
|
||||
|
||||
using HANDLE = unsigned long;
|
||||
using UCHAR = unsigned char;
|
||||
using USHORT = unsigned short;
|
||||
using ULONG = unsigned long;
|
||||
using PULONG = unsigned long*;
|
||||
typedef unsigned long long ULONG_PTR;
|
||||
|
||||
// this is a demo of resolving non-exported symbols...
|
||||
// win32kfull.sys export example...
|
||||
extern "C" void NtUserRegisterShellPTPListener();
|
||||
extern "C" void* PiDDBCacheTable;
|
||||
|
||||
extern "C" unsigned char* IoGetCurrentProcess();
|
||||
extern "C" unsigned long DbgPrint(const char* format, ...);
|
||||
extern "C" PVOID ExAllocatePool(ULONG, ULONG);
|
||||
extern "C" void ExFreePool(PVOID);
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#define WINUSERAPI
|
||||
#define _KERNEL32_
|
||||
#define _ACRTIMP
|
||||
#define NTKERNELAPI
|
||||
|
||||
#define THEO_OBFUSCATE(...) \
|
||||
_Pragma("code_seg(\".theo\")") \
|
||||
__VA_ARGS__ \
|
||||
_Pragma("code_seg()")
|
||||
|
||||
#define THEO_MUTATE(...) \
|
||||
_Pragma("code_seg(\".theo1\")") \
|
||||
__VA_ARGS__ \
|
||||
_Pragma("code_seg()")
|
||||
|
||||
#define LLVM_BCF __attribute((__annotate__(("bcf"))))
|
||||
#define LLVM_SUB __attribute((__annotate__(("sub"))))
|
||||
#define LLVM_FLA __attribute((__annotate__(("fla"))))
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
*.inc linguist-language=C
|
@ -1,101 +0,0 @@
|
||||
# Created by https://www.gitignore.io/api/c,c++,cmake
|
||||
|
||||
### C ###
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
|
||||
|
||||
### C++ ###
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
|
||||
### CMake ###
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
CTestTestfile.cmake
|
||||
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
|
||||
build*
|
||||
|
||||
# MSVC
|
||||
.vs
|
||||
*.vcxproj.user
|
||||
*.suo
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
msvc/**/*.user
|
||||
msvc/**/obj/
|
||||
msvc/**/bin/
|
||||
|
||||
doc/html
|
||||
|
||||
.vscode
|
||||
.idea
|
||||
cmake-build-debug
|
@ -1,3 +0,0 @@
|
||||
[submodule "dependencies/zycore"]
|
||||
path = dependencies/zycore
|
||||
url = https://github.com/zyantific/zycore-c
|
@ -1,296 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
||||
|
||||
project(Zydis VERSION 3.1.0.0 LANGUAGES C CXX)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# =============================================================================================== #
|
||||
# Overridable options #
|
||||
# =============================================================================================== #
|
||||
|
||||
# Features
|
||||
option(ZYDIS_MINIMAL_MODE
|
||||
"Enable minimal mode (forces ZYDIS_DECODER_MODE_MINIMAL runtime option)"
|
||||
OFF)
|
||||
option(ZYDIS_FEATURE_DECODER
|
||||
"Enable instruction decoding functionality"
|
||||
ON)
|
||||
option(ZYDIS_FEATURE_FORMATTER
|
||||
"Enable instruction formatting functionality"
|
||||
ON)
|
||||
option(ZYDIS_FEATURE_AVX512
|
||||
"Enable support for AVX-512 instructions"
|
||||
ON)
|
||||
option(ZYDIS_FEATURE_KNC
|
||||
"Enable support for KNC instructions"
|
||||
ON)
|
||||
|
||||
# Build configuration
|
||||
option(ZYDIS_BUILD_SHARED_LIB
|
||||
"Build shared library"
|
||||
OFF)
|
||||
option(ZYDIS_BUILD_EXAMPLES
|
||||
"Build examples"
|
||||
ON)
|
||||
option(ZYDIS_BUILD_TOOLS
|
||||
"Build tools"
|
||||
ON)
|
||||
option(ZYDIS_FUZZ_AFL_FAST
|
||||
"Enables AFL persistent mode and reduces prints in ZydisFuzzIn"
|
||||
OFF)
|
||||
option(ZYDIS_LIBFUZZER
|
||||
"Enables LLVM libfuzzer mode and reduces prints in ZydisFuzzIn"
|
||||
OFF)
|
||||
set(ZYDIS_ZYCORE_PATH
|
||||
"${CMAKE_CURRENT_LIST_DIR}/dependencies/zycore"
|
||||
CACHE
|
||||
PATH
|
||||
"The path to look for Zycore")
|
||||
|
||||
# =============================================================================================== #
|
||||
# Dependencies #
|
||||
# =============================================================================================== #
|
||||
|
||||
# Try to initialize the Zycore submodule using Git
|
||||
if (NOT EXISTS "${ZYDIS_ZYCORE_PATH}/CMakeLists.txt" AND
|
||||
"${ZYDIS_ZYCORE_PATH}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}/dependencies/zycore")
|
||||
find_package(Git QUIET)
|
||||
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (NOT EXISTS "${ZYDIS_ZYCORE_PATH}/CMakeLists.txt")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Can't find zycore submodule. Please make sure to clone the repo recursively.\n"
|
||||
"You can fix this by running\n"
|
||||
" git submodule update --init\n"
|
||||
"or by cloning using\n"
|
||||
" git clone --recursive <url>\n"
|
||||
"Alternatively, you can manually clone zycore to some path and set ZYDIS_ZYCORE_PATH."
|
||||
)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(${ZYDIS_ZYCORE_PATH} "zycore" EXCLUDE_FROM_ALL)
|
||||
|
||||
# =============================================================================================== #
|
||||
# Library configuration #
|
||||
# =============================================================================================== #
|
||||
|
||||
if (ZYDIS_BUILD_SHARED_LIB)
|
||||
add_library("Zydis" SHARED)
|
||||
else ()
|
||||
add_library("Zydis" STATIC)
|
||||
endif ()
|
||||
|
||||
target_link_libraries("Zydis" PUBLIC "Zycore")
|
||||
target_include_directories("Zydis"
|
||||
PUBLIC "include" ${PROJECT_BINARY_DIR}
|
||||
PRIVATE "src")
|
||||
target_compile_definitions("Zydis" PRIVATE "_CRT_SECURE_NO_WARNINGS" "ZYDIS_EXPORTS")
|
||||
zyan_set_common_flags("Zydis")
|
||||
zyan_maybe_enable_wpo_for_lib("Zydis")
|
||||
generate_export_header("Zydis" BASE_NAME "ZYDIS" EXPORT_FILE_NAME "ZydisExportConfig.h")
|
||||
|
||||
if (ZYDIS_FEATURE_FORMATTER AND NOT ZYDIS_FEATURE_DECODER)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"\nZYDIS_FEATURE_FORMATTER requires ZYDIS_FEATURE_DECODER to be enabled"
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (ZYDIS_MINIMAL_MODE)
|
||||
target_compile_definitions("Zydis" PUBLIC "ZYDIS_MINIMAL_MODE")
|
||||
endif ()
|
||||
if (NOT ZYDIS_FEATURE_DECODER)
|
||||
target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_DECODER")
|
||||
endif ()
|
||||
if (NOT ZYDIS_FEATURE_FORMATTER)
|
||||
target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_FORMATTER")
|
||||
endif ()
|
||||
if (NOT ZYDIS_FEATURE_AVX512)
|
||||
target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_AVX512")
|
||||
endif ()
|
||||
if (NOT ZYDIS_FEATURE_KNC)
|
||||
target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_KNC")
|
||||
endif ()
|
||||
|
||||
target_sources("Zydis"
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/MetaInfo.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Mnemonic.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Register.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/SharedTypes.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/ShortString.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Status.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Utils.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Zydis.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/SharedData.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/String.h"
|
||||
"src/MetaInfo.c"
|
||||
"src/Mnemonic.c"
|
||||
"src/Register.c"
|
||||
"src/SharedData.c"
|
||||
"src/String.c"
|
||||
"src/Utils.c"
|
||||
"src/Zydis.c")
|
||||
|
||||
if (ZYDIS_FEATURE_DECODER)
|
||||
target_sources("Zydis"
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Decoder.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/DecoderTypes.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/DecoderData.h"
|
||||
"src/Decoder.c"
|
||||
"src/DecoderData.c")
|
||||
if (ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE))
|
||||
target_sources("Zydis"
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Formatter.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/FormatterBuffer.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterATT.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterBase.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Internal/FormatterIntel.h"
|
||||
"src/Formatter.c"
|
||||
"src/FormatterBuffer.c"
|
||||
"src/FormatterATT.c"
|
||||
"src/FormatterBase.c"
|
||||
"src/FormatterIntel.c")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (ZYDIS_BUILD_SHARED_LIB AND WIN32)
|
||||
target_sources("Zydis" PRIVATE "resources/VersionInfo.rc")
|
||||
endif ()
|
||||
|
||||
zyan_set_source_group("Zydis")
|
||||
|
||||
configure_package_config_file(cmake/zydis-config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zydis-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/cmake"
|
||||
)
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zydis-config.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/cmake"
|
||||
)
|
||||
|
||||
install(TARGETS "Zydis"
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/ZydisExportConfig.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
install(DIRECTORY "include/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
function (_maybe_set_emscripten_cfg target)
|
||||
if (EMSCRIPTEN)
|
||||
# Yep, that madness below is how Emscripten likes its quotes.
|
||||
set_target_properties("${target}"
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
"-s \"EXPORT_NAME='${target}'\" -s MODULARIZE=1")
|
||||
set_target_properties("${target}"
|
||||
PROPERTIES LINK_FLAGS_RELEASE
|
||||
"-s \"EXPORT_NAME='${target}'\" -s MODULARIZE=1")
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
# =============================================================================================== #
|
||||
# Examples #
|
||||
# =============================================================================================== #
|
||||
|
||||
if (ZYDIS_BUILD_EXAMPLES AND NOT ZYAN_NO_LIBC)
|
||||
if (ZYDIS_FEATURE_DECODER AND ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE))
|
||||
add_executable("Formatter01" "examples/Formatter01.c")
|
||||
target_link_libraries("Formatter01" "Zydis")
|
||||
set_target_properties("Formatter01" PROPERTIES FOLDER "Examples/Formatter")
|
||||
target_compile_definitions("Formatter01" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("Formatter01")
|
||||
zyan_maybe_enable_wpo("Formatter01")
|
||||
_maybe_set_emscripten_cfg("Formatter01")
|
||||
|
||||
add_executable("Formatter02" "examples/Formatter02.c")
|
||||
target_link_libraries("Formatter02" "Zydis")
|
||||
set_target_properties("Formatter02" PROPERTIES FOLDER "Examples/Formatter")
|
||||
target_compile_definitions("Formatter02" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("Formatter02")
|
||||
zyan_maybe_enable_wpo("Formatter02")
|
||||
_maybe_set_emscripten_cfg("Formatter02")
|
||||
|
||||
add_executable("Formatter03" "examples/Formatter03.c")
|
||||
target_link_libraries("Formatter03" "Zydis")
|
||||
set_target_properties("Formatter03" PROPERTIES FOLDER "Examples/Formatter")
|
||||
target_compile_definitions("Formatter03" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("Formatter03")
|
||||
zyan_maybe_enable_wpo("Formatter03")
|
||||
_maybe_set_emscripten_cfg("Formatter03")
|
||||
|
||||
add_executable("ZydisPerfTest" "examples/ZydisPerfTest.c")
|
||||
target_link_libraries("ZydisPerfTest" "Zydis")
|
||||
set_target_properties("ZydisPerfTest" PROPERTIES FOLDER "Examples")
|
||||
target_compile_definitions("ZydisPerfTest" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("ZydisPerfTest")
|
||||
zyan_maybe_enable_wpo("ZydisPerfTest")
|
||||
_maybe_set_emscripten_cfg("ZydisPerfTest")
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"
|
||||
OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_compile_definitions("ZydisPerfTest" PRIVATE "_GNU_SOURCE")
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries("ZydisPerfTest" Threads::Threads)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# =============================================================================================== #
|
||||
# Tools #
|
||||
# =============================================================================================== #
|
||||
|
||||
if (ZYDIS_BUILD_TOOLS AND NOT ZYAN_NO_LIBC)
|
||||
if (ZYDIS_FEATURE_DECODER AND ZYDIS_FEATURE_FORMATTER AND (NOT ZYDIS_MINIMAL_MODE))
|
||||
add_executable("ZydisDisasm" "tools/ZydisDisasm.c")
|
||||
target_link_libraries("ZydisDisasm" "Zydis")
|
||||
set_target_properties ("ZydisDisasm" PROPERTIES FOLDER "Tools")
|
||||
target_compile_definitions("ZydisDisasm" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("ZydisDisasm")
|
||||
zyan_maybe_enable_wpo("ZydisDisasm")
|
||||
_maybe_set_emscripten_cfg("ZydisDisasm")
|
||||
install(TARGETS "ZydisDisasm" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
add_executable("ZydisFuzzIn" "tools/ZydisFuzzIn.c")
|
||||
target_link_libraries("ZydisFuzzIn" "Zydis")
|
||||
set_target_properties("ZydisFuzzIn" PROPERTIES FOLDER "Tools")
|
||||
target_compile_definitions("ZydisFuzzIn" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("ZydisFuzzIn")
|
||||
zyan_maybe_enable_wpo("ZydisFuzzIn")
|
||||
_maybe_set_emscripten_cfg("ZydisFuzzIn")
|
||||
if (ZYDIS_FUZZ_AFL_FAST)
|
||||
target_compile_definitions("ZydisFuzzIn" PRIVATE "ZYDIS_FUZZ_AFL_FAST")
|
||||
endif ()
|
||||
if (ZYDIS_LIBFUZZER)
|
||||
target_compile_definitions("ZydisFuzzIn" PRIVATE "ZYDIS_LIBFUZZER")
|
||||
endif ()
|
||||
|
||||
add_executable("ZydisInfo" "tools/ZydisInfo.c")
|
||||
target_link_libraries("ZydisInfo" "Zydis")
|
||||
set_target_properties ("ZydisInfo" PROPERTIES FOLDER "Tools")
|
||||
target_compile_definitions("ZydisInfo" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("ZydisInfo")
|
||||
zyan_maybe_enable_wpo("ZydisInfo")
|
||||
_maybe_set_emscripten_cfg("ZydisInfo")
|
||||
install(TARGETS "ZydisInfo" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
add_executable("ZydisPE" "tools/ZydisPE.c")
|
||||
target_link_libraries("ZydisPE" "Zydis")
|
||||
set_target_properties ("ZydisPE" PROPERTIES FOLDER "Tools")
|
||||
target_compile_definitions("ZydisPE" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_set_common_flags("ZydisPE")
|
||||
zyan_maybe_enable_wpo("ZydisPE")
|
||||
_maybe_set_emscripten_cfg("ZydisPE")
|
||||
endif ()
|
||||
endif ()
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
||||
@INCLUDE = Doxyfile
|
||||
GENERATE_HTML = NO
|
||||
GENERATE_XML = YES
|
||||
XML_PROGRAMLISTING = NO
|
||||
##!M_LINKS_NAVBAR1 = modules files
|
||||
##!M_LINKS_NAVBAR2 =
|
||||
##!M_FILE_TREE_EXPAND_LEVELS = 2
|
@ -1,23 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2020 Florian Bernd
|
||||
Copyright (c) 2014-2020 Joel Höner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
@ -1,175 +0,0 @@
|
||||
<p align="center">
|
||||
<img alt="zydis logo" src="https://zydis.re/img/logo.svg" width="400px">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT">
|
||||
<a href="https://github.com/zyantific/zydis/actions"><img src="https://github.com/zyantific/zydis/workflows/GitHub%20Actions%20CI/badge.svg" alt="GitHub Actions"></a>
|
||||
<a href="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zydis"><img src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/zydis.svg" alt="Fuzzing Status"></a>
|
||||
<a href="https://gitter.im/zyantific/zydis?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge"><img src="https://badges.gitter.im/zyantific/zyan-disassembler-engine.svg" alt="Gitter"></a>
|
||||
<a href="https://discord.zyantific.com/"><img src="https://img.shields.io/discord/390136917779415060.svg?logo=discord&label=Discord" alt="Discord"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">Fast and lightweight x86/x86-64 disassembler library.</p>
|
||||
|
||||
## Features
|
||||
- Supports all x86 and x86-64 (AMD64) instructions and [extensions](./include/Zydis/Generated/EnumISAExt.h)
|
||||
- Optimized for high performance
|
||||
- No dynamic memory allocation ("malloc")
|
||||
- Thread-safe by design
|
||||
- Very small file-size overhead compared to other common disassembler libraries
|
||||
- [Complete doxygen documentation](https://zydis.re/doc/3/)
|
||||
- Absolutely no third party dependencies — not even libc
|
||||
- Should compile on any platform with a working C99 compiler
|
||||
- Tested on Windows, macOS, FreeBSD, Linux and UEFI, both user and kernel mode
|
||||
|
||||
## Quick Example
|
||||
The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console ([more examples here](./examples/)).
|
||||
|
||||
```C
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <Zydis/Zydis.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ZyanU8 data[] =
|
||||
{
|
||||
0x51, 0x8D, 0x45, 0xFF, 0x50, 0xFF, 0x75, 0x0C, 0xFF, 0x75,
|
||||
0x08, 0xFF, 0x15, 0xA0, 0xA5, 0x48, 0x76, 0x85, 0xC0, 0x0F,
|
||||
0x88, 0xFC, 0xDA, 0x02, 0x00
|
||||
};
|
||||
|
||||
// Initialize decoder context
|
||||
ZydisDecoder decoder;
|
||||
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
|
||||
|
||||
// Initialize formatter. Only required when you actually plan to do instruction
|
||||
// formatting ("disassembling"), like we do here
|
||||
ZydisFormatter formatter;
|
||||
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||
|
||||
// Loop over the instructions in our buffer.
|
||||
// The runtime-address (instruction pointer) is chosen arbitrary here in order to better
|
||||
// visualize relative addressing
|
||||
ZyanU64 runtime_address = 0x007FFFFFFF400000;
|
||||
ZyanUSize offset = 0;
|
||||
const ZyanUSize length = sizeof(data);
|
||||
ZydisDecodedInstruction instruction;
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, data + offset, length - offset,
|
||||
&instruction)))
|
||||
{
|
||||
// Print current instruction pointer.
|
||||
printf("%016" PRIX64 " ", runtime_address);
|
||||
|
||||
// Format & print the binary instruction structure to human readable format
|
||||
char buffer[256];
|
||||
ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer),
|
||||
runtime_address);
|
||||
puts(buffer);
|
||||
|
||||
offset += instruction.length;
|
||||
runtime_address += instruction.length;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Sample Output
|
||||
The above example program generates the following output:
|
||||
|
||||
```asm
|
||||
007FFFFFFF400000 push rcx
|
||||
007FFFFFFF400001 lea eax, [rbp-0x01]
|
||||
007FFFFFFF400004 push rax
|
||||
007FFFFFFF400005 push qword ptr [rbp+0x0C]
|
||||
007FFFFFFF400008 push qword ptr [rbp+0x08]
|
||||
007FFFFFFF40000B call [0x008000007588A5B1]
|
||||
007FFFFFFF400011 test eax, eax
|
||||
007FFFFFFF400013 js 0x007FFFFFFF42DB15
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
#### Unix
|
||||
Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C99 compiler.
|
||||
|
||||
```bash
|
||||
git clone --recursive 'https://github.com/zyantific/zydis.git'
|
||||
cd zydis
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
#### Windows
|
||||
Either use the [Visual Studio 2017 project](./msvc/) or build Zydis using [CMake](https://cmake.org/download/) ([video guide](https://www.youtube.com/watch?v=fywLDK1OAtQ)).
|
||||
|
||||
#### Building Zydis - Using vcpkg
|
||||
|
||||
You can download and install Zydis using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install zydis
|
||||
```
|
||||
The Zydis port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Using Zydis in a CMake project
|
||||
An example on how to use Zydis in your own CMake based project [can be found in this repo](https://github.com/zyantific/zydis-submodule-example).
|
||||
|
||||
## `ZydisInfo` tool
|
||||
![ZydisInfo](./assets/screenshots/ZydisInfo.png)
|
||||
|
||||
## Bindings
|
||||
Official bindings exist for a selection of languages:
|
||||
- [Pascal](https://github.com/zyantific/zydis-pascal)
|
||||
- [Python 3](https://github.com/zyantific/zydis-py)
|
||||
- [Rust](https://github.com/zyantific/zydis-rs)
|
||||
|
||||
Unofficial but actively maintained bindings:
|
||||
- [Go](https://github.com/jpap/go-zydis)
|
||||
- [LuaJIT](https://github.com/Wiladams/lj2zydis)
|
||||
- [Haskell](https://github.com/nerded1337/zydiskell)
|
||||
|
||||
## Versions
|
||||
|
||||
#### Scheme
|
||||
Versions follow the [semantic versioning scheme](https://semver.org/). All stability guarantees apply to the API only — ABI stability between patches cannot be assumed unless explicitly mentioned in the release notes.
|
||||
|
||||
#### Branches & Tags
|
||||
- `master` holds the bleeding edge code of the next, unreleased Zydis version. Elevated amounts of bugs and issues must be expected, API stability is not guaranteed outside of tagged commits.
|
||||
- Stable and preview versions are annotated with git tags
|
||||
- beta and other preview versions have `-beta`, `-rc`, etc. suffixes
|
||||
- `maintenance/v2` contains the code of the latest legacy release of v2
|
||||
- v2 is now deprecated, but will receive security fixes until 2021
|
||||
|
||||
## Credits
|
||||
- Intel (for open-sourcing [XED](https://github.com/intelxed/xed), allowing for automatic comparision of our tables against theirs, improving both)
|
||||
- [LLVM](https://llvm.org) (for providing pretty solid instruction data as well)
|
||||
- Christian Ludloff (http://sandpile.org, insanely helpful)
|
||||
- [LekoArts](https://www.lekoarts.de/) (for creating the project logo)
|
||||
- Our [contributors on GitHub](https://github.com/zyantific/zydis/graphs/contributors)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
#### `-fPIC` for shared library builds
|
||||
|
||||
```
|
||||
/usr/bin/ld: ./libfoo.a(foo.c.o): relocation R_X86_64_PC32 against symbol `bar' can not be used when making a shared object; recompile with -fPIC
|
||||
```
|
||||
|
||||
Under some circumstances (e.g. when building Zydis as a static library using
|
||||
CMake and then using Makefiles to manually link it into a shared library), CMake
|
||||
might fail to detect that relocation information must be emitted. This can be forced
|
||||
by passing `-DCMAKE_POSITION_INDEPENDENT_CODE=ON` to the CMake invocation.
|
||||
|
||||
## Donations
|
||||
|
||||
Since GitHub Sponsors currently doesn't support sponsoring teams directly, donations are collected and distributed using [flobernd](https://github.com/users/flobernd/sponsorship)s account.
|
||||
|
||||
## License
|
||||
|
||||
Zydis is licensed under the MIT license.
|
@ -1,41 +0,0 @@
|
||||
|
||||
#ifndef ZYDIS_EXPORT_H
|
||||
#define ZYDIS_EXPORT_H
|
||||
|
||||
#ifdef ZYDIS_STATIC_DEFINE
|
||||
# define ZYDIS_EXPORT
|
||||
# define ZYDIS_NO_EXPORT
|
||||
#else
|
||||
# ifndef ZYDIS_EXPORT
|
||||
# ifdef Zydis_EXPORTS
|
||||
/* We are building this library */
|
||||
# define ZYDIS_EXPORT
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define ZYDIS_EXPORT
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ZYDIS_NO_EXPORT
|
||||
# define ZYDIS_NO_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DEPRECATED
|
||||
# define ZYDIS_DEPRECATED __attribute__ ((__deprecated__))
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DEPRECATED_EXPORT
|
||||
# define ZYDIS_DEPRECATED_EXPORT ZYDIS_EXPORT ZYDIS_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifndef ZYDIS_DEPRECATED_NO_EXPORT
|
||||
# define ZYDIS_DEPRECATED_NO_EXPORT ZYDIS_NO_EXPORT ZYDIS_DEPRECATED
|
||||
#endif
|
||||
|
||||
#define DEFINE_NO_DEPRECATED 0
|
||||
#if DEFINE_NO_DEPRECATED
|
||||
# define ZYDIS_NO_DEPRECATED
|
||||
#endif
|
||||
|
||||
#endif
|
Binary file not shown.
Before Width: | Height: | Size: 58 KiB |
@ -1,4 +0,0 @@
|
||||
- CMakeLists (VERSION)
|
||||
- Doxyfile
|
||||
- resources/VersionInfo.rc (4 locations)
|
||||
- include/Zydis/Zydis.h (ZYDIS_VERSION macro)
|
@ -1,8 +0,0 @@
|
||||
set(zydis_VERSION @PROJECT_VERSION@)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set_and_check(zydis_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
|
||||
set_and_check(zydis_LIB_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
|
||||
|
||||
check_required_components(zydis)
|
@ -1,100 +0,0 @@
|
||||
# Created by https://www.gitignore.io/api/c,c++,cmake
|
||||
|
||||
### C ###
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
|
||||
|
||||
### C++ ###
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
|
||||
### CMake ###
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
CTestTestfile.cmake
|
||||
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
|
||||
build*
|
||||
|
||||
# MSVC
|
||||
.vs
|
||||
*.vcxproj.user
|
||||
*.suo
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
msvc/**/obj/
|
||||
msvc/**/bin/
|
||||
|
||||
doc/html
|
||||
|
||||
/.vscode
|
||||
/.idea
|
||||
/cmake-build-*
|
@ -1,266 +0,0 @@
|
||||
if (TARGET Zycore)
|
||||
return()
|
||||
endif ()
|
||||
|
||||
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
||||
include(GenerateExportHeader)
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
project(Zycore VERSION 1.0.0.0 LANGUAGES C CXX)
|
||||
|
||||
# =============================================================================================== #
|
||||
# Overridable options #
|
||||
# =============================================================================================== #
|
||||
|
||||
# Global configuration
|
||||
option(ZYAN_WHOLE_PROGRAM_OPTIMIZATION
|
||||
"Enable whole program optimization (all targets)"
|
||||
OFF)
|
||||
option(ZYAN_NO_LIBC
|
||||
"Don't use any C standard library functions (for exotic build-envs like kernel drivers)"
|
||||
OFF)
|
||||
option(ZYAN_DEV_MODE
|
||||
"Enable developer mode (-Wall, -Werror, ...)"
|
||||
OFF)
|
||||
|
||||
# Build configuration
|
||||
option(ZYCORE_BUILD_SHARED_LIB
|
||||
"Build shared library"
|
||||
OFF)
|
||||
option(ZYCORE_BUILD_EXAMPLES
|
||||
"Build examples"
|
||||
OFF)
|
||||
option(ZYCORE_BUILD_TESTS
|
||||
"Build tests"
|
||||
OFF)
|
||||
|
||||
# =============================================================================================== #
|
||||
# GoogleTest #
|
||||
# =============================================================================================== #
|
||||
|
||||
# Download and unpack googletest
|
||||
if (ZYCORE_BUILD_TESTS)
|
||||
if (NOT DEFINED ZYCORE_DOWNLOADED_GTEST)
|
||||
configure_file("CMakeLists.txt.in" "${CMAKE_BINARY_DIR}/gtest/download/CMakeLists.txt")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/gtest/download")
|
||||
if (result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/gtest/download")
|
||||
if (result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
set(ZYCORE_DOWNLOADED_GTEST TRUE CACHE BOOL "")
|
||||
mark_as_advanced(ZYCORE_DOWNLOADED_GTEST)
|
||||
endif ()
|
||||
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
add_subdirectory("${CMAKE_BINARY_DIR}/gtest/src" "${CMAKE_BINARY_DIR}/gtest/build"
|
||||
EXCLUDE_FROM_ALL)
|
||||
endif ()
|
||||
|
||||
# =============================================================================================== #
|
||||
# Exported functions #
|
||||
# =============================================================================================== #
|
||||
|
||||
function (zyan_set_common_flags target)
|
||||
if (NOT MSVC)
|
||||
target_compile_options("${target}" PRIVATE "-std=c99")
|
||||
endif ()
|
||||
|
||||
if (ZYAN_DEV_MODE)
|
||||
# If in developer mode, be pedantic.
|
||||
if (MSVC)
|
||||
target_compile_options("${target}" PUBLIC "/WX" "/W4")
|
||||
else ()
|
||||
target_compile_options("${target}" PUBLIC "-Wall" "-pedantic" "-Wextra" "-Werror")
|
||||
endif ()
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
function (zyan_set_source_group target)
|
||||
if (ZYAN_DEV_MODE)
|
||||
if (((CMAKE_MAJOR_VERSION GREATER 3) OR (CMAKE_MAJOR_VERSION EQUAL 3)) AND
|
||||
((CMAKE_MINOR_VERSION GREATER 8) OR (CMAKE_MINOR_VERSION EQUAL 8)))
|
||||
# Mirror directory structure in project files
|
||||
get_property("TARGET_SOURCE_FILES" TARGET "${target}" PROPERTY SOURCES)
|
||||
source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${TARGET_SOURCE_FILES})
|
||||
endif ()
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
function (zyan_maybe_enable_wpo target)
|
||||
if (ZYAN_WHOLE_PROGRAM_OPTIMIZATION AND MSVC)
|
||||
set_target_properties("${target}" PROPERTIES COMPILE_FLAGS "/GL")
|
||||
set_target_properties("${target}" PROPERTIES LINK_FLAGS_RELEASE "/LTCG")
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
function (zyan_maybe_enable_wpo_for_lib target)
|
||||
if (ZYAN_WHOLE_PROGRAM_OPTIMIZATION AND MSVC)
|
||||
set_target_properties("${target}" PROPERTIES COMPILE_FLAGS "/GL")
|
||||
set_target_properties("${target}" PROPERTIES LINK_FLAGS_RELEASE "/LTCG")
|
||||
set_target_properties("${target}" PROPERTIES STATIC_LIBRARY_FLAGS_RELEASE "/LTCG")
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
# =============================================================================================== #
|
||||
# Library configuration #
|
||||
# =============================================================================================== #
|
||||
|
||||
if (ZYCORE_BUILD_SHARED_LIB)
|
||||
add_library("Zycore" SHARED)
|
||||
else ()
|
||||
add_library("Zycore" STATIC)
|
||||
endif ()
|
||||
|
||||
set_target_properties("Zycore" PROPERTIES LINKER_LANGUAGE C)
|
||||
target_include_directories("Zycore"
|
||||
PUBLIC "include" ${PROJECT_BINARY_DIR}
|
||||
PRIVATE "src")
|
||||
target_compile_definitions("Zycore" PRIVATE "_CRT_SECURE_NO_WARNINGS" "ZYCORE_EXPORTS")
|
||||
zyan_set_common_flags("Zycore")
|
||||
zyan_maybe_enable_wpo_for_lib("Zycore")
|
||||
generate_export_header("Zycore" BASE_NAME "ZYCORE" EXPORT_FILE_NAME "ZycoreExportConfig.h")
|
||||
|
||||
if (ZYAN_NO_LIBC)
|
||||
target_compile_definitions("Zycore" PUBLIC "ZYAN_NO_LIBC")
|
||||
if (UNIX)
|
||||
set_target_properties("Zycore" PROPERTIES LINK_FLAGS "-nostdlib -nodefaultlibs")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
target_sources("Zycore"
|
||||
PRIVATE
|
||||
# API
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Memory.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Process.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Synchronization.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Terminal.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/API/Thread.h"
|
||||
# Common
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Allocator.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/ArgParse.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Bitset.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Comparison.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Defines.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Format.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/LibC.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/List.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Object.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Status.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/String.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Types.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Vector.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/include/Zycore/Zycore.h"
|
||||
# Common
|
||||
"src/Allocator.c"
|
||||
"src/ArgParse.c"
|
||||
"src/Bitset.c"
|
||||
"src/Format.c"
|
||||
"src/List.c"
|
||||
"src/String.c"
|
||||
"src/Vector.c"
|
||||
"src/Zycore.c")
|
||||
|
||||
if (NOT ZYAN_NO_LIBC)
|
||||
target_sources("Zycore"
|
||||
PRIVATE
|
||||
# API
|
||||
"src/API/Memory.c"
|
||||
"src/API/Process.c"
|
||||
"src/API/Synchronization.c"
|
||||
"src/API/Terminal.c"
|
||||
"src/API/Thread.c")
|
||||
endif ()
|
||||
|
||||
if (ZYCORE_BUILD_SHARED_LIB AND WIN32)
|
||||
target_sources("Zycore" PRIVATE "resources/VersionInfo.rc")
|
||||
endif ()
|
||||
|
||||
zyan_set_source_group("Zycore")
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ZYAN_NO_LIBC)
|
||||
target_compile_definitions("Zycore" PRIVATE "_GNU_SOURCE")
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries("Zycore" Threads::Threads)
|
||||
endif ()
|
||||
|
||||
configure_package_config_file(cmake/zycore-config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zycore-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/cmake"
|
||||
)
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/zycore-config.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/cmake"
|
||||
)
|
||||
|
||||
install(TARGETS "Zycore"
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/ZycoreExportConfig.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
install(DIRECTORY "include/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
# =============================================================================================== #
|
||||
# Developer mode #
|
||||
# =============================================================================================== #
|
||||
|
||||
if (ZYAN_DEV_MODE)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
endif ()
|
||||
|
||||
# =============================================================================================== #
|
||||
# Examples #
|
||||
# =============================================================================================== #
|
||||
|
||||
if (ZYCORE_BUILD_EXAMPLES)
|
||||
add_executable("String" "examples/String.c")
|
||||
zyan_set_common_flags("String" "Zycore")
|
||||
target_link_libraries("String" "Zycore")
|
||||
set_target_properties("String" PROPERTIES FOLDER "Examples")
|
||||
target_compile_definitions("String" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_maybe_enable_wpo("String")
|
||||
|
||||
add_executable("Vector" "examples/Vector.c")
|
||||
zyan_set_common_flags("Vector" "Zycore")
|
||||
target_link_libraries("Vector" "Zycore")
|
||||
set_target_properties("Vector" PROPERTIES FOLDER "Examples")
|
||||
target_compile_definitions("Vector" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_maybe_enable_wpo("Vector")
|
||||
endif ()
|
||||
|
||||
# =============================================================================================== #
|
||||
# Tests #
|
||||
# =============================================================================================== #
|
||||
|
||||
function (zyan_add_test test)
|
||||
add_executable("Test${test}" "tests/${test}.cpp")
|
||||
|
||||
if (NOT MSVC)
|
||||
target_compile_options("Test${test}" PRIVATE "-std=c++17")
|
||||
endif ()
|
||||
|
||||
target_link_libraries("Test${test}" "Zycore")
|
||||
target_link_libraries("Test${test}" "gtest")
|
||||
set_target_properties("Test${test}" PROPERTIES FOLDER "Tests")
|
||||
target_compile_definitions("Test${test}" PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
zyan_maybe_enable_wpo("Test${test}")
|
||||
endfunction ()
|
||||
|
||||
if (ZYCORE_BUILD_TESTS)
|
||||
zyan_add_test("String")
|
||||
zyan_add_test("Vector")
|
||||
zyan_add_test("ArgParse")
|
||||
endif ()
|
||||
|
||||
# =============================================================================================== #
|
@ -1,15 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG ee3aa831172090fd5442820f215cb04ab6062756
|
||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/gtest/src"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/gtest/build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2020 Florian Bernd
|
||||
Copyright (c) 2018-2020 Joel Höner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
@ -1,25 +0,0 @@
|
||||
# Zyan Core Library for C
|
||||
|
||||
Internal library providing platform independent types, macros and a fallback for environments without LibC.
|
||||
|
||||
## Features
|
||||
|
||||
- Platform independent types
|
||||
- Integer types (`ZyanU8`, `ZyanI32`, `ZyanUSize`, ...)
|
||||
- `ZyanBool` (+ `ZYAN_FALSE`, `ZYAN_TRUE`)
|
||||
- `ZYAN_NULL`
|
||||
- Macros
|
||||
- Compiler/Platform/Architecture detection
|
||||
- Asserts and static asserts
|
||||
- Utils (`ARRAY_LENGTH`, `FALLTHROUGH`, `UNUSED`, ...)
|
||||
- Common types
|
||||
- `ZyanBitset`
|
||||
- `ZyanString`/`ZyanStringView`
|
||||
- Container types
|
||||
- `ZyanVector`
|
||||
- `ZyanList`
|
||||
- LibC abstraction (WiP)
|
||||
|
||||
## License
|
||||
|
||||
Zycore is licensed under the MIT license.
|
@ -1,8 +0,0 @@
|
||||
set(zycore_VERSION @PROJECT_VERSION@)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set_and_check(zycore_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
|
||||
set_and_check(zycore_LIB_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
|
||||
|
||||
check_required_components(zycore)
|
@ -1,192 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Demonstrates the `String` implementation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/String.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Tests */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Basic tests */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Performs some basic test on the given `ZyanString` instance.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus PerformBasicTests(ZyanString* string)
|
||||
{
|
||||
ZYAN_ASSERT(string);
|
||||
ZYAN_UNUSED(string);
|
||||
|
||||
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs basic tests on a string that dynamically manages memory.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus TestDynamic(void)
|
||||
{
|
||||
PerformBasicTests(ZYAN_NULL);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs basic tests on a string that uses a static buffer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus TestStatic(void)
|
||||
{
|
||||
PerformBasicTests(ZYAN_NULL);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Custom allocator */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
//static ZyanStatus AllocatorAllocate(ZyanAllocator* allocator, void** p, ZyanUSize element_size,
|
||||
// ZyanUSize n)
|
||||
//{
|
||||
// ZYAN_ASSERT(allocator);
|
||||
// ZYAN_ASSERT(p);
|
||||
// ZYAN_ASSERT(element_size);
|
||||
// ZYAN_ASSERT(n);
|
||||
//
|
||||
// ZYAN_UNUSED(allocator);
|
||||
//
|
||||
// *p = ZYAN_MALLOC(element_size * n);
|
||||
// if (!*p)
|
||||
// {
|
||||
// return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
// }
|
||||
//
|
||||
// return ZYAN_STATUS_SUCCESS;
|
||||
//}
|
||||
//
|
||||
//static ZyanStatus AllocatorReallocate(ZyanAllocator* allocator, void** p, ZyanUSize element_size,
|
||||
// ZyanUSize n)
|
||||
//{
|
||||
// ZYAN_ASSERT(allocator);
|
||||
// ZYAN_ASSERT(p);
|
||||
// ZYAN_ASSERT(element_size);
|
||||
// ZYAN_ASSERT(n);
|
||||
//
|
||||
// ZYAN_UNUSED(allocator);
|
||||
//
|
||||
// void* const x = ZYAN_REALLOC(*p, element_size * n);
|
||||
// if (!x)
|
||||
// {
|
||||
// return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
// }
|
||||
// *p = x;
|
||||
//
|
||||
// return ZYAN_STATUS_SUCCESS;
|
||||
//}
|
||||
//
|
||||
//static ZyanStatus AllocatorDeallocate(ZyanAllocator* allocator, void* p, ZyanUSize element_size,
|
||||
// ZyanUSize n)
|
||||
//{
|
||||
// ZYAN_ASSERT(allocator);
|
||||
// ZYAN_ASSERT(p);
|
||||
// ZYAN_ASSERT(element_size);
|
||||
// ZYAN_ASSERT(n);
|
||||
//
|
||||
// ZYAN_UNUSED(allocator);
|
||||
// ZYAN_UNUSED(element_size);
|
||||
// ZYAN_UNUSED(n);
|
||||
//
|
||||
// ZYAN_FREE(p);
|
||||
//
|
||||
// return ZYAN_STATUS_SUCCESS;
|
||||
//}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Performs basic tests on a vector that dynamically manages memory using a custom
|
||||
* allocator and modified growth-factor/shrink-threshold.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus TestAllocator(void)
|
||||
{
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!ZYAN_SUCCESS(TestDynamic()))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!ZYAN_SUCCESS(TestStatic()))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!ZYAN_SUCCESS(TestAllocator()))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,395 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Demonstrates the `ZyanVector` implementation.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Vector.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `TestStruct` struct that represents a single element in the vector.
|
||||
*/
|
||||
typedef struct TestStruct_
|
||||
{
|
||||
ZyanU32 u32;
|
||||
ZyanU64 u64;
|
||||
float f;
|
||||
} TestStruct;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Initializes the given `TestStruct` struct.
|
||||
*
|
||||
* @param data A pointer to the `TestStruct` struct.
|
||||
* @param n The number to initialize the struct with.
|
||||
*/
|
||||
static void InitTestdata(TestStruct* data, ZyanU32 n)
|
||||
{
|
||||
ZYAN_ASSERT(data);
|
||||
|
||||
data->u32 = n;
|
||||
data->u64 = n;
|
||||
data->f = (float)n;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Tests */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Basic tests */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Performs some basic test on the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus PerformBasicTests(ZyanVector* vector)
|
||||
{
|
||||
ZYAN_ASSERT(vector);
|
||||
|
||||
static TestStruct e_v;
|
||||
static const TestStruct* e_p;
|
||||
|
||||
// Insert `20` elements. The vector automatically manages its size
|
||||
for (ZyanU32 i = 0; i < 20; ++i)
|
||||
{
|
||||
InitTestdata(&e_v, i);
|
||||
ZYAN_CHECK(ZyanVectorPushBack(vector, &e_v));
|
||||
}
|
||||
|
||||
// Remove elements `#05..#09`
|
||||
ZYAN_CHECK(ZyanVectorDeleteRange(vector, 5, 5));
|
||||
|
||||
// Insert a new element at index `#05`
|
||||
InitTestdata(&e_v, 12345678);
|
||||
ZYAN_CHECK(ZyanVectorInsert(vector, 5, &e_v));
|
||||
|
||||
// Change value of element `#15`
|
||||
InitTestdata(&e_v, 87654321);
|
||||
ZYAN_CHECK(ZyanVectorSet(vector, 10, &e_v));
|
||||
|
||||
// Print `u64` of all vector elements
|
||||
ZyanUSize value;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(vector, &value));
|
||||
puts("ELEMENTS");
|
||||
for (ZyanUSize i = 0; i < value; ++i)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(vector, i, (const void**)&e_p));
|
||||
printf(" Element #%02" PRIuPTR ": %08" PRIu64 "\n", i, e_p->u64);
|
||||
}
|
||||
|
||||
// Print infos
|
||||
puts("INFO");
|
||||
printf(" Size : %08" PRIuPTR "\n", value);
|
||||
ZYAN_CHECK(ZyanVectorGetCapacity(vector, &value));
|
||||
printf(" Capacity : %08" PRIuPTR "\n\n", value);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* A dummy comparison function for the `TestStruct` that uses the `u32` field as key
|
||||
* value.
|
||||
*
|
||||
* @param left A pointer to the first element.
|
||||
* @param right A pointer to the second element.
|
||||
*
|
||||
* @return Returns values in the following range:
|
||||
* `left == right -> result == 0`
|
||||
* `left < right -> result < 0`
|
||||
* `left > right -> result > 0`
|
||||
*/
|
||||
static ZyanI32 TestDataComparison(const TestStruct* left, const TestStruct* right)
|
||||
{
|
||||
ZYAN_ASSERT(left);
|
||||
ZYAN_ASSERT(right);
|
||||
|
||||
if (left->u32 < right->u32)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (left->u32 > right->u32)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the binary-search functionality of the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus PerformBinarySearchTest(ZyanVector* vector)
|
||||
{
|
||||
ZYAN_ASSERT(vector);
|
||||
|
||||
static TestStruct e_v;
|
||||
static const TestStruct* e_p;
|
||||
|
||||
ZyanUSize value;
|
||||
ZYAN_CHECK(ZyanVectorGetCapacity(vector, &value));
|
||||
|
||||
// Create a sorted test vector
|
||||
for (ZyanUSize i = 0; i < value; ++i)
|
||||
{
|
||||
const ZyanU32 n = rand() % 100;
|
||||
InitTestdata(&e_v, n);
|
||||
|
||||
ZyanUSize found_index;
|
||||
ZYAN_CHECK(ZyanVectorBinarySearch(vector, &e_v, &found_index,
|
||||
(ZyanComparison)&TestDataComparison));
|
||||
ZYAN_CHECK(ZyanVectorInsert(vector, found_index, &e_v));
|
||||
}
|
||||
|
||||
// Print `u32` of all vector elements
|
||||
ZYAN_CHECK(ZyanVectorGetSize(vector, &value));
|
||||
puts("ELEMENTS");
|
||||
for (ZyanUSize i = 0; i < value; ++i)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(vector, i, (const void**)&e_p));
|
||||
printf(" Element #%02" PRIuPTR ": %08" PRIu32 "\n", i, e_p->u32);
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs basic tests on a vector that dynamically manages memory.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus TestDynamic(void)
|
||||
{
|
||||
// Initialize vector with a base capacity of `10` elements
|
||||
ZyanVector vector;
|
||||
ZYAN_CHECK(ZyanVectorInit(&vector, sizeof(TestStruct), 10, ZYAN_NULL));
|
||||
|
||||
ZYAN_CHECK(PerformBasicTests(&vector));
|
||||
ZYAN_CHECK(ZyanVectorClear(&vector));
|
||||
ZYAN_CHECK(ZyanVectorReserve(&vector, 20));
|
||||
ZYAN_CHECK(PerformBinarySearchTest(&vector));
|
||||
|
||||
// Cleanup
|
||||
return ZyanVectorDestroy(&vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs basic tests on a vector that uses a static buffer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus TestStatic(void)
|
||||
{
|
||||
static TestStruct buffer[20];
|
||||
|
||||
// Initialize vector to use a static buffer with a total capacity of `20` elements.
|
||||
ZyanVector vector;
|
||||
ZYAN_CHECK(ZyanVectorInitCustomBuffer(&vector, sizeof(TestStruct), buffer,
|
||||
ZYAN_ARRAY_LENGTH(buffer), ZYAN_NULL));
|
||||
|
||||
// Compare elements
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&vector, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
static TestStruct* element;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&vector, i, (const void**)&element));
|
||||
if (element->u64 != buffer[i].u64)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
||||
ZYAN_CHECK(PerformBasicTests(&vector));
|
||||
ZYAN_CHECK(ZyanVectorClear(&vector));
|
||||
ZYAN_CHECK(PerformBinarySearchTest(&vector));
|
||||
|
||||
// Cleanup
|
||||
return ZyanVectorDestroy(&vector);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Custom allocator */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static ZyanStatus AllocatorAllocate(ZyanAllocator* allocator, void** p, ZyanUSize element_size,
|
||||
ZyanUSize n)
|
||||
{
|
||||
ZYAN_ASSERT(allocator);
|
||||
ZYAN_ASSERT(p);
|
||||
ZYAN_ASSERT(element_size);
|
||||
ZYAN_ASSERT(n);
|
||||
|
||||
ZYAN_UNUSED(allocator);
|
||||
|
||||
*p = ZYAN_MALLOC(element_size * n);
|
||||
if (!*p)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZyanStatus AllocatorReallocate(ZyanAllocator* allocator, void** p, ZyanUSize element_size,
|
||||
ZyanUSize n)
|
||||
{
|
||||
ZYAN_ASSERT(allocator);
|
||||
ZYAN_ASSERT(p);
|
||||
ZYAN_ASSERT(element_size);
|
||||
ZYAN_ASSERT(n);
|
||||
|
||||
ZYAN_UNUSED(allocator);
|
||||
|
||||
void* const x = ZYAN_REALLOC(*p, element_size * n);
|
||||
if (!x)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
*p = x;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZyanStatus AllocatorDeallocate(ZyanAllocator* allocator, void* p, ZyanUSize element_size,
|
||||
ZyanUSize n)
|
||||
{
|
||||
ZYAN_ASSERT(allocator);
|
||||
ZYAN_ASSERT(p);
|
||||
ZYAN_ASSERT(element_size);
|
||||
ZYAN_ASSERT(n);
|
||||
|
||||
ZYAN_UNUSED(allocator);
|
||||
ZYAN_UNUSED(element_size);
|
||||
ZYAN_UNUSED(n);
|
||||
|
||||
ZYAN_FREE(p);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Performs basic tests on a vector that dynamically manages memory using a custom
|
||||
* allocator and modified growth-factor/shrink-threshold.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus TestAllocator(void)
|
||||
{
|
||||
ZyanAllocator allocator;
|
||||
ZYAN_CHECK(ZyanAllocatorInit(&allocator, &AllocatorAllocate, &AllocatorReallocate,
|
||||
&AllocatorDeallocate));
|
||||
|
||||
// Initialize vector with a base capacity of `10` elements. Growth-factor is set to 10 and
|
||||
// dynamic shrinking is disabled
|
||||
ZyanVector vector;
|
||||
ZYAN_CHECK(ZyanVectorInitEx(&vector, sizeof(TestStruct), 5, ZYAN_NULL, &allocator,
|
||||
10.0f, 0.0f));
|
||||
|
||||
static TestStruct e_v;
|
||||
|
||||
// Insert `10` elements. The vector automatically manages its size
|
||||
for (ZyanU32 i = 0; i < 10; ++i)
|
||||
{
|
||||
InitTestdata(&e_v, i);
|
||||
ZYAN_CHECK(ZyanVectorPushBack(&vector, &e_v));
|
||||
}
|
||||
|
||||
// Check capacity
|
||||
ZyanUSize value;
|
||||
ZYAN_CHECK(ZyanVectorGetCapacity(&vector, &value));
|
||||
if (value != 60) // (5 + 1) * 10.0f
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// Remove all elements
|
||||
ZYAN_CHECK(ZyanVectorClear(&vector));
|
||||
|
||||
// Print infos
|
||||
puts("INFO");
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&vector, &value));
|
||||
printf(" Size : %08" PRIuPTR "\n", value);
|
||||
ZYAN_CHECK(ZyanVectorGetCapacity(&vector, &value));
|
||||
printf(" Capacity : %08" PRIuPTR "\n\n", value);
|
||||
|
||||
// Cleanup
|
||||
return ZyanVectorDestroy(&vector);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main()
|
||||
{
|
||||
time_t t;
|
||||
srand((unsigned)time(&t));
|
||||
|
||||
if (!ZYAN_SUCCESS(TestDynamic()))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!ZYAN_SUCCESS(TestStatic()))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!ZYAN_SUCCESS(TestAllocator()))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,134 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_MEMORY_H
|
||||
#define ZYCORE_API_MEMORY_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
# include <windows.h>
|
||||
#elif defined(ZYAN_POSIX)
|
||||
# include <sys/mman.h>
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanMemoryPageProtection` enum.
|
||||
*/
|
||||
typedef enum ZyanMemoryPageProtection_
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
ZYAN_PAGE_READONLY = PAGE_READONLY,
|
||||
ZYAN_PAGE_READWRITE = PAGE_READWRITE,
|
||||
ZYAN_PAGE_EXECUTE = PAGE_EXECUTE,
|
||||
ZYAN_PAGE_EXECUTE_READ = PAGE_EXECUTE_READ,
|
||||
ZYAN_PAGE_EXECUTE_READWRITE = PAGE_EXECUTE_READWRITE
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
ZYAN_PAGE_READONLY = PROT_READ,
|
||||
ZYAN_PAGE_READWRITE = PROT_READ | PROT_WRITE,
|
||||
ZYAN_PAGE_EXECUTE = PROT_EXEC,
|
||||
ZYAN_PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ,
|
||||
ZYAN_PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE
|
||||
|
||||
#endif
|
||||
} ZyanMemoryPageProtection;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the system page size.
|
||||
*
|
||||
* @return The system page size.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemPageSize();
|
||||
|
||||
/**
|
||||
* Returns the system allocation granularity.
|
||||
*
|
||||
* The system allocation granularity specifies the minimum amount of bytes which can be allocated
|
||||
* at a specific address by a single call of `ZyanMemoryVirtualAlloc`.
|
||||
*
|
||||
* This value is typically 64KiB on Windows systems and equal to the page size on most POSIX
|
||||
* platforms.
|
||||
*
|
||||
* @return The system allocation granularity.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemAllocationGranularity();
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Changes the memory protection value of one or more pages.
|
||||
*
|
||||
* @param address The start address aligned to a page boundary.
|
||||
* @param size The size.
|
||||
* @param protection The new page protection value.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size,
|
||||
ZyanMemoryPageProtection protection);
|
||||
|
||||
/**
|
||||
* Releases one or more memory pages starting at the given address.
|
||||
*
|
||||
* @param address The start address aligned to a page boundary.
|
||||
* @param size The size.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_API_MEMORY_H */
|
@ -1,67 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_PROCESS_H
|
||||
#define ZYCORE_API_PROCESS_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Flushes the process instruction cache.
|
||||
*
|
||||
* @param address The address.
|
||||
* @param size The size.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_API_PROCESS_H */
|
@ -1,133 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_SYNCHRONIZATION_H
|
||||
#define ZYCORE_API_SYNCHRONIZATION_H
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
typedef pthread_mutex_t ZyanCriticalSection;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
typedef CRITICAL_SECTION ZyanCriticalSection;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Initializes a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Enters a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Tries to enter a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the critical section was successfully entered or `ZYAN_FALSE`,
|
||||
* if not.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Leaves a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section);
|
||||
|
||||
/**
|
||||
* Deletes a critical section.
|
||||
*
|
||||
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYAN_NO_LIBC */
|
||||
|
||||
#endif /* ZYCORE_API_SYNCHRONIZATION_H */
|
@ -1,163 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Provides cross-platform terminal helper functions.
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_TERMINAL_H
|
||||
#define ZYCORE_API_TERMINAL_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* VT100 CSI SGR sequences */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_VT100SGR_RESET "\033[0m"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Foreground colors */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_VT100SGR_FG_DEFAULT "\033[39m"
|
||||
|
||||
#define ZYAN_VT100SGR_FG_BLACK "\033[30m"
|
||||
#define ZYAN_VT100SGR_FG_RED "\033[31m"
|
||||
#define ZYAN_VT100SGR_FG_GREEN "\033[32m"
|
||||
#define ZYAN_VT100SGR_FG_YELLOW "\033[33m"
|
||||
#define ZYAN_VT100SGR_FG_BLUE "\033[34m"
|
||||
#define ZYAN_VT100SGR_FG_MAGENTA "\033[35m"
|
||||
#define ZYAN_VT100SGR_FG_CYAN "\033[36m"
|
||||
#define ZYAN_VT100SGR_FG_WHITE "\033[37m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_BLACK "\033[90m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_RED "\033[91m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_GREEN "\033[92m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_YELLOW "\033[93m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_BLUE "\033[94m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_MAGENTA "\033[95m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_CYAN "\033[96m"
|
||||
#define ZYAN_VT100SGR_FG_BRIGHT_WHITE "\033[97m"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Background color */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_VT100SGR_BG_DEFAULT "\033[49m"
|
||||
|
||||
#define ZYAN_VT100SGR_BG_BLACK "\033[40m"
|
||||
#define ZYAN_VT100SGR_BG_RED "\033[41m"
|
||||
#define ZYAN_VT100SGR_BG_GREEN "\033[42m"
|
||||
#define ZYAN_VT100SGR_BG_YELLOW "\033[43m"
|
||||
#define ZYAN_VT100SGR_BG_BLUE "\033[44m"
|
||||
#define ZYAN_VT100SGR_BG_MAGENTA "\033[45m"
|
||||
#define ZYAN_VT100SGR_BG_CYAN "\033[46m"
|
||||
#define ZYAN_VT100SGR_BG_WHITE "\033[47m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_BLACK "\033[100m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_RED "\033[101m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_GREEN "\033[102m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_YELLOW "\033[103m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_BLUE "\033[104m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_MAGENTA "\033[105m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_CYAN "\033[106m"
|
||||
#define ZYAN_VT100SGR_BG_BRIGHT_WHITE "\033[107m"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Declares the `ZyanStandardStream` enum.
|
||||
*/
|
||||
typedef enum ZyanStandardStream_
|
||||
{
|
||||
/**
|
||||
* The default input stream.
|
||||
*/
|
||||
ZYAN_STDSTREAM_IN,
|
||||
/**
|
||||
* The default output stream.
|
||||
*/
|
||||
ZYAN_STDSTREAM_OUT,
|
||||
/**
|
||||
* The default error stream.
|
||||
*/
|
||||
ZYAN_STDSTREAM_ERR
|
||||
} ZyanStandardStream;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Enables VT100 ansi escape codes for the given stream.
|
||||
*
|
||||
* @param stream Either `ZYAN_STDSTREAM_OUT` or `ZYAN_STDSTREAM_ERR`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This functions returns `ZYAN_STATUS_SUCCESS` on all non-Windows systems without performing any
|
||||
* operations, assuming that VT100 is supported by default.
|
||||
*
|
||||
* On Windows systems, VT100 functionality is only supported on Windows 10 build 1607 (anniversary
|
||||
* update) and later.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream);
|
||||
|
||||
/**
|
||||
* Checks, if the given standard stream reads from or writes to a terminal.
|
||||
*
|
||||
* @param stream The standard stream to check.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the stream is bound to a terminal, `ZYAN_STATUS_FALSE` if not,
|
||||
* or another zyan status code if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_API_TERMINAL_H */
|
@ -1,244 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_API_THREAD_H
|
||||
#define ZYCORE_API_THREAD_H
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThread` data-type.
|
||||
*/
|
||||
typedef pthread_t ZyanThread;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadId` data-type.
|
||||
*/
|
||||
typedef ZyanU64 ZyanThreadId;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsIndex` data-type.
|
||||
*/
|
||||
typedef pthread_key_t ZyanThreadTlsIndex;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsCallback` function prototype.
|
||||
*/
|
||||
typedef void(*ZyanThreadTlsCallback)(void* data);
|
||||
|
||||
/**
|
||||
* Declares a Thread Local Storage (TLS) callback function.
|
||||
*
|
||||
* @param name The callback function name.
|
||||
* @param param_type The callback data parameter type.
|
||||
* @param param_name The callback data parameter name.
|
||||
*/
|
||||
#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \
|
||||
void name(param_type* param_name)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThread` data-type.
|
||||
*/
|
||||
typedef HANDLE ZyanThread;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadId` data-type.
|
||||
*/
|
||||
typedef DWORD ZyanThreadId;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsIndex` data-type.
|
||||
*/
|
||||
typedef DWORD ZyanThreadTlsIndex;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanThreadTlsCallback` function prototype.
|
||||
*/
|
||||
typedef PFLS_CALLBACK_FUNCTION ZyanThreadTlsCallback;
|
||||
|
||||
/**
|
||||
* Declares a Thread Local Storage (TLS) callback function.
|
||||
*
|
||||
* @param name The callback function name.
|
||||
* @param param_type The callback data parameter type.
|
||||
* @param param_name The callback data parameter name.
|
||||
*/
|
||||
#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \
|
||||
VOID NTAPI name(param_type* param_name)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the handle of the current thread.
|
||||
*
|
||||
* @param thread Receives the handle of the current thread.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread);
|
||||
|
||||
/**
|
||||
* Returns the unique id of the current thread.
|
||||
*
|
||||
* @param thread_id Receives the unique id of the current thread.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Allocates a new Thread Local Storage (TLS) slot.
|
||||
*
|
||||
* @param index Receives the TLS slot index.
|
||||
* @param destructor A pointer to a destructor callback which is invoked to finalize the data
|
||||
* in the TLS slot or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* The maximum available number of TLS slots is implementation specific and different on each
|
||||
* platform:
|
||||
* - Windows
|
||||
* - A total amount of 128 slots per process are guaranteed
|
||||
* - POSIX
|
||||
* - A total amount of 128 slots per process are guaranteed
|
||||
* - Some systems guarantee larger amounts like e.g. 1024 slots per process
|
||||
*
|
||||
* Note that the invocation rules for the destructor callback are implementation specific and
|
||||
* different on each platform:
|
||||
* - Windows
|
||||
* - The callback is invoked when a thread exits
|
||||
* - The callback is invoked when the process exits
|
||||
* - The callback is invoked when the TLS slot is released
|
||||
* - POSIX
|
||||
* - The callback is invoked when a thread exits and the stored value is not null
|
||||
* - The callback is NOT invoked when the process exits
|
||||
* - The callback is NOT invoked when the TLS slot is released
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index,
|
||||
ZyanThreadTlsCallback destructor);
|
||||
|
||||
/**
|
||||
* Releases a Thread Local Storage (TLS) slot.
|
||||
*
|
||||
* @param index The TLS slot index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index);
|
||||
|
||||
/**
|
||||
* Returns the value inside the given Thread Local Storage (TLS) slot for the
|
||||
* calling thread.
|
||||
*
|
||||
* @param index The TLS slot index.
|
||||
* @param data Receives the value inside the given Thread Local Storage
|
||||
* (TLS) slot for the calling thread.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data);
|
||||
|
||||
/**
|
||||
* Set the value of the given Thread Local Storage (TLS) slot for the calling thread.
|
||||
*
|
||||
* @param index The TLS slot index.
|
||||
* @param data The value to store inside the given Thread Local Storage (TLS) slot for the
|
||||
* calling thread
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYAN_NO_LIBC */
|
||||
|
||||
#endif /* ZYCORE_API_THREAD_H */
|
@ -1,143 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_ALLOCATOR_H
|
||||
#define ZYCORE_ALLOCATOR_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
struct ZyanAllocator_;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanAllocatorAllocate` function prototype.
|
||||
*
|
||||
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||
* @param p Receives a pointer to the first memory block sufficient to hold an
|
||||
* array of `n` elements with a size of `element_size`.
|
||||
* @param element_size The size of a single element.
|
||||
* @param n The number of elements to allocate storage for.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This prototype is used for the `allocate()` and `reallocate()` functions.
|
||||
*
|
||||
* The result of the `reallocate()` function is undefined, if `p` does not point to a memory block
|
||||
* previously obtained by `(re-)allocate()`.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p,
|
||||
ZyanUSize element_size, ZyanUSize n);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanAllocatorDeallocate` function prototype.
|
||||
*
|
||||
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||
* @param p The pointer obtained from `(re-)allocate()`.
|
||||
* @param element_size The size of a single element.
|
||||
* @param n The number of elements earlier passed to `(re-)allocate()`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p,
|
||||
ZyanUSize element_size, ZyanUSize n);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanAllocator` struct.
|
||||
*
|
||||
* This is the base class for all custom allocator implementations.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanAllocator_
|
||||
{
|
||||
/**
|
||||
* The allocate function.
|
||||
*/
|
||||
ZyanAllocatorAllocate allocate;
|
||||
/**
|
||||
* The reallocate function.
|
||||
*/
|
||||
ZyanAllocatorAllocate reallocate;
|
||||
/**
|
||||
* The deallocate function.
|
||||
*/
|
||||
ZyanAllocatorDeallocate deallocate;
|
||||
} ZyanAllocator;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanAllocator` instance.
|
||||
*
|
||||
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||
* @param allocate The allocate function.
|
||||
* @param reallocate The reallocate function.
|
||||
* @param deallocate The deallocate function.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate,
|
||||
ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate);
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Returns the default `ZyanAllocator` instance.
|
||||
*
|
||||
* @return A pointer to the default `ZyanAllocator` instance.
|
||||
*
|
||||
* The default allocator uses the default memory manager to allocate memory on the heap.
|
||||
*
|
||||
* You should in no case modify the returned allocator instance to avoid unexpected behavior.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_ALLOCATOR_H */
|
@ -1,173 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements command-line argument parsing.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_ARGPARSE_H
|
||||
#define ZYCORE_ARGPARSE_H
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Vector.h>
|
||||
#include <Zycore/String.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Structs and other types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Definition of a single argument.
|
||||
*/
|
||||
typedef struct ZyanArgParseDefinition_
|
||||
{
|
||||
/**
|
||||
* The argument name, e.g. `--help`.
|
||||
*
|
||||
* Must start with either one or two dashes. Single dash arguments must consist of a single
|
||||
* character, (e.g. `-n`), double-dash arguments can be of arbitrary length.
|
||||
*/
|
||||
const char* name;
|
||||
/**
|
||||
* Whether the argument is boolean or expects a value.
|
||||
*/
|
||||
ZyanBool boolean;
|
||||
/**
|
||||
* Whether this argument is required (error if missing).
|
||||
*/
|
||||
ZyanBool required;
|
||||
} ZyanArgParseDefinition;
|
||||
|
||||
/**
|
||||
* Configuration for argument parsing.
|
||||
*/
|
||||
typedef struct ZyanArgParseConfig_
|
||||
{
|
||||
/**
|
||||
* `argv` argument passed to `main` by LibC.
|
||||
*/
|
||||
const char** argv;
|
||||
/**
|
||||
* `argc` argument passed to `main` by LibC.
|
||||
*/
|
||||
ZyanUSize argc;
|
||||
/**
|
||||
* Minimum # of accepted unnamed / anonymous arguments.
|
||||
*/
|
||||
ZyanUSize min_unnamed_args;
|
||||
/**
|
||||
* Maximum # of accepted unnamed / anonymous arguments.
|
||||
*/
|
||||
ZyanUSize max_unnamed_args;
|
||||
/**
|
||||
* Argument definition array, or `ZYAN_NULL`.
|
||||
*
|
||||
* Expects a pointer to an array of `ZyanArgParseDefinition` instances. The array is
|
||||
* terminated by setting the `.name` field of the last element to `ZYAN_NULL`. If no named
|
||||
* arguments should be parsed, you can also set this to `ZYAN_NULL`.
|
||||
*/
|
||||
ZyanArgParseDefinition* args;
|
||||
} ZyanArgParseConfig;
|
||||
|
||||
/**
|
||||
* Information about a parsed argument.
|
||||
*/
|
||||
typedef struct ZyanArgParseArg_
|
||||
{
|
||||
/**
|
||||
* Corresponding argument definition, or `ZYAN_NULL` for unnamed args.
|
||||
*
|
||||
* This pointer is borrowed from the `cfg` pointer passed to `ZyanArgParse`.
|
||||
*/
|
||||
const ZyanArgParseDefinition* def;
|
||||
/**
|
||||
* Whether the argument has a value (is non-boolean).
|
||||
*/
|
||||
ZyanBool has_value;
|
||||
/**
|
||||
* If `has_value == true`, then the argument value.
|
||||
*
|
||||
* This is a view into the `argv` string array passed to `ZyanArgParse` via the `cfg` argument.
|
||||
*/
|
||||
ZyanStringView value;
|
||||
} ZyanArgParseArg;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Parse arguments according to a `ZyanArgParseConfig` definition.
|
||||
*
|
||||
* @param cfg Argument parser config to use.
|
||||
* @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is
|
||||
* transferred to the user. Input is expected to be uninitialized. On error,
|
||||
* the vector remains uninitialized.
|
||||
* @param error_token On error, if it makes sense, receives the argument fragment causing the
|
||||
* error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg`
|
||||
* struct and doesn't have to be freed by the user.
|
||||
*
|
||||
* @return A `ZyanStatus` status determining whether the parsing succeeded.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||
const char** error_token);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Parse arguments according to a `ZyanArgParseConfig` definition.
|
||||
*
|
||||
* This version allows specification of a custom memory allocator and thus supports no-libc.
|
||||
*
|
||||
* @param cfg Argument parser config to use.
|
||||
* @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is
|
||||
* transferred to the user. Input is expected to be uninitialized. On error,
|
||||
* the vector remains uninitialized.
|
||||
* @param error_token On error, if it makes sense, receives the argument fragment causing the
|
||||
* error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg`
|
||||
* struct and doesn't have to be freed by the user.
|
||||
* @param allocator The `ZyanAllocator` to be used for allocating the output vector's data.
|
||||
*
|
||||
* @return A `ZyanStatus` status determining whether the parsing succeeded.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||
const char** error_token, ZyanAllocator* allocator);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_ARGPARSE_H */
|
@ -1,484 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the bitset class.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_BITSET_H
|
||||
#define ZYCORE_BITSET_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Vector.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVector` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanBitset_
|
||||
{
|
||||
/**
|
||||
* The bitset size.
|
||||
*/
|
||||
ZyanUSize size;
|
||||
/**
|
||||
* The bitset data.
|
||||
*/
|
||||
ZyanVector bits;
|
||||
} ZyanBitset;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanBitsetByteOperation` function prototype.
|
||||
*
|
||||
* @param v1 A pointer to the first byte. This value receives the result after performing the
|
||||
* desired operation.
|
||||
* @param v2 A pointer to the second byte.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function is used to perform byte-wise operations on two `ZyanBitset` instances.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanBitsetByteOperation)(ZyanU8* v1, const ZyanU8* v2);
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The initial amount of bits.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The space for the bitset is dynamically allocated by the default allocator using the default
|
||||
* growth factor of `2.0f` and the default shrink threshold of `0.5f`.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanBitset` instance and sets a custom `allocator` and memory
|
||||
* allocation/deallocation parameters.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The initial amount of bits.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||
* dynamic shrinking.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count,
|
||||
ZyanAllocator* allocator, float growth_factor, float shrink_threshold);
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanBitset` instance and configures it to use a custom user
|
||||
* defined buffer with a fixed size.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The initial amount of bits.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the bits.
|
||||
* @param capacity The maximum capacity (number of bytes) of the buffer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer,
|
||||
ZyanUSize capacity);
|
||||
|
||||
/**
|
||||
* Destroys the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Logical operations */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Performs a byte-wise `operation` for every byte in the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
* @param operation A pointer to the function that performs the desired operation.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The `operation` callback is invoked once for every byte in the smallest of the `ZyanBitset`
|
||||
* instances.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination,
|
||||
const ZyanBitset* source, ZyanBitsetByteOperation operation);
|
||||
|
||||
/**
|
||||
* Performs a logical `AND` operation on the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||
* bits will be undefined.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source);
|
||||
|
||||
/**
|
||||
* Performs a logical `OR` operation on the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||
* bits will be undefined.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source);
|
||||
|
||||
/**
|
||||
* Performs a logical `XOR` operation on the given `ZyanBitset` instances.
|
||||
*
|
||||
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||
* as the destination.
|
||||
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||
* bits will be undefined.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source);
|
||||
|
||||
/**
|
||||
* Flips all bits of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Bit access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sets the bit at `index` of the given `ZyanBitset` instance to `1`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Sets the bit at `index` of the given `ZyanBitset` instance to `0`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Sets the bit at `index` of the given `ZyanBitset` instance to the specified `value`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
* @param value The new value.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value);
|
||||
|
||||
/**
|
||||
* Toggles the bit at `index` of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns the value of the bit at `index`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not, Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns the value of the most significant bit.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Returns the value of the least significant bit.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sets all bits of the given `ZyanBitset` instance to `1`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Sets all bits of the given `ZyanBitset` instance to `0`.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Size management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new bit at the end of the bitset.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param value The value of the new bit.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value);
|
||||
|
||||
/**
|
||||
* Removes the last bit of the bitset.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetPop(ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Deletes all bits of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetClear(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Changes the capacity of the given `ZyanBitset` instance.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count The new capacity (number of bits).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Shrinks the capacity of the given bitset to match it's size.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current size of the bitset in bits.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param size Receives the size of the bitset in bits.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size);
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the bitset in bits.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param capacity Receives the size of the bitset in bits.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity);
|
||||
|
||||
/**
|
||||
* Returns the current size of the bitset in bytes.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param size Receives the size of the bitset in bytes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size);
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the bitset in bytes.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param capacity Receives the size of the bitset in bytes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the amount of bits set in the given bitset.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
* @param count Receives the amount of bits set in the given bitset.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count);
|
||||
|
||||
/**
|
||||
* Checks, if all bits of the given bitset are set.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if all bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Checks, if at least one bit of the given bitset is set.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if at least one bit is set, `ZYAN_STATUS_FALSE`, if not. Another
|
||||
* zyan status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset);
|
||||
|
||||
/**
|
||||
* Checks, if none bits of the given bitset are set.
|
||||
*
|
||||
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE`, if none bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||
* status code, if an error occured.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset);
|
||||
|
||||
///* ---------------------------------------------------------------------------------------------- */
|
||||
//
|
||||
///**
|
||||
// * Returns a 32-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @param bitset A pointer to the `ZyanBitset` instance.
|
||||
// * @param value Receives the 32-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @return A zyan status code.
|
||||
// */
|
||||
//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value);
|
||||
//
|
||||
///**
|
||||
// * Returns a 64-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @param bitset A pointer to the `ZyanBitset` instance.
|
||||
// * @param value Receives the 64-bit unsigned integer representation of the data.
|
||||
// *
|
||||
// * @return A zyan status code.
|
||||
// */
|
||||
//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_BITSET_H */
|
@ -1,316 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines prototypes of general-purpose comparison functions.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_COMPARISON_H
|
||||
#define ZYCORE_COMPARISON_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanEqualityComparison` function prototype.
|
||||
*
|
||||
* @param left A pointer to the first element.
|
||||
* @param right A pointer to the second element.
|
||||
*
|
||||
* @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one
|
||||
* or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanComparison` function prototype.
|
||||
*
|
||||
* @param left A pointer to the first element.
|
||||
* @param right A pointer to the second element.
|
||||
*
|
||||
* @return This function should return values in the following range:
|
||||
* `left == right -> result == 0`
|
||||
* `left < right -> result < 0`
|
||||
* `left > right -> result > 0`
|
||||
*/
|
||||
typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right);
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Equality comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Declares a generic equality comparison function for an integral data-type.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
*/
|
||||
#define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \
|
||||
ZyanBool name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares a generic equality comparison function that compares a single integral
|
||||
* data-type field of a struct.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
* @param field_name The name of the struct field.
|
||||
*/
|
||||
#define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \
|
||||
ZyanBool name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Declares a generic comparison function for an integral data-type.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
*/
|
||||
#define ZYAN_DECLARE_COMPARISON(name, type) \
|
||||
ZyanI32 name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
if (*left < *right) \
|
||||
{ \
|
||||
return -1; \
|
||||
} \
|
||||
if (*left > *right) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares a generic comparison function that compares a single integral data-type field
|
||||
* of a struct.
|
||||
*
|
||||
* @param name The name of the function.
|
||||
* @param type The name of the integral data-type.
|
||||
* @param field_name The name of the struct field.
|
||||
*/
|
||||
#define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \
|
||||
ZyanI32 name(const type* left, const type* right) \
|
||||
{ \
|
||||
ZYAN_ASSERT(left); \
|
||||
ZYAN_ASSERT(right); \
|
||||
\
|
||||
if (left->field_name < right->field_name) \
|
||||
{ \
|
||||
return -1; \
|
||||
} \
|
||||
if (left->field_name > right->field_name) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Default equality comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for pointer values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for `ZyanBool` values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 8-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 16-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 32-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32)
|
||||
|
||||
/**
|
||||
* Defines a default equality comparison function for 64-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||
* not.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Default comparison functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for pointer values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for `ZyanBool` values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 8-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 16-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 32-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32)
|
||||
|
||||
/**
|
||||
* Defines a default comparison function for 64-bit numeric values.
|
||||
*
|
||||
* @param left A pointer to the first value.
|
||||
* @param right A pointer to the second value.
|
||||
*
|
||||
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||
*/
|
||||
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_COMPARISON_H */
|
@ -1,443 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* General helper and platform detection macros.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_DEFINES_H
|
||||
#define ZYCORE_DEFINES_H
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Meta macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Concatenates two values using the stringify operator (`##`).
|
||||
*
|
||||
* @param x The first value.
|
||||
* @param y The second value.
|
||||
*
|
||||
* @return The combined string of the given values.
|
||||
*/
|
||||
#define ZYAN_MACRO_CONCAT(x, y) x ## y
|
||||
|
||||
/**
|
||||
* Concatenates two values using the stringify operator (`##`) and expands the value to
|
||||
* be used in another macro.
|
||||
*
|
||||
* @param x The first value.
|
||||
* @param y The second value.
|
||||
*
|
||||
* @return The combined string of the given values.
|
||||
*/
|
||||
#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Compiler detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(__clang__)
|
||||
# define ZYAN_CLANG
|
||||
# define ZYAN_GNUC
|
||||
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
||||
# define ZYAN_ICC
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
# define ZYAN_GCC
|
||||
# define ZYAN_GNUC
|
||||
#elif defined(_MSC_VER)
|
||||
# define ZYAN_MSVC
|
||||
#elif defined(__BORLANDC__)
|
||||
# define ZYAN_BORLAND
|
||||
#else
|
||||
# define ZYAN_UNKNOWN_COMPILER
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Platform detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define ZYAN_WINDOWS
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
# define ZYAN_EMSCRIPTEN
|
||||
#elif defined(__APPLE__)
|
||||
# define ZYAN_APPLE
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__linux)
|
||||
# define ZYAN_LINUX
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__FreeBSD__)
|
||||
# define ZYAN_FREEBSD
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(sun) || defined(__sun)
|
||||
# define ZYAN_SOLARIS
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__unix)
|
||||
# define ZYAN_UNIX
|
||||
# define ZYAN_POSIX
|
||||
#elif defined(__posix)
|
||||
# define ZYAN_POSIX
|
||||
#else
|
||||
# define ZYAN_UNKNOWN_PLATFORM
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Kernel mode detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
|
||||
(defined(ZYAN_APPLE) && defined(KERNEL)) || \
|
||||
(defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
|
||||
(defined(__FreeBSD_kernel__))
|
||||
# define ZYAN_KERNEL
|
||||
#else
|
||||
# define ZYAN_USER
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Architecture detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(_M_AMD64) || defined(__x86_64__)
|
||||
# define ZYAN_X64
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
# define ZYAN_X86
|
||||
#elif defined(_M_ARM64) || defined(__aarch64__)
|
||||
# define ZYAN_AARCH64
|
||||
#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
|
||||
# define ZYAN_ARM
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
// Nothing to do, `ZYAN_EMSCRIPTEN` is both platform and arch macro for this one.
|
||||
#else
|
||||
# error "Unsupported architecture detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Debug/Release detection */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
|
||||
# ifdef _DEBUG
|
||||
# define ZYAN_DEBUG
|
||||
# else
|
||||
# define ZYAN_RELEASE
|
||||
# endif
|
||||
#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
|
||||
# ifdef NDEBUG
|
||||
# define ZYAN_RELEASE
|
||||
# else
|
||||
# define ZYAN_DEBUG
|
||||
# endif
|
||||
#else
|
||||
# define ZYAN_RELEASE
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Misc compatibility macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_CLANG)
|
||||
# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
|
||||
#else
|
||||
# define ZYAN_NO_SANITIZE(what)
|
||||
#endif
|
||||
|
||||
#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
|
||||
# define ZYAN_INLINE __inline
|
||||
#else
|
||||
# define ZYAN_INLINE static inline
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Debugging and optimization macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Runtime debug assertion.
|
||||
*/
|
||||
#if defined(ZYAN_NO_LIBC)
|
||||
# define ZYAN_ASSERT(condition) (void)(condition)
|
||||
#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
|
||||
# include <wdm.h>
|
||||
# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
|
||||
#else
|
||||
# include <assert.h>
|
||||
# define ZYAN_ASSERT(condition) assert(condition)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compiler-time assertion.
|
||||
*/
|
||||
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
||||
# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
|
||||
#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
|
||||
(defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||
(defined (_MSC_VER) && (_MSC_VER >= 1800))
|
||||
# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
|
||||
#else
|
||||
# define ZYAN_STATIC_ASSERT(x) \
|
||||
typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Marks the current code path as unreachable.
|
||||
*/
|
||||
#if defined(ZYAN_RELEASE)
|
||||
# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
|
||||
# if __has_builtin(__builtin_unreachable)
|
||||
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||
# else
|
||||
# define ZYAN_UNREACHABLE for(;;)
|
||||
# endif
|
||||
# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
|
||||
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||
# elif defined(ZYAN_ICC)
|
||||
# ifdef ZYAN_WINDOWS
|
||||
# include <stdlib.h> // "missing return statement" workaround
|
||||
# define ZYAN_UNREACHABLE __assume(0); (void)abort()
|
||||
# else
|
||||
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||
# endif
|
||||
# elif defined(ZYAN_MSVC)
|
||||
# define ZYAN_UNREACHABLE __assume(0)
|
||||
# else
|
||||
# define ZYAN_UNREACHABLE for(;;)
|
||||
# endif
|
||||
#elif defined(ZYAN_NO_LIBC)
|
||||
# define ZYAN_UNREACHABLE for(;;)
|
||||
#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
|
||||
# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
# define ZYAN_UNREACHABLE { assert(0); abort(); }
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Utils */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General purpose */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Marks the specified parameter as unused.
|
||||
*
|
||||
* @param x The name of the unused parameter.
|
||||
*/
|
||||
#define ZYAN_UNUSED(x) (void)(x)
|
||||
|
||||
/**
|
||||
* Intentional fallthrough.
|
||||
*/
|
||||
#if defined(ZYAN_GCC) && __GNUC__ >= 7
|
||||
# define ZYAN_FALLTHROUGH __attribute__((fallthrough))
|
||||
#else
|
||||
# define ZYAN_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Declares a bitfield.
|
||||
*
|
||||
* @param x The size (in bits) of the bitfield.
|
||||
*/
|
||||
#define ZYAN_BITFIELD(x) : x
|
||||
|
||||
/**
|
||||
* Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
|
||||
*/
|
||||
#define ZYAN_REQUIRES_LIBC
|
||||
|
||||
/**
|
||||
* Decorator for `printf`-style functions.
|
||||
*
|
||||
* @param format_index The 1-based index of the format string parameter.
|
||||
* @param first_to_check The 1-based index of the format arguments parameter.
|
||||
*/
|
||||
#if defined(__RESHARPER__)
|
||||
# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
|
||||
[[gnu::format(printf, format_index, first_to_check)]]
|
||||
#elif defined(ZYAN_GCC)
|
||||
# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
|
||||
__attribute__((format(printf, format_index, first_to_check)))
|
||||
#else
|
||||
# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decorator for `wprintf`-style functions.
|
||||
*
|
||||
* @param format_index The 1-based index of the format string parameter.
|
||||
* @param first_to_check The 1-based index of the format arguments parameter.
|
||||
*/
|
||||
#if defined(__RESHARPER__)
|
||||
# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
|
||||
[[rscpp::format(wprintf, format_index, first_to_check)]]
|
||||
#else
|
||||
# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Arrays */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the length (number of elements) of an array.
|
||||
*
|
||||
* @param a The name of the array.
|
||||
*
|
||||
* @return The number of elements of the given array.
|
||||
*/
|
||||
#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Arithmetic */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the smaller value of `a` or `b`.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
*
|
||||
* @return The smaller value of `a` or `b`.
|
||||
*/
|
||||
#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* Returns the bigger value of `a` or `b`.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
*
|
||||
* @return The bigger value of `a` or `b`.
|
||||
*/
|
||||
#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* Returns the absolute value of `a`.
|
||||
*
|
||||
* @param a The value.
|
||||
*
|
||||
* @return The absolute value of `a`.
|
||||
*/
|
||||
#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
|
||||
|
||||
/**
|
||||
* Checks, if the given value is a power of 2.
|
||||
*
|
||||
* @param x The value.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
|
||||
*
|
||||
* Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
|
||||
*/
|
||||
#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
|
||||
|
||||
/**
|
||||
* Checks, if the given value is properly aligned.
|
||||
*
|
||||
* Note that this macro only works for powers of 2.
|
||||
*/
|
||||
#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
|
||||
|
||||
/**
|
||||
* Aligns the value to the nearest given alignment boundary (by rounding it up).
|
||||
*
|
||||
* @param x The value.
|
||||
* @param align The desired alignment.
|
||||
*
|
||||
* @return The aligned value.
|
||||
*
|
||||
* Note that this macro only works for powers of 2.
|
||||
*/
|
||||
#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
/**
|
||||
* Aligns the value to the nearest given alignment boundary (by rounding it down).
|
||||
*
|
||||
* @param x The value.
|
||||
* @param align The desired alignment.
|
||||
*
|
||||
* @return The aligned value.
|
||||
*
|
||||
* Note that this macro only works for powers of 2.
|
||||
*/
|
||||
#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Bit operations */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Checks, if the bit at index `b` is required to present the ordinal value `n`.
|
||||
*
|
||||
* @param n The ordinal value.
|
||||
* @param b The bit index.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
|
||||
* `ZYAN_FALSE`, if not.
|
||||
*
|
||||
* Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
|
||||
*/
|
||||
#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
|
||||
|
||||
/*
|
||||
* Returns the number of bits required to represent the ordinal value `n`.
|
||||
*
|
||||
* @param n The ordinal value.
|
||||
*
|
||||
* @return The number of bits required to represent the ordinal value `n`.
|
||||
*
|
||||
* Note that this macro returns `0` for `n == 0`.
|
||||
*/
|
||||
#define ZYAN_BITS_TO_REPRESENT(n) \
|
||||
( \
|
||||
ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
|
||||
ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
|
||||
ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
|
||||
ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
|
||||
ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
|
||||
ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
|
||||
ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
|
||||
ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
|
||||
ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
|
||||
ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
|
||||
ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
|
||||
ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
|
||||
ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
|
||||
ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
|
||||
ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
|
||||
ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_DEFINES_H */
|
@ -1,286 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides helper functions for performant number to string conversion.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_FORMAT_H
|
||||
#define ZYCORE_FORMAT_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/String.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helpers */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the absolute value of a 64 bit int.
|
||||
*
|
||||
* @param x The value to process.
|
||||
* @return The absolute, unsigned value.
|
||||
*
|
||||
* This gracefully deals with the special case of `x` being `INT_MAX`.
|
||||
*/
|
||||
ZYAN_INLINE ZyanU64 ZyanAbsI64(ZyanI64 x)
|
||||
{
|
||||
// INT_MIN special case. Can't use the value directly because GCC thinks
|
||||
// it's too big for an INT64 literal, however is perfectly happy to accept
|
||||
// this expression. This is also hit INT64_MIN is defined in `stdint.h`.
|
||||
if (x == (-0x7fffffffffffffff - 1))
|
||||
{
|
||||
return 0x8000000000000000u;
|
||||
}
|
||||
|
||||
return (ZyanU64)(x < 0 ? -x : x);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Inserts formatted text in the destination string at the given `index`.
|
||||
*
|
||||
* @param string The destination string.
|
||||
* @param index The insert index.
|
||||
* @param format The format string.
|
||||
* @param ... The format arguments.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYAN_PRINTF_ATTR(3, 4)
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index,
|
||||
const char* format, ...);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||
ZyanU8 padding_length);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool force_sign, const ZyanString* prefix);
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||
* inserts it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param index The insert index.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Appending */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Appends formatted text to the destination string.
|
||||
*
|
||||
* @param string The destination string.
|
||||
* @param format The format string.
|
||||
* @param ... The format arguments.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYAN_PRINTF_ATTR(2, 3)
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringAppendFormat(
|
||||
ZyanString* string, const char* format, ...);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value,
|
||||
ZyanU8 padding_length);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix);
|
||||
|
||||
/**
|
||||
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase);
|
||||
|
||||
/**
|
||||
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||
* appends it to the `string`.
|
||||
*
|
||||
* @param string A pointer to the `ZyanString` instance.
|
||||
* @param value The value.
|
||||
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||
* less than the `padding_length`.
|
||||
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||
* ones ('a'-'f').
|
||||
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||
* `ZyanString` instance.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value,
|
||||
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZYCORE_FORMAT_H
|
@ -1,511 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides a simple LibC abstraction and fallback routines.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_LIBC_H
|
||||
#define ZYCORE_LIBC_H
|
||||
|
||||
#ifndef ZYAN_CUSTOM_LIBC
|
||||
|
||||
// Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC
|
||||
// replacement functions
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* LibC is available */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* errno.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define ZYAN_ERRNO errno
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdarg.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVAList` datatype.
|
||||
*/
|
||||
typedef va_list ZyanVAList;
|
||||
|
||||
#define ZYAN_VA_START va_start
|
||||
#define ZYAN_VA_ARG va_arg
|
||||
#define ZYAN_VA_END va_end
|
||||
#define ZYAN_VA_COPY(dest, source) va_copy((dest), (source))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdio.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ZYAN_FPUTS fputs
|
||||
#define ZYAN_FPUTC fputc
|
||||
#define ZYAN_FPRINTF fprintf
|
||||
#define ZYAN_PRINTF printf
|
||||
#define ZYAN_PUTC putc
|
||||
#define ZYAN_PUTS puts
|
||||
#define ZYAN_SCANF scanf
|
||||
#define ZYAN_SSCANF sscanf
|
||||
#define ZYAN_VSNPRINTF vsnprintf
|
||||
|
||||
/**
|
||||
* Defines the `ZyanFile` datatype.
|
||||
*/
|
||||
typedef FILE ZyanFile;
|
||||
|
||||
#define ZYAN_STDIN stdin
|
||||
#define ZYAN_STDOUT stdout
|
||||
#define ZYAN_STDERR stderr
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdlib.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdlib.h>
|
||||
#define ZYAN_CALLOC calloc
|
||||
#define ZYAN_FREE free
|
||||
#define ZYAN_MALLOC malloc
|
||||
#define ZYAN_REALLOC realloc
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* string.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#include <string.h>
|
||||
#define ZYAN_MEMCHR memchr
|
||||
#define ZYAN_MEMCMP memcmp
|
||||
#define ZYAN_MEMCPY memcpy
|
||||
#define ZYAN_MEMMOVE memmove
|
||||
#define ZYAN_MEMSET memset
|
||||
#define ZYAN_STRCAT strcat
|
||||
#define ZYAN_STRCHR strchr
|
||||
#define ZYAN_STRCMP strcmp
|
||||
#define ZYAN_STRCOLL strcoll
|
||||
#define ZYAN_STRCPY strcpy
|
||||
#define ZYAN_STRCSPN strcspn
|
||||
#define ZYAN_STRLEN strlen
|
||||
#define ZYAN_STRNCAT strncat
|
||||
#define ZYAN_STRNCMP strncmp
|
||||
#define ZYAN_STRNCPY strncpy
|
||||
#define ZYAN_STRPBRK strpbrk
|
||||
#define ZYAN_STRRCHR strrchr
|
||||
#define ZYAN_STRSPN strspn
|
||||
#define ZYAN_STRSTR strstr
|
||||
#define ZYAN_STRTOK strtok
|
||||
#define ZYAN_STRXFRM strxfrm
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else // if ZYAN_NO_LIBC
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* No LibC available, use our own functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/*
|
||||
* These implementations are by no means optimized and will be outperformed by pretty much any
|
||||
* libc implementation out there. We do not aim towards providing competetive implementations here,
|
||||
* but towards providing a last resort fallback for environments without a working libc.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdarg.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVAList` datatype.
|
||||
*/
|
||||
typedef char* ZyanVAList;
|
||||
|
||||
# define ZYAN_VA_START __crt_va_start
|
||||
# define ZYAN_VA_ARG __crt_va_arg
|
||||
# define ZYAN_VA_END __crt_va_end
|
||||
# define ZYAN_VA_COPY(destination, source) ((destination) = (source))
|
||||
|
||||
#elif defined(ZYAN_GNUC)
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVAList` datatype.
|
||||
*/
|
||||
typedef __builtin_va_list ZyanVAList;
|
||||
|
||||
# define ZYAN_VA_START(v, l) __builtin_va_start(v, l)
|
||||
# define ZYAN_VA_END(v) __builtin_va_end(v)
|
||||
# define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l)
|
||||
# define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s)
|
||||
|
||||
#else
|
||||
# error "Unsupported compiler for no-libc mode."
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdio.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count,
|
||||
// char const* const format, ZyanVAList args)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(buffer);
|
||||
// ZYAN_UNUSED(count);
|
||||
// ZYAN_UNUSED(format);
|
||||
// ZYAN_UNUSED(args);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* stdlib.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(nitems);
|
||||
// ZYAN_UNUSED(size);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
//
|
||||
// ZYAN_INLINE void ZYAN_FREE(void *p)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(p);
|
||||
// }
|
||||
//
|
||||
// ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(n);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
//
|
||||
// ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n)
|
||||
// {
|
||||
// // We cant provide a fallback implementation for this function
|
||||
// ZYAN_UNUSED(p);
|
||||
// ZYAN_UNUSED(n);
|
||||
// return ZYAN_NULL;
|
||||
// }
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* string.h */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n)
|
||||
{
|
||||
const ZyanU8* p = (ZyanU8*)str;
|
||||
while (n--)
|
||||
{
|
||||
if (*p != (ZyanU8)c)
|
||||
{
|
||||
p++;
|
||||
} else
|
||||
{
|
||||
return (void*)p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n)
|
||||
{
|
||||
const ZyanU8* p1 = s1, *p2 = s2;
|
||||
while (n--)
|
||||
{
|
||||
if (*p1 != *p2)
|
||||
{
|
||||
return *p1 - *p2;
|
||||
}
|
||||
p1++, p2++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n)
|
||||
{
|
||||
volatile ZyanU8* dp = dst;
|
||||
const ZyanU8* sp = src;
|
||||
while (n--)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n)
|
||||
{
|
||||
volatile ZyanU8* pd = dst;
|
||||
const ZyanU8* ps = src;
|
||||
if (ps < pd)
|
||||
{
|
||||
for (pd += n, ps += n; n--;)
|
||||
{
|
||||
*--pd = *--ps;
|
||||
}
|
||||
} else
|
||||
{
|
||||
while (n--)
|
||||
{
|
||||
*pd++ = *ps++;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n)
|
||||
{
|
||||
volatile ZyanU8* p = dst;
|
||||
while (n--)
|
||||
{
|
||||
*p++ = (unsigned char)val;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src)
|
||||
{
|
||||
char* ret = dest;
|
||||
while (*dest)
|
||||
{
|
||||
dest++;
|
||||
}
|
||||
while ((*dest++ = *src++));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c)
|
||||
{
|
||||
while (*s != (char)c)
|
||||
{
|
||||
if (!*s++)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2)
|
||||
{
|
||||
while (*s1 && (*s1 == *s2))
|
||||
{
|
||||
s1++, s2++;
|
||||
}
|
||||
return *(const ZyanU8*)s1 - *(const ZyanU8*)s2;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2)
|
||||
{
|
||||
// TODO: Implement
|
||||
|
||||
ZYAN_UNUSED(s1);
|
||||
ZYAN_UNUSED(s2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src)
|
||||
{
|
||||
char* ret = dest;
|
||||
while ((*dest++ = *src++));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2)
|
||||
{
|
||||
ZyanUSize ret = 0;
|
||||
while (*s1)
|
||||
{
|
||||
if (ZYAN_STRCHR(s2, *s1))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
s1++, ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str)
|
||||
{
|
||||
const char* p = str;
|
||||
while (*str)
|
||||
{
|
||||
++str;
|
||||
}
|
||||
return str - p;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n)
|
||||
{
|
||||
char* ret = dest;
|
||||
while (*dest)
|
||||
{
|
||||
dest++;
|
||||
}
|
||||
while (n--)
|
||||
{
|
||||
if (!(*dest++ = *src++))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
*dest = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n)
|
||||
{
|
||||
while (n--)
|
||||
{
|
||||
if (*s1++ != *s2++)
|
||||
{
|
||||
return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n)
|
||||
{
|
||||
char* ret = dest;
|
||||
do
|
||||
{
|
||||
if (!n--)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
} while ((*dest++ = *src++));
|
||||
while (n--)
|
||||
{
|
||||
*dest++ = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2)
|
||||
{
|
||||
while (*s1)
|
||||
{
|
||||
if(ZYAN_STRCHR(s2, *s1++))
|
||||
{
|
||||
return (char*)--s1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c)
|
||||
{
|
||||
char* ret = 0;
|
||||
do
|
||||
{
|
||||
if (*s == (char)c)
|
||||
{
|
||||
ret = (char*)s;
|
||||
}
|
||||
} while (*s++);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2)
|
||||
{
|
||||
ZyanUSize ret = 0;
|
||||
while (*s1 && ZYAN_STRCHR(s2, *s1++))
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2)
|
||||
{
|
||||
const ZyanUSize n = ZYAN_STRLEN(s2);
|
||||
while (*s1)
|
||||
{
|
||||
if (!ZYAN_MEMCMP(s1++, s2, n))
|
||||
{
|
||||
return (char*)(s1 - 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim)
|
||||
{
|
||||
static char* p = 0;
|
||||
if (str)
|
||||
{
|
||||
p = str;
|
||||
} else
|
||||
if (!p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
str = p + ZYAN_STRSPN(p, delim);
|
||||
p = str + ZYAN_STRCSPN(str, delim);
|
||||
if (p == str)
|
||||
{
|
||||
return p = 0;
|
||||
}
|
||||
p = *p ? *p = 0, p + 1 : 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n)
|
||||
{
|
||||
const ZyanUSize n2 = ZYAN_STRLEN(src);
|
||||
if (n > n2)
|
||||
{
|
||||
ZYAN_STRCPY(dest, src);
|
||||
}
|
||||
return n2;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_LIBC_H */
|
@ -1,574 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements a doubly linked list.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_LIST_H
|
||||
#define ZYCORE_LIST_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Object.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanListNode` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanListNode_
|
||||
{
|
||||
/**
|
||||
* A pointer to the previous list node.
|
||||
*/
|
||||
struct ZyanListNode_* prev;
|
||||
/**
|
||||
* A pointer to the next list node.
|
||||
*/
|
||||
struct ZyanListNode_* next;
|
||||
} ZyanListNode;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanList` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanList_
|
||||
{
|
||||
/**
|
||||
* The memory allocator.
|
||||
*/
|
||||
ZyanAllocator* allocator;
|
||||
/**
|
||||
* The current number of elements in the list.
|
||||
*/
|
||||
ZyanUSize size;
|
||||
/**
|
||||
* The size of a single element in bytes.
|
||||
*/
|
||||
ZyanUSize element_size;
|
||||
/**
|
||||
* The element destructor callback.
|
||||
*/
|
||||
ZyanMemberProcedure destructor;
|
||||
/**
|
||||
* The head node.
|
||||
*/
|
||||
ZyanListNode* head;
|
||||
/**
|
||||
* The tail node.
|
||||
*/
|
||||
ZyanListNode* tail;
|
||||
/**
|
||||
* The data buffer.
|
||||
*
|
||||
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||
*/
|
||||
void* buffer;
|
||||
/**
|
||||
* The data buffer capacity (number of bytes).
|
||||
*
|
||||
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||
*/
|
||||
ZyanUSize capacity;
|
||||
/**
|
||||
* The first unused node.
|
||||
*
|
||||
* When removing a node, the first-unused value is updated to point at the removed node and the
|
||||
* next node of the removed node will be updated to point at the old first-unused node.
|
||||
*
|
||||
* When appending the memory of the first unused-node is recycled to store the new node. The
|
||||
* value of the first-unused node is then updated to point at the reused nodes next node.
|
||||
*
|
||||
* If the first-unused value is `ZYAN_NULL`, any new node will be "allocated" behind the tail
|
||||
* node (if there is enough space left in the fixed size buffer).
|
||||
*
|
||||
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||
*/
|
||||
ZyanListNode* first_unused;
|
||||
} ZyanList;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines an uninitialized `ZyanList` instance.
|
||||
*/
|
||||
#define ZYAN_LIST_INITIALIZER \
|
||||
{ \
|
||||
/* allocator */ ZYAN_NULL, \
|
||||
/* size */ 0, \
|
||||
/* element_size */ 0, \
|
||||
/* head */ ZYAN_NULL, \
|
||||
/* destructor */ ZYAN_NULL, \
|
||||
/* tail */ ZYAN_NULL, \
|
||||
/* buffer */ ZYAN_NULL, \
|
||||
/* capacity */ 0, \
|
||||
/* first_unused */ ZYAN_NULL \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the data value of the given `node`.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @result The data value of the given `node`.
|
||||
*
|
||||
* Note that this function is unsafe and might dereference a null-pointer.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define ZYAN_LIST_GET(type, node) \
|
||||
(*reinterpret_cast<const type*>(ZyanListGetNodeData(node)))
|
||||
#else
|
||||
#define ZYAN_LIST_GET(type, node) \
|
||||
(*(const type*)ZyanListGetNodeData(node))
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the list elements is dynamically allocated by the default allocator.
|
||||
*
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanList` instance and sets a custom `allocator`.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor, ZyanAllocator* allocator);
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanList` instance and configures it to use a custom user
|
||||
* defined buffer with a fixed size.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of bytes) of the buffer including the
|
||||
* space required for the list-nodes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The buffer capacity required to store `n` elements of type `T` is be calculated by:
|
||||
* `size = n * sizeof(ZyanListNode) + n * sizeof(T)`
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity);
|
||||
|
||||
/**
|
||||
* Destroys the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListDestroy(ZyanList* list);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Duplication */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanList` instance by duplicating an existing list.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||
* @param source A pointer to the source list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the list is dynamically allocated by the default allocator.
|
||||
*
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListDuplicate(ZyanList* destination,
|
||||
const ZyanList* source);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanList` instance by duplicating an existing list and sets a
|
||||
* custom `allocator`.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||
* @param source A pointer to the source list.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
|
||||
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListDuplicateEx(ZyanList* destination, const ZyanList* source,
|
||||
ZyanAllocator* allocator);
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanList` instance by duplicating an existing list and
|
||||
* configures it to use a custom user defined buffer with a fixed size.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||
* @param source A pointer to the source list.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of bytes) of the buffer including the
|
||||
* space required for the list-nodes.
|
||||
|
||||
* This function will fail, if the capacity of the buffer is not sufficient
|
||||
* to store all elements of the source list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The buffer capacity required to store `n` elements of type `T` is be calculated by:
|
||||
* `size = n * sizeof(ZyanListNode) + n * sizeof(T)`
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListDuplicateCustomBuffer(ZyanList* destination,
|
||||
const ZyanList* source, void* buffer, ZyanUSize capacity);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Item access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns a pointer to the first `ZyanListNode` struct of the given list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node Receives a pointer to the first `ZyanListNode` struct of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the last `ZyanListNode` struct of the given list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node Receives a pointer to the last `ZyanListNode` struct of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Receives a pointer to the previous `ZyanListNode` struct linked to the passed one.
|
||||
*
|
||||
* @param node Receives a pointer to the previous `ZyanListNode` struct linked to the passed
|
||||
* one.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Receives a pointer to the next `ZyanListNode` struct linked to the passed one.
|
||||
*
|
||||
* @param node Receives a pointer to the next `ZyanListNode` struct linked to the passed one.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetNextNode(const ZyanListNode** node);
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the data of the given `node`.
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A constant pointer to the the data of the given `node` or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Take a look at `ZyanListGetNodeDataEx`, if you need a function that returns a zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT const void* ZyanListGetNodeData(const ZyanListNode* node);
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the data of the given `node`..
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
* @param value Receives a constant pointer to the data of the given `node`.
|
||||
*
|
||||
* Take a look at `ZyanListGetNodeData`, if you need a function that directly returns a pointer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the data of the given `node`.
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A mutable pointer to the the data of the given `node` or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Take a look at `ZyanListGetPointerMutableEx` instead, if you need a function that returns a
|
||||
* zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT void* ZyanListGetNodeDataMutable(const ZyanListNode* node);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the data of the given `node`..
|
||||
*
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
* @param value Receives a mutable pointer to the data of the given `node`.
|
||||
*
|
||||
* Take a look at `ZyanListGetNodeDataMutable`, if you need a function that directly returns a
|
||||
* pointer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value);
|
||||
|
||||
/**
|
||||
* Assigns a new data value to the given `node`.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
* @param value The value to assign.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node,
|
||||
const void* value);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new `item` to the end of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item A pointer to the item to add.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPushBack(ZyanList* list, const void* item);
|
||||
|
||||
/**
|
||||
* Adds a new `item` to the beginning of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item A pointer to the item to add.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPushFront(ZyanList* list, const void* item);
|
||||
|
||||
/**
|
||||
* Constructs an `item` in-place at the end of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item Receives a pointer to the new item.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item,
|
||||
ZyanMemberFunction constructor);
|
||||
|
||||
/**
|
||||
* Constructs an `item` in-place at the beginning of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param item Receives a pointer to the new item.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item,
|
||||
ZyanMemberFunction constructor);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Deletion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Removes the last element of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPopBack(ZyanList* list);
|
||||
|
||||
/**
|
||||
* Removes the firstelement of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListPopFront(ZyanList* list);
|
||||
|
||||
/**
|
||||
* Removes the given `node` from the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node);
|
||||
|
||||
/**
|
||||
* Removes multiple nodes from the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param first A pointer to the first node.
|
||||
* @param last A pointer to the last node.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first,
|
||||
const ZyanListNode* last);
|
||||
|
||||
/**
|
||||
* Erases all elements of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListClear(ZyanList* list);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Searching */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
// TODO:
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param size The new size of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size);
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanList` instance.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param size The new size of the list.
|
||||
* @param initializer A pointer to a value to be used as initializer for new items.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current size of the list.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param size Receives the size of the list.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_VECTOR_H */
|
@ -1,84 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines some generic object-related datatypes.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_OBJECT_H
|
||||
#define ZYCORE_OBJECT_H
|
||||
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanMemberProcedure` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*/
|
||||
typedef void (*ZyanMemberProcedure)(void* object);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstMemberProcedure` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*/
|
||||
typedef void (*ZyanConstMemberProcedure)(const void* object);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanMemberFunction` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanMemberFunction)(void* object);
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstMemberFunction` function prototype.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_OBJECT_H */
|
@ -1,287 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zyan-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Status code definitions and check macros.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_STATUS_H
|
||||
#define ZYCORE_STATUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanStatus` data type.
|
||||
*/
|
||||
typedef ZyanU32 ZyanStatus;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Definition */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines a zyan status code.
|
||||
*
|
||||
* @param error `1`, if the status code signals an error or `0`, if not.
|
||||
* @param module The module id.
|
||||
* @param code The actual code.
|
||||
*
|
||||
* @return The zyan status code.
|
||||
*/
|
||||
#define ZYAN_MAKE_STATUS(error, module, code) \
|
||||
(ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu))
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Checks */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Checks if a zyan operation was successful.
|
||||
*
|
||||
* @param status The zyan status-code to check.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
#define ZYAN_SUCCESS(status) \
|
||||
(!((status) & 0x80000000u))
|
||||
|
||||
/**
|
||||
* Checks if a zyan operation failed.
|
||||
*
|
||||
* @param status The zyan status-code to check.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
#define ZYAN_FAILED(status) \
|
||||
((status) & 0x80000000u)
|
||||
|
||||
/**
|
||||
* Checks if a zyan operation was successful and returns with the status-code, if not.
|
||||
*
|
||||
* @param status The zyan status-code to check.
|
||||
*/
|
||||
#define ZYAN_CHECK(status) \
|
||||
do \
|
||||
{ \
|
||||
const ZyanStatus status_047620348 = (status); \
|
||||
if (!ZYAN_SUCCESS(status_047620348)) \
|
||||
{ \
|
||||
return status_047620348; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the module id of a zyan status-code.
|
||||
*
|
||||
* @param status The zyan status-code.
|
||||
*
|
||||
* @return The module id of the zyan status-code.
|
||||
*/
|
||||
#define ZYAN_STATUS_MODULE(status) \
|
||||
(((status) >> 20) & 0x7FFu)
|
||||
|
||||
/**
|
||||
* Returns the code of a zyan status-code.
|
||||
*
|
||||
* @param status The zyan status-code.
|
||||
*
|
||||
* @return The code of the zyan status-code.
|
||||
*/
|
||||
#define ZYAN_STATUS_CODE(status) \
|
||||
((status) & 0xFFFFFu)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Status codes */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Module IDs */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The zycore generic module id.
|
||||
*/
|
||||
#define ZYAN_MODULE_ZYCORE 0x001u
|
||||
|
||||
/**
|
||||
* The zycore arg-parse submodule id.
|
||||
*/
|
||||
#define ZYAN_MODULE_ARGPARSE 0x003u
|
||||
|
||||
/**
|
||||
* The base module id for user-defined status codes.
|
||||
*/
|
||||
#define ZYAN_MODULE_USER 0x3FFu
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Status codes (general purpose) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The operation completed successfully.
|
||||
*/
|
||||
#define ZYAN_STATUS_SUCCESS \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u)
|
||||
|
||||
/**
|
||||
* The operation failed with an generic error.
|
||||
*/
|
||||
#define ZYAN_STATUS_FAILED \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u)
|
||||
|
||||
/**
|
||||
* The operation completed successfully and returned `ZYAN_TRUE`.
|
||||
*/
|
||||
#define ZYAN_STATUS_TRUE \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u)
|
||||
|
||||
/**
|
||||
* The operation completed successfully and returned `ZYAN_FALSE`.
|
||||
*/
|
||||
#define ZYAN_STATUS_FALSE \
|
||||
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u)
|
||||
|
||||
/**
|
||||
* An invalid argument was passed to a function.
|
||||
*/
|
||||
#define ZYAN_STATUS_INVALID_ARGUMENT \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u)
|
||||
|
||||
/**
|
||||
* An attempt was made to perform an invalid operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_INVALID_OPERATION \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u)
|
||||
|
||||
/**
|
||||
* Insufficient privileges to perform the requested operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_ACCESS_DENIED \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u)
|
||||
|
||||
/**
|
||||
* The requested entity was not found.
|
||||
*/
|
||||
#define ZYAN_STATUS_NOT_FOUND \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u)
|
||||
|
||||
/**
|
||||
* An index passed to a function was out of bounds.
|
||||
*/
|
||||
#define ZYAN_STATUS_OUT_OF_RANGE \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u)
|
||||
|
||||
/**
|
||||
* A buffer passed to a function was too small to complete the requested operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u)
|
||||
|
||||
/**
|
||||
* Insufficient memory to perform the operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_NOT_ENOUGH_MEMORY \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au)
|
||||
|
||||
/**
|
||||
* An unknown error occurred during a system function call.
|
||||
*/
|
||||
#define ZYAN_STATUS_BAD_SYSTEMCALL \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu)
|
||||
|
||||
/**
|
||||
* The process ran out of resources while performing an operation.
|
||||
*/
|
||||
#define ZYAN_STATUS_OUT_OF_RESOURCES \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu)
|
||||
|
||||
/**
|
||||
* A dependency library was not found or does have an unexpected version number or
|
||||
* feature-set.
|
||||
*/
|
||||
#define ZYAN_STATUS_MISSING_DEPENDENCY \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Status codes (arg parse) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Argument was not expected.
|
||||
*/
|
||||
#define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u)
|
||||
|
||||
/**
|
||||
* Too few arguments were provided.
|
||||
*/
|
||||
#define ZYAN_STATUS_TOO_FEW_ARGS \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u)
|
||||
|
||||
/**
|
||||
* Too many arguments were provided.
|
||||
*/
|
||||
#define ZYAN_STATUS_TOO_MANY_ARGS \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u)
|
||||
|
||||
/**
|
||||
* An argument that expected a value misses its value.
|
||||
*/
|
||||
#define ZYAN_STATUS_ARG_MISSES_VALUE \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u)
|
||||
|
||||
/**
|
||||
* A required argument is missing.
|
||||
*/
|
||||
#define ZYAN_STATUS_REQUIRED_ARG_MISSING \
|
||||
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_STATUS_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,195 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zyan-C)
|
||||
|
||||
Original Author : Florian Bernd, Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Includes and defines some default data types.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_TYPES_H
|
||||
#define ZYCORE_TYPES_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Integer types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_NO_LIBC) || \
|
||||
(defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h.
|
||||
// No LibC mode, use compiler built-in types / macros.
|
||||
# if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
|
||||
typedef unsigned __int8 ZyanU8;
|
||||
typedef unsigned __int16 ZyanU16;
|
||||
typedef unsigned __int32 ZyanU32;
|
||||
typedef unsigned __int64 ZyanU64;
|
||||
typedef signed __int8 ZyanI8;
|
||||
typedef signed __int16 ZyanI16;
|
||||
typedef signed __int32 ZyanI32;
|
||||
typedef signed __int64 ZyanI64;
|
||||
# if _WIN64
|
||||
typedef ZyanU64 ZyanUSize;
|
||||
typedef ZyanI64 ZyanISize;
|
||||
typedef ZyanU64 ZyanUPointer;
|
||||
typedef ZyanI64 ZyanIPointer;
|
||||
# else
|
||||
typedef ZyanU32 ZyanUSize;
|
||||
typedef ZyanI32 ZyanISize;
|
||||
typedef ZyanU32 ZyanUPointer;
|
||||
typedef ZyanI32 ZyanIPointer;
|
||||
# endif
|
||||
# elif defined(ZYAN_GNUC)
|
||||
typedef __UINT8_TYPE__ ZyanU8;
|
||||
typedef __UINT16_TYPE__ ZyanU16;
|
||||
typedef __UINT32_TYPE__ ZyanU32;
|
||||
typedef __UINT64_TYPE__ ZyanU64;
|
||||
typedef __INT8_TYPE__ ZyanI8;
|
||||
typedef __INT16_TYPE__ ZyanI16;
|
||||
typedef __INT32_TYPE__ ZyanI32;
|
||||
typedef __INT64_TYPE__ ZyanI64;
|
||||
typedef __SIZE_TYPE__ ZyanUSize;
|
||||
typedef __PTRDIFF_TYPE__ ZyanISize;
|
||||
typedef __UINTPTR_TYPE__ ZyanUPointer;
|
||||
typedef __INTPTR_TYPE__ ZyanIPointer;
|
||||
# else
|
||||
# error "Unsupported compiler for no-libc mode."
|
||||
# endif
|
||||
#else
|
||||
// If is LibC present, we use stdint types.
|
||||
# include <stdint.h>
|
||||
# include <stddef.h>
|
||||
typedef uint8_t ZyanU8;
|
||||
typedef uint16_t ZyanU16;
|
||||
typedef uint32_t ZyanU32;
|
||||
typedef uint64_t ZyanU64;
|
||||
typedef int8_t ZyanI8;
|
||||
typedef int16_t ZyanI16;
|
||||
typedef int32_t ZyanI32;
|
||||
typedef int64_t ZyanI64;
|
||||
typedef size_t ZyanUSize;
|
||||
typedef ptrdiff_t ZyanISize;
|
||||
typedef uintptr_t ZyanUPointer;
|
||||
typedef intptr_t ZyanIPointer;
|
||||
#endif
|
||||
|
||||
// Verify size assumptions.
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 );
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect!
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect!
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*));
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*));
|
||||
|
||||
// Verify signedness assumptions (relies on size checks above).
|
||||
ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1));
|
||||
ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1));
|
||||
ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1));
|
||||
ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1));
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Pointer */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVoidPointer` data-type.
|
||||
*/
|
||||
typedef char* ZyanVoidPointer;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstVoidPointer` data-type.
|
||||
*/
|
||||
typedef const void* ZyanConstVoidPointer;
|
||||
|
||||
#define ZYAN_NULL ((void*)0)
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Logic types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Boolean */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYAN_FALSE 0
|
||||
#define ZYAN_TRUE 1
|
||||
|
||||
/**
|
||||
* Defines the `ZyanBool` data-type.
|
||||
*
|
||||
* Represents a default boolean data-type where `0` is interpreted as `false` and all other values
|
||||
* as `true`.
|
||||
*/
|
||||
typedef ZyanU8 ZyanBool;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Ternary */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanTernary` data-type.
|
||||
*
|
||||
* The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`,
|
||||
* `false` and an indeterminate third value.
|
||||
*/
|
||||
typedef ZyanI8 ZyanTernary;
|
||||
|
||||
#define ZYAN_TERNARY_FALSE (-1)
|
||||
#define ZYAN_TERNARY_UNKNOWN 0x00
|
||||
#define ZYAN_TERNARY_TRUE 0x01
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* String types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* C-style strings */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanCharPointer` data-type.
|
||||
*
|
||||
* This type is most often used to represent null-terminated strings aka. C-style strings.
|
||||
*/
|
||||
typedef char* ZyanCharPointer;
|
||||
|
||||
/**
|
||||
* Defines the `ZyanConstCharPointer` data-type.
|
||||
*
|
||||
* This type is most often used to represent null-terminated strings aka. C-style strings.
|
||||
*/
|
||||
typedef const char* ZyanConstCharPointer;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#endif /* ZYCORE_TYPES_H */
|
@ -1,723 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the vector container class.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_VECTOR_H
|
||||
#define ZYCORE_VECTOR_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/Comparison.h>
|
||||
#include <Zycore/Object.h>
|
||||
#include <Zycore/Status.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Constants */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* The initial minimum capacity (number of elements) for all dynamically allocated vector
|
||||
* instances.
|
||||
*/
|
||||
#define ZYAN_VECTOR_MIN_CAPACITY 1
|
||||
|
||||
/**
|
||||
* The default growth factor for all vector instances.
|
||||
*/
|
||||
#define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2.00f
|
||||
|
||||
/**
|
||||
* The default shrink threshold for all vector instances.
|
||||
*/
|
||||
#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 0.25f
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZyanVector` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZyanVector_
|
||||
{
|
||||
/**
|
||||
* The memory allocator.
|
||||
*/
|
||||
ZyanAllocator* allocator;
|
||||
/**
|
||||
* The growth factor.
|
||||
*/
|
||||
float growth_factor;
|
||||
/**
|
||||
* The shrink threshold.
|
||||
*/
|
||||
float shrink_threshold;
|
||||
/**
|
||||
* The current number of elements in the vector.
|
||||
*/
|
||||
ZyanUSize size;
|
||||
/**
|
||||
* The maximum capacity (number of elements).
|
||||
*/
|
||||
ZyanUSize capacity;
|
||||
/**
|
||||
* The size of a single element in bytes.
|
||||
*/
|
||||
ZyanUSize element_size;
|
||||
/**
|
||||
* The element destructor callback.
|
||||
*/
|
||||
ZyanMemberProcedure destructor;
|
||||
/**
|
||||
* The data pointer.
|
||||
*/
|
||||
void* data;
|
||||
} ZyanVector;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines an uninitialized `ZyanVector` instance.
|
||||
*/
|
||||
#define ZYAN_VECTOR_INITIALIZER \
|
||||
{ \
|
||||
/* allocator */ ZYAN_NULL, \
|
||||
/* growth_factor */ 0.0f, \
|
||||
/* shrink_threshold */ 0.0f, \
|
||||
/* size */ 0, \
|
||||
/* capacity */ 0, \
|
||||
/* element_size */ 0, \
|
||||
/* destructor */ ZYAN_NULL, \
|
||||
/* data */ ZYAN_NULL \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the value of the element at the given `index`.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @result The value of the desired element in the vector.
|
||||
*
|
||||
* Note that this function is unsafe and might dereference a null-pointer.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define ZYAN_VECTOR_GET(type, vector, index) \
|
||||
(*reinterpret_cast<const type*>(ZyanVectorGet(vector, index)))
|
||||
#else
|
||||
#define ZYAN_VECTOR_GET(type, vector, index) \
|
||||
(*(const type*)ZyanVectorGet(vector, index))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Loops through all elements of the vector.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param item_name The name of the iterator item.
|
||||
* @param body The body to execute for each item in the vector.
|
||||
*/
|
||||
#define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \
|
||||
{ \
|
||||
const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \
|
||||
for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \
|
||||
++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \
|
||||
{ \
|
||||
const type item_name = ZYAN_VECTOR_GET(type, vector, \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \
|
||||
body \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through all elements of the vector.
|
||||
*
|
||||
* @param type The desired value type.
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param item_name The name of the iterator item.
|
||||
* @param body The body to execute for each item in the vector.
|
||||
*/
|
||||
#define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \
|
||||
{ \
|
||||
const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \
|
||||
for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \
|
||||
++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \
|
||||
{ \
|
||||
type* const item_name = ZyanVectorGetMutable(vector, \
|
||||
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \
|
||||
body \
|
||||
} \
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the vector elements is dynamically allocated by the default allocator using the
|
||||
* default growth factor of `2.0f` and the default shrink threshold of `0.25f`.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector,
|
||||
ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory
|
||||
* allocation/deallocation parameters.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted,
|
||||
* or `ZYAN_NULL` if not needed.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||
* dynamic shrinking.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size,
|
||||
ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator,
|
||||
float growth_factor, float shrink_threshold);
|
||||
|
||||
/**
|
||||
* Initializes the given `ZyanVector` instance and configures it to use a custom user
|
||||
* defined buffer with a fixed size.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element_size The size of a single element in bytes.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of elements) of the buffer.
|
||||
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||
* `ZYAN_NULL` if not needed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size,
|
||||
void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor);
|
||||
|
||||
/**
|
||||
* Destroys the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance..
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Duplication */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanVector` instance by duplicating an existing vector.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||
* @param source A pointer to the source vector.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
*
|
||||
* This value is automatically adjusted to the size of the source vector, if
|
||||
* a smaller value was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* The memory for the vector is dynamically allocated by the default allocator using the default
|
||||
* growth factor of `2.0f` and the default shrink threshold of `0.25f`.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination,
|
||||
const ZyanVector* source, ZyanUSize capacity);
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a
|
||||
* custom `allocator` and memory allocation/deallocation parameters.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||
* @param source A pointer to the source vector.
|
||||
* @param capacity The initial capacity (number of elements).
|
||||
|
||||
* This value is automatically adjusted to the size of the source
|
||||
* vector, if a smaller value was passed.
|
||||
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||
* dynamic shrinking.
|
||||
*
|
||||
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source,
|
||||
ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, float shrink_threshold);
|
||||
|
||||
/**
|
||||
* Initializes a new `ZyanVector` instance by duplicating an existing vector and
|
||||
* configures it to use a custom user defined buffer with a fixed size.
|
||||
*
|
||||
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||
* @param source A pointer to the source vector.
|
||||
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||
* @param capacity The maximum capacity (number of elements) of the buffer.
|
||||
|
||||
* This function will fail, if the capacity of the buffer is less than the
|
||||
* size of the source vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Finalization is not required for instances created by this function.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination,
|
||||
const ZyanVector* source, void* buffer, ZyanUSize capacity);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Element access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status
|
||||
* code.
|
||||
*/
|
||||
ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error
|
||||
* occured.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a
|
||||
* zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
* @param value Receives a constant pointer to the desired element in the vector.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index,
|
||||
const void** value);
|
||||
|
||||
/**
|
||||
* Returns a mutable pointer to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
* @param value Receives a mutable pointer to the desired element in the vector.
|
||||
*
|
||||
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index,
|
||||
void** value);
|
||||
|
||||
/**
|
||||
* Assigns a new value to the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The value index.
|
||||
* @param value The value to assign.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index,
|
||||
const void* value);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new `element` to the end of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to add.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element);
|
||||
|
||||
/**
|
||||
* Inserts an `element` at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The insert index.
|
||||
* @param element A pointer to the element to insert.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index,
|
||||
const void* element);
|
||||
|
||||
/**
|
||||
* Inserts multiple `elements` at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The insert index.
|
||||
* @param elements A pointer to the first element.
|
||||
* @param count The number of elements to insert.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index,
|
||||
const void* elements, ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Constructs an `element` in-place at the end of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element Receives a pointer to the new element.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element,
|
||||
ZyanMemberFunction constructor);
|
||||
|
||||
/**
|
||||
* Constructs an `element` in-place and inserts it at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The insert index.
|
||||
* @param element Receives a pointer to the new element.
|
||||
* @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in
|
||||
* undefined state, if no constructor was passed.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index,
|
||||
void** element, ZyanMemberFunction constructor);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Utils */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Swaps the element at `index_first` with the element at `index_second`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index_first The index of the first element.
|
||||
* @param index_second The index of the second element.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function requires the vector to have spare capacity for one temporary element. Call
|
||||
* `ZyanVectorReserve` before this function to increase capacity, if needed.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first,
|
||||
ZyanUSize index_second);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Deletion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Deletes the element at the given `index` of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index);
|
||||
|
||||
/**
|
||||
* Deletes multiple elements from the given vector, starting at `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The index of the first element to delete.
|
||||
* @param count The number of elements to delete.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index,
|
||||
ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Removes the last element of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector);
|
||||
|
||||
/**
|
||||
* Erases all elements of the given vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Searching */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sequentially searches for the first occurrence of `element` in the given vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* The `found_index` is set to `-1`, if the element was not found.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element,
|
||||
ZyanISize* found_index, ZyanEqualityComparison comparison);
|
||||
|
||||
/**
|
||||
* Sequentially searches for the first occurrence of `element` in the given vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
* @param index The start index.
|
||||
* @param count The maximum number of elements to iterate, beginning from the start `index`.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* The `found_index` is set to `-1`, if the element was not found.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element,
|
||||
ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count);
|
||||
|
||||
/**
|
||||
* Searches for the first occurrence of `element` in the given vector using a binary-
|
||||
* search algorithm.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* If found, `found_index` contains the zero-based index of `element`. If not found, `found_index`
|
||||
* contains the index of the first entry larger than `element`.
|
||||
*
|
||||
* This function requires all elements in the vector to be strictly ordered (sorted).
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element,
|
||||
ZyanUSize* found_index, ZyanComparison comparison);
|
||||
|
||||
/**
|
||||
* Searches for the first occurrence of `element` in the given vector using a binary-
|
||||
* search algorithm.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param element A pointer to the element to search for.
|
||||
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||
* @param comparison The comparison function to use.
|
||||
* @param index The start index.
|
||||
* @param count The maximum number of elements to iterate, beginning from the start `index`.
|
||||
*
|
||||
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||
* zyan status code if an error occured.
|
||||
*
|
||||
* If found, `found_index` contains the zero-based index of `element`. If not found, `found_index`
|
||||
* contains the index of the first entry larger than `element`.
|
||||
*
|
||||
* This function requires all elements in the vector to be strictly ordered (sorted).
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element,
|
||||
ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param size The new size of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size);
|
||||
|
||||
/**
|
||||
* Resizes the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param size The new size of the vector.
|
||||
* @param initializer A pointer to a value to be used as initializer for new items.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size,
|
||||
const void* initializer);
|
||||
|
||||
/**
|
||||
* Changes the capacity of the given `ZyanVector` instance.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param capacity The new minimum capacity of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity);
|
||||
|
||||
/**
|
||||
* Shrinks the capacity of the given vector to match it's size.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param capacity Receives the size of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity);
|
||||
|
||||
/**
|
||||
* Returns the current size of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param size Receives the size of the vector.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_VECTOR_H */
|
@ -1,111 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Master include file, including everything else.
|
||||
*/
|
||||
|
||||
#ifndef ZYCORE_H
|
||||
#define ZYCORE_H
|
||||
|
||||
#include <ZycoreExportConfig.h>
|
||||
#include <Zycore/Types.h>
|
||||
|
||||
// TODO:
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constants */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* A macro that defines the zycore version.
|
||||
*/
|
||||
#define ZYCORE_VERSION (ZyanU64)0x0001000000000000
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Extracts the major-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_MAJOR(version) (ZyanU16)((version & 0xFFFF000000000000) >> 48)
|
||||
|
||||
/**
|
||||
* Extracts the minor-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_MINOR(version) (ZyanU16)((version & 0x0000FFFF00000000) >> 32)
|
||||
|
||||
/**
|
||||
* Extracts the patch-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_PATCH(version) (ZyanU16)((version & 0x00000000FFFF0000) >> 16)
|
||||
|
||||
/**
|
||||
* Extracts the build-part of the zycore version.
|
||||
*
|
||||
* @param version The zycore version value
|
||||
*/
|
||||
#define ZYCORE_VERSION_BUILD(version) (ZyanU16)(version & 0x000000000000FFFF)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Returns the zycore version.
|
||||
*
|
||||
* @return The zycore version.
|
||||
*
|
||||
* Use the macros provided in this file to extract the major, minor, patch and build part from the
|
||||
* returned version value.
|
||||
*/
|
||||
ZYCORE_EXPORT ZyanU64 ZycoreGetVersion(void);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYCORE_H */
|
Binary file not shown.
@ -1,128 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/API/Memory.h>
|
||||
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanU32 ZyanMemoryGetSystemPageSize()
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
|
||||
return system_info.dwPageSize;
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
return sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
ZyanU32 ZyanMemoryGetSystemAllocationGranularity()
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
|
||||
return system_info.dwAllocationGranularity;
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
return sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size,
|
||||
ZyanMemoryPageProtection protection)
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
DWORD old;
|
||||
if (!VirtualProtect(address, size, protection, &old))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
if (mprotect(address, size, protection))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size)
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
ZYAN_UNUSED(size);
|
||||
if (!VirtualFree(address, 0, MEM_RELEASE))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
if (munmap(address, size))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,68 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
# include <windows.h>
|
||||
#elif defined(ZYAN_POSIX)
|
||||
# include <sys/mman.h>
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
#include <Zycore/API/Process.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size)
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
if (!FlushInstructionCache(GetCurrentProcess(), address, size))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
#elif defined(ZYAN_POSIX)
|
||||
|
||||
if (msync(address, size, MS_SYNC | MS_INVALIDATE))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,200 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/API/Synchronization.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Critical Section */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
pthread_mutexattr_t attribute;
|
||||
|
||||
int error = pthread_mutexattr_init(&attribute);
|
||||
if (error != 0)
|
||||
{
|
||||
if (error == ENOMEM)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
pthread_mutexattr_settype(&attribute, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
error = pthread_mutex_init(critical_section, &attribute);
|
||||
pthread_mutexattr_destroy(&attribute);
|
||||
if (error != 0)
|
||||
{
|
||||
if (error == EAGAIN)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
if (error == ENOMEM)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
if (error == EPERM)
|
||||
{
|
||||
return ZYAN_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
if ((error == EBUSY) || (error == EINVAL))
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
const int error = pthread_mutex_lock(critical_section);
|
||||
if (error != 0)
|
||||
{
|
||||
if (error == EINVAL)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (error == EAGAIN)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_OPERATION;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
// No fine grained error handling for this one
|
||||
return pthread_mutex_trylock(critical_section) ? ZYAN_FALSE : ZYAN_TRUE;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
const int error = pthread_mutex_unlock(critical_section);
|
||||
if (error != 0)
|
||||
{
|
||||
if (error == EINVAL)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (error == EPERM)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_OPERATION;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
const int error = pthread_mutex_destroy(critical_section);
|
||||
if (error != 0)
|
||||
{
|
||||
if ((error == EBUSY) || (error == EINVAL))
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
InitializeCriticalSection(critical_section);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
EnterCriticalSection(critical_section);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
return TryEnterCriticalSection(critical_section) ? ZYAN_TRUE : ZYAN_FALSE;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
LeaveCriticalSection(critical_section);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section)
|
||||
{
|
||||
DeleteCriticalSection(critical_section);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,156 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/API/Terminal.h>
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
# include <unistd.h>
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
// Provide fallback for old SDK versions
|
||||
#ifdef ZYAN_WINDOWS
|
||||
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream)
|
||||
{
|
||||
if ((stream != ZYAN_STDSTREAM_OUT) && (stream != ZYAN_STDSTREAM_ERR))
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
#ifdef ZYAN_WINDOWS
|
||||
// Get file descriptor
|
||||
int file;
|
||||
switch (stream)
|
||||
{
|
||||
case ZYAN_STDSTREAM_OUT:
|
||||
file = _fileno(ZYAN_STDOUT);
|
||||
break;
|
||||
case ZYAN_STDSTREAM_ERR:
|
||||
file = _fileno(ZYAN_STDERR);
|
||||
break;
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
if (file < 0)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
HANDLE const handle = (HANDLE)_get_osfhandle(file);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
DWORD mode;
|
||||
if (!GetConsoleMode(handle, &mode))
|
||||
{
|
||||
// The given standard stream is not bound to a terminal
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (!SetConsoleMode(handle, mode))
|
||||
{
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream)
|
||||
{
|
||||
// Get file descriptor
|
||||
int file;
|
||||
#ifdef ZYAN_WINDOWS
|
||||
switch (stream)
|
||||
{
|
||||
case ZYAN_STDSTREAM_IN:
|
||||
file = _fileno(ZYAN_STDIN);
|
||||
break;
|
||||
case ZYAN_STDSTREAM_OUT:
|
||||
file = _fileno(ZYAN_STDOUT);
|
||||
break;
|
||||
case ZYAN_STDSTREAM_ERR:
|
||||
file = _fileno(ZYAN_STDERR);
|
||||
break;
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
if (file < 0)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
#else
|
||||
switch (stream)
|
||||
{
|
||||
case ZYAN_STDSTREAM_IN:
|
||||
file = STDIN_FILENO;
|
||||
break;
|
||||
case ZYAN_STDSTREAM_OUT:
|
||||
file = STDOUT_FILENO;
|
||||
break;
|
||||
case ZYAN_STDSTREAM_ERR:
|
||||
file = STDERR_FILENO;
|
||||
break;
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZYAN_WINDOWS
|
||||
if (_isatty(file))
|
||||
#else
|
||||
if ( isatty(file))
|
||||
#endif
|
||||
{
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
if (ZYAN_ERRNO == EBADF)
|
||||
{
|
||||
// Invalid file descriptor
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
//ZYAN_ASSERT((errno == EINVAL) || (errno == ENOTTY));
|
||||
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,194 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/API/Thread.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#if defined(ZYAN_POSIX)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread)
|
||||
{
|
||||
*thread = pthread_self();
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZYAN_STATIC_ASSERT(sizeof(ZyanThreadId) <= sizeof(ZyanU64));
|
||||
ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id)
|
||||
{
|
||||
// TODO: Use `pthread_getthreadid_np` on platforms where it is available
|
||||
|
||||
pthread_t ptid = pthread_self();
|
||||
*thread_id = *(ZyanThreadId*)ptid;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, ZyanThreadTlsCallback destructor)
|
||||
{
|
||||
ZyanThreadTlsIndex value;
|
||||
const int error = pthread_key_create(&value, destructor);
|
||||
if (error != 0)
|
||||
{
|
||||
if (error == EAGAIN)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
if (error == ENOMEM)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
*index = value;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index)
|
||||
{
|
||||
return !pthread_key_delete(index) ? ZYAN_STATUS_SUCCESS : ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data)
|
||||
{
|
||||
*data = pthread_getspecific(index);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data)
|
||||
{
|
||||
const int error = pthread_setspecific(index, data);
|
||||
if (error != 0)
|
||||
{
|
||||
if (error == EINVAL)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(ZYAN_WINDOWS)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* General */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread)
|
||||
{
|
||||
*thread = GetCurrentThread();
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id)
|
||||
{
|
||||
*thread_id = GetCurrentThreadId();
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Thread Local Storage (TLS) */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, ZyanThreadTlsCallback destructor)
|
||||
{
|
||||
const ZyanThreadTlsIndex value = FlsAlloc(destructor);
|
||||
if (value == FLS_OUT_OF_INDEXES)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
*index = value;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index)
|
||||
{
|
||||
return FlsFree(index) ? ZYAN_STATUS_SUCCESS : ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data)
|
||||
{
|
||||
*data = FlsGetValue(index);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data)
|
||||
{
|
||||
if (!FlsSetValue(index, data))
|
||||
{
|
||||
const DWORD error = GetLastError();
|
||||
if (error == ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
return ZYAN_STATUS_BAD_SYSTEMCALL;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,134 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/Allocator.h>
|
||||
#include <Zycore/LibC.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Default allocator */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
static ZyanStatus ZyanAllocatorDefaultAllocate(ZyanAllocator* allocator, void** p,
|
||||
ZyanUSize element_size, ZyanUSize n)
|
||||
{
|
||||
ZYAN_ASSERT(allocator);
|
||||
ZYAN_ASSERT(p);
|
||||
ZYAN_ASSERT(element_size);
|
||||
ZYAN_ASSERT(n);
|
||||
|
||||
ZYAN_UNUSED(allocator);
|
||||
|
||||
*p = ZYAN_MALLOC(element_size * n);
|
||||
if (!*p)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZyanStatus ZyanAllocatorDefaultReallocate(ZyanAllocator* allocator, void** p,
|
||||
ZyanUSize element_size, ZyanUSize n)
|
||||
{
|
||||
ZYAN_ASSERT(allocator);
|
||||
ZYAN_ASSERT(p);
|
||||
ZYAN_ASSERT(element_size);
|
||||
ZYAN_ASSERT(n);
|
||||
|
||||
ZYAN_UNUSED(allocator);
|
||||
|
||||
void* const x = ZYAN_REALLOC(*p, element_size * n);
|
||||
if (!x)
|
||||
{
|
||||
return ZYAN_STATUS_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
*p = x;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZyanStatus ZyanAllocatorDefaultDeallocate(ZyanAllocator* allocator, void* p,
|
||||
ZyanUSize element_size, ZyanUSize n)
|
||||
{
|
||||
ZYAN_ASSERT(allocator);
|
||||
ZYAN_ASSERT(p);
|
||||
ZYAN_ASSERT(element_size);
|
||||
ZYAN_ASSERT(n);
|
||||
|
||||
ZYAN_UNUSED(allocator);
|
||||
ZYAN_UNUSED(element_size);
|
||||
ZYAN_UNUSED(n);
|
||||
|
||||
ZYAN_FREE(p);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate,
|
||||
ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate)
|
||||
{
|
||||
if (!allocator || !allocate || !reallocate || !deallocate)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
allocator->allocate = allocate;
|
||||
allocator->reallocate = reallocate;
|
||||
allocator->deallocate = deallocate;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZyanAllocator* ZyanAllocatorDefault(void)
|
||||
{
|
||||
static ZyanAllocator allocator =
|
||||
{
|
||||
&ZyanAllocatorDefaultAllocate,
|
||||
&ZyanAllocatorDefaultReallocate,
|
||||
&ZyanAllocatorDefaultDeallocate
|
||||
};
|
||||
return &allocator;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,279 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/ArgParse.h>
|
||||
#include <Zycore/LibC.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||
const char** error_token)
|
||||
{
|
||||
return ZyanArgParseEx(cfg, parsed, error_token, ZyanAllocatorDefault());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||
const char** error_token, ZyanAllocator* allocator)
|
||||
{
|
||||
# define ZYAN_ERR_TOK(tok) if (error_token) { *error_token = tok; }
|
||||
|
||||
ZYAN_ASSERT(cfg);
|
||||
ZYAN_ASSERT(parsed);
|
||||
|
||||
// TODO: Once we have a decent hash map impl, refactor this to use it. The majority of for
|
||||
// loops through the argument list could be avoided.
|
||||
|
||||
if (cfg->min_unnamed_args > cfg->max_unnamed_args)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Check argument syntax.
|
||||
for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def)
|
||||
{
|
||||
// TODO: Duplicate check
|
||||
|
||||
if (!def->name)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize arg_len = ZYAN_STRLEN(def->name);
|
||||
if (arg_len < 2 || def->name[0] != '-')
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Single dash arguments only accept a single char name.
|
||||
if (def->name[1] != '-' && arg_len != 2)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize output vector.
|
||||
ZYAN_CHECK(ZyanVectorInitEx(parsed, sizeof(ZyanArgParseArg), cfg->argc, ZYAN_NULL, allocator,
|
||||
ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD));
|
||||
|
||||
ZyanStatus err;
|
||||
ZyanBool accept_dash_args = ZYAN_TRUE;
|
||||
ZyanUSize num_unnamed_args = 0;
|
||||
for (ZyanUSize i = 1; i < cfg->argc; ++i)
|
||||
{
|
||||
const char* cur_arg = cfg->argv[i];
|
||||
ZyanUSize arg_len = ZYAN_STRLEN(cfg->argv[i]);
|
||||
|
||||
// Double-dash argument?
|
||||
if (accept_dash_args && arg_len >= 2 && ZYAN_MEMCMP(cur_arg, "--", 2) == 0)
|
||||
{
|
||||
// GNU style end of argument parsing.
|
||||
if (arg_len == 2)
|
||||
{
|
||||
accept_dash_args = ZYAN_FALSE;
|
||||
}
|
||||
// Regular double-dash argument.
|
||||
else
|
||||
{
|
||||
// Allocate parsed argument struct.
|
||||
ZyanArgParseArg* parsed_arg;
|
||||
ZYAN_CHECK(ZyanVectorEmplace(parsed, (void**)&parsed_arg, ZYAN_NULL));
|
||||
ZYAN_MEMSET(parsed_arg, 0, sizeof(*parsed_arg));
|
||||
|
||||
// Find corresponding argument definition.
|
||||
for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def)
|
||||
{
|
||||
if (ZYAN_STRCMP(def->name, cur_arg) == 0)
|
||||
{
|
||||
parsed_arg->def = def;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Search exhausted & argument not found. RIP.
|
||||
if (!parsed_arg->def)
|
||||
{
|
||||
err = ZYAN_STATUS_ARG_NOT_UNDERSTOOD;
|
||||
ZYAN_ERR_TOK(cur_arg);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// Does the argument expect a value? If yes, consume next token.
|
||||
if (!parsed_arg->def->boolean)
|
||||
{
|
||||
if (i == cfg->argc - 1)
|
||||
{
|
||||
err = ZYAN_STATUS_ARG_MISSES_VALUE;
|
||||
ZYAN_ERR_TOK(cur_arg);
|
||||
goto failure;
|
||||
}
|
||||
parsed_arg->has_value = ZYAN_TRUE;
|
||||
ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, cfg->argv[++i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Continue parsing at next token.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Single-dash argument?
|
||||
// TODO: How to deal with just dashes? Current code treats it as unnamed arg.
|
||||
if (accept_dash_args && arg_len > 1 && cur_arg[0] == '-')
|
||||
{
|
||||
// Iterate argument token chars until there are either no more chars left
|
||||
// or we encounter a non-boolean argument, in which case we consume the
|
||||
// remaining chars as its value.
|
||||
for (const char* read_ptr = cur_arg + 1; *read_ptr; ++read_ptr)
|
||||
{
|
||||
// Allocate parsed argument struct.
|
||||
ZyanArgParseArg* parsed_arg;
|
||||
ZYAN_CHECK(ZyanVectorEmplace(parsed, (void**)&parsed_arg, ZYAN_NULL));
|
||||
ZYAN_MEMSET(parsed_arg, 0, sizeof(*parsed_arg));
|
||||
|
||||
// Find corresponding argument definition.
|
||||
for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def)
|
||||
{
|
||||
if (ZYAN_STRLEN(def->name) == 2 &&
|
||||
def->name[0] == '-' &&
|
||||
def->name[1] == *read_ptr)
|
||||
{
|
||||
parsed_arg->def = def;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Search exhausted, no match found?
|
||||
if (!parsed_arg->def)
|
||||
{
|
||||
err = ZYAN_STATUS_ARG_NOT_UNDERSTOOD;
|
||||
ZYAN_ERR_TOK(cur_arg);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// Requires value?
|
||||
if (!parsed_arg->def->boolean)
|
||||
{
|
||||
// If there are chars left, consume them (e.g. `-n1000`).
|
||||
if (read_ptr[1])
|
||||
{
|
||||
parsed_arg->has_value = ZYAN_TRUE;
|
||||
ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, read_ptr + 1));
|
||||
}
|
||||
// If not, consume next token (e.g. `-n 1000`).
|
||||
else
|
||||
{
|
||||
if (i == cfg->argc - 1)
|
||||
{
|
||||
err = ZYAN_STATUS_ARG_MISSES_VALUE;
|
||||
ZYAN_ERR_TOK(cur_arg)
|
||||
goto failure;
|
||||
}
|
||||
|
||||
parsed_arg->has_value = ZYAN_TRUE;
|
||||
ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, cfg->argv[++i]));
|
||||
}
|
||||
|
||||
// Either way, continue with next argument.
|
||||
goto continue_main_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Still here? We're looking at an unnamed argument.
|
||||
++num_unnamed_args;
|
||||
if (num_unnamed_args > cfg->max_unnamed_args)
|
||||
{
|
||||
err = ZYAN_STATUS_TOO_MANY_ARGS;
|
||||
ZYAN_ERR_TOK(cur_arg);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// Allocate parsed argument struct.
|
||||
ZyanArgParseArg* parsed_arg;
|
||||
ZYAN_CHECK(ZyanVectorEmplace(parsed, (void**)&parsed_arg, ZYAN_NULL));
|
||||
ZYAN_MEMSET(parsed_arg, 0, sizeof(*parsed_arg));
|
||||
parsed_arg->has_value = ZYAN_TRUE;
|
||||
ZYAN_CHECK(ZyanStringViewInsideBuffer(&parsed_arg->value, cur_arg));
|
||||
|
||||
continue_main_loop:;
|
||||
}
|
||||
|
||||
// All tokens processed. Do we have enough unnamed arguments?
|
||||
if (num_unnamed_args < cfg->min_unnamed_args)
|
||||
{
|
||||
err = ZYAN_STATUS_TOO_FEW_ARGS;
|
||||
// No sensible error token for this error type.
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// Check whether all required arguments are present.
|
||||
ZyanUSize num_parsed_args;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(parsed, &num_parsed_args));
|
||||
for (const ZyanArgParseDefinition* def = cfg->args; def && def->name; ++def)
|
||||
{
|
||||
if (!def->required) continue;
|
||||
|
||||
ZyanBool arg_found = ZYAN_FALSE;
|
||||
for (ZyanUSize i = 0; i < num_parsed_args; ++i)
|
||||
{
|
||||
const ZyanArgParseArg* arg = ZYAN_NULL;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(parsed, i, (const void**)&arg));
|
||||
|
||||
// Skip unnamed args.
|
||||
if (!arg->def) continue;
|
||||
|
||||
if (arg->def == def)
|
||||
{
|
||||
arg_found = ZYAN_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arg_found)
|
||||
{
|
||||
err = ZYAN_STATUS_REQUIRED_ARG_MISSING;
|
||||
ZYAN_ERR_TOK(def->name);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
// Yay!
|
||||
ZYAN_ERR_TOK(ZYAN_NULL);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
|
||||
failure:
|
||||
ZYAN_CHECK(ZyanVectorDestroy(parsed));
|
||||
return err;
|
||||
|
||||
# undef ZYAN_ERR_TOK
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,670 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/Bitset.h>
|
||||
#include <Zycore/LibC.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal constants */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#define ZYAN_BITSET_GROWTH_FACTOR 2.00f
|
||||
#define ZYAN_BITSET_SHRINK_THRESHOLD 0.50f
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Computes the smallest integer value not less than `x`.
|
||||
*
|
||||
* @param x The value.
|
||||
*
|
||||
* @return The smallest integer value not less than `x`.
|
||||
*/
|
||||
#define ZYAN_BITSET_CEIL(x) \
|
||||
(((x) == ((ZyanU32)(x))) ? (ZyanU32)(x) : ((ZyanU32)(x)) + 1)
|
||||
|
||||
/**
|
||||
* Converts bits to bytes.
|
||||
*
|
||||
* @param x The value in bits.
|
||||
*
|
||||
* @return The amount of bytes needed to fit `x` bits.
|
||||
*/
|
||||
#define ZYAN_BITSET_BITS_TO_BYTES(x) \
|
||||
ZYAN_BITSET_CEIL((x) / 8.0f)
|
||||
|
||||
/**
|
||||
* Returns the offset of the given bit.
|
||||
*
|
||||
* @param index The bit index.
|
||||
*
|
||||
* @return The offset of the given bit.
|
||||
*/
|
||||
#define ZYAN_BITSET_BIT_OFFSET(index) \
|
||||
(7 - ((index) % 8))
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Initializes the given `vector` with `count` "zero"-bytes.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param count The number of bytes.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus ZyanBitsetInitVectorElements(ZyanVector* vector, ZyanUSize count)
|
||||
{
|
||||
ZYAN_ASSERT(vector);
|
||||
|
||||
static const ZyanU8 zero = 0;
|
||||
for (ZyanUSize i = 0; i < count; ++i)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorPushBack(vector, &zero));
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Byte operations */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static ZyanStatus ZyanBitsetOperationAND(ZyanU8* b1, const ZyanU8* b2)
|
||||
{
|
||||
*b1 &= *b2;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZyanStatus ZyanBitsetOperationOR (ZyanU8* b1, const ZyanU8* b2)
|
||||
{
|
||||
*b1 |= *b2;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZyanStatus ZyanBitsetOperationXOR(ZyanU8* b1, const ZyanU8* b2)
|
||||
{
|
||||
*b1 ^= *b2;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count)
|
||||
{
|
||||
return ZyanBitsetInitEx(bitset, count, ZyanAllocatorDefault(), ZYAN_BITSET_GROWTH_FACTOR,
|
||||
ZYAN_BITSET_SHRINK_THRESHOLD);
|
||||
}
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count, ZyanAllocator* allocator,
|
||||
float growth_factor, float shrink_threshold)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const ZyanU32 bytes = ZYAN_BITSET_BITS_TO_BYTES(count);
|
||||
|
||||
bitset->size = count;
|
||||
ZYAN_CHECK(ZyanVectorInitEx(&bitset->bits, sizeof(ZyanU8), bytes, ZYAN_NULL, allocator,
|
||||
growth_factor, shrink_threshold));
|
||||
ZYAN_CHECK(ZyanBitsetInitVectorElements(&bitset->bits, bytes));
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer,
|
||||
ZyanUSize capacity)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const ZyanU32 bytes = ZYAN_BITSET_BITS_TO_BYTES(count);
|
||||
if (capacity < bytes)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
bitset->size = count;
|
||||
ZYAN_CHECK(ZyanVectorInitCustomBuffer(&bitset->bits, sizeof(ZyanU8), buffer, capacity,
|
||||
ZYAN_NULL));
|
||||
ZYAN_CHECK(ZyanBitsetInitVectorElements(&bitset->bits, bytes));
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorDestroy(&bitset->bits);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Logical operations */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination, const ZyanBitset* source,
|
||||
ZyanBitsetByteOperation operation)
|
||||
{
|
||||
if (!destination || !source || !operation)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize s1;
|
||||
ZyanUSize s2;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&destination->bits, &s1));
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&source->bits, &s2));
|
||||
|
||||
const ZyanUSize min = ZYAN_MIN(s1, s2);
|
||||
for (ZyanUSize i = 0; i < min; ++i)
|
||||
{
|
||||
ZyanU8* v1;
|
||||
const ZyanU8* v2;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&destination->bits, i, (void**)&v1));
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&source->bits, i, (const void**)&v2));
|
||||
|
||||
ZYAN_ASSERT(v1);
|
||||
ZYAN_ASSERT(v2);
|
||||
|
||||
ZYAN_CHECK(operation(v1, v2));
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source)
|
||||
{
|
||||
return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationAND);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source)
|
||||
{
|
||||
return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationOR );
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source)
|
||||
{
|
||||
return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationXOR);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value));
|
||||
*value = ~(*value);
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Bit access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= bitset->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value));
|
||||
|
||||
*value |= (1 << ZYAN_BITSET_BIT_OFFSET(index));
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= bitset->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value));
|
||||
*value &= ~(1 << ZYAN_BITSET_BIT_OFFSET(index));
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
return ZyanBitsetSet(bitset, index);
|
||||
}
|
||||
return ZyanBitsetReset(bitset, index);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= bitset->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value));
|
||||
*value ^= (1 << ZYAN_BITSET_BIT_OFFSET(index));
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= bitset->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
const ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, index / 8, (const void**)&value));
|
||||
if ((*value & (1 << ZYAN_BITSET_BIT_OFFSET(index))) == 0)
|
||||
{
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanBitsetTest(bitset, bitset->size - 1);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset)
|
||||
{
|
||||
return ZyanBitsetTest(bitset, 0);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value));
|
||||
*value = 0xFF;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value));
|
||||
*value = 0x00;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Size management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if ((bitset->size++ % 8) == 0)
|
||||
{
|
||||
static const ZyanU8 zero = 0;
|
||||
ZYAN_CHECK(ZyanVectorPushBack(&bitset->bits, &zero));
|
||||
}
|
||||
|
||||
return ZyanBitsetAssign(bitset, bitset->size - 1, value);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetPop(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if ((--bitset->size % 8) == 0)
|
||||
{
|
||||
return ZyanVectorPopBack(&bitset->bits);
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetClear(ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
bitset->size = 0;
|
||||
return ZyanVectorClear(&bitset->bits);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count)
|
||||
{
|
||||
return ZyanVectorReserve(&bitset->bits, ZYAN_BITSET_BITS_TO_BYTES(count));
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset)
|
||||
{
|
||||
return ZyanVectorShrinkToFit(&bitset->bits);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*size = bitset->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity)
|
||||
{
|
||||
ZYAN_CHECK(ZyanBitsetGetCapacityBytes(bitset, capacity));
|
||||
*capacity *= 8;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorGetSize(&bitset->bits, size);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorGetCapacity(&bitset->bits, capacity);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count)
|
||||
{
|
||||
if (!bitset || !count)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*count = 0;
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
|
||||
|
||||
ZyanU8 popcnt = *value;
|
||||
popcnt = (popcnt & 0x55) + ((popcnt >> 1) & 0x55);
|
||||
popcnt = (popcnt & 0x33) + ((popcnt >> 2) & 0x33);
|
||||
popcnt = (popcnt & 0x0F) + ((popcnt >> 4) & 0x0F);
|
||||
|
||||
*count += popcnt;
|
||||
}
|
||||
|
||||
*count = ZYAN_MIN(*count, bitset->size);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
|
||||
if (i < (size - 1))
|
||||
{
|
||||
if (*value != 0xFF)
|
||||
{
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
} else
|
||||
{
|
||||
const ZyanU8 mask = ~(8 - (bitset->size % 8));
|
||||
if ((*value & mask) != mask)
|
||||
{
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
|
||||
if (i < (size - 1))
|
||||
{
|
||||
if (*value != 0x00)
|
||||
{
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
} else
|
||||
{
|
||||
const ZyanU8 mask = ~(8 - (bitset->size % 8));
|
||||
if ((*value & mask) != 0x00)
|
||||
{
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset)
|
||||
{
|
||||
if (!bitset)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanUSize size;
|
||||
ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
|
||||
for (ZyanUSize i = 0; i < size; ++i)
|
||||
{
|
||||
ZyanU8* value;
|
||||
ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
|
||||
if (i < (size - 1))
|
||||
{
|
||||
if (*value != 0x00)
|
||||
{
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
} else
|
||||
{
|
||||
const ZyanU8 mask = ~(8 - (bitset->size % 8));
|
||||
if ((*value & mask) != 0x00)
|
||||
{
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
//ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value)
|
||||
//{
|
||||
// if (!bitset)
|
||||
// {
|
||||
// return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
// }
|
||||
// if (bitset->size > 32)
|
||||
// {
|
||||
// return ZYAN_STATUS_INVALID_OPERATION;
|
||||
// }
|
||||
//
|
||||
// // TODO:
|
||||
//
|
||||
// return ZYAN_STATUS_SUCCESS;
|
||||
//}
|
||||
//
|
||||
//ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value)
|
||||
//{
|
||||
// if (!bitset)
|
||||
// {
|
||||
// return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
// }
|
||||
// if (bitset->size > 64)
|
||||
// {
|
||||
// return ZYAN_STATUS_INVALID_OPERATION;
|
||||
// }
|
||||
//
|
||||
// // TODO:
|
||||
//
|
||||
// return ZYAN_STATUS_SUCCESS;
|
||||
//}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,507 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/Format.h>
|
||||
#include <Zycore/LibC.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Constants */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Defines */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define ZYCORE_MAXCHARS_DEC_32 10
|
||||
#define ZYCORE_MAXCHARS_DEC_64 20
|
||||
#define ZYCORE_MAXCHARS_HEX_32 8
|
||||
#define ZYCORE_MAXCHARS_HEX_64 16
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Lookup Tables */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static const char* const DECIMAL_LOOKUP =
|
||||
"00010203040506070809"
|
||||
"10111213141516171819"
|
||||
"20212223242526272829"
|
||||
"30313233343536373839"
|
||||
"40414243444546474849"
|
||||
"50515253545556575859"
|
||||
"60616263646566676869"
|
||||
"70717273747576777879"
|
||||
"80818283848586878889"
|
||||
"90919293949596979899";
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Static strings */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static const ZyanStringView STR_ADD = ZYAN_DEFINE_STRING_VIEW("+");
|
||||
static const ZyanStringView STR_SUB = ZYAN_DEFINE_STRING_VIEW("-");
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Writes a terminating '\0' character at the end of the string data.
|
||||
*/
|
||||
#define ZYCORE_STRING_NULLTERMINATE(string) \
|
||||
*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0';
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decimal */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ZYAN_X86) || defined(ZYAN_ARM) || defined(ZYAN_EMSCRIPTEN)
|
||||
ZyanStatus ZyanStringAppendDecU32(ZyanString* string, ZyanU32 value, ZyanU8 padding_length)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
char buffer[ZYCORE_MAXCHARS_DEC_32];
|
||||
char *buffer_end = &buffer[ZYCORE_MAXCHARS_DEC_32];
|
||||
char *buffer_write_pointer = buffer_end;
|
||||
while (value >= 100)
|
||||
{
|
||||
const ZyanU32 value_old = value;
|
||||
buffer_write_pointer -= 2;
|
||||
value /= 100;
|
||||
ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[(value_old - (value * 100)) * 2], 2);
|
||||
}
|
||||
buffer_write_pointer -= 2;
|
||||
ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[value * 2], 2);
|
||||
|
||||
const ZyanUSize offset_odd = (ZyanUSize)(value < 10);
|
||||
const ZyanUSize length_number = buffer_end - buffer_write_pointer - offset_odd;
|
||||
const ZyanUSize length_total = ZYAN_MAX(length_number, padding_length);
|
||||
const ZyanUSize length_target = string->vector.size;
|
||||
|
||||
if (string->vector.size + length_total > string->vector.capacity)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, string->vector.size + length_total - 1));
|
||||
}
|
||||
|
||||
ZyanUSize offset_write = 0;
|
||||
if (padding_length > length_number)
|
||||
{
|
||||
offset_write = padding_length - length_number;
|
||||
ZYAN_MEMSET((char*)string->vector.data + length_target - 1, '0', offset_write);
|
||||
}
|
||||
|
||||
ZYAN_MEMCPY((char*)string->vector.data + length_target + offset_write - 1,
|
||||
buffer_write_pointer + offset_odd, length_number);
|
||||
string->vector.size = length_target + length_total;
|
||||
ZYCORE_STRING_NULLTERMINATE(string);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZyanStatus ZyanStringAppendDecU64(ZyanString* string, ZyanU64 value, ZyanU8 padding_length)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
char buffer[ZYCORE_MAXCHARS_DEC_64];
|
||||
char *buffer_end = &buffer[ZYCORE_MAXCHARS_DEC_64];
|
||||
char *buffer_write_pointer = buffer_end;
|
||||
while (value >= 100)
|
||||
{
|
||||
const ZyanU64 value_old = value;
|
||||
buffer_write_pointer -= 2;
|
||||
value /= 100;
|
||||
ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[(value_old - (value * 100)) * 2], 2);
|
||||
}
|
||||
buffer_write_pointer -= 2;
|
||||
ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[value * 2], 2);
|
||||
|
||||
const ZyanUSize offset_odd = (ZyanUSize)(value < 10);
|
||||
const ZyanUSize length_number = buffer_end - buffer_write_pointer - offset_odd;
|
||||
const ZyanUSize length_total = ZYAN_MAX(length_number, padding_length);
|
||||
const ZyanUSize length_target = string->vector.size;
|
||||
|
||||
if (string->vector.size + length_total > string->vector.capacity)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, string->vector.size + length_total - 1));
|
||||
}
|
||||
|
||||
ZyanUSize offset_write = 0;
|
||||
if (padding_length > length_number)
|
||||
{
|
||||
offset_write = padding_length - length_number;
|
||||
ZYAN_MEMSET((char*)string->vector.data + length_target - 1, '0', offset_write);
|
||||
}
|
||||
|
||||
ZYAN_MEMCPY((char*)string->vector.data + length_target + offset_write - 1,
|
||||
buffer_write_pointer + offset_odd, length_number);
|
||||
string->vector.size = length_target + length_total;
|
||||
ZYCORE_STRING_NULLTERMINATE(string);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Hexadecimal */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ZYAN_X86) || defined(ZYAN_ARM) || defined(ZYAN_EMSCRIPTEN)
|
||||
ZyanStatus ZyanStringAppendHexU32(ZyanString* string, ZyanU32 value, ZyanU8 padding_length,
|
||||
ZyanBool uppercase)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const ZyanUSize len = string->vector.size;
|
||||
ZyanUSize remaining = string->vector.capacity - string->vector.size;
|
||||
|
||||
if (remaining < (ZyanUSize)padding_length)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, len + padding_length - 1));
|
||||
remaining = padding_length;
|
||||
}
|
||||
|
||||
if (!value)
|
||||
{
|
||||
const ZyanU8 n = (padding_length ? padding_length : 1);
|
||||
|
||||
if (remaining < (ZyanUSize)n)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, string->vector.size + n - 1));
|
||||
}
|
||||
|
||||
ZYAN_MEMSET((char*)string->vector.data + len - 1, '0', n);
|
||||
string->vector.size = len + n;
|
||||
ZYCORE_STRING_NULLTERMINATE(string);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanU8 n = 0;
|
||||
char* buffer = ZYAN_NULL;
|
||||
for (ZyanI8 i = ZYCORE_MAXCHARS_HEX_32 - 1; i >= 0; --i)
|
||||
{
|
||||
const ZyanU8 v = (value >> i * 4) & 0x0F;
|
||||
if (!n)
|
||||
{
|
||||
if (!v)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (remaining <= (ZyanU8)i)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, string->vector.size + i));
|
||||
}
|
||||
buffer = (char*)string->vector.data + len - 1;
|
||||
if (padding_length > i)
|
||||
{
|
||||
n = padding_length - i - 1;
|
||||
ZYAN_MEMSET(buffer, '0', n);
|
||||
}
|
||||
}
|
||||
ZYAN_ASSERT(buffer);
|
||||
if (uppercase)
|
||||
{
|
||||
buffer[n++] = "0123456789ABCDEF"[v];
|
||||
} else
|
||||
{
|
||||
buffer[n++] = "0123456789abcdef"[v];
|
||||
}
|
||||
}
|
||||
string->vector.size = len + n;
|
||||
ZYCORE_STRING_NULLTERMINATE(string);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZyanStatus ZyanStringAppendHexU64(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
|
||||
ZyanBool uppercase)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const ZyanUSize len = string->vector.size;
|
||||
ZyanUSize remaining = string->vector.capacity - string->vector.size;
|
||||
|
||||
if (remaining < (ZyanUSize)padding_length)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, len + padding_length - 1));
|
||||
remaining = padding_length;
|
||||
}
|
||||
|
||||
if (!value)
|
||||
{
|
||||
const ZyanU8 n = (padding_length ? padding_length : 1);
|
||||
|
||||
if (remaining < (ZyanUSize)n)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, string->vector.size + n - 1));
|
||||
}
|
||||
|
||||
ZYAN_MEMSET((char*)string->vector.data + len - 1, '0', n);
|
||||
string->vector.size = len + n;
|
||||
ZYCORE_STRING_NULLTERMINATE(string);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanU8 n = 0;
|
||||
char* buffer = ZYAN_NULL;
|
||||
for (ZyanI8 i = ((value & 0xFFFFFFFF00000000) ?
|
||||
ZYCORE_MAXCHARS_HEX_64 : ZYCORE_MAXCHARS_HEX_32) - 1; i >= 0; --i)
|
||||
{
|
||||
const ZyanU8 v = (value >> i * 4) & 0x0F;
|
||||
if (!n)
|
||||
{
|
||||
if (!v)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (remaining <= (ZyanU8)i)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringResize(string, string->vector.size + i));
|
||||
}
|
||||
buffer = (char*)string->vector.data + len - 1;
|
||||
if (padding_length > i)
|
||||
{
|
||||
n = padding_length - i - 1;
|
||||
ZYAN_MEMSET(buffer, '0', n);
|
||||
}
|
||||
}
|
||||
ZYAN_ASSERT(buffer);
|
||||
if (uppercase)
|
||||
{
|
||||
buffer[n++] = "0123456789ABCDEF"[v];
|
||||
} else
|
||||
{
|
||||
buffer[n++] = "0123456789abcdef"[v];
|
||||
}
|
||||
}
|
||||
string->vector.size = len + n;
|
||||
ZYCORE_STRING_NULLTERMINATE(string);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
//ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index, const char* format, ...)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
///* ---------------------------------------------------------------------------------------------- */
|
||||
//
|
||||
//ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||
// ZyanUSize padding_length)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
//ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||
// ZyanUSize padding_length, ZyanBool force_sign, const ZyanString* prefix)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
//ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||
// ZyanUSize padding_length, ZyanBool uppercase)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
//ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||
// ZyanUSize padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Appending */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanStringAppendFormat(ZyanString* string, const char* format, ...)
|
||||
{
|
||||
if (!string || !format)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanVAList arglist;
|
||||
ZYAN_VA_START(arglist, format);
|
||||
|
||||
const ZyanUSize len = string->vector.size;
|
||||
|
||||
ZyanI32 w = ZYAN_VSNPRINTF((char*)string->vector.data + len - 1,
|
||||
string->vector.capacity - len + 1, format, arglist);
|
||||
if (w < 0)
|
||||
{
|
||||
ZYAN_VA_END(arglist);
|
||||
return ZYAN_STATUS_FAILED;
|
||||
}
|
||||
if (w <= (ZyanI32)(string->vector.capacity - len))
|
||||
{
|
||||
string->vector.size = len + w;
|
||||
|
||||
ZYAN_VA_END(arglist);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// The remaining capacity was not sufficent to fit the formatted string. Trying to resize ..
|
||||
const ZyanStatus status = ZyanStringResize(string, string->vector.size + w - 1);
|
||||
if (!ZYAN_SUCCESS(status))
|
||||
{
|
||||
ZYAN_VA_END(arglist);
|
||||
return status;
|
||||
}
|
||||
|
||||
w = ZYAN_VSNPRINTF((char*)string->vector.data + len - 1,
|
||||
string->vector.capacity - string->vector.size + 1, format, arglist);
|
||||
if (w < 0)
|
||||
{
|
||||
ZYAN_VA_END(arglist);
|
||||
return ZYAN_STATUS_FAILED;
|
||||
}
|
||||
ZYAN_ASSERT(w <= (ZyanI32)(string->vector.capacity - string->vector.size));
|
||||
|
||||
ZYAN_VA_END(arglist);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length)
|
||||
{
|
||||
#if defined(ZYAN_X64) || defined(ZYAN_AARCH64)
|
||||
return ZyanStringAppendDecU64(string, value, padding_length);
|
||||
#else
|
||||
// Working with 64-bit values is slow on non 64-bit systems
|
||||
if (value & 0xFFFFFFFF00000000)
|
||||
{
|
||||
return ZyanStringAppendDecU64(string, value, padding_length);
|
||||
}
|
||||
return ZyanStringAppendDecU32(string, (ZyanU32)value, padding_length);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value, ZyanU8 padding_length,
|
||||
ZyanBool force_sign, const ZyanStringView* prefix)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringAppend(string, &STR_SUB));
|
||||
if (prefix)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringAppend(string, prefix));
|
||||
}
|
||||
return ZyanStringAppendDecU(string, ZyanAbsI64(value), padding_length);
|
||||
}
|
||||
|
||||
if (force_sign)
|
||||
{
|
||||
ZYAN_ASSERT(value >= 0);
|
||||
ZYAN_CHECK(ZyanStringAppend(string, &STR_ADD));
|
||||
}
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringAppend(string, prefix));
|
||||
}
|
||||
return ZyanStringAppendDecU(string, value, padding_length);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
|
||||
ZyanBool uppercase)
|
||||
{
|
||||
#if defined(ZYAN_X64) || defined(ZYAN_AARCH64)
|
||||
return ZyanStringAppendHexU64(string, value, padding_length, uppercase);
|
||||
#else
|
||||
// Working with 64-bit values is slow on non 64-bit systems
|
||||
if (value & 0xFFFFFFFF00000000)
|
||||
{
|
||||
return ZyanStringAppendHexU64(string, value, padding_length, uppercase);
|
||||
}
|
||||
return ZyanStringAppendHexU32(string, (ZyanU32)value, padding_length, uppercase);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value, ZyanU8 padding_length,
|
||||
ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringAppend(string, &STR_SUB));
|
||||
if (prefix)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringAppend(string, prefix));
|
||||
}
|
||||
return ZyanStringAppendHexU(string, ZyanAbsI64(value), padding_length, uppercase);
|
||||
}
|
||||
|
||||
if (force_sign)
|
||||
{
|
||||
ZYAN_ASSERT(value >= 0);
|
||||
ZYAN_CHECK(ZyanStringAppend(string, &STR_ADD));
|
||||
}
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
ZYAN_CHECK(ZyanStringAppend(string, prefix));
|
||||
}
|
||||
return ZyanStringAppendHexU(string, value, padding_length, uppercase);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,673 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/List.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Returns a pointer to the data of the given `node`.
|
||||
*
|
||||
* @param node A pointer to the `ZyanNodeData` struct.
|
||||
*
|
||||
* @return A pointer to the data of the given `node`.
|
||||
*/
|
||||
#define ZYCORE_LIST_GET_NODE_DATA(node) \
|
||||
((void*)(node + 1))
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Allocates memory for a new list node.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node Receives a pointer to the new `ZyanListNode` struct.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus ZyanListAllocateNode(ZyanList* list, ZyanListNode** node)
|
||||
{
|
||||
ZYAN_ASSERT(list);
|
||||
ZYAN_ASSERT(node);
|
||||
|
||||
const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
|
||||
if (is_dynamic)
|
||||
{
|
||||
ZYAN_ASSERT(list->allocator->allocate);
|
||||
ZYAN_CHECK(list->allocator->allocate(list->allocator, (void**)node,
|
||||
sizeof(ZyanListNode) + list->element_size, 1));
|
||||
} else
|
||||
{
|
||||
if (list->first_unused)
|
||||
{
|
||||
*node = list->first_unused;
|
||||
list->first_unused = (*node)->next;
|
||||
} else
|
||||
{
|
||||
const ZyanUSize size = list->size * (sizeof(ZyanListNode) + list->element_size);
|
||||
if (size + (sizeof(ZyanListNode) + list->element_size) > list->capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
*node = (ZyanListNode*)((ZyanU8*)list->buffer + size);
|
||||
}
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees memory of a node.
|
||||
*
|
||||
* @param list A pointer to the `ZyanList` instance.
|
||||
* @param node A pointer to the `ZyanListNode` struct.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus ZyanListDeallocateNode(ZyanList* list, ZyanListNode* node)
|
||||
{
|
||||
ZYAN_ASSERT(list);
|
||||
ZYAN_ASSERT(node);
|
||||
|
||||
const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
|
||||
if (is_dynamic)
|
||||
{
|
||||
ZYAN_ASSERT(list->allocator->deallocate);
|
||||
ZYAN_CHECK(list->allocator->deallocate(list->allocator, (void*)node,
|
||||
sizeof(ZyanListNode) + list->element_size, 1));
|
||||
} else
|
||||
{
|
||||
node->next = list->first_unused;
|
||||
list->first_unused = node;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor)
|
||||
{
|
||||
return ZyanListInitEx(list, element_size, destructor, ZyanAllocatorDefault());
|
||||
}
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size, ZyanMemberProcedure destructor,
|
||||
ZyanAllocator* allocator)
|
||||
{
|
||||
if (!list || !element_size || !allocator)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
list->allocator = allocator;
|
||||
list->size = 0;
|
||||
list->element_size = element_size;
|
||||
list->destructor = destructor;
|
||||
list->head = ZYAN_NULL;
|
||||
list->tail = ZYAN_NULL;
|
||||
list->buffer = ZYAN_NULL;
|
||||
list->capacity = 0;
|
||||
list->first_unused = ZYAN_NULL;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size,
|
||||
ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity)
|
||||
{
|
||||
if (!list || !element_size || !buffer || !capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
list->allocator = ZYAN_NULL;
|
||||
list->size = 0;
|
||||
list->element_size = element_size;
|
||||
list->destructor = destructor;
|
||||
list->head = ZYAN_NULL;
|
||||
list->tail = ZYAN_NULL;
|
||||
list->buffer = buffer;
|
||||
list->capacity = capacity;
|
||||
list->first_unused = ZYAN_NULL;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListDestroy(ZyanList* list)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(list->element_size);
|
||||
|
||||
const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
|
||||
ZyanListNode* node = (is_dynamic || list->destructor) ? list->head : ZYAN_NULL;
|
||||
while (node)
|
||||
{
|
||||
if (list->destructor)
|
||||
{
|
||||
list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
|
||||
}
|
||||
|
||||
ZyanListNode* const next = node->next;
|
||||
|
||||
if (is_dynamic)
|
||||
{
|
||||
ZYAN_CHECK(list->allocator->deallocate(list->allocator, node,
|
||||
sizeof(ZyanListNode) + list->element_size, 1));
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Duplication */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Item access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*node = list->head;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*node = list->tail;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node)
|
||||
{
|
||||
if (!node || !*node)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*node = (*node)->prev;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListGetNextNode(const ZyanListNode** node)
|
||||
{
|
||||
if (!node || !*node)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*node = (*node)->next;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const void* ZyanListGetNodeData(const ZyanListNode* node)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return ZYAN_NULL;
|
||||
}
|
||||
|
||||
return (const void*)ZYCORE_LIST_GET_NODE_DATA(node);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*value = (const void*)ZYCORE_LIST_GET_NODE_DATA(node);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void* ZyanListGetNodeDataMutable(const ZyanListNode* node)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return ZYAN_NULL;
|
||||
}
|
||||
|
||||
return ZYCORE_LIST_GET_NODE_DATA(node);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*value = ZYCORE_LIST_GET_NODE_DATA(node);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node, const void* value)
|
||||
{
|
||||
if (!list || !node || !value)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (list->destructor)
|
||||
{
|
||||
list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(list->element_size);
|
||||
ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), value, list->element_size);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanListPushBack(ZyanList* list, const void* item)
|
||||
{
|
||||
if (!list || !item)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanListNode* node;
|
||||
ZYAN_CHECK(ZyanListAllocateNode(list, &node));
|
||||
node->prev = list->tail;
|
||||
node->next = ZYAN_NULL;
|
||||
|
||||
ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), item, list->element_size);
|
||||
|
||||
if (!list->head)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
} else
|
||||
{
|
||||
list->tail->next = node;
|
||||
list->tail = node;
|
||||
}
|
||||
++list->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListPushFront(ZyanList* list, const void* item)
|
||||
{
|
||||
if (!list || !item)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanListNode* node;
|
||||
ZYAN_CHECK(ZyanListAllocateNode(list, &node));
|
||||
node->prev = ZYAN_NULL;
|
||||
node->next = list->head;
|
||||
|
||||
ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), item, list->element_size);
|
||||
|
||||
if (!list->head)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
} else
|
||||
{
|
||||
list->head->prev= node;
|
||||
list->head = node;
|
||||
}
|
||||
++list->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item, ZyanMemberFunction constructor)
|
||||
{
|
||||
if (!list || !item)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanListNode* node;
|
||||
ZYAN_CHECK(ZyanListAllocateNode(list, &node));
|
||||
node->prev = list->tail;
|
||||
node->next = ZYAN_NULL;
|
||||
|
||||
*item = ZYCORE_LIST_GET_NODE_DATA(node);
|
||||
if (constructor)
|
||||
{
|
||||
constructor(*item);
|
||||
}
|
||||
|
||||
if (!list->head)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
} else
|
||||
{
|
||||
list->tail->next = node;
|
||||
list->tail = node;
|
||||
}
|
||||
++list->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item, ZyanMemberFunction constructor)
|
||||
{
|
||||
if (!list || !item)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZyanListNode* node;
|
||||
ZYAN_CHECK(ZyanListAllocateNode(list, &node));
|
||||
node->prev = ZYAN_NULL;
|
||||
node->next = list->head;
|
||||
|
||||
*item = ZYCORE_LIST_GET_NODE_DATA(node);
|
||||
if (constructor)
|
||||
{
|
||||
constructor(*item);
|
||||
}
|
||||
|
||||
if (!list->head)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
} else
|
||||
{
|
||||
list->head->prev= node;
|
||||
list->head = node;
|
||||
}
|
||||
++list->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Deletion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanListPopBack(ZyanList* list)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (!list->tail)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
ZyanListNode* const node = list->tail;
|
||||
|
||||
if (list->destructor)
|
||||
{
|
||||
list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
|
||||
}
|
||||
|
||||
list->tail = node->prev;
|
||||
if (list->tail)
|
||||
{
|
||||
list->tail->next = ZYAN_NULL;
|
||||
}
|
||||
if (list->head == node)
|
||||
{
|
||||
list->head = list->tail;
|
||||
}
|
||||
--list->size;
|
||||
|
||||
return ZyanListDeallocateNode(list, node);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListPopFront(ZyanList* list)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (!list->head)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
ZyanListNode* const node = list->head;
|
||||
|
||||
if (list->destructor)
|
||||
{
|
||||
list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
|
||||
}
|
||||
|
||||
list->head = node->next;
|
||||
if (list->head)
|
||||
{
|
||||
list->head->prev = ZYAN_NULL;
|
||||
}
|
||||
if (list->tail == node)
|
||||
{
|
||||
list->tail = list->head;
|
||||
}
|
||||
--list->size;
|
||||
|
||||
return ZyanListDeallocateNode(list, node);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node)
|
||||
{
|
||||
ZYAN_UNUSED(list);
|
||||
ZYAN_UNUSED(node);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first, const ZyanListNode* last)
|
||||
{
|
||||
ZYAN_UNUSED(list);
|
||||
ZYAN_UNUSED(first);
|
||||
ZYAN_UNUSED(last);
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListClear(ZyanList* list)
|
||||
{
|
||||
return ZyanListResizeEx(list, 0, ZYAN_NULL);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Searching */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size)
|
||||
{
|
||||
return ZyanListResizeEx(list, size, ZYAN_NULL);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (size == list->size)
|
||||
{
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
|
||||
ZyanListNode* node = (is_dynamic || list->destructor) ? list->head : ZYAN_NULL;
|
||||
while (node)
|
||||
{
|
||||
if (list->destructor)
|
||||
{
|
||||
list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
|
||||
}
|
||||
|
||||
ZyanListNode* const next = node->next;
|
||||
|
||||
if (is_dynamic)
|
||||
{
|
||||
ZYAN_CHECK(list->allocator->deallocate(list->allocator, node,
|
||||
sizeof(ZyanListNode) + list->element_size, 1));
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
||||
list->size = 0;
|
||||
list->head = 0;
|
||||
list->tail = 0;
|
||||
list->first_unused = ZYAN_NULL;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (size > list->size)
|
||||
{
|
||||
ZyanListNode* node;
|
||||
for (ZyanUSize i = list->size; i < size; ++i)
|
||||
{
|
||||
ZYAN_CHECK(ZyanListAllocateNode(list, &node));
|
||||
node->prev = list->tail;
|
||||
node->next = ZYAN_NULL;
|
||||
|
||||
if (initializer)
|
||||
{
|
||||
ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), initializer, list->element_size);
|
||||
}
|
||||
|
||||
if (!list->head)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
} else
|
||||
{
|
||||
list->tail->next = node;
|
||||
list->tail = node;
|
||||
}
|
||||
|
||||
// `ZyanListAllocateNode` needs the list size
|
||||
++list->size;
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (ZyanUSize i = size; i < list->size; ++i)
|
||||
{
|
||||
ZyanListNode* const node = list->tail;
|
||||
|
||||
if (list->destructor)
|
||||
{
|
||||
list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
|
||||
}
|
||||
|
||||
list->tail = node->prev;
|
||||
if (list->tail)
|
||||
{
|
||||
list->tail->next = ZYAN_NULL;
|
||||
}
|
||||
|
||||
ZYAN_CHECK(ZyanListDeallocateNode(list, node));
|
||||
}
|
||||
|
||||
list->size = size;
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*size = list->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
File diff suppressed because it is too large
Load Diff
@ -1,848 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zycore/Vector.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal macros */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Checks, if the passed vector should grow.
|
||||
*
|
||||
* @param size The desired size of the vector.
|
||||
* @param capacity The current capacity of the vector.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the vector should grow or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
#define ZYCORE_VECTOR_SHOULD_GROW(size, capacity) \
|
||||
((size) > (capacity))
|
||||
|
||||
/**
|
||||
* Checks, if the passed vector should shrink.
|
||||
*
|
||||
* @param size The desired size of the vector.
|
||||
* @param capacity The current capacity of the vector.
|
||||
* @param threshold The shrink threshold.
|
||||
*
|
||||
* @return `ZYAN_TRUE`, if the vector should shrink or `ZYAN_FALSE`, if not.
|
||||
*/
|
||||
#define ZYCORE_VECTOR_SHOULD_SHRINK(size, capacity, threshold) \
|
||||
((size) < (capacity) * (threshold))
|
||||
|
||||
/**
|
||||
* Returns the offset of the element at the given `index`.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The element index.
|
||||
*
|
||||
* @return The offset of the element at the given `index`.
|
||||
*/
|
||||
#define ZYCORE_VECTOR_OFFSET(vector, index) \
|
||||
((void*)((ZyanU8*)(vector)->data + ((index) * (vector)->element_size)))
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper functions */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Reallocates the internal buffer of the vector.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param capacity The new capacity.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus ZyanVectorReallocate(ZyanVector* vector, ZyanUSize capacity)
|
||||
{
|
||||
ZYAN_ASSERT(vector);
|
||||
ZYAN_ASSERT(vector->capacity >= ZYAN_VECTOR_MIN_CAPACITY);
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
if (!vector->allocator)
|
||||
{
|
||||
if (vector->capacity < capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->allocator);
|
||||
ZYAN_ASSERT(vector->allocator->reallocate);
|
||||
|
||||
if (capacity < ZYAN_VECTOR_MIN_CAPACITY)
|
||||
{
|
||||
if (vector->capacity > ZYAN_VECTOR_MIN_CAPACITY)
|
||||
{
|
||||
capacity = ZYAN_VECTOR_MIN_CAPACITY;
|
||||
} else
|
||||
{
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
vector->capacity = capacity;
|
||||
ZYAN_CHECK(vector->allocator->reallocate(vector->allocator, &vector->data,
|
||||
vector->element_size, vector->capacity));
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts all elements starting at the specified `index` by the amount of
|
||||
* `count` to the left.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The start index.
|
||||
* @param count The amount of shift operations.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus ZyanVectorShiftLeft(ZyanVector* vector, ZyanUSize index, ZyanUSize count)
|
||||
{
|
||||
ZYAN_ASSERT(vector);
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
ZYAN_ASSERT(count > 0);
|
||||
//ZYAN_ASSERT((ZyanISize)count - (ZyanISize)index + 1 >= 0);
|
||||
|
||||
void* const source = ZYCORE_VECTOR_OFFSET(vector, index + count);
|
||||
void* const dest = ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
const ZyanUSize size = (vector->size - index - count) * vector->element_size;
|
||||
ZYAN_MEMMOVE(dest, source, size);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts all elements starting at the specified `index` by the amount of
|
||||
* `count` to the right.
|
||||
*
|
||||
* @param vector A pointer to the `ZyanVector` instance.
|
||||
* @param index The start index.
|
||||
* @param count The amount of shift operations.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus ZyanVectorShiftRight(ZyanVector* vector, ZyanUSize index, ZyanUSize count)
|
||||
{
|
||||
ZYAN_ASSERT(vector);
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
ZYAN_ASSERT(count > 0);
|
||||
ZYAN_ASSERT(vector->size + count <= vector->capacity);
|
||||
|
||||
void* const source = ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
void* const dest = ZYCORE_VECTOR_OFFSET(vector, index + count);
|
||||
const ZyanUSize size = (vector->size - index) * vector->element_size;
|
||||
ZYAN_MEMMOVE(dest, source, size);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Constructor and destructor */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanVectorInit(ZyanVector* vector, ZyanUSize element_size, ZyanUSize capacity,
|
||||
ZyanMemberProcedure destructor)
|
||||
{
|
||||
return ZyanVectorInitEx(vector, element_size, capacity, destructor, ZyanAllocatorDefault(),
|
||||
ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD);
|
||||
}
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size, ZyanUSize capacity,
|
||||
ZyanMemberProcedure destructor, ZyanAllocator* allocator, float growth_factor,
|
||||
float shrink_threshold)
|
||||
{
|
||||
if (!vector || !element_size || !allocator || (growth_factor < 1.0f) ||
|
||||
(shrink_threshold < 0.0f) || (shrink_threshold > 1.0f))
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(allocator->allocate);
|
||||
|
||||
vector->allocator = allocator;
|
||||
vector->growth_factor = growth_factor;
|
||||
vector->shrink_threshold = shrink_threshold;
|
||||
vector->size = 0;
|
||||
vector->capacity = ZYAN_MAX(ZYAN_VECTOR_MIN_CAPACITY, capacity);
|
||||
vector->element_size = element_size;
|
||||
vector->destructor = destructor;
|
||||
vector->data = ZYAN_NULL;
|
||||
|
||||
return allocator->allocate(vector->allocator, &vector->data, vector->element_size,
|
||||
vector->capacity);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size,
|
||||
void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor)
|
||||
{
|
||||
if (!vector || !element_size || !buffer || !capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
vector->allocator = ZYAN_NULL;
|
||||
vector->growth_factor = 1.0f;
|
||||
vector->shrink_threshold = 0.0f;
|
||||
vector->size = 0;
|
||||
vector->capacity = capacity;
|
||||
vector->element_size = element_size;
|
||||
vector->destructor = destructor;
|
||||
vector->data = buffer;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorDestroy(ZyanVector* vector)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
if (vector->destructor)
|
||||
{
|
||||
for (ZyanUSize i = 0; i < vector->size; ++i)
|
||||
{
|
||||
vector->destructor(ZYCORE_VECTOR_OFFSET(vector, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (vector->allocator && vector->capacity)
|
||||
{
|
||||
ZYAN_ASSERT(vector->allocator->deallocate);
|
||||
ZYAN_CHECK(vector->allocator->deallocate(vector->allocator, vector->data,
|
||||
vector->element_size, vector->capacity));
|
||||
}
|
||||
|
||||
vector->data = ZYAN_NULL;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Duplication */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanVectorDuplicate(ZyanVector* destination, const ZyanVector* source,
|
||||
ZyanUSize capacity)
|
||||
{
|
||||
return ZyanVectorDuplicateEx(destination, source, capacity, ZyanAllocatorDefault(),
|
||||
ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD);
|
||||
}
|
||||
|
||||
#endif // ZYAN_NO_LIBC
|
||||
|
||||
ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source,
|
||||
ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, float shrink_threshold)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const ZyanUSize len = source->size;
|
||||
|
||||
capacity = ZYAN_MAX(capacity, len);
|
||||
ZYAN_CHECK(ZyanVectorInitEx(destination, source->element_size, capacity, source->destructor,
|
||||
allocator, growth_factor, shrink_threshold));
|
||||
ZYAN_ASSERT(destination->capacity >= len);
|
||||
|
||||
ZYAN_MEMCPY(destination->data, source->data, len * source->element_size);
|
||||
destination->size = len;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination, const ZyanVector* source,
|
||||
void* buffer, ZyanUSize capacity)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const ZyanUSize len = source->size;
|
||||
|
||||
if (capacity < len)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZYAN_CHECK(ZyanVectorInitCustomBuffer(destination, source->element_size, buffer, capacity,
|
||||
source->destructor));
|
||||
ZYAN_ASSERT(destination->capacity >= len);
|
||||
|
||||
ZYAN_MEMCPY(destination->data, source->data, len * source->element_size);
|
||||
destination->size = len;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Element access */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index)
|
||||
{
|
||||
if (!vector || (index >= vector->size))
|
||||
{
|
||||
return ZYAN_NULL;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
return ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
}
|
||||
|
||||
void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index)
|
||||
{
|
||||
if (!vector || (index >= vector->size))
|
||||
{
|
||||
return ZYAN_NULL;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
return ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index, const void** value)
|
||||
{
|
||||
if (!vector || !value)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
*value = (const void*)ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index, void** value)
|
||||
{
|
||||
if (!vector || !value)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
*value = ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index, const void* value)
|
||||
{
|
||||
if (!vector || !value)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index >= vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
void* const offset = ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
if (vector->destructor)
|
||||
{
|
||||
vector->destructor(offset);
|
||||
}
|
||||
ZYAN_MEMCPY(offset, value, vector->element_size);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Insertion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element)
|
||||
{
|
||||
if (!vector || !element)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
if (ZYCORE_VECTOR_SHOULD_GROW(vector->size + 1, vector->capacity))
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorReallocate(vector,
|
||||
ZYAN_MAX(1, (ZyanUSize)((vector->size + 1) * vector->growth_factor))));
|
||||
}
|
||||
|
||||
void* const offset = ZYCORE_VECTOR_OFFSET(vector, vector->size);
|
||||
ZYAN_MEMCPY(offset, element, vector->element_size);
|
||||
|
||||
++vector->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index, const void* element)
|
||||
{
|
||||
return ZyanVectorInsertRange(vector, index, element, 1);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index, const void* elements,
|
||||
ZyanUSize count)
|
||||
{
|
||||
if (!vector || !elements || !count)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index > vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
if (ZYCORE_VECTOR_SHOULD_GROW(vector->size + count, vector->capacity))
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorReallocate(vector,
|
||||
ZYAN_MAX(1, (ZyanUSize)((vector->size + count) * vector->growth_factor))));
|
||||
}
|
||||
|
||||
if (index < vector->size)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorShiftRight(vector, index, count));
|
||||
}
|
||||
|
||||
void* const offset = ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
ZYAN_MEMCPY(offset, elements, count * vector->element_size);
|
||||
vector->size += count;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element, ZyanMemberFunction constructor)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorEmplaceEx(vector, vector->size, element, constructor);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index, void** element,
|
||||
ZyanMemberFunction constructor)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index > vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
if (ZYCORE_VECTOR_SHOULD_GROW(vector->size + 1, vector->capacity))
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorReallocate(vector,
|
||||
ZYAN_MAX(1, (ZyanUSize)((vector->size + 1) * vector->growth_factor))));
|
||||
}
|
||||
|
||||
if (index < vector->size)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorShiftRight(vector, index, 1));
|
||||
}
|
||||
|
||||
*element = ZYCORE_VECTOR_OFFSET(vector, index);
|
||||
if (constructor)
|
||||
{
|
||||
ZYAN_CHECK(constructor(*element));
|
||||
}
|
||||
|
||||
++vector->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Utils */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first, ZyanUSize index_second)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if ((index_first >= vector->size) || (index_second >= vector->size))
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
if (vector->size == vector->capacity)
|
||||
{
|
||||
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
ZyanU64* const t = ZYCORE_VECTOR_OFFSET(vector, vector->size);
|
||||
ZyanU64* const a = ZYCORE_VECTOR_OFFSET(vector, index_first);
|
||||
ZyanU64* const b = ZYCORE_VECTOR_OFFSET(vector, index_second);
|
||||
ZYAN_MEMCPY(t, a, vector->element_size);
|
||||
ZYAN_MEMCPY(a, b, vector->element_size);
|
||||
ZYAN_MEMCPY(b, t, vector->element_size);
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Deletion */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index)
|
||||
{
|
||||
return ZyanVectorDeleteRange(vector, index, 1);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index, ZyanUSize count)
|
||||
{
|
||||
if (!vector || !count)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (index + count > vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
if (vector->destructor)
|
||||
{
|
||||
for (ZyanUSize i = index; i < index + count; ++i)
|
||||
{
|
||||
vector->destructor(ZYCORE_VECTOR_OFFSET(vector, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (index + count < vector->size)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorShiftLeft(vector, index, count));
|
||||
}
|
||||
|
||||
vector->size -= count;
|
||||
if (ZYCORE_VECTOR_SHOULD_SHRINK(vector->size, vector->capacity, vector->shrink_threshold))
|
||||
{
|
||||
return ZyanVectorReallocate(vector,
|
||||
ZYAN_MAX(1, (ZyanUSize)(vector->size * vector->growth_factor)));
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorPopBack(ZyanVector* vector)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (vector->size == 0)
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
if (vector->destructor)
|
||||
{
|
||||
vector->destructor(ZYCORE_VECTOR_OFFSET(vector, vector->size - 1));
|
||||
}
|
||||
|
||||
--vector->size;
|
||||
if (ZYCORE_VECTOR_SHOULD_SHRINK(vector->size, vector->capacity, vector->shrink_threshold))
|
||||
{
|
||||
return ZyanVectorReallocate(vector,
|
||||
ZYAN_MAX(1, (ZyanUSize)(vector->size * vector->growth_factor)));
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorClear(ZyanVector* vector)
|
||||
{
|
||||
return ZyanVectorResizeEx(vector, 0, ZYAN_NULL);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Searching */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element, ZyanISize* found_index,
|
||||
ZyanEqualityComparison comparison)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorFindEx(vector, element, found_index, comparison, 0, vector->size);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element, ZyanISize* found_index,
|
||||
ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if ((index + count > vector->size) || (index == vector->size))
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
if (!count)
|
||||
{
|
||||
*found_index = -1;
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
for (ZyanUSize i = index; i < index + count; ++i)
|
||||
{
|
||||
if (comparison(ZYCORE_VECTOR_OFFSET(vector, i), element))
|
||||
{
|
||||
*found_index = i;
|
||||
return ZYAN_STATUS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
*found_index = -1;
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element,
|
||||
ZyanUSize* found_index, ZyanComparison comparison)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorBinarySearchEx(vector, element, found_index, comparison, 0, vector->size);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element,
|
||||
ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (((index >= vector->size) && (count > 0)) || (index + count > vector->size))
|
||||
{
|
||||
return ZYAN_STATUS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
if (!count)
|
||||
{
|
||||
*found_index = index;
|
||||
return ZYAN_STATUS_FALSE;
|
||||
}
|
||||
|
||||
ZYAN_ASSERT(vector->element_size);
|
||||
ZYAN_ASSERT(vector->data);
|
||||
|
||||
ZyanStatus status = ZYAN_STATUS_FALSE;
|
||||
ZyanISize l = index;
|
||||
ZyanISize h = index + count - 1;
|
||||
while (l <= h)
|
||||
{
|
||||
const ZyanUSize mid = l + ((h - l) >> 1);
|
||||
const ZyanI32 cmp = comparison(ZYCORE_VECTOR_OFFSET(vector, mid), element);
|
||||
if (cmp < 0)
|
||||
{
|
||||
l = mid + 1;
|
||||
} else
|
||||
{
|
||||
h = mid - 1;
|
||||
if (cmp == 0)
|
||||
{
|
||||
status = ZYAN_STATUS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*found_index = l;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Memory management */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size)
|
||||
{
|
||||
return ZyanVectorResizeEx(vector, size, ZYAN_NULL);
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size, const void* initializer)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
if (size == vector->size)
|
||||
{
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (vector->destructor && (size < vector->size))
|
||||
{
|
||||
for (ZyanUSize i = size; i < vector->size; ++i)
|
||||
{
|
||||
vector->destructor(ZYCORE_VECTOR_OFFSET(vector, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (ZYCORE_VECTOR_SHOULD_GROW(size, vector->capacity) ||
|
||||
ZYCORE_VECTOR_SHOULD_SHRINK(size, vector->capacity, vector->shrink_threshold))
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorReallocate(vector, (ZyanUSize)(size * vector->growth_factor)));
|
||||
};
|
||||
|
||||
if (initializer && (size > vector->size))
|
||||
{
|
||||
for (ZyanUSize i = vector->size; i < size; ++i)
|
||||
{
|
||||
ZYAN_MEMCPY(ZYCORE_VECTOR_OFFSET(vector, i), initializer, vector->element_size);
|
||||
}
|
||||
}
|
||||
|
||||
vector->size = size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (capacity > vector->capacity)
|
||||
{
|
||||
ZYAN_CHECK(ZyanVectorReallocate(vector, capacity));
|
||||
}
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ZyanVectorReallocate(vector, vector->size);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Information */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*capacity = vector->capacity;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size)
|
||||
{
|
||||
if (!vector)
|
||||
{
|
||||
return ZYAN_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*size = vector->size;
|
||||
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,38 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <Zycore/Zycore.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZyanU64 ZycoreGetVersion(void)
|
||||
{
|
||||
return ZYCORE_VERSION;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,320 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Joel Hoener
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Tests the the arg parse implementation.
|
||||
*/
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <Zycore/ArgParse.h>
|
||||
#include <Zycore/LibC.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helpers */
|
||||
/* ============================================================================================== */
|
||||
|
||||
auto cvt_string_view(const ZyanStringView *sv)
|
||||
{
|
||||
const char* buf;
|
||||
if (ZYAN_FAILED(ZyanStringViewGetData(sv, &buf))) throw std::exception{};
|
||||
ZyanUSize len;
|
||||
if (ZYAN_FAILED(ZyanStringViewGetSize(sv, &len))) throw std::exception{};
|
||||
|
||||
return std::string_view{buf, len};
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Tests */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Unnamed args */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static auto UnnamedArgTest(ZyanU64 min, ZyanU64 max)
|
||||
{
|
||||
const char* argv[]
|
||||
{
|
||||
"./test", "a", "xxx"
|
||||
};
|
||||
|
||||
ZyanArgParseConfig cfg
|
||||
{
|
||||
argv, // argv
|
||||
3, // argc
|
||||
min, // min_unnamed_args
|
||||
max, // max_unnamed_args
|
||||
nullptr // args
|
||||
};
|
||||
|
||||
ZyanVector parsed;
|
||||
const char* err_tok = nullptr;
|
||||
ZYAN_MEMSET(&parsed, 0, sizeof(parsed));
|
||||
auto status = ZyanArgParse(&cfg, &parsed, &err_tok);
|
||||
return std::make_tuple(status, parsed, err_tok);
|
||||
}
|
||||
|
||||
TEST(UnnamedArgs, TooFew)
|
||||
{
|
||||
auto [status, parsed, err_tok] = UnnamedArgTest(5, 5);
|
||||
ASSERT_EQ(status, ZYAN_STATUS_TOO_FEW_ARGS);
|
||||
ASSERT_STREQ(err_tok, nullptr);
|
||||
}
|
||||
|
||||
TEST(UnnamedArgs, TooMany)
|
||||
{
|
||||
auto [status, parsed, err_tok] = UnnamedArgTest(1, 1);
|
||||
ASSERT_EQ(status, ZYAN_STATUS_TOO_MANY_ARGS);
|
||||
ASSERT_STREQ(err_tok, "xxx");
|
||||
}
|
||||
|
||||
TEST(UnnamedArgs, PerfectFit)
|
||||
{
|
||||
auto [status, parsed, err_tok] = UnnamedArgTest(2, 2);
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(status));
|
||||
|
||||
ZyanUSize size;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetSize(&parsed, &size)));
|
||||
ASSERT_EQ(size, 2);
|
||||
|
||||
auto arg = (const ZyanArgParseArg*)ZyanVectorGet(&parsed, 0);
|
||||
ASSERT_NE(arg, nullptr);
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "a");
|
||||
|
||||
arg = (const ZyanArgParseArg*)ZyanVectorGet(&parsed, 1);
|
||||
ASSERT_NE(arg, nullptr);
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "xxx");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Dash args */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
TEST(DashArg, MixedBoolAndValueArgs)
|
||||
{
|
||||
const char* argv[]
|
||||
{
|
||||
"./test", "-aio42", "-n", "xxx"
|
||||
};
|
||||
|
||||
ZyanArgParseDefinition args[]
|
||||
{
|
||||
{"-o", ZYAN_FALSE, ZYAN_FALSE},
|
||||
{"-a", ZYAN_TRUE, ZYAN_FALSE},
|
||||
{"-n", ZYAN_FALSE, ZYAN_FALSE},
|
||||
{"-i", ZYAN_TRUE, ZYAN_FALSE},
|
||||
{nullptr, ZYAN_FALSE, ZYAN_FALSE}
|
||||
};
|
||||
|
||||
ZyanArgParseConfig cfg
|
||||
{
|
||||
argv, // argv
|
||||
4, // argc
|
||||
0, // min_unnamed_args
|
||||
0, // max_unnamed_args
|
||||
args // args
|
||||
};
|
||||
|
||||
ZyanVector parsed;
|
||||
ZYAN_MEMSET(&parsed, 0, sizeof(parsed));
|
||||
auto status = ZyanArgParse(&cfg, &parsed, nullptr);
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(status));
|
||||
|
||||
ZyanUSize size;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetSize(&parsed, &size)));
|
||||
ASSERT_EQ(size, 4);
|
||||
|
||||
const ZyanArgParseArg* arg;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 0, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "-a");
|
||||
ASSERT_FALSE(arg->has_value);
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 1, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "-i");
|
||||
ASSERT_FALSE(arg->has_value);
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 2, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "-o");
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "42");
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 3, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "-n");
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "xxx");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Double dash args */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
TEST(DoubleDashArg, PerfectFit)
|
||||
{
|
||||
const char* argv[]
|
||||
{
|
||||
"./test", "--help", "--stuff", "1337"
|
||||
};
|
||||
|
||||
ZyanArgParseDefinition args[]
|
||||
{
|
||||
{"--help", ZYAN_TRUE, ZYAN_FALSE},
|
||||
{"--stuff", ZYAN_FALSE, ZYAN_FALSE},
|
||||
{nullptr, ZYAN_FALSE, ZYAN_FALSE}
|
||||
};
|
||||
|
||||
ZyanArgParseConfig cfg
|
||||
{
|
||||
argv, // argv
|
||||
4, // argc
|
||||
0, // min_unnamed_args
|
||||
0, // max_unnamed_args
|
||||
args // args
|
||||
};
|
||||
|
||||
ZyanVector parsed;
|
||||
ZYAN_MEMSET(&parsed, 0, sizeof(parsed));
|
||||
auto status = ZyanArgParse(&cfg, &parsed, nullptr);
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(status));
|
||||
|
||||
ZyanUSize size;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetSize(&parsed, &size)));
|
||||
ASSERT_EQ(size, 2);
|
||||
|
||||
const ZyanArgParseArg* arg;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 0, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "--help");
|
||||
ASSERT_FALSE(arg->has_value);
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 1, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "--stuff");
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "1337");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Mixed */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
TEST(MixedArgs, MissingRequiredArg)
|
||||
{
|
||||
const char* argv[]
|
||||
{
|
||||
"./test", "blah.c", "woof.moo"
|
||||
};
|
||||
|
||||
ZyanArgParseDefinition args[]
|
||||
{
|
||||
{"--feature-xyz", ZYAN_TRUE, ZYAN_FALSE},
|
||||
{"-n", ZYAN_FALSE, ZYAN_TRUE},
|
||||
{nullptr, ZYAN_FALSE, ZYAN_FALSE}
|
||||
};
|
||||
|
||||
ZyanArgParseConfig cfg
|
||||
{
|
||||
argv, // argv
|
||||
3, // argc
|
||||
0, // min_unnamed_args
|
||||
100, // max_unnamed_args
|
||||
args // args
|
||||
};
|
||||
|
||||
ZyanVector parsed;
|
||||
ZYAN_MEMSET(&parsed, 0, sizeof(parsed));
|
||||
const char* err_tok = nullptr;
|
||||
auto status = ZyanArgParse(&cfg, &parsed, &err_tok);
|
||||
ASSERT_EQ(status, ZYAN_STATUS_REQUIRED_ARG_MISSING);
|
||||
ASSERT_STREQ(err_tok, "-n");
|
||||
}
|
||||
|
||||
TEST(MixedArgs, Stuff)
|
||||
{
|
||||
const char* argv[]
|
||||
{
|
||||
"./test", "--feature-xyz", "-n5", "blah.c", "woof.moo"
|
||||
};
|
||||
|
||||
ZyanArgParseDefinition args[]
|
||||
{
|
||||
{"--feature-xyz", ZYAN_TRUE, ZYAN_FALSE},
|
||||
{"-n", ZYAN_FALSE, ZYAN_FALSE},
|
||||
{nullptr, ZYAN_FALSE, ZYAN_FALSE}
|
||||
};
|
||||
|
||||
ZyanArgParseConfig cfg
|
||||
{
|
||||
argv, // argv
|
||||
5, // argc
|
||||
0, // min_unnamed_args
|
||||
100, // max_unnamed_args
|
||||
args // args
|
||||
};
|
||||
|
||||
ZyanVector parsed;
|
||||
ZYAN_MEMSET(&parsed, 0, sizeof(parsed));
|
||||
auto status = ZyanArgParse(&cfg, &parsed, nullptr);
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(status));
|
||||
|
||||
ZyanUSize size;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetSize(&parsed, &size)));
|
||||
ASSERT_EQ(size, 4);
|
||||
|
||||
const ZyanArgParseArg* arg;
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 0, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "--feature-xyz");
|
||||
ASSERT_FALSE(arg->has_value);
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 1, (const void**)&arg)));
|
||||
ASSERT_STREQ(arg->def->name, "-n");
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "5");
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 2, (const void**)&arg)));
|
||||
ASSERT_EQ(arg->def, nullptr);
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "blah.c");
|
||||
|
||||
ASSERT_TRUE(ZYAN_SUCCESS(ZyanVectorGetPointer(&parsed, 3, (const void**)&arg)));
|
||||
ASSERT_EQ(arg->def, nullptr);
|
||||
ASSERT_TRUE(arg->has_value);
|
||||
ASSERT_EQ(cvt_string_view(&arg->value), "woof.moo");
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,69 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Tests the `ZyanString` implementation.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <Zycore/String.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Tests */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,505 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Core Library (Zycore-C)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Tests the `ZyanVector` implementation.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <Zycore/Comparison.h>
|
||||
#include <Zycore/Vector.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Fixtures */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* VectorTestBase */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Implements a fixture-class that provides an initialized `ZyanVector` instance for
|
||||
* `ZyanU64` values.
|
||||
*/
|
||||
class VectorTestBase : public ::testing::TestWithParam<bool>
|
||||
{
|
||||
protected:
|
||||
static const ZyanUSize m_test_size = 100;
|
||||
ZyanBool m_has_fixed_capacity;
|
||||
ZyanVector m_vector;
|
||||
std::vector<ZyanU64> m_buffer;
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
m_has_fixed_capacity = GetParam();
|
||||
|
||||
if (!m_has_fixed_capacity)
|
||||
{
|
||||
ASSERT_EQ(ZyanVectorInit(&m_vector, sizeof(ZyanU64), m_test_size,
|
||||
reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL)), ZYAN_STATUS_SUCCESS);
|
||||
} else
|
||||
{
|
||||
m_buffer.reserve(m_test_size);
|
||||
ASSERT_EQ(ZyanVectorInitCustomBuffer(&m_vector, sizeof(ZyanU64), m_buffer.data(),
|
||||
m_test_size, reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL)),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
EXPECT_EQ(ZyanVectorDestroy(&m_vector), ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* VectorTestFilled */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Implements a fixture-class that provides an initialized `ZyanVector` instance which
|
||||
* is filled with `ZyanU64` values from 0..100.
|
||||
*/
|
||||
class VectorTestFilled : public VectorTestBase
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
VectorTestBase::SetUp();
|
||||
|
||||
if (m_has_fixed_capacity)
|
||||
{
|
||||
m_buffer.resize(m_test_size);
|
||||
}
|
||||
for (ZyanU64 i = 0; i < m_test_size; ++i)
|
||||
{
|
||||
ASSERT_EQ(ZyanVectorPushBack(&m_vector, &i), ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @brief A dummy constructor for `ZyanU64` objects.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus InitZyanU64(ZyanU64* object)
|
||||
{
|
||||
*object = 1337;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A dummy destructor for `ZyanU16` objects.
|
||||
*
|
||||
* @param object A pointer to the object.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
static ZyanStatus FreeZyanU16(ZyanU16* object)
|
||||
{
|
||||
*object = 0;
|
||||
return ZYAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Tests */
|
||||
/* ============================================================================================== */
|
||||
|
||||
TEST(VectorTest, InitBasic)
|
||||
{
|
||||
ZyanVector vector;
|
||||
|
||||
ASSERT_EQ(ZyanVectorInit(&vector, sizeof(ZyanU64), 0,
|
||||
reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL)), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(vector.allocator, ZyanAllocatorDefault());
|
||||
EXPECT_FLOAT_EQ(vector.growth_factor, ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR);
|
||||
EXPECT_FLOAT_EQ(vector.shrink_threshold, ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD);
|
||||
EXPECT_EQ(vector.size, static_cast<ZyanUSize>(0));
|
||||
EXPECT_EQ(vector.capacity, static_cast<ZyanUSize>(ZYAN_VECTOR_MIN_CAPACITY));
|
||||
EXPECT_EQ(vector.element_size, sizeof(ZyanU64));
|
||||
EXPECT_NE(vector.data, ZYAN_NULL);
|
||||
EXPECT_EQ(ZyanVectorDestroy(&vector), ZYAN_STATUS_SUCCESS);
|
||||
|
||||
// Custom capacity
|
||||
EXPECT_EQ(ZyanVectorInit(&vector, sizeof(ZyanU16), 10,
|
||||
reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL)), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(vector.capacity, static_cast<ZyanUSize>(ZYAN_MAX(ZYAN_VECTOR_MIN_CAPACITY, 10)));
|
||||
EXPECT_EQ(ZyanVectorDestroy(&vector), ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(VectorTest, InitAdvanced)
|
||||
{
|
||||
ZyanVector vector;
|
||||
|
||||
ASSERT_EQ(ZyanVectorInitEx(&vector, sizeof(ZyanU16), 0,
|
||||
reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL), ZyanAllocatorDefault(), 1.0f, 0.0f),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(vector.allocator, ZyanAllocatorDefault());
|
||||
EXPECT_FLOAT_EQ(vector.growth_factor, 1.0f);
|
||||
EXPECT_FLOAT_EQ(vector.shrink_threshold, 0.0f);
|
||||
EXPECT_EQ(vector.size, static_cast<ZyanUSize>(0));
|
||||
EXPECT_EQ(vector.capacity, static_cast<ZyanUSize>(ZYAN_VECTOR_MIN_CAPACITY));
|
||||
EXPECT_EQ(vector.element_size, sizeof(ZyanU16));
|
||||
EXPECT_NE(vector.data, ZYAN_NULL);
|
||||
EXPECT_EQ(ZyanVectorDestroy(&vector), ZYAN_STATUS_SUCCESS);
|
||||
|
||||
// Custom capacity
|
||||
EXPECT_EQ(ZyanVectorInitEx(&vector, sizeof(ZyanU16), 10,
|
||||
reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL), ZyanAllocatorDefault(), 1.0f, 0.0f),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(vector.capacity, static_cast<ZyanUSize>(ZYAN_MAX(ZYAN_VECTOR_MIN_CAPACITY, 10)));
|
||||
EXPECT_EQ(ZyanVectorDestroy(&vector), ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(VectorTest, InitCustomBuffer)
|
||||
{
|
||||
ZyanVector vector;
|
||||
|
||||
ZyanU16 buffer[32];
|
||||
EXPECT_EQ(ZyanVectorInitCustomBuffer(&vector, sizeof(ZyanU16), &buffer, 0,
|
||||
reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL)), ZYAN_STATUS_INVALID_ARGUMENT);
|
||||
ASSERT_EQ(ZyanVectorInitCustomBuffer(&vector, sizeof(ZyanU16), &buffer,
|
||||
ZYAN_ARRAY_LENGTH(buffer), reinterpret_cast<ZyanMemberProcedure>(ZYAN_NULL)),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(vector.allocator, ZYAN_NULL);
|
||||
EXPECT_FLOAT_EQ(vector.growth_factor, 1.0f);
|
||||
EXPECT_FLOAT_EQ(vector.shrink_threshold, 0.0f);
|
||||
EXPECT_EQ(vector.size, static_cast<ZyanUSize>(0));
|
||||
EXPECT_EQ(vector.capacity, ZYAN_ARRAY_LENGTH(buffer));
|
||||
EXPECT_EQ(vector.element_size, sizeof(ZyanU16));
|
||||
EXPECT_EQ(vector.data, &buffer);
|
||||
EXPECT_EQ(ZyanVectorDestroy(&vector), ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(VectorTest, Destructor)
|
||||
{
|
||||
ZyanVector vector;
|
||||
|
||||
ZyanU16 buffer[16];
|
||||
ASSERT_EQ(ZyanVectorInitCustomBuffer(&vector, sizeof(ZyanU16), &buffer,
|
||||
ZYAN_ARRAY_LENGTH(buffer), reinterpret_cast<ZyanMemberProcedure>(&FreeZyanU16)),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
|
||||
for (ZyanUSize i = 0; i < ZYAN_ARRAY_LENGTH(buffer); ++i)
|
||||
{
|
||||
const auto element = static_cast<ZyanU16>(i) + 0;
|
||||
ASSERT_EQ(ZyanVectorPushBack(&vector, &element), ZYAN_STATUS_SUCCESS);
|
||||
ASSERT_EQ(buffer[i], element);
|
||||
}
|
||||
|
||||
ASSERT_EQ(ZyanVectorPopBack(&vector), ZYAN_STATUS_SUCCESS);
|
||||
ASSERT_EQ(buffer[15], 0);
|
||||
|
||||
ASSERT_EQ(ZyanVectorDeleteRange(&vector, 12, 3), ZYAN_STATUS_SUCCESS);
|
||||
ASSERT_EQ(buffer[12], 0);
|
||||
ASSERT_EQ(buffer[13], 0);
|
||||
ASSERT_EQ(buffer[14], 0);
|
||||
|
||||
ASSERT_EQ(ZyanVectorClear(&vector), ZYAN_STATUS_SUCCESS);
|
||||
for (ZyanUSize i : buffer)
|
||||
{
|
||||
ASSERT_EQ(i, 0);
|
||||
}
|
||||
|
||||
for (ZyanUSize i = 0; i < ZYAN_ARRAY_LENGTH(buffer); ++i)
|
||||
{
|
||||
const auto element = static_cast<ZyanU16>(i) + 1;
|
||||
ASSERT_EQ(ZyanVectorPushBack(&vector, &element), ZYAN_STATUS_SUCCESS);
|
||||
ASSERT_EQ(buffer[i], element);
|
||||
}
|
||||
|
||||
EXPECT_EQ(ZyanVectorDestroy(&vector), ZYAN_STATUS_SUCCESS);
|
||||
for (ZyanUSize i : buffer)
|
||||
{
|
||||
ASSERT_EQ(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(VectorTestFilled, ElementAccess)
|
||||
{
|
||||
static const ZyanU64 element_in = 1337;
|
||||
const ZyanU64* element_dummy;
|
||||
ZyanU64* element_out_mut;
|
||||
|
||||
EXPECT_EQ(ZyanVectorSet(&m_vector, m_vector.size, &element_in),
|
||||
ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorSet(&m_vector, m_vector.size - 1, &element_in),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
|
||||
EXPECT_EQ(ZyanVectorGetPointer(&m_vector, m_vector.size,
|
||||
reinterpret_cast<const void**>(&element_dummy)), ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, m_vector.size - 1), element_in);
|
||||
|
||||
EXPECT_EQ(ZyanVectorGetPointerMutable(&m_vector, m_vector.size,
|
||||
reinterpret_cast<void**>(&element_out_mut)), ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorGetPointerMutable(&m_vector, m_vector.size - 1,
|
||||
reinterpret_cast<void**>(&element_out_mut)), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(*element_out_mut, element_in);
|
||||
*element_out_mut = 42;
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, m_vector.size - 1), 42);
|
||||
|
||||
if (m_has_fixed_capacity)
|
||||
{
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, m_vector.size - 1),
|
||||
m_buffer[m_vector.size - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(VectorTestFilled, PushPop)
|
||||
{
|
||||
static const ZyanU64 element_in = 1337;
|
||||
const ZyanUSize size = m_vector.size;
|
||||
|
||||
if (!m_has_fixed_capacity)
|
||||
{
|
||||
EXPECT_EQ(ZyanVectorPushBack(&m_vector, &element_in), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size + 1);
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, size), element_in);
|
||||
EXPECT_EQ(ZyanVectorPopBack(&m_vector), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size);
|
||||
} else
|
||||
{
|
||||
EXPECT_EQ(ZyanVectorPushBack(&m_vector, &element_in), ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE);
|
||||
EXPECT_EQ(m_vector.size, size);
|
||||
EXPECT_EQ(ZyanVectorPopBack(&m_vector), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size - 1);
|
||||
EXPECT_EQ(ZyanVectorPushBack(&m_vector, &element_in), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size);
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, size - 1), element_in);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(VectorTestFilled, Insert)
|
||||
{
|
||||
static const ZyanU64 elements[4] =
|
||||
{
|
||||
1337, 1338, 1339, 1340
|
||||
};
|
||||
const ZyanUSize count = ZYAN_ARRAY_LENGTH(elements);
|
||||
|
||||
if (m_has_fixed_capacity)
|
||||
{
|
||||
const ZyanUSize size_temp = m_vector.size;
|
||||
EXPECT_EQ(ZyanVectorInsertRange(&m_vector, size_temp / 2, &elements, count),
|
||||
ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE);
|
||||
EXPECT_EQ(ZyanVectorResize(&m_vector, size_temp - count), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size_temp - count);
|
||||
}
|
||||
|
||||
const ZyanUSize size = m_vector.size;
|
||||
const ZyanUSize half = (size / 2);
|
||||
|
||||
EXPECT_EQ(ZyanVectorInsertRange(&m_vector, half, &elements, ZYAN_ARRAY_LENGTH(elements)),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size + count);
|
||||
for (ZyanUSize i = 0; i < m_vector.size; ++i)
|
||||
{
|
||||
const ZyanU64 element_out = ZYAN_VECTOR_GET(ZyanU64, &m_vector, i);
|
||||
|
||||
if ((i >= half) && (i < half + count))
|
||||
{
|
||||
EXPECT_EQ(element_out, elements[i - half]);
|
||||
} else
|
||||
if (i < half)
|
||||
{
|
||||
EXPECT_EQ(element_out, i);
|
||||
} else
|
||||
{
|
||||
EXPECT_EQ(element_out, i - count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(VectorTestFilled, Delete)
|
||||
{
|
||||
EXPECT_EQ(ZyanVectorDeleteRange(&m_vector, m_vector.size, 1), ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorDeleteRange(&m_vector, 1, m_vector.size), ZYAN_STATUS_OUT_OF_RANGE);
|
||||
|
||||
const ZyanUSize size = m_vector.size;
|
||||
const ZyanUSize half = (size / 2);
|
||||
const ZyanUSize count = (half / 2);
|
||||
|
||||
EXPECT_EQ(ZyanVectorDeleteRange(&m_vector, half, count), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(m_vector.size, size - count);
|
||||
for (ZyanUSize i = 0; i < m_vector.size; ++i)
|
||||
{
|
||||
const ZyanU64 element_out = ZYAN_VECTOR_GET(ZyanU64, &m_vector, i);
|
||||
|
||||
if ((i >= half) && (i < half + count))
|
||||
{
|
||||
EXPECT_EQ(element_out, i + count);
|
||||
} else
|
||||
if (i < half)
|
||||
{
|
||||
EXPECT_EQ(element_out, i);
|
||||
} else
|
||||
{
|
||||
EXPECT_EQ(element_out, i - count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(VectorTestFilled, Find)
|
||||
{
|
||||
ZyanISize index;
|
||||
ZyanU64 element_in = m_vector.size / 2;
|
||||
EXPECT_EQ(ZyanVectorFind(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanEqualityComparison>(&ZyanEqualsNumeric64)), ZYAN_STATUS_TRUE);
|
||||
EXPECT_EQ(static_cast<ZyanU64>(index), element_in);
|
||||
|
||||
element_in = 1337;
|
||||
EXPECT_EQ(ZyanVectorFind(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanEqualityComparison>(&ZyanEqualsNumeric64)), ZYAN_STATUS_FALSE);
|
||||
EXPECT_EQ(index, -1);
|
||||
|
||||
// Edge cases
|
||||
EXPECT_EQ(ZyanVectorFindEx(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanEqualityComparison>(&ZyanEqualsNumeric64), 0, 0),
|
||||
ZYAN_STATUS_FALSE);
|
||||
EXPECT_EQ(ZyanVectorFindEx(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanEqualityComparison>(&ZyanEqualsNumeric64), 0, m_vector.size + 1),
|
||||
ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorFindEx(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanEqualityComparison>(&ZyanEqualsNumeric64), 1, m_vector.size),
|
||||
ZYAN_STATUS_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST_P(VectorTestBase, BinarySearch)
|
||||
{
|
||||
EXPECT_EQ(ZyanVectorReserve(&m_vector, 100), ZYAN_STATUS_SUCCESS);
|
||||
for (ZyanUSize i = 0; i < 100; ++i)
|
||||
{
|
||||
const ZyanU64 element = rand() % 100;
|
||||
|
||||
ZyanUSize index;
|
||||
const ZyanStatus status = ZyanVectorBinarySearch(&m_vector, &element, &index,
|
||||
reinterpret_cast<ZyanComparison>(&ZyanCompareNumeric64));
|
||||
EXPECT_EQ(ZYAN_SUCCESS(status), ZYAN_TRUE);
|
||||
EXPECT_EQ(ZyanVectorInsert(&m_vector, index, &element), ZYAN_STATUS_SUCCESS);
|
||||
}
|
||||
EXPECT_EQ(m_vector.size, static_cast<ZyanUSize>(100));
|
||||
|
||||
ZyanU64 element_out = ZYAN_VECTOR_GET(ZyanU64, &m_vector, 0);
|
||||
for (ZyanUSize i = 1; i < m_vector.size; ++i)
|
||||
{
|
||||
const ZyanU64 value = element_out;
|
||||
element_out = ZYAN_VECTOR_GET(ZyanU64, &m_vector, i);
|
||||
EXPECT_GE(element_out, value);
|
||||
}
|
||||
|
||||
// Edge cases
|
||||
const ZyanU64 element_in = 1337;
|
||||
ZyanUSize index;
|
||||
EXPECT_EQ(ZyanVectorBinarySearchEx(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanComparison>(&ZyanCompareNumeric64), 0, 101),
|
||||
ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorBinarySearchEx(&m_vector, &element_in, &index,
|
||||
reinterpret_cast<ZyanComparison>(&ZyanCompareNumeric64), 1, 100),
|
||||
ZYAN_STATUS_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST_P(VectorTestBase, Emplace)
|
||||
{
|
||||
ZyanU64* element_new;
|
||||
|
||||
for (ZyanUSize i = 0; i < 10; ++i)
|
||||
{
|
||||
EXPECT_EQ(ZyanVectorEmplace(&m_vector, reinterpret_cast<void**>(&element_new),
|
||||
reinterpret_cast<ZyanMemberFunction>(ZYAN_NULL)), ZYAN_STATUS_SUCCESS);
|
||||
*element_new = i;
|
||||
}
|
||||
EXPECT_EQ(m_vector.size, static_cast<ZyanUSize>(10));
|
||||
|
||||
for (ZyanUSize i = 0; i < m_vector.size; ++i)
|
||||
{
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, i), i);
|
||||
}
|
||||
|
||||
EXPECT_EQ(ZyanVectorEmplaceEx(&m_vector, 5, reinterpret_cast<void**>(&element_new),
|
||||
reinterpret_cast<ZyanMemberFunction>(&InitZyanU64)), ZYAN_STATUS_SUCCESS);
|
||||
EXPECT_EQ(*element_new, 1337);
|
||||
EXPECT_EQ(ZYAN_VECTOR_GET(ZyanU64, &m_vector, 5), 1337);
|
||||
}
|
||||
|
||||
TEST_P(VectorTestFilled, SwapElements)
|
||||
{
|
||||
EXPECT_EQ(m_vector.capacity, m_vector.size);
|
||||
|
||||
// Edge cases
|
||||
EXPECT_EQ(ZyanVectorSwapElements(&m_vector, 0, m_vector.size), ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorSwapElements(&m_vector, m_vector.size, 0), ZYAN_STATUS_OUT_OF_RANGE);
|
||||
EXPECT_EQ(ZyanVectorSwapElements(&m_vector, 0, m_vector.size - 1),
|
||||
ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE);
|
||||
|
||||
// Free space for the temporary element
|
||||
EXPECT_EQ(ZyanVectorPopBack(&m_vector), ZYAN_STATUS_SUCCESS);
|
||||
|
||||
// Retrieve element pointers
|
||||
const ZyanU64* element_first;
|
||||
EXPECT_EQ(ZyanVectorGetPointer(&m_vector, 0, reinterpret_cast<const void**>(&element_first)),
|
||||
ZYAN_STATUS_SUCCESS);
|
||||
const ZyanU64* element_second;
|
||||
EXPECT_EQ(ZyanVectorGetPointer(&m_vector, m_vector.size - 1,
|
||||
reinterpret_cast<const void**>(&element_second)), ZYAN_STATUS_SUCCESS);
|
||||
|
||||
const ZyanU64 values_before[2] = { *element_first, *element_second };
|
||||
EXPECT_EQ(ZyanVectorSwapElements(&m_vector, 0, m_vector.size - 1), ZYAN_STATUS_SUCCESS);
|
||||
const ZyanU64 values_after [2] = { *element_first, *element_second };
|
||||
|
||||
EXPECT_EQ(values_before[0], values_after[1]);
|
||||
EXPECT_EQ(values_before[1], values_after[0]);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(Param, VectorTestBase, ::testing::Values(false, true));
|
||||
INSTANTIATE_TEST_SUITE_P(Param, VectorTestFilled, ::testing::Values(false, true));
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
time_t t;
|
||||
srand(static_cast<unsigned>(time(&t)));
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,163 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Demonstrates basic hooking functionality of the `ZydisFormatter` class by implementing
|
||||
* a custom symbol-resolver.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Zycore/Format.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zydis/Zydis.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and Types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisSymbol` struct.
|
||||
*/
|
||||
typedef struct ZydisSymbol_
|
||||
{
|
||||
/**
|
||||
* The symbol address.
|
||||
*/
|
||||
ZyanU64 address;
|
||||
/**
|
||||
* The symbol name.
|
||||
*/
|
||||
const char* name;
|
||||
} ZydisSymbol;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Static data */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* A static symbol table with some dummy symbols.
|
||||
*/
|
||||
static const ZydisSymbol SYMBOL_TABLE[3] =
|
||||
{
|
||||
{ 0x007FFFFFFF401000, "SomeModule.EntryPoint" },
|
||||
{ 0x007FFFFFFF530040, "SomeModule.SomeData" },
|
||||
{ 0x007FFFFFFF401100, "SomeModule.SomeFunction" }
|
||||
};
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Hook callbacks */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZydisFormatterFunc default_print_address_absolute;
|
||||
|
||||
static ZyanStatus ZydisFormatterPrintAddressAbsolute(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
|
||||
{
|
||||
ZyanU64 address;
|
||||
ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand,
|
||||
context->runtime_address, &address));
|
||||
|
||||
for (ZyanUSize i = 0; i < ZYAN_ARRAY_LENGTH(SYMBOL_TABLE); ++i)
|
||||
{
|
||||
if (SYMBOL_TABLE[i].address == address)
|
||||
{
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, ZYDIS_TOKEN_SYMBOL));
|
||||
ZyanString* string;
|
||||
ZYAN_CHECK(ZydisFormatterBufferGetString(buffer, &string));
|
||||
return ZyanStringAppendFormat(string, "<%s>", SYMBOL_TABLE[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
return default_print_address_absolute(formatter, buffer, context);
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize length)
|
||||
{
|
||||
ZydisFormatter formatter;
|
||||
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
|
||||
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
|
||||
|
||||
// Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that formats the absolute
|
||||
// addresses
|
||||
default_print_address_absolute = (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
|
||||
ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS,
|
||||
(const void**)&default_print_address_absolute);
|
||||
|
||||
ZyanU64 runtime_address = 0x007FFFFFFF400000;
|
||||
|
||||
ZydisDecodedInstruction instruction;
|
||||
char buffer[256];
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(decoder, data, length, &instruction)))
|
||||
{
|
||||
ZYAN_PRINTF("%016" PRIX64 " ", runtime_address);
|
||||
// We have to pass a `runtime_address` different to `ZYDIS_RUNTIME_ADDRESS_NONE` to
|
||||
// enable printing of absolute addresses
|
||||
ZydisFormatterFormatInstruction(&formatter, &instruction, &buffer[0], sizeof(buffer),
|
||||
runtime_address);
|
||||
ZYAN_PRINTF(" %s\n", &buffer[0]);
|
||||
data += instruction.length;
|
||||
length -= instruction.length;
|
||||
runtime_address += instruction.length;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (ZydisGetVersion() != ZYDIS_VERSION)
|
||||
{
|
||||
fputs("Invalid zydis version\n", ZYAN_STDERR);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ZyanU8 data[] =
|
||||
{
|
||||
0x48, 0x8B, 0x05, 0x39, 0x00, 0x13, 0x00, // mov rax, qword ptr ds:[<SomeModule.SomeData>]
|
||||
0x50, // push rax
|
||||
0xFF, 0x15, 0xF2, 0x10, 0x00, 0x00, // call qword ptr ds:[<SomeModule.SomeFunction>]
|
||||
0x85, 0xC0, // test eax, eax
|
||||
0x0F, 0x84, 0x00, 0x00, 0x00, 0x00, // jz 0x007FFFFFFF400016
|
||||
0xE9, 0xE5, 0x0F, 0x00, 0x00 // jmp <SomeModule.EntryPoint>
|
||||
};
|
||||
|
||||
ZydisDecoder decoder;
|
||||
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
|
||||
|
||||
DisassembleBuffer(&decoder, &data[0], sizeof(data));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,265 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Demonstrates basic hooking functionality of the `ZydisFormatter` class and the ability
|
||||
* to completely omit specific operands.
|
||||
*
|
||||
* This example demonstrates the hooking functionality of the `ZydisFormatter` class by
|
||||
* rewriting the mnemonics of `(V)CMPPS` and `(V)CMPPD` to their corresponding alias-forms (based
|
||||
* on the condition encoded in the immediate operand).
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Zycore/Format.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zydis/Zydis.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Static data */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Static array with the condition-code strings.
|
||||
*/
|
||||
static const char* const CONDITION_CODE_STRINGS[0x20] =
|
||||
{
|
||||
/*00*/ "eq",
|
||||
/*01*/ "lt",
|
||||
/*02*/ "le",
|
||||
/*03*/ "unord",
|
||||
/*04*/ "neq",
|
||||
/*05*/ "nlt",
|
||||
/*06*/ "nle",
|
||||
/*07*/ "ord",
|
||||
/*08*/ "eq_uq",
|
||||
/*09*/ "nge",
|
||||
/*0A*/ "ngt",
|
||||
/*0B*/ "false",
|
||||
/*0C*/ "oq",
|
||||
/*0D*/ "ge",
|
||||
/*0E*/ "gt",
|
||||
/*0F*/ "true",
|
||||
/*10*/ "eq_os",
|
||||
/*11*/ "lt_oq",
|
||||
/*12*/ "le_oq",
|
||||
/*13*/ "unord_s",
|
||||
/*14*/ "neq_us",
|
||||
/*15*/ "nlt_uq",
|
||||
/*16*/ "nle_uq",
|
||||
/*17*/ "ord_s",
|
||||
/*18*/ "eq_us",
|
||||
/*19*/ "nge_uq",
|
||||
/*1A*/ "ngt_uq",
|
||||
/*1B*/ "false_os",
|
||||
/*1C*/ "neq_os",
|
||||
/*1D*/ "ge_oq",
|
||||
/*1E*/ "gt_oq",
|
||||
/*1F*/ "true_us"
|
||||
};
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and Types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* Custom user data struct for the formatter.
|
||||
*/
|
||||
typedef struct ZydisCustomUserData_
|
||||
{
|
||||
ZyanBool omit_immediate;
|
||||
} ZydisCustomUserData;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Hook callbacks */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZydisFormatterFunc default_print_mnemonic;
|
||||
|
||||
static ZyanStatus ZydisFormatterPrintMnemonic(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
|
||||
{
|
||||
// We use the user-data to pass data to the `ZydisFormatterFormatOperandImm` function
|
||||
ZydisCustomUserData* user_data = (ZydisCustomUserData*)context->user_data;
|
||||
user_data->omit_immediate = ZYAN_TRUE;
|
||||
|
||||
// Rewrite the instruction-mnemonic for the given instructions
|
||||
if (context->instruction->operand_count &&
|
||||
context->instruction->operands[context->instruction->operand_count - 1].type ==
|
||||
ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
// Retrieve the `ZyanString` instance of the formatter-buffer
|
||||
ZyanString* string;
|
||||
ZYAN_CHECK(ZydisFormatterBufferGetString(buffer, &string));
|
||||
|
||||
const ZyanU8 condition_code = (ZyanU8)context->instruction->operands[
|
||||
context->instruction->operand_count - 1].imm.value.u;
|
||||
switch (context->instruction->mnemonic)
|
||||
{
|
||||
case ZYDIS_MNEMONIC_CMPPS:
|
||||
if (condition_code < 0x08)
|
||||
{
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, ZYDIS_TOKEN_MNEMONIC));
|
||||
return ZyanStringAppendFormat(string, "cmp%sps",
|
||||
CONDITION_CODE_STRINGS[condition_code]);
|
||||
}
|
||||
break;
|
||||
case ZYDIS_MNEMONIC_CMPPD:
|
||||
if (condition_code < 0x08)
|
||||
{
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, ZYDIS_TOKEN_MNEMONIC));
|
||||
return ZyanStringAppendFormat(string, "cmp%spd",
|
||||
CONDITION_CODE_STRINGS[condition_code]);
|
||||
}
|
||||
break;
|
||||
case ZYDIS_MNEMONIC_VCMPPS:
|
||||
if (condition_code < 0x20)
|
||||
{
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, ZYDIS_TOKEN_MNEMONIC));
|
||||
return ZyanStringAppendFormat(string, "vcmp%sps",
|
||||
CONDITION_CODE_STRINGS[condition_code]);
|
||||
}
|
||||
break;
|
||||
case ZYDIS_MNEMONIC_VCMPPD:
|
||||
if (condition_code < 0x20)
|
||||
{
|
||||
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, ZYDIS_TOKEN_MNEMONIC));
|
||||
return ZyanStringAppendFormat(string, "vcmp%spd",
|
||||
CONDITION_CODE_STRINGS[condition_code]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We did not rewrite the instruction-mnemonic. Signal the `ZydisFormatterFormatOperandImm`
|
||||
// function not to omit the operand
|
||||
user_data->omit_immediate = ZYAN_FALSE;
|
||||
|
||||
// Default mnemonic printing
|
||||
return default_print_mnemonic(formatter, buffer, context);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZydisFormatterFunc default_format_operand_imm;
|
||||
|
||||
static ZyanStatus ZydisFormatterFormatOperandIMM(const ZydisFormatter* formatter,
|
||||
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
|
||||
{
|
||||
// The `ZydisFormatterFormatMnemonic` sinals us to omit the immediate (condition-code)
|
||||
// operand, because it got replaced by the alias-mnemonic
|
||||
const ZydisCustomUserData* user_data = (ZydisCustomUserData*)context->user_data;
|
||||
if (user_data->omit_immediate)
|
||||
{
|
||||
return ZYDIS_STATUS_SKIP_TOKEN;
|
||||
}
|
||||
|
||||
// Default immediate formatting
|
||||
return default_format_operand_imm(formatter, buffer, context);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize length,
|
||||
ZyanBool install_hooks)
|
||||
{
|
||||
ZydisFormatter formatter;
|
||||
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
|
||||
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
|
||||
|
||||
if (install_hooks)
|
||||
{
|
||||
default_print_mnemonic = (ZydisFormatterFunc)&ZydisFormatterPrintMnemonic;
|
||||
ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC,
|
||||
(const void**)&default_print_mnemonic);
|
||||
default_format_operand_imm = (ZydisFormatterFunc)&ZydisFormatterFormatOperandIMM;
|
||||
ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM,
|
||||
(const void**)&default_format_operand_imm);
|
||||
}
|
||||
|
||||
ZyanU64 runtime_address = 0x007FFFFFFF400000;
|
||||
|
||||
ZydisDecodedInstruction instruction;
|
||||
ZydisCustomUserData user_data;
|
||||
char buffer[256];
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(decoder, data, length, &instruction)))
|
||||
{
|
||||
ZYAN_PRINTF("%016" PRIX64 " ", runtime_address);
|
||||
ZydisFormatterFormatInstructionEx(&formatter, &instruction, &buffer[0], sizeof(buffer),
|
||||
runtime_address, &user_data);
|
||||
ZYAN_PRINTF(" %s\n", &buffer[0]);
|
||||
data += instruction.length;
|
||||
length -= instruction.length;
|
||||
runtime_address += instruction.length;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (ZydisGetVersion() != ZYDIS_VERSION)
|
||||
{
|
||||
fputs("Invalid zydis version\n", ZYAN_STDERR);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ZyanU8 data[] =
|
||||
{
|
||||
// nop
|
||||
0x90,
|
||||
|
||||
// cmpps xmm1, xmm4, 0x03
|
||||
0x0F, 0xC2, 0xCC, 0x03,
|
||||
|
||||
// vcmppd xmm1, xmm2, xmm3, 0x17
|
||||
0xC5, 0xE9, 0xC2, 0xCB, 0x17,
|
||||
|
||||
// vcmpps k2 {k7}, zmm2, dword ptr ds:[rax + rbx*4 + 0x100] {1to16}, 0x0F
|
||||
0x62, 0xF1, 0x6C, 0x5F, 0xC2, 0x54, 0x98, 0x40, 0x0F
|
||||
};
|
||||
|
||||
ZydisDecoder decoder;
|
||||
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
|
||||
|
||||
DisassembleBuffer(&decoder, &data[0], sizeof(data), ZYAN_FALSE);
|
||||
ZYAN_PUTS("");
|
||||
DisassembleBuffer(&decoder, &data[0], sizeof(data), ZYAN_TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,126 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Demonstrates the tokenizing feature of the `ZydisFormatter` class.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Zycore/Format.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zydis/Zydis.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Static data */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static const char* const TOKEN_TYPES[] =
|
||||
{
|
||||
"INVALID ",
|
||||
"WHITESPACE ",
|
||||
"DELIMITER ",
|
||||
"PARENTHESIS_OPEN ",
|
||||
"PARENTHESIS_CLOSE",
|
||||
"PREFIX ",
|
||||
"MNEMONIC ",
|
||||
"REGISTER ",
|
||||
"ADDRESS_ABS ",
|
||||
"ADDRESS_REL ",
|
||||
"DISPLACEMENT ",
|
||||
"IMMEDIATE ",
|
||||
"TYPECAST ",
|
||||
"DECORATOR ",
|
||||
"SYMBOL "
|
||||
};
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize length)
|
||||
{
|
||||
ZydisFormatter formatter;
|
||||
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE);
|
||||
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE);
|
||||
|
||||
ZyanU64 runtime_address = 0x007FFFFFFF400000;
|
||||
|
||||
ZydisDecodedInstruction instruction;
|
||||
char buffer[256];
|
||||
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(decoder, data, length, &instruction)))
|
||||
{
|
||||
const ZydisFormatterToken* token;
|
||||
if (ZYAN_SUCCESS(ZydisFormatterTokenizeInstruction(&formatter, &instruction, &buffer[0],
|
||||
sizeof(buffer), runtime_address, &token)))
|
||||
{
|
||||
ZydisTokenType token_type;
|
||||
ZyanConstCharPointer token_value = ZYAN_NULL;
|
||||
while (token)
|
||||
{
|
||||
ZydisFormatterTokenGetValue(token, &token_type, &token_value);
|
||||
printf("ZYDIS_TOKEN_%17s (%02X): \"%s\"\n", TOKEN_TYPES[token_type], token_type,
|
||||
token_value);
|
||||
if (!ZYAN_SUCCESS(ZydisFormatterTokenNext(&token)))
|
||||
{
|
||||
token = ZYAN_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
data += instruction.length;
|
||||
length -= instruction.length;
|
||||
runtime_address += instruction.length;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (ZydisGetVersion() != ZYDIS_VERSION)
|
||||
{
|
||||
fputs("Invalid zydis version\n", ZYAN_STDERR);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ZyanU8 data[] =
|
||||
{
|
||||
// vcmpps k2 {k7}, zmm2, dword ptr ds:[rax + rbx*4 + 0x100] {1to16}, 0x0F
|
||||
0x62, 0xF1, 0x6C, 0x5F, 0xC2, 0x54, 0x98, 0x40, 0x0F
|
||||
};
|
||||
|
||||
ZydisDecoder decoder;
|
||||
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
|
||||
|
||||
DisassembleBuffer(&decoder, &data[0], sizeof(data));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,23 +0,0 @@
|
||||
# Zydis Examples
|
||||
|
||||
## Decoder
|
||||
|
||||
Comming soon™ ...
|
||||
|
||||
## Formatter
|
||||
|
||||
### [Formatter01](./Formatter01.c)
|
||||
Demonstrates basic hooking functionality of the `ZydisFormatter` class by implementing a custom symbol-resolver.
|
||||
|
||||
### [Formatter02](./Formatter02.c)
|
||||
Demonstrates basic hooking functionality of the `ZydisFormatter` class and the ability to completely omit specific operands.
|
||||
|
||||
The example demonstrates the hooking functionality of the `ZydisFormatter` class by rewriting the mnemonics of `(V)CMPPS` and `(V)CMPPD` to their corresponding alias-forms (based on the condition encoded in the immediate operand).
|
||||
|
||||
### [Formatter03](./Formatter03.c)
|
||||
Demonstrates the tokenizing feature of the `ZydisFormatter` class.
|
||||
|
||||
## Misc
|
||||
|
||||
### [ZydisWinKernel](./ZydisWinKernel.c)
|
||||
Implements an example Windows kernel-mode driver.
|
@ -1,578 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <Zycore/API/Terminal.h>
|
||||
#include <Zycore/LibC.h>
|
||||
#include <Zydis/Zydis.h>
|
||||
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
# include <Windows.h>
|
||||
#elif defined(ZYAN_APPLE)
|
||||
# include <mach/mach_time.h>
|
||||
#elif defined(ZYAN_LINUX) || defined(ZYAN_SOLARIS)
|
||||
# include <sys/time.h>
|
||||
# include <pthread.h>
|
||||
#elif defined(ZYAN_FREEBSD)
|
||||
# include <sys/time.h>
|
||||
# include <pthread.h>
|
||||
# include <pthread_np.h>
|
||||
#else
|
||||
# error "Unsupported platform detected"
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Colors */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Configuration */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define COLOR_DEFAULT ZYAN_VT100SGR_FG_DEFAULT
|
||||
#define COLOR_ERROR ZYAN_VT100SGR_FG_BRIGHT_RED
|
||||
#define COLOR_VALUE_R ZYAN_VT100SGR_FG_BRIGHT_RED
|
||||
#define COLOR_VALUE_G ZYAN_VT100SGR_FG_BRIGHT_GREEN
|
||||
#define COLOR_VALUE_B ZYAN_VT100SGR_FG_CYAN
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Global variables */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static ZyanBool g_vt100_stdout;
|
||||
static ZyanBool g_vt100_stderr;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Helper macros */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Conditionally expands to the passed VT100 sequence, if `g_colors_stdout` is
|
||||
* `ZYAN_TRUE`, or an empty string, if not.
|
||||
*
|
||||
* @param The VT100 SGT sequence.
|
||||
*/
|
||||
#define CVT100_OUT(sequence) (g_vt100_stdout ? (sequence) : "")
|
||||
|
||||
/**
|
||||
* Conditionally expands to the passed VT100 sequence, if `g_colors_stderr` is
|
||||
* `ZYAN_TRUE`, or an empty string, if not.
|
||||
*
|
||||
* @param The VT100 SGT sequence.
|
||||
*/
|
||||
#define CVT100_ERR(sequence) (g_vt100_stderr ? (sequence) : "")
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Time measurement */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
double counter_freq = 0.0;
|
||||
ZyanU64 counter_start = 0;
|
||||
|
||||
static void StartCounter(void)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
if (!QueryPerformanceFrequency(&li))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sError: QueryPerformanceFrequency failed!%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
counter_freq = (double)li.QuadPart / 1000.0;
|
||||
QueryPerformanceCounter(&li);
|
||||
counter_start = li.QuadPart;
|
||||
}
|
||||
|
||||
static double GetCounter(void)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
QueryPerformanceCounter(&li);
|
||||
return (double)(li.QuadPart - counter_start) / counter_freq;
|
||||
}
|
||||
|
||||
#elif defined(ZYAN_APPLE)
|
||||
|
||||
ZyanU64 counter_start = 0;
|
||||
mach_timebase_info_data_t timebase_info;
|
||||
|
||||
static void StartCounter(void)
|
||||
{
|
||||
counter_start = mach_absolute_time();
|
||||
}
|
||||
|
||||
static double GetCounter(void)
|
||||
{
|
||||
ZyanU64 elapsed = mach_absolute_time() - counter_start;
|
||||
|
||||
if (timebase_info.denom == 0)
|
||||
{
|
||||
mach_timebase_info(&timebase_info);
|
||||
}
|
||||
|
||||
return (double)elapsed * timebase_info.numer / timebase_info.denom / 1000000;
|
||||
}
|
||||
|
||||
#elif defined(ZYAN_LINUX) || defined(ZYAN_FREEBSD) || defined(ZYAN_SOLARIS)
|
||||
|
||||
struct timeval t1;
|
||||
|
||||
static void StartCounter(void)
|
||||
{
|
||||
gettimeofday(&t1, NULL);
|
||||
}
|
||||
|
||||
static double GetCounter(void)
|
||||
{
|
||||
struct timeval t2;
|
||||
gettimeofday(&t2, NULL);
|
||||
|
||||
double t = (t2.tv_sec - t1.tv_sec) * 1000.0;
|
||||
return t + (t2.tv_usec - t1.tv_usec) / 1000.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Process & Thread Priority */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void AdjustProcessAndThreadPriority(void)
|
||||
{
|
||||
#if defined(ZYAN_WINDOWS)
|
||||
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
if (info.dwNumberOfProcessors > 1)
|
||||
{
|
||||
if (!SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)1))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sWarning: Could not set thread affinity mask%s\n",
|
||||
CVT100_ERR(ZYAN_VT100SGR_FG_YELLOW), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
}
|
||||
if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sWarning: Could not set process priority class%s\n",
|
||||
CVT100_ERR(ZYAN_VT100SGR_FG_YELLOW), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
}
|
||||
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sWarning: Could not set thread priority class%s\n",
|
||||
CVT100_ERR(ZYAN_VT100SGR_FG_YELLOW), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(ZYAN_LINUX) || defined(ZYAN_FREEBSD)
|
||||
|
||||
pthread_t thread = pthread_self();
|
||||
|
||||
#if defined(ZYAN_LINUX)
|
||||
cpu_set_t cpus;
|
||||
#else // FreeBSD
|
||||
cpuset_t cpus;
|
||||
#endif
|
||||
|
||||
CPU_ZERO(&cpus);
|
||||
CPU_SET(0, &cpus);
|
||||
if (pthread_setaffinity_np(thread, sizeof(cpus), &cpus))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sWarning: Could not set thread affinity mask%s\n",
|
||||
CVT100_ERR(ZYAN_VT100SGR_FG_YELLOW), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static ZyanU64 ProcessBuffer(const ZydisDecoder* decoder, const ZydisFormatter* formatter,
|
||||
/* const ZydisCacheTable* cache, */
|
||||
const ZyanU8* buffer, ZyanUSize length, ZyanBool format, ZyanBool tokenize, ZyanBool use_cache)
|
||||
{
|
||||
ZyanU64 count = 0;
|
||||
ZyanUSize offset = 0;
|
||||
ZyanStatus status;
|
||||
ZydisDecodedInstruction instruction_data;
|
||||
ZydisDecodedInstruction* instruction;
|
||||
char format_buffer[256];
|
||||
|
||||
while (length > offset)
|
||||
{
|
||||
if (use_cache)
|
||||
{
|
||||
ZYAN_UNREACHABLE;
|
||||
// status = ZydisDecoderDecodeBufferCached(decoder, cache, buffer + offset,
|
||||
// length - offset, &instruction);
|
||||
} else
|
||||
{
|
||||
status = ZydisDecoderDecodeBuffer(decoder, buffer + offset, length - offset,
|
||||
&instruction_data);
|
||||
instruction = &instruction_data;
|
||||
}
|
||||
|
||||
if (status == ZYDIS_STATUS_NO_MORE_DATA)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!ZYAN_SUCCESS(status))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sUnexpected decoding error. Data: ",
|
||||
CVT100_ERR(COLOR_ERROR));
|
||||
for (ZyanUSize i = 0; i < ZYAN_MIN(ZYDIS_MAX_INSTRUCTION_LENGTH,
|
||||
length - offset); ++i)
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%02X ", (ZyanU8)buffer[offset + i]);
|
||||
}
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%s\n", CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
ZYAN_ASSERT(ZYAN_FALSE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (format)
|
||||
{
|
||||
if (tokenize)
|
||||
{
|
||||
const ZydisFormatterToken* token;
|
||||
ZydisFormatterTokenizeInstruction(formatter, instruction, format_buffer,
|
||||
sizeof(format_buffer), offset, &token);
|
||||
} else
|
||||
{
|
||||
ZydisFormatterFormatInstruction(formatter, instruction, format_buffer,
|
||||
sizeof(format_buffer), offset);
|
||||
}
|
||||
}
|
||||
|
||||
offset += instruction->length;
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void TestPerformance(const ZyanU8* buffer, ZyanUSize length, ZyanBool minimal_mode,
|
||||
ZyanBool format, ZyanBool tokenize, ZyanBool use_cache)
|
||||
{
|
||||
ZydisDecoder decoder;
|
||||
if (!ZYAN_SUCCESS(ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64,
|
||||
ZYDIS_ADDRESS_WIDTH_64)))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sFailed to initialize decoder%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!ZYAN_SUCCESS(ZydisDecoderEnableMode(&decoder, ZYDIS_DECODER_MODE_MINIMAL, minimal_mode)))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sFailed to adjust decoder-mode%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ZydisCacheTable cache;
|
||||
// if (use_cache && !ZYAN_SUCCESS(ZydisDecoderInitCache(&decoder, &cache)))
|
||||
// {
|
||||
// ZYAN_FPRINTF(ZYAN_STDERR, "%sFailed to initialize decoder-cache%s\n",
|
||||
// CVT100_ERR(COLOR_ERROR), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
|
||||
ZydisFormatter formatter;
|
||||
if (format)
|
||||
{
|
||||
if (!ZYAN_SUCCESS(ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL)) ||
|
||||
!ZYAN_SUCCESS(ZydisFormatterSetProperty(&formatter,
|
||||
ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE)) ||
|
||||
!ZYAN_SUCCESS(ZydisFormatterSetProperty(&formatter,
|
||||
ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE)))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sFailed to initialize instruction-formatter%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Cache warmup
|
||||
ProcessBuffer(&decoder, &formatter, /* cache, */ buffer, length, format, tokenize, use_cache);
|
||||
|
||||
// Testing
|
||||
ZyanU64 count = 0;
|
||||
StartCounter();
|
||||
for (ZyanU8 j = 0; j < 100; ++j)
|
||||
{
|
||||
count += ProcessBuffer(&decoder, &formatter, /* cache, */ buffer, length, format,
|
||||
tokenize, use_cache);
|
||||
}
|
||||
const char* color[4];
|
||||
color[0] = minimal_mode ? CVT100_OUT(COLOR_VALUE_G) : CVT100_OUT(COLOR_VALUE_B);
|
||||
color[1] = format ? CVT100_OUT(COLOR_VALUE_G) : CVT100_OUT(COLOR_VALUE_B);
|
||||
color[2] = tokenize ? CVT100_OUT(COLOR_VALUE_G) : CVT100_OUT(COLOR_VALUE_B);
|
||||
color[3] = use_cache ? CVT100_OUT(COLOR_VALUE_G) : CVT100_OUT(COLOR_VALUE_B);
|
||||
ZYAN_PRINTF("Minimal-Mode %s%d%s, Format %s%d%s, Tokenize %s%d%s, Caching %s%d%s, " \
|
||||
"Instructions: %s%6.2fM%s, Time: %s%8.2f%s msec\n",
|
||||
color[0], minimal_mode, CVT100_OUT(COLOR_DEFAULT),
|
||||
color[1], format, CVT100_OUT(COLOR_DEFAULT),
|
||||
color[2], tokenize, CVT100_OUT(COLOR_DEFAULT),
|
||||
color[3], use_cache, CVT100_OUT(COLOR_DEFAULT),
|
||||
CVT100_OUT(COLOR_VALUE_B), (double)count / 1000000, CVT100_OUT(COLOR_DEFAULT),
|
||||
CVT100_OUT(COLOR_VALUE_G), GetCounter(), CVT100_OUT(COLOR_DEFAULT));
|
||||
}
|
||||
|
||||
static void GenerateTestData(FILE* file, ZyanU8 encoding)
|
||||
{
|
||||
ZydisDecoder decoder;
|
||||
if (!ZYAN_SUCCESS(
|
||||
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64)))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sFailed to initialize decoder%s\n", CVT100_ERR(COLOR_ERROR),
|
||||
CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ZyanU8 last = 0;
|
||||
ZyanU32 count = 0;
|
||||
ZydisDecodedInstruction instruction;
|
||||
while (count < 100000)
|
||||
{
|
||||
ZyanU8 data[ZYDIS_MAX_INSTRUCTION_LENGTH];
|
||||
for (int i = 0; i < ZYDIS_MAX_INSTRUCTION_LENGTH; ++i)
|
||||
{
|
||||
data[i] = rand() % 256;
|
||||
}
|
||||
const ZyanU8 offset = rand() % (ZYDIS_MAX_INSTRUCTION_LENGTH - 2);
|
||||
switch (encoding)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
data[offset ] = 0x0F;
|
||||
data[offset + 1] = 0x0F;
|
||||
break;
|
||||
case 2:
|
||||
data[offset ] = 0x8F;
|
||||
break;
|
||||
case 3:
|
||||
data[offset ] = 0xC4;
|
||||
break;
|
||||
case 4:
|
||||
data[offset ] = 0xC5;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
data[offset ] = 0x62;
|
||||
break;
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
if (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, data, sizeof(data), &instruction)))
|
||||
{
|
||||
ZyanBool b = ZYAN_FALSE;
|
||||
switch (encoding)
|
||||
{
|
||||
case 0:
|
||||
b = (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_LEGACY);
|
||||
break;
|
||||
case 1:
|
||||
b = (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW);
|
||||
break;
|
||||
case 2:
|
||||
b = (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_XOP);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
b = (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_VEX);
|
||||
break;
|
||||
case 5:
|
||||
b = (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX);
|
||||
break;
|
||||
case 6:
|
||||
b = (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX);
|
||||
break;
|
||||
default:
|
||||
ZYAN_UNREACHABLE;
|
||||
}
|
||||
if (b)
|
||||
{
|
||||
fwrite(&data[0], sizeof(ZyanU8), instruction.length, file);
|
||||
++count;
|
||||
|
||||
const ZyanU8 p = (ZyanU8)((double)count / 100000 * 100);
|
||||
if (last < p)
|
||||
{
|
||||
last = p;
|
||||
ZYAN_PRINTF("%3.0d%%\n", p);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Enable VT100 escape sequences on Windows, if the output is not redirected
|
||||
g_vt100_stdout = (ZyanTerminalIsTTY(ZYAN_STDSTREAM_OUT) == ZYAN_STATUS_TRUE) &&
|
||||
ZYAN_SUCCESS(ZyanTerminalEnableVT100(ZYAN_STDSTREAM_OUT));
|
||||
g_vt100_stderr = (ZyanTerminalIsTTY(ZYAN_STDSTREAM_ERR) == ZYAN_STATUS_TRUE) &&
|
||||
ZYAN_SUCCESS(ZyanTerminalEnableVT100(ZYAN_STDSTREAM_ERR));
|
||||
|
||||
if (ZydisGetVersion() != ZYDIS_VERSION)
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sInvalid zydis version%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (argc < 3 || (ZYAN_STRCMP(argv[1], "-test") && ZYAN_STRCMP(argv[1], "-generate")))
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sUsage: %s -[test|generate] [directory]%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), (argc > 0 ? argv[0] : "PerfTest"),
|
||||
CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ZyanBool generate = ZYAN_FALSE;
|
||||
if (!ZYAN_STRCMP(argv[1], "-generate"))
|
||||
{
|
||||
generate = ZYAN_TRUE;
|
||||
}
|
||||
const char* directory = argv[2];
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char* encoding;
|
||||
const char* filename;
|
||||
} tests[7] =
|
||||
{
|
||||
{ "DEFAULT", "enc_default.dat" },
|
||||
{ "3DNOW" , "enc_3dnow.dat" },
|
||||
{ "XOP" , "enc_xop.dat" },
|
||||
{ "VEX_C4" , "enc_vex_c4.dat" },
|
||||
{ "VEX_C5" , "enc_vex_c5.dat" },
|
||||
{ "EVEX" , "enc_evex.dat" },
|
||||
{ "MVEX" , "enc_mvex.dat" }
|
||||
};
|
||||
|
||||
if (generate)
|
||||
{
|
||||
time_t t;
|
||||
srand((unsigned)time(&t));
|
||||
} else
|
||||
{
|
||||
AdjustProcessAndThreadPriority();
|
||||
}
|
||||
|
||||
for (ZyanU8 i = 0; i < ZYAN_ARRAY_LENGTH(tests); ++i)
|
||||
{
|
||||
FILE* file;
|
||||
|
||||
const ZyanUSize len = strlen(directory);
|
||||
char buf[1024];
|
||||
strncpy(&buf[0], directory, sizeof(buf) - 1);
|
||||
if (generate)
|
||||
{
|
||||
file = fopen(strncat(buf, tests[i].filename, sizeof(buf) - len - 1), "wb");
|
||||
} else
|
||||
{
|
||||
file = fopen(strncat(buf, tests[i].filename, sizeof(buf) - len - 1), "rb");
|
||||
}
|
||||
if (!file)
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR, "%sCould not open file \"%s\": %s%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), &buf[0], strerror(ZYAN_ERRNO),
|
||||
CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (generate)
|
||||
{
|
||||
ZYAN_PRINTF("Generating %s%s%s ...\n", CVT100_OUT(COLOR_VALUE_B), tests[i].encoding,
|
||||
CVT100_OUT(ZYAN_VT100SGR_RESET));
|
||||
GenerateTestData(file, i);
|
||||
} else
|
||||
{
|
||||
fseek(file, 0L, SEEK_END);
|
||||
const long length = ftell(file);
|
||||
void* buffer = malloc(length);
|
||||
if (!buffer)
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR,
|
||||
"%sFailed to allocate %" PRIu64 " bytes on the heap%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), (ZyanU64)length, CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
goto NextFile2;
|
||||
}
|
||||
|
||||
rewind(file);
|
||||
if (fread(buffer, 1, length, file) != (ZyanUSize)length)
|
||||
{
|
||||
ZYAN_FPRINTF(ZYAN_STDERR,
|
||||
"%sCould not read %" PRIu64 " bytes from file \"%s\"%s\n",
|
||||
CVT100_ERR(COLOR_ERROR), (ZyanU64)length, &buf[0],
|
||||
CVT100_ERR(ZYAN_VT100SGR_RESET));
|
||||
goto NextFile1;
|
||||
}
|
||||
|
||||
ZYAN_PRINTF("%sTesting %s%s%s ...\n", CVT100_OUT(ZYAN_VT100SGR_FG_MAGENTA),
|
||||
CVT100_OUT(ZYAN_VT100SGR_FG_BRIGHT_MAGENTA), tests[i].encoding,
|
||||
CVT100_OUT(COLOR_DEFAULT));
|
||||
TestPerformance(buffer, length, ZYAN_TRUE , ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE);
|
||||
TestPerformance(buffer, length, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE);
|
||||
// TestPerformance(buffer, length, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_TRUE);
|
||||
TestPerformance(buffer, length, ZYAN_FALSE, ZYAN_TRUE , ZYAN_FALSE, ZYAN_FALSE);
|
||||
// TestPerformance(buffer, length, ZYAN_FALSE, ZYAN_TRUE , ZYAN_FALSE, ZYAN_TRUE);
|
||||
TestPerformance(buffer, length, ZYAN_FALSE, ZYAN_TRUE , ZYAN_TRUE , ZYAN_FALSE);
|
||||
// TestPerformance(buffer, length, ZYAN_FALSE, ZYAN_TRUE , ZYAN_TRUE , ZYAN_TRUE);
|
||||
ZYAN_PUTS("");
|
||||
|
||||
NextFile1:
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
NextFile2:
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,189 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Engine (Zydis)
|
||||
|
||||
Original Author : Matthijs Lavrijsen
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Windows kernel mode driver sample.
|
||||
*
|
||||
* This is a Windows kernel mode driver. It links against the kernel mode-compatible version of Zydis.
|
||||
* The driver finds its own entry point and decodes and prints the disassembly of this function.
|
||||
* To view the log, either attach a kernel debugger or use a tool like Sysinternals DebugView.
|
||||
*/
|
||||
|
||||
#include <wdm.h>
|
||||
#include <ntimage.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "Zydis/Zydis.h"
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Forward declarations */
|
||||
/* ============================================================================================== */
|
||||
|
||||
NTKERNELAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
RtlPcToFileHeader(
|
||||
_In_ PVOID PcValue,
|
||||
_Out_ PVOID *BaseOfImage
|
||||
);
|
||||
|
||||
NTKERNELAPI
|
||||
PIMAGE_NT_HEADERS
|
||||
NTAPI
|
||||
RtlImageNtHeader(
|
||||
_In_ PVOID ImageBase
|
||||
);
|
||||
|
||||
#if defined(ZYAN_CLANG) || defined(ZYAN_GNUC)
|
||||
__attribute__((section("INIT")))
|
||||
#endif
|
||||
DRIVER_INITIALIZE
|
||||
DriverEntry;
|
||||
|
||||
#if defined(ALLOC_PRAGMA) && !(defined(ZYAN_CLANG) || defined(ZYAN_GNUC))
|
||||
#pragma alloc_text(INIT, DriverEntry)
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Helper functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
VOID
|
||||
Print(
|
||||
_In_ PCCH Format,
|
||||
_In_ ...
|
||||
)
|
||||
{
|
||||
CHAR message[512];
|
||||
va_list argList;
|
||||
va_start(argList, Format);
|
||||
const int n = _vsnprintf_s(message, sizeof(message), sizeof(message) - 1, Format, argList);
|
||||
message[n] = '\0';
|
||||
vDbgPrintExWithPrefix("[ZYDIS] ", DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, message, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Entry point */
|
||||
/* ============================================================================================== */
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PUNICODE_STRING RegistryPath
|
||||
)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(RegistryPath);
|
||||
|
||||
if (ZydisGetVersion() != ZYDIS_VERSION)
|
||||
{
|
||||
Print("Invalid zydis version\n");
|
||||
return STATUS_UNKNOWN_REVISION;
|
||||
}
|
||||
|
||||
// Get the driver's image base and PE headers
|
||||
ULONG_PTR imageBase;
|
||||
RtlPcToFileHeader((PVOID)DriverObject->DriverInit, (PVOID*)&imageBase);
|
||||
if (imageBase == 0)
|
||||
return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
|
||||
const PIMAGE_NT_HEADERS ntHeaders = RtlImageNtHeader((PVOID)imageBase);
|
||||
if (ntHeaders == NULL)
|
||||
return STATUS_INVALID_IMAGE_FORMAT;
|
||||
|
||||
// Get the section headers of the INIT section
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
PIMAGE_SECTION_HEADER initSection = NULL;
|
||||
for (USHORT i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
||||
{
|
||||
if (memcmp(section->Name, "INIT", sizeof("INIT") - 1) == 0)
|
||||
{
|
||||
initSection = section;
|
||||
break;
|
||||
}
|
||||
section++;
|
||||
}
|
||||
if (initSection == NULL)
|
||||
return STATUS_NOT_FOUND;
|
||||
|
||||
// Get the RVAs of the entry point and import directory. If the import directory lies within the INIT section,
|
||||
// stop disassembling when its address is reached. Otherwise, disassemble until the end of the INIT section.
|
||||
const ULONG entryPointRva = (ULONG)((ULONG_PTR)DriverObject->DriverInit - imageBase);
|
||||
const ULONG importDirRva = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||
SIZE_T length = initSection->VirtualAddress + initSection->SizeOfRawData - entryPointRva;
|
||||
if (importDirRva > entryPointRva && importDirRva > initSection->VirtualAddress &&
|
||||
importDirRva < initSection->VirtualAddress + initSection->SizeOfRawData)
|
||||
length = importDirRva - entryPointRva;
|
||||
|
||||
Print("Driver image base: 0x%p, size: 0x%X\n", (PVOID)imageBase, ntHeaders->OptionalHeader.SizeOfImage);
|
||||
Print("Entry point RVA: 0x%X (0x%p)\n", entryPointRva, DriverObject->DriverInit);
|
||||
|
||||
// Initialize Zydis decoder and formatter
|
||||
ZydisDecoder decoder;
|
||||
#ifdef _M_AMD64
|
||||
if (!ZYAN_SUCCESS(ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64)))
|
||||
#else
|
||||
if (!ZYAN_SUCCESS(ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_ADDRESS_WIDTH_32)))
|
||||
#endif
|
||||
return STATUS_DRIVER_INTERNAL_ERROR;
|
||||
|
||||
ZydisFormatter formatter;
|
||||
if (!ZYAN_SUCCESS(ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL)))
|
||||
return STATUS_DRIVER_INTERNAL_ERROR;
|
||||
|
||||
SIZE_T readOffset = 0;
|
||||
ZydisDecodedInstruction instruction;
|
||||
ZyanStatus status;
|
||||
CHAR printBuffer[128];
|
||||
|
||||
// Start the decode loop
|
||||
while ((status = ZydisDecoderDecodeBuffer(&decoder, (PVOID)(imageBase + entryPointRva + readOffset),
|
||||
length - readOffset, &instruction)) != ZYDIS_STATUS_NO_MORE_DATA)
|
||||
{
|
||||
NT_ASSERT(ZYAN_SUCCESS(status));
|
||||
if (!ZYAN_SUCCESS(status))
|
||||
{
|
||||
readOffset++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Format and print the instruction
|
||||
const ZyanU64 instrAddress = (ZyanU64)(imageBase + entryPointRva + readOffset);
|
||||
ZydisFormatterFormatInstruction(
|
||||
&formatter, &instruction, printBuffer, sizeof(printBuffer), instrAddress);
|
||||
Print("+%-4X 0x%-16llX\t\t%hs\n", (ULONG)readOffset, instrAddress, printBuffer);
|
||||
|
||||
readOffset += instruction.length;
|
||||
}
|
||||
|
||||
// Return an error status so that the driver does not have to be unloaded after running.
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -1,12 +0,0 @@
|
||||
/** @dir include
|
||||
* @brief Top-level include dir
|
||||
*/
|
||||
/** @dir include/Zydis
|
||||
* @brief Zydis include dir
|
||||
*/
|
||||
/** @dir include/Zydis/Generated
|
||||
* @brief Generated files
|
||||
*/
|
||||
/** @dir include/Zydis/Internal
|
||||
* @brief Internal APIs
|
||||
*/
|
@ -1,237 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functions for decoding instructions.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_DECODER_H
|
||||
#define ZYDIS_DECODER_H
|
||||
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
#include <Zydis/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder mode */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderMode` enum.
|
||||
*/
|
||||
typedef enum ZydisDecoderMode_
|
||||
{
|
||||
/**
|
||||
* Enables minimal instruction decoding without semantic analysis.
|
||||
*
|
||||
* This mode provides access to the mnemonic, the instruction-length, the effective
|
||||
* operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`)
|
||||
* and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct.
|
||||
*
|
||||
* Operands, most attributes and other specific information (like `AVX` info) are not
|
||||
* accessible in this mode.
|
||||
*
|
||||
* This mode is NOT enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_MINIMAL,
|
||||
/**
|
||||
* Enables the `AMD`-branch mode.
|
||||
*
|
||||
* Intel ignores the operand-size override-prefix (`0x66`) for all branches with 32-bit
|
||||
* immediates and forces the operand-size of the instruction to 64-bit in 64-bit mode.
|
||||
* In `AMD`-branch mode `0x66` is not ignored and changes the operand-size and the size of the
|
||||
* immediate to 16-bit.
|
||||
*
|
||||
* This mode is NOT enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_AMD_BRANCHES,
|
||||
/**
|
||||
* Enables `KNC` compatibility-mode.
|
||||
*
|
||||
* `KNC` and `KNL+` chips are sharing opcodes and encodings for some mask-related instructions.
|
||||
* Enable this mode to use the old `KNC` specifications (different mnemonics, operands, ..).
|
||||
*
|
||||
* This mode is NOT enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_KNC,
|
||||
/**
|
||||
* Enables the `MPX` mode.
|
||||
*
|
||||
* The `MPX` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_MPX,
|
||||
/**
|
||||
* Enables the `CET` mode.
|
||||
*
|
||||
* The `CET` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_CET,
|
||||
/**
|
||||
* Enables the `LZCNT` mode.
|
||||
*
|
||||
* The `LZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_LZCNT,
|
||||
/**
|
||||
* Enables the `TZCNT` mode.
|
||||
*
|
||||
* The `TZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_TZCNT,
|
||||
/**
|
||||
* Enables the `WBNOINVD` mode.
|
||||
*
|
||||
* The `WBINVD` instruction is interpreted as `WBNOINVD` on ICL chips, if a `F3` prefix is
|
||||
* used.
|
||||
*
|
||||
* This mode is disabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_WBNOINVD,
|
||||
/**
|
||||
* Enables the `CLDEMOTE` mode.
|
||||
*
|
||||
* The `CLDEMOTE` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||
*
|
||||
* This mode is enabled by default.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_CLDEMOTE,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_MAX_VALUE = ZYDIS_DECODER_MODE_CLDEMOTE,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_DECODER_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECODER_MODE_MAX_VALUE)
|
||||
} ZydisDecoderMode;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder struct */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoder` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZydisDecoder_
|
||||
{
|
||||
/**
|
||||
* The machine mode.
|
||||
*/
|
||||
ZydisMachineMode machine_mode;
|
||||
/**
|
||||
* The address width.
|
||||
*/
|
||||
ZydisAddressWidth address_width;
|
||||
/**
|
||||
* The decoder mode array.
|
||||
*/
|
||||
ZyanBool decoder_mode[ZYDIS_DECODER_MODE_MAX_VALUE + 1];
|
||||
} ZydisDecoder;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @addtogroup decoder Decoder
|
||||
* Functions allowing decoding of instruction bytes to a machine interpretable struct.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initializes the given `ZydisDecoder` instance.
|
||||
*
|
||||
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||
* @param machine_mode The machine mode.
|
||||
* @param address_width The address width.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
|
||||
ZydisAddressWidth address_width);
|
||||
|
||||
/**
|
||||
* Enables or disables the specified decoder-mode.
|
||||
*
|
||||
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||
* @param mode The decoder mode.
|
||||
* @param enabled `ZYAN_TRUE` to enable, or `ZYAN_FALSE` to disable the specified decoder-mode.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode,
|
||||
ZyanBool enabled);
|
||||
|
||||
/**
|
||||
* Decodes the instruction in the given input `buffer`.
|
||||
*
|
||||
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||
* @param buffer A pointer to the input buffer.
|
||||
* @param length The length of the input buffer. Note that this can be bigger than the
|
||||
* actual size of the instruction -- you don't have to know the size up
|
||||
* front. This length is merely used to prevent Zydis from doing
|
||||
* out-of-bounds reads on your buffer.
|
||||
* @param instruction A pointer to the `ZydisDecodedInstruction` struct, that receives the
|
||||
* details about the decoded instruction.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder,
|
||||
const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction);
|
||||
|
||||
/** @} */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_DECODER_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,306 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the `ZydisFormatterToken` type and provides functions to use it.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_FORMATTER_TOKEN_H
|
||||
#define ZYDIS_FORMATTER_TOKEN_H
|
||||
|
||||
#include <ZydisExportConfig.h>
|
||||
#include <Zycore/String.h>
|
||||
#include <Zycore/Types.h>
|
||||
#include <Zydis/Status.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Constants */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Token types */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @biref Defines the `ZydisTokenType` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisTokenType;
|
||||
|
||||
#define ZYDIS_TOKEN_INVALID 0x00
|
||||
/**
|
||||
* A whitespace character.
|
||||
*/
|
||||
#define ZYDIS_TOKEN_WHITESPACE 0x01
|
||||
/**
|
||||
* A delimiter character (like `','`, `':'`, `'+'`, `'-'`, `'*'`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_DELIMITER 0x02
|
||||
/**
|
||||
* An opening parenthesis character (like `'('`, `'['`, `'{'`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_PARENTHESIS_OPEN 0x03
|
||||
/**
|
||||
* A closing parenthesis character (like `')'`, `']'`, `'}'`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_PARENTHESIS_CLOSE 0x04
|
||||
/**
|
||||
* A prefix literal (like `"LOCK"`, `"REP"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_PREFIX 0x05
|
||||
/**
|
||||
* A mnemonic literal (like `"MOV"`, `"VCMPPSD"`, `"LCALL"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_MNEMONIC 0x06
|
||||
/**
|
||||
* A register literal (like `"RAX"`, `"DS"`, `"%ECX"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_REGISTER 0x07
|
||||
/**
|
||||
* An absolute address literal (like `0x00400000`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_ADDRESS_ABS 0x08
|
||||
/**
|
||||
* A relative address literal (like `-0x100`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_ADDRESS_REL 0x09
|
||||
/**
|
||||
* A displacement literal (like `0xFFFFFFFF`, `-0x100`, `+0x1234`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_DISPLACEMENT 0x0A
|
||||
/**
|
||||
* An immediate literal (like `0xC0`, `-0x1234`, `$0x0000`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_IMMEDIATE 0x0B
|
||||
/**
|
||||
* A typecast literal (like `DWORD PTR`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_TYPECAST 0x0C
|
||||
/**
|
||||
* A decorator literal (like `"Z"`, `"1TO4"`).
|
||||
*/
|
||||
#define ZYDIS_TOKEN_DECORATOR 0x0D
|
||||
/**
|
||||
* A symbol literal.
|
||||
*/
|
||||
#define ZYDIS_TOKEN_SYMBOL 0x0E
|
||||
|
||||
/**
|
||||
* The base for user-defined token types.
|
||||
*/
|
||||
#define ZYDIS_TOKEN_USER 0x80
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Token */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFormatterToken` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||
* behavior.
|
||||
*/
|
||||
typedef struct ZydisFormatterToken_
|
||||
{
|
||||
/**
|
||||
* The token type.
|
||||
*/
|
||||
ZydisTokenType type;
|
||||
/**
|
||||
* An offset to the next token, or `0`.
|
||||
*/
|
||||
ZyanU8 next;
|
||||
} ZydisFormatterToken;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFormatterTokenConst` data-type.
|
||||
*/
|
||||
typedef const ZydisFormatterToken ZydisFormatterTokenConst;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Buffer */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisFormatterBuffer` struct.
|
||||
*
|
||||
* All fields in this struct should be considered as "private". Any changes may
|
||||
* lead to unexpected behavior.
|
||||
*/
|
||||
typedef struct ZydisFormatterBuffer_
|
||||
{
|
||||
/**
|
||||
* `ZYAN_TRUE`, if the buffer contains a token stream or `ZYAN_FALSE, if it
|
||||
* contains a simple string.
|
||||
*/
|
||||
ZyanBool is_token_list;
|
||||
/**
|
||||
* The remaining capacity of the buffer.
|
||||
*/
|
||||
ZyanUSize capacity;
|
||||
/**
|
||||
* The `ZyanString` instance that refers to the literal value of the most
|
||||
* recently added token.
|
||||
*/
|
||||
ZyanString string;
|
||||
} ZydisFormatterBuffer;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Token */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the `type` and the string `value` of the given `token`.
|
||||
*
|
||||
* @param token A pointer to the `ZydisFormatterToken` struct.
|
||||
* @param type Receives the token type.
|
||||
* @param value Receives a pointer to the string value of the token.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token,
|
||||
ZydisTokenType* type, ZyanConstCharPointer* value);
|
||||
|
||||
/**
|
||||
* Obtains the next `token` linked to the passed one.
|
||||
*
|
||||
* @param token Receives a pointer to the next `ZydisFormatterToken` struct
|
||||
* linked to the passed one.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Buffer */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Returns the current (most recently added) token.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param token Receives a pointer to the current token.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least
|
||||
* one token.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer,
|
||||
ZydisFormatterTokenConst** token);
|
||||
|
||||
/**
|
||||
* Returns the `ZyanString` instance associated with the given buffer.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param string Receives a pointer to the `ZyanString` instance associated with the given
|
||||
* buffer.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least
|
||||
* one token.
|
||||
*
|
||||
* The returned string always refers to the literal value of the current (most recently added)
|
||||
* token and will remain valid until the buffer is destroyed.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer,
|
||||
ZyanString** string);
|
||||
|
||||
/**
|
||||
* Appends a new token to the `buffer`.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param type The type of the new token.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will
|
||||
* automatically be updated by calling this function.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer,
|
||||
ZydisTokenType type);
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the buffer-state.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param state Receives a snapshot of the buffer-state.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon
|
||||
* as the buffer gets overwritten or destroyed.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer,
|
||||
ZyanUPointer* state);
|
||||
|
||||
/**
|
||||
* Restores a previously saved buffer-state.
|
||||
*
|
||||
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||
* @param state The buffer-state to restore.
|
||||
*
|
||||
* @return A zyan status code.
|
||||
*
|
||||
* All tokens added after obtaining the given `state` snapshot will be removed. This function
|
||||
* does NOT restore any string content.
|
||||
*
|
||||
* Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will
|
||||
* automatically be updated by calling this function.
|
||||
*/
|
||||
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer,
|
||||
ZyanUPointer state);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_FORMATTER_TOKEN_H */
|
@ -1,98 +0,0 @@
|
||||
/**
|
||||
* Defines the `ZydisISAExt` enum.
|
||||
*/
|
||||
typedef enum ZydisISAExt_
|
||||
{
|
||||
ZYDIS_ISA_EXT_INVALID,
|
||||
ZYDIS_ISA_EXT_ADOX_ADCX,
|
||||
ZYDIS_ISA_EXT_AES,
|
||||
ZYDIS_ISA_EXT_AMD3DNOW,
|
||||
ZYDIS_ISA_EXT_AMD3DNOW_PREFETCH,
|
||||
ZYDIS_ISA_EXT_AMD_INVLPGB,
|
||||
ZYDIS_ISA_EXT_AMX_BF16,
|
||||
ZYDIS_ISA_EXT_AMX_INT8,
|
||||
ZYDIS_ISA_EXT_AMX_TILE,
|
||||
ZYDIS_ISA_EXT_AVX,
|
||||
ZYDIS_ISA_EXT_AVX2,
|
||||
ZYDIS_ISA_EXT_AVX2GATHER,
|
||||
ZYDIS_ISA_EXT_AVX512EVEX,
|
||||
ZYDIS_ISA_EXT_AVX512VEX,
|
||||
ZYDIS_ISA_EXT_AVXAES,
|
||||
ZYDIS_ISA_EXT_BASE,
|
||||
ZYDIS_ISA_EXT_BMI1,
|
||||
ZYDIS_ISA_EXT_BMI2,
|
||||
ZYDIS_ISA_EXT_CET,
|
||||
ZYDIS_ISA_EXT_CLDEMOTE,
|
||||
ZYDIS_ISA_EXT_CLFLUSHOPT,
|
||||
ZYDIS_ISA_EXT_CLFSH,
|
||||
ZYDIS_ISA_EXT_CLWB,
|
||||
ZYDIS_ISA_EXT_CLZERO,
|
||||
ZYDIS_ISA_EXT_ENQCMD,
|
||||
ZYDIS_ISA_EXT_F16C,
|
||||
ZYDIS_ISA_EXT_FMA,
|
||||
ZYDIS_ISA_EXT_FMA4,
|
||||
ZYDIS_ISA_EXT_GFNI,
|
||||
ZYDIS_ISA_EXT_INVPCID,
|
||||
ZYDIS_ISA_EXT_KNC,
|
||||
ZYDIS_ISA_EXT_KNCE,
|
||||
ZYDIS_ISA_EXT_KNCV,
|
||||
ZYDIS_ISA_EXT_LONGMODE,
|
||||
ZYDIS_ISA_EXT_LZCNT,
|
||||
ZYDIS_ISA_EXT_MCOMMIT,
|
||||
ZYDIS_ISA_EXT_MMX,
|
||||
ZYDIS_ISA_EXT_MONITOR,
|
||||
ZYDIS_ISA_EXT_MONITORX,
|
||||
ZYDIS_ISA_EXT_MOVBE,
|
||||
ZYDIS_ISA_EXT_MOVDIR,
|
||||
ZYDIS_ISA_EXT_MPX,
|
||||
ZYDIS_ISA_EXT_PADLOCK,
|
||||
ZYDIS_ISA_EXT_PAUSE,
|
||||
ZYDIS_ISA_EXT_PCLMULQDQ,
|
||||
ZYDIS_ISA_EXT_PCONFIG,
|
||||
ZYDIS_ISA_EXT_PKU,
|
||||
ZYDIS_ISA_EXT_PREFETCHWT1,
|
||||
ZYDIS_ISA_EXT_PT,
|
||||
ZYDIS_ISA_EXT_RDPID,
|
||||
ZYDIS_ISA_EXT_RDPRU,
|
||||
ZYDIS_ISA_EXT_RDRAND,
|
||||
ZYDIS_ISA_EXT_RDSEED,
|
||||
ZYDIS_ISA_EXT_RDTSCP,
|
||||
ZYDIS_ISA_EXT_RDWRFSGS,
|
||||
ZYDIS_ISA_EXT_RTM,
|
||||
ZYDIS_ISA_EXT_SERIALIZE,
|
||||
ZYDIS_ISA_EXT_SGX,
|
||||
ZYDIS_ISA_EXT_SGX_ENCLV,
|
||||
ZYDIS_ISA_EXT_SHA,
|
||||
ZYDIS_ISA_EXT_SMAP,
|
||||
ZYDIS_ISA_EXT_SMX,
|
||||
ZYDIS_ISA_EXT_SNP,
|
||||
ZYDIS_ISA_EXT_SSE,
|
||||
ZYDIS_ISA_EXT_SSE2,
|
||||
ZYDIS_ISA_EXT_SSE3,
|
||||
ZYDIS_ISA_EXT_SSE4,
|
||||
ZYDIS_ISA_EXT_SSE4A,
|
||||
ZYDIS_ISA_EXT_SSSE3,
|
||||
ZYDIS_ISA_EXT_SVM,
|
||||
ZYDIS_ISA_EXT_TBM,
|
||||
ZYDIS_ISA_EXT_TSX_LDTRK,
|
||||
ZYDIS_ISA_EXT_VAES,
|
||||
ZYDIS_ISA_EXT_VMFUNC,
|
||||
ZYDIS_ISA_EXT_VPCLMULQDQ,
|
||||
ZYDIS_ISA_EXT_VTX,
|
||||
ZYDIS_ISA_EXT_WAITPKG,
|
||||
ZYDIS_ISA_EXT_X87,
|
||||
ZYDIS_ISA_EXT_XOP,
|
||||
ZYDIS_ISA_EXT_XSAVE,
|
||||
ZYDIS_ISA_EXT_XSAVEC,
|
||||
ZYDIS_ISA_EXT_XSAVEOPT,
|
||||
ZYDIS_ISA_EXT_XSAVES,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_EXT_MAX_VALUE = ZYDIS_ISA_EXT_XSAVES,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_EXT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_EXT_MAX_VALUE)
|
||||
} ZydisISAExt;
|
@ -1,184 +0,0 @@
|
||||
/**
|
||||
* Defines the `ZydisISASet` enum.
|
||||
*/
|
||||
typedef enum ZydisISASet_
|
||||
{
|
||||
ZYDIS_ISA_SET_INVALID,
|
||||
ZYDIS_ISA_SET_ADOX_ADCX,
|
||||
ZYDIS_ISA_SET_AES,
|
||||
ZYDIS_ISA_SET_AMD,
|
||||
ZYDIS_ISA_SET_AMD3DNOW,
|
||||
ZYDIS_ISA_SET_AMX_BF16,
|
||||
ZYDIS_ISA_SET_AMX_INT8,
|
||||
ZYDIS_ISA_SET_AMX_TILE,
|
||||
ZYDIS_ISA_SET_AVX,
|
||||
ZYDIS_ISA_SET_AVX2,
|
||||
ZYDIS_ISA_SET_AVX2GATHER,
|
||||
ZYDIS_ISA_SET_AVX512BW_128,
|
||||
ZYDIS_ISA_SET_AVX512BW_128N,
|
||||
ZYDIS_ISA_SET_AVX512BW_256,
|
||||
ZYDIS_ISA_SET_AVX512BW_512,
|
||||
ZYDIS_ISA_SET_AVX512BW_KOP,
|
||||
ZYDIS_ISA_SET_AVX512CD_128,
|
||||
ZYDIS_ISA_SET_AVX512CD_256,
|
||||
ZYDIS_ISA_SET_AVX512CD_512,
|
||||
ZYDIS_ISA_SET_AVX512DQ_128,
|
||||
ZYDIS_ISA_SET_AVX512DQ_128N,
|
||||
ZYDIS_ISA_SET_AVX512DQ_256,
|
||||
ZYDIS_ISA_SET_AVX512DQ_512,
|
||||
ZYDIS_ISA_SET_AVX512DQ_KOP,
|
||||
ZYDIS_ISA_SET_AVX512DQ_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512ER_512,
|
||||
ZYDIS_ISA_SET_AVX512ER_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512F_128,
|
||||
ZYDIS_ISA_SET_AVX512F_128N,
|
||||
ZYDIS_ISA_SET_AVX512F_256,
|
||||
ZYDIS_ISA_SET_AVX512F_512,
|
||||
ZYDIS_ISA_SET_AVX512F_KOP,
|
||||
ZYDIS_ISA_SET_AVX512F_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512PF_512,
|
||||
ZYDIS_ISA_SET_AVX512_4FMAPS_512,
|
||||
ZYDIS_ISA_SET_AVX512_4FMAPS_SCALAR,
|
||||
ZYDIS_ISA_SET_AVX512_4VNNIW_512,
|
||||
ZYDIS_ISA_SET_AVX512_BF16_128,
|
||||
ZYDIS_ISA_SET_AVX512_BF16_256,
|
||||
ZYDIS_ISA_SET_AVX512_BF16_512,
|
||||
ZYDIS_ISA_SET_AVX512_BITALG_128,
|
||||
ZYDIS_ISA_SET_AVX512_BITALG_256,
|
||||
ZYDIS_ISA_SET_AVX512_BITALG_512,
|
||||
ZYDIS_ISA_SET_AVX512_GFNI_128,
|
||||
ZYDIS_ISA_SET_AVX512_GFNI_256,
|
||||
ZYDIS_ISA_SET_AVX512_GFNI_512,
|
||||
ZYDIS_ISA_SET_AVX512_IFMA_128,
|
||||
ZYDIS_ISA_SET_AVX512_IFMA_256,
|
||||
ZYDIS_ISA_SET_AVX512_IFMA_512,
|
||||
ZYDIS_ISA_SET_AVX512_VAES_128,
|
||||
ZYDIS_ISA_SET_AVX512_VAES_256,
|
||||
ZYDIS_ISA_SET_AVX512_VAES_512,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI2_128,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI2_256,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI2_512,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI_128,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI_256,
|
||||
ZYDIS_ISA_SET_AVX512_VBMI_512,
|
||||
ZYDIS_ISA_SET_AVX512_VNNI_128,
|
||||
ZYDIS_ISA_SET_AVX512_VNNI_256,
|
||||
ZYDIS_ISA_SET_AVX512_VNNI_512,
|
||||
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_128,
|
||||
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_256,
|
||||
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_512,
|
||||
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_128,
|
||||
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_256,
|
||||
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_512,
|
||||
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_128,
|
||||
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_256,
|
||||
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_512,
|
||||
ZYDIS_ISA_SET_AVXAES,
|
||||
ZYDIS_ISA_SET_AVX_GFNI,
|
||||
ZYDIS_ISA_SET_BMI1,
|
||||
ZYDIS_ISA_SET_BMI2,
|
||||
ZYDIS_ISA_SET_CET,
|
||||
ZYDIS_ISA_SET_CLDEMOTE,
|
||||
ZYDIS_ISA_SET_CLFLUSHOPT,
|
||||
ZYDIS_ISA_SET_CLFSH,
|
||||
ZYDIS_ISA_SET_CLWB,
|
||||
ZYDIS_ISA_SET_CLZERO,
|
||||
ZYDIS_ISA_SET_CMOV,
|
||||
ZYDIS_ISA_SET_CMPXCHG16B,
|
||||
ZYDIS_ISA_SET_ENQCMD,
|
||||
ZYDIS_ISA_SET_F16C,
|
||||
ZYDIS_ISA_SET_FAT_NOP,
|
||||
ZYDIS_ISA_SET_FCMOV,
|
||||
ZYDIS_ISA_SET_FMA,
|
||||
ZYDIS_ISA_SET_FMA4,
|
||||
ZYDIS_ISA_SET_FXSAVE,
|
||||
ZYDIS_ISA_SET_FXSAVE64,
|
||||
ZYDIS_ISA_SET_GFNI,
|
||||
ZYDIS_ISA_SET_I186,
|
||||
ZYDIS_ISA_SET_I286PROTECTED,
|
||||
ZYDIS_ISA_SET_I286REAL,
|
||||
ZYDIS_ISA_SET_I386,
|
||||
ZYDIS_ISA_SET_I486,
|
||||
ZYDIS_ISA_SET_I486REAL,
|
||||
ZYDIS_ISA_SET_I86,
|
||||
ZYDIS_ISA_SET_INVPCID,
|
||||
ZYDIS_ISA_SET_KNCE,
|
||||
ZYDIS_ISA_SET_KNCJKBR,
|
||||
ZYDIS_ISA_SET_KNCSTREAM,
|
||||
ZYDIS_ISA_SET_KNCV,
|
||||
ZYDIS_ISA_SET_KNC_MISC,
|
||||
ZYDIS_ISA_SET_KNC_PF_HINT,
|
||||
ZYDIS_ISA_SET_LAHF,
|
||||
ZYDIS_ISA_SET_LONGMODE,
|
||||
ZYDIS_ISA_SET_LZCNT,
|
||||
ZYDIS_ISA_SET_MCOMMIT,
|
||||
ZYDIS_ISA_SET_MONITOR,
|
||||
ZYDIS_ISA_SET_MONITORX,
|
||||
ZYDIS_ISA_SET_MOVBE,
|
||||
ZYDIS_ISA_SET_MOVDIR,
|
||||
ZYDIS_ISA_SET_MPX,
|
||||
ZYDIS_ISA_SET_PADLOCK_ACE,
|
||||
ZYDIS_ISA_SET_PADLOCK_PHE,
|
||||
ZYDIS_ISA_SET_PADLOCK_PMM,
|
||||
ZYDIS_ISA_SET_PADLOCK_RNG,
|
||||
ZYDIS_ISA_SET_PAUSE,
|
||||
ZYDIS_ISA_SET_PCLMULQDQ,
|
||||
ZYDIS_ISA_SET_PCONFIG,
|
||||
ZYDIS_ISA_SET_PENTIUMMMX,
|
||||
ZYDIS_ISA_SET_PENTIUMREAL,
|
||||
ZYDIS_ISA_SET_PKU,
|
||||
ZYDIS_ISA_SET_POPCNT,
|
||||
ZYDIS_ISA_SET_PPRO,
|
||||
ZYDIS_ISA_SET_PREFETCHWT1,
|
||||
ZYDIS_ISA_SET_PREFETCH_NOP,
|
||||
ZYDIS_ISA_SET_PT,
|
||||
ZYDIS_ISA_SET_RDPID,
|
||||
ZYDIS_ISA_SET_RDPMC,
|
||||
ZYDIS_ISA_SET_RDPRU,
|
||||
ZYDIS_ISA_SET_RDRAND,
|
||||
ZYDIS_ISA_SET_RDSEED,
|
||||
ZYDIS_ISA_SET_RDTSCP,
|
||||
ZYDIS_ISA_SET_RDWRFSGS,
|
||||
ZYDIS_ISA_SET_RTM,
|
||||
ZYDIS_ISA_SET_SERIALIZE,
|
||||
ZYDIS_ISA_SET_SGX,
|
||||
ZYDIS_ISA_SET_SGX_ENCLV,
|
||||
ZYDIS_ISA_SET_SHA,
|
||||
ZYDIS_ISA_SET_SMAP,
|
||||
ZYDIS_ISA_SET_SMX,
|
||||
ZYDIS_ISA_SET_SSE,
|
||||
ZYDIS_ISA_SET_SSE2,
|
||||
ZYDIS_ISA_SET_SSE2MMX,
|
||||
ZYDIS_ISA_SET_SSE3,
|
||||
ZYDIS_ISA_SET_SSE3X87,
|
||||
ZYDIS_ISA_SET_SSE4,
|
||||
ZYDIS_ISA_SET_SSE42,
|
||||
ZYDIS_ISA_SET_SSE4A,
|
||||
ZYDIS_ISA_SET_SSEMXCSR,
|
||||
ZYDIS_ISA_SET_SSE_PREFETCH,
|
||||
ZYDIS_ISA_SET_SSSE3,
|
||||
ZYDIS_ISA_SET_SSSE3MMX,
|
||||
ZYDIS_ISA_SET_SVM,
|
||||
ZYDIS_ISA_SET_TBM,
|
||||
ZYDIS_ISA_SET_TSX_LDTRK,
|
||||
ZYDIS_ISA_SET_VAES,
|
||||
ZYDIS_ISA_SET_VMFUNC,
|
||||
ZYDIS_ISA_SET_VPCLMULQDQ,
|
||||
ZYDIS_ISA_SET_VTX,
|
||||
ZYDIS_ISA_SET_WAITPKG,
|
||||
ZYDIS_ISA_SET_X87,
|
||||
ZYDIS_ISA_SET_XOP,
|
||||
ZYDIS_ISA_SET_XSAVE,
|
||||
ZYDIS_ISA_SET_XSAVEC,
|
||||
ZYDIS_ISA_SET_XSAVEOPT,
|
||||
ZYDIS_ISA_SET_XSAVES,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_SET_MAX_VALUE = ZYDIS_ISA_SET_XSAVES,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_ISA_SET_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_SET_MAX_VALUE)
|
||||
} ZydisISASet;
|
@ -1,117 +0,0 @@
|
||||
/**
|
||||
* Defines the `ZydisInstructionCategory` enum.
|
||||
*/
|
||||
typedef enum ZydisInstructionCategory_
|
||||
{
|
||||
ZYDIS_CATEGORY_INVALID,
|
||||
ZYDIS_CATEGORY_ADOX_ADCX,
|
||||
ZYDIS_CATEGORY_AES,
|
||||
ZYDIS_CATEGORY_AMD3DNOW,
|
||||
ZYDIS_CATEGORY_AMX_TILE,
|
||||
ZYDIS_CATEGORY_AVX,
|
||||
ZYDIS_CATEGORY_AVX2,
|
||||
ZYDIS_CATEGORY_AVX2GATHER,
|
||||
ZYDIS_CATEGORY_AVX512,
|
||||
ZYDIS_CATEGORY_AVX512_4FMAPS,
|
||||
ZYDIS_CATEGORY_AVX512_4VNNIW,
|
||||
ZYDIS_CATEGORY_AVX512_BITALG,
|
||||
ZYDIS_CATEGORY_AVX512_VBMI,
|
||||
ZYDIS_CATEGORY_AVX512_VP2INTERSECT,
|
||||
ZYDIS_CATEGORY_BINARY,
|
||||
ZYDIS_CATEGORY_BITBYTE,
|
||||
ZYDIS_CATEGORY_BLEND,
|
||||
ZYDIS_CATEGORY_BMI1,
|
||||
ZYDIS_CATEGORY_BMI2,
|
||||
ZYDIS_CATEGORY_BROADCAST,
|
||||
ZYDIS_CATEGORY_CALL,
|
||||
ZYDIS_CATEGORY_CET,
|
||||
ZYDIS_CATEGORY_CLDEMOTE,
|
||||
ZYDIS_CATEGORY_CLFLUSHOPT,
|
||||
ZYDIS_CATEGORY_CLWB,
|
||||
ZYDIS_CATEGORY_CLZERO,
|
||||
ZYDIS_CATEGORY_CMOV,
|
||||
ZYDIS_CATEGORY_COMPRESS,
|
||||
ZYDIS_CATEGORY_COND_BR,
|
||||
ZYDIS_CATEGORY_CONFLICT,
|
||||
ZYDIS_CATEGORY_CONVERT,
|
||||
ZYDIS_CATEGORY_DATAXFER,
|
||||
ZYDIS_CATEGORY_DECIMAL,
|
||||
ZYDIS_CATEGORY_ENQCMD,
|
||||
ZYDIS_CATEGORY_EXPAND,
|
||||
ZYDIS_CATEGORY_FCMOV,
|
||||
ZYDIS_CATEGORY_FLAGOP,
|
||||
ZYDIS_CATEGORY_FMA4,
|
||||
ZYDIS_CATEGORY_GATHER,
|
||||
ZYDIS_CATEGORY_GFNI,
|
||||
ZYDIS_CATEGORY_IFMA,
|
||||
ZYDIS_CATEGORY_INTERRUPT,
|
||||
ZYDIS_CATEGORY_IO,
|
||||
ZYDIS_CATEGORY_IOSTRINGOP,
|
||||
ZYDIS_CATEGORY_KMASK,
|
||||
ZYDIS_CATEGORY_KNC,
|
||||
ZYDIS_CATEGORY_KNCMASK,
|
||||
ZYDIS_CATEGORY_KNCSCALAR,
|
||||
ZYDIS_CATEGORY_LOGICAL,
|
||||
ZYDIS_CATEGORY_LOGICAL_FP,
|
||||
ZYDIS_CATEGORY_LZCNT,
|
||||
ZYDIS_CATEGORY_MISC,
|
||||
ZYDIS_CATEGORY_MMX,
|
||||
ZYDIS_CATEGORY_MOVDIR,
|
||||
ZYDIS_CATEGORY_MPX,
|
||||
ZYDIS_CATEGORY_NOP,
|
||||
ZYDIS_CATEGORY_PADLOCK,
|
||||
ZYDIS_CATEGORY_PCLMULQDQ,
|
||||
ZYDIS_CATEGORY_PCONFIG,
|
||||
ZYDIS_CATEGORY_PKU,
|
||||
ZYDIS_CATEGORY_POP,
|
||||
ZYDIS_CATEGORY_PREFETCH,
|
||||
ZYDIS_CATEGORY_PREFETCHWT1,
|
||||
ZYDIS_CATEGORY_PT,
|
||||
ZYDIS_CATEGORY_PUSH,
|
||||
ZYDIS_CATEGORY_RDPID,
|
||||
ZYDIS_CATEGORY_RDPRU,
|
||||
ZYDIS_CATEGORY_RDRAND,
|
||||
ZYDIS_CATEGORY_RDSEED,
|
||||
ZYDIS_CATEGORY_RDWRFSGS,
|
||||
ZYDIS_CATEGORY_RET,
|
||||
ZYDIS_CATEGORY_ROTATE,
|
||||
ZYDIS_CATEGORY_SCATTER,
|
||||
ZYDIS_CATEGORY_SEGOP,
|
||||
ZYDIS_CATEGORY_SEMAPHORE,
|
||||
ZYDIS_CATEGORY_SERIALIZE,
|
||||
ZYDIS_CATEGORY_SETCC,
|
||||
ZYDIS_CATEGORY_SGX,
|
||||
ZYDIS_CATEGORY_SHA,
|
||||
ZYDIS_CATEGORY_SHIFT,
|
||||
ZYDIS_CATEGORY_SMAP,
|
||||
ZYDIS_CATEGORY_SSE,
|
||||
ZYDIS_CATEGORY_STRINGOP,
|
||||
ZYDIS_CATEGORY_STTNI,
|
||||
ZYDIS_CATEGORY_SYSCALL,
|
||||
ZYDIS_CATEGORY_SYSRET,
|
||||
ZYDIS_CATEGORY_SYSTEM,
|
||||
ZYDIS_CATEGORY_TBM,
|
||||
ZYDIS_CATEGORY_TSX_LDTRK,
|
||||
ZYDIS_CATEGORY_UFMA,
|
||||
ZYDIS_CATEGORY_UNCOND_BR,
|
||||
ZYDIS_CATEGORY_VAES,
|
||||
ZYDIS_CATEGORY_VBMI2,
|
||||
ZYDIS_CATEGORY_VFMA,
|
||||
ZYDIS_CATEGORY_VPCLMULQDQ,
|
||||
ZYDIS_CATEGORY_VTX,
|
||||
ZYDIS_CATEGORY_WAITPKG,
|
||||
ZYDIS_CATEGORY_WIDENOP,
|
||||
ZYDIS_CATEGORY_X87_ALU,
|
||||
ZYDIS_CATEGORY_XOP,
|
||||
ZYDIS_CATEGORY_XSAVE,
|
||||
ZYDIS_CATEGORY_XSAVEOPT,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_CATEGORY_MAX_VALUE = ZYDIS_CATEGORY_XSAVEOPT,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_CATEGORY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CATEGORY_MAX_VALUE)
|
||||
} ZydisInstructionCategory;
|
File diff suppressed because it is too large
Load Diff
@ -1,301 +0,0 @@
|
||||
/**
|
||||
* Defines the `ZydisRegister` enum.
|
||||
*/
|
||||
typedef enum ZydisRegister_
|
||||
{
|
||||
ZYDIS_REGISTER_NONE,
|
||||
|
||||
// General purpose registers 8-bit
|
||||
ZYDIS_REGISTER_AL,
|
||||
ZYDIS_REGISTER_CL,
|
||||
ZYDIS_REGISTER_DL,
|
||||
ZYDIS_REGISTER_BL,
|
||||
ZYDIS_REGISTER_AH,
|
||||
ZYDIS_REGISTER_CH,
|
||||
ZYDIS_REGISTER_DH,
|
||||
ZYDIS_REGISTER_BH,
|
||||
ZYDIS_REGISTER_SPL,
|
||||
ZYDIS_REGISTER_BPL,
|
||||
ZYDIS_REGISTER_SIL,
|
||||
ZYDIS_REGISTER_DIL,
|
||||
ZYDIS_REGISTER_R8B,
|
||||
ZYDIS_REGISTER_R9B,
|
||||
ZYDIS_REGISTER_R10B,
|
||||
ZYDIS_REGISTER_R11B,
|
||||
ZYDIS_REGISTER_R12B,
|
||||
ZYDIS_REGISTER_R13B,
|
||||
ZYDIS_REGISTER_R14B,
|
||||
ZYDIS_REGISTER_R15B,
|
||||
// General purpose registers 16-bit
|
||||
ZYDIS_REGISTER_AX,
|
||||
ZYDIS_REGISTER_CX,
|
||||
ZYDIS_REGISTER_DX,
|
||||
ZYDIS_REGISTER_BX,
|
||||
ZYDIS_REGISTER_SP,
|
||||
ZYDIS_REGISTER_BP,
|
||||
ZYDIS_REGISTER_SI,
|
||||
ZYDIS_REGISTER_DI,
|
||||
ZYDIS_REGISTER_R8W,
|
||||
ZYDIS_REGISTER_R9W,
|
||||
ZYDIS_REGISTER_R10W,
|
||||
ZYDIS_REGISTER_R11W,
|
||||
ZYDIS_REGISTER_R12W,
|
||||
ZYDIS_REGISTER_R13W,
|
||||
ZYDIS_REGISTER_R14W,
|
||||
ZYDIS_REGISTER_R15W,
|
||||
// General purpose registers 32-bit
|
||||
ZYDIS_REGISTER_EAX,
|
||||
ZYDIS_REGISTER_ECX,
|
||||
ZYDIS_REGISTER_EDX,
|
||||
ZYDIS_REGISTER_EBX,
|
||||
ZYDIS_REGISTER_ESP,
|
||||
ZYDIS_REGISTER_EBP,
|
||||
ZYDIS_REGISTER_ESI,
|
||||
ZYDIS_REGISTER_EDI,
|
||||
ZYDIS_REGISTER_R8D,
|
||||
ZYDIS_REGISTER_R9D,
|
||||
ZYDIS_REGISTER_R10D,
|
||||
ZYDIS_REGISTER_R11D,
|
||||
ZYDIS_REGISTER_R12D,
|
||||
ZYDIS_REGISTER_R13D,
|
||||
ZYDIS_REGISTER_R14D,
|
||||
ZYDIS_REGISTER_R15D,
|
||||
// General purpose registers 64-bit
|
||||
ZYDIS_REGISTER_RAX,
|
||||
ZYDIS_REGISTER_RCX,
|
||||
ZYDIS_REGISTER_RDX,
|
||||
ZYDIS_REGISTER_RBX,
|
||||
ZYDIS_REGISTER_RSP,
|
||||
ZYDIS_REGISTER_RBP,
|
||||
ZYDIS_REGISTER_RSI,
|
||||
ZYDIS_REGISTER_RDI,
|
||||
ZYDIS_REGISTER_R8,
|
||||
ZYDIS_REGISTER_R9,
|
||||
ZYDIS_REGISTER_R10,
|
||||
ZYDIS_REGISTER_R11,
|
||||
ZYDIS_REGISTER_R12,
|
||||
ZYDIS_REGISTER_R13,
|
||||
ZYDIS_REGISTER_R14,
|
||||
ZYDIS_REGISTER_R15,
|
||||
// Floating point legacy registers
|
||||
ZYDIS_REGISTER_ST0,
|
||||
ZYDIS_REGISTER_ST1,
|
||||
ZYDIS_REGISTER_ST2,
|
||||
ZYDIS_REGISTER_ST3,
|
||||
ZYDIS_REGISTER_ST4,
|
||||
ZYDIS_REGISTER_ST5,
|
||||
ZYDIS_REGISTER_ST6,
|
||||
ZYDIS_REGISTER_ST7,
|
||||
ZYDIS_REGISTER_X87CONTROL,
|
||||
ZYDIS_REGISTER_X87STATUS,
|
||||
ZYDIS_REGISTER_X87TAG,
|
||||
// Floating point multimedia registers
|
||||
ZYDIS_REGISTER_MM0,
|
||||
ZYDIS_REGISTER_MM1,
|
||||
ZYDIS_REGISTER_MM2,
|
||||
ZYDIS_REGISTER_MM3,
|
||||
ZYDIS_REGISTER_MM4,
|
||||
ZYDIS_REGISTER_MM5,
|
||||
ZYDIS_REGISTER_MM6,
|
||||
ZYDIS_REGISTER_MM7,
|
||||
// Floating point vector registers 128-bit
|
||||
ZYDIS_REGISTER_XMM0,
|
||||
ZYDIS_REGISTER_XMM1,
|
||||
ZYDIS_REGISTER_XMM2,
|
||||
ZYDIS_REGISTER_XMM3,
|
||||
ZYDIS_REGISTER_XMM4,
|
||||
ZYDIS_REGISTER_XMM5,
|
||||
ZYDIS_REGISTER_XMM6,
|
||||
ZYDIS_REGISTER_XMM7,
|
||||
ZYDIS_REGISTER_XMM8,
|
||||
ZYDIS_REGISTER_XMM9,
|
||||
ZYDIS_REGISTER_XMM10,
|
||||
ZYDIS_REGISTER_XMM11,
|
||||
ZYDIS_REGISTER_XMM12,
|
||||
ZYDIS_REGISTER_XMM13,
|
||||
ZYDIS_REGISTER_XMM14,
|
||||
ZYDIS_REGISTER_XMM15,
|
||||
ZYDIS_REGISTER_XMM16,
|
||||
ZYDIS_REGISTER_XMM17,
|
||||
ZYDIS_REGISTER_XMM18,
|
||||
ZYDIS_REGISTER_XMM19,
|
||||
ZYDIS_REGISTER_XMM20,
|
||||
ZYDIS_REGISTER_XMM21,
|
||||
ZYDIS_REGISTER_XMM22,
|
||||
ZYDIS_REGISTER_XMM23,
|
||||
ZYDIS_REGISTER_XMM24,
|
||||
ZYDIS_REGISTER_XMM25,
|
||||
ZYDIS_REGISTER_XMM26,
|
||||
ZYDIS_REGISTER_XMM27,
|
||||
ZYDIS_REGISTER_XMM28,
|
||||
ZYDIS_REGISTER_XMM29,
|
||||
ZYDIS_REGISTER_XMM30,
|
||||
ZYDIS_REGISTER_XMM31,
|
||||
// Floating point vector registers 256-bit
|
||||
ZYDIS_REGISTER_YMM0,
|
||||
ZYDIS_REGISTER_YMM1,
|
||||
ZYDIS_REGISTER_YMM2,
|
||||
ZYDIS_REGISTER_YMM3,
|
||||
ZYDIS_REGISTER_YMM4,
|
||||
ZYDIS_REGISTER_YMM5,
|
||||
ZYDIS_REGISTER_YMM6,
|
||||
ZYDIS_REGISTER_YMM7,
|
||||
ZYDIS_REGISTER_YMM8,
|
||||
ZYDIS_REGISTER_YMM9,
|
||||
ZYDIS_REGISTER_YMM10,
|
||||
ZYDIS_REGISTER_YMM11,
|
||||
ZYDIS_REGISTER_YMM12,
|
||||
ZYDIS_REGISTER_YMM13,
|
||||
ZYDIS_REGISTER_YMM14,
|
||||
ZYDIS_REGISTER_YMM15,
|
||||
ZYDIS_REGISTER_YMM16,
|
||||
ZYDIS_REGISTER_YMM17,
|
||||
ZYDIS_REGISTER_YMM18,
|
||||
ZYDIS_REGISTER_YMM19,
|
||||
ZYDIS_REGISTER_YMM20,
|
||||
ZYDIS_REGISTER_YMM21,
|
||||
ZYDIS_REGISTER_YMM22,
|
||||
ZYDIS_REGISTER_YMM23,
|
||||
ZYDIS_REGISTER_YMM24,
|
||||
ZYDIS_REGISTER_YMM25,
|
||||
ZYDIS_REGISTER_YMM26,
|
||||
ZYDIS_REGISTER_YMM27,
|
||||
ZYDIS_REGISTER_YMM28,
|
||||
ZYDIS_REGISTER_YMM29,
|
||||
ZYDIS_REGISTER_YMM30,
|
||||
ZYDIS_REGISTER_YMM31,
|
||||
// Floating point vector registers 512-bit
|
||||
ZYDIS_REGISTER_ZMM0,
|
||||
ZYDIS_REGISTER_ZMM1,
|
||||
ZYDIS_REGISTER_ZMM2,
|
||||
ZYDIS_REGISTER_ZMM3,
|
||||
ZYDIS_REGISTER_ZMM4,
|
||||
ZYDIS_REGISTER_ZMM5,
|
||||
ZYDIS_REGISTER_ZMM6,
|
||||
ZYDIS_REGISTER_ZMM7,
|
||||
ZYDIS_REGISTER_ZMM8,
|
||||
ZYDIS_REGISTER_ZMM9,
|
||||
ZYDIS_REGISTER_ZMM10,
|
||||
ZYDIS_REGISTER_ZMM11,
|
||||
ZYDIS_REGISTER_ZMM12,
|
||||
ZYDIS_REGISTER_ZMM13,
|
||||
ZYDIS_REGISTER_ZMM14,
|
||||
ZYDIS_REGISTER_ZMM15,
|
||||
ZYDIS_REGISTER_ZMM16,
|
||||
ZYDIS_REGISTER_ZMM17,
|
||||
ZYDIS_REGISTER_ZMM18,
|
||||
ZYDIS_REGISTER_ZMM19,
|
||||
ZYDIS_REGISTER_ZMM20,
|
||||
ZYDIS_REGISTER_ZMM21,
|
||||
ZYDIS_REGISTER_ZMM22,
|
||||
ZYDIS_REGISTER_ZMM23,
|
||||
ZYDIS_REGISTER_ZMM24,
|
||||
ZYDIS_REGISTER_ZMM25,
|
||||
ZYDIS_REGISTER_ZMM26,
|
||||
ZYDIS_REGISTER_ZMM27,
|
||||
ZYDIS_REGISTER_ZMM28,
|
||||
ZYDIS_REGISTER_ZMM29,
|
||||
ZYDIS_REGISTER_ZMM30,
|
||||
ZYDIS_REGISTER_ZMM31,
|
||||
// Matrix registers
|
||||
ZYDIS_REGISTER_TMM0,
|
||||
ZYDIS_REGISTER_TMM1,
|
||||
ZYDIS_REGISTER_TMM2,
|
||||
ZYDIS_REGISTER_TMM3,
|
||||
ZYDIS_REGISTER_TMM4,
|
||||
ZYDIS_REGISTER_TMM5,
|
||||
ZYDIS_REGISTER_TMM6,
|
||||
ZYDIS_REGISTER_TMM7,
|
||||
// Flags registers
|
||||
ZYDIS_REGISTER_FLAGS,
|
||||
ZYDIS_REGISTER_EFLAGS,
|
||||
ZYDIS_REGISTER_RFLAGS,
|
||||
// Instruction-pointer registers
|
||||
ZYDIS_REGISTER_IP,
|
||||
ZYDIS_REGISTER_EIP,
|
||||
ZYDIS_REGISTER_RIP,
|
||||
// Segment registers
|
||||
ZYDIS_REGISTER_ES,
|
||||
ZYDIS_REGISTER_CS,
|
||||
ZYDIS_REGISTER_SS,
|
||||
ZYDIS_REGISTER_DS,
|
||||
ZYDIS_REGISTER_FS,
|
||||
ZYDIS_REGISTER_GS,
|
||||
// Table registers
|
||||
ZYDIS_REGISTER_GDTR,
|
||||
ZYDIS_REGISTER_LDTR,
|
||||
ZYDIS_REGISTER_IDTR,
|
||||
ZYDIS_REGISTER_TR,
|
||||
// Test registers
|
||||
ZYDIS_REGISTER_TR0,
|
||||
ZYDIS_REGISTER_TR1,
|
||||
ZYDIS_REGISTER_TR2,
|
||||
ZYDIS_REGISTER_TR3,
|
||||
ZYDIS_REGISTER_TR4,
|
||||
ZYDIS_REGISTER_TR5,
|
||||
ZYDIS_REGISTER_TR6,
|
||||
ZYDIS_REGISTER_TR7,
|
||||
// Control registers
|
||||
ZYDIS_REGISTER_CR0,
|
||||
ZYDIS_REGISTER_CR1,
|
||||
ZYDIS_REGISTER_CR2,
|
||||
ZYDIS_REGISTER_CR3,
|
||||
ZYDIS_REGISTER_CR4,
|
||||
ZYDIS_REGISTER_CR5,
|
||||
ZYDIS_REGISTER_CR6,
|
||||
ZYDIS_REGISTER_CR7,
|
||||
ZYDIS_REGISTER_CR8,
|
||||
ZYDIS_REGISTER_CR9,
|
||||
ZYDIS_REGISTER_CR10,
|
||||
ZYDIS_REGISTER_CR11,
|
||||
ZYDIS_REGISTER_CR12,
|
||||
ZYDIS_REGISTER_CR13,
|
||||
ZYDIS_REGISTER_CR14,
|
||||
ZYDIS_REGISTER_CR15,
|
||||
// Debug registers
|
||||
ZYDIS_REGISTER_DR0,
|
||||
ZYDIS_REGISTER_DR1,
|
||||
ZYDIS_REGISTER_DR2,
|
||||
ZYDIS_REGISTER_DR3,
|
||||
ZYDIS_REGISTER_DR4,
|
||||
ZYDIS_REGISTER_DR5,
|
||||
ZYDIS_REGISTER_DR6,
|
||||
ZYDIS_REGISTER_DR7,
|
||||
ZYDIS_REGISTER_DR8,
|
||||
ZYDIS_REGISTER_DR9,
|
||||
ZYDIS_REGISTER_DR10,
|
||||
ZYDIS_REGISTER_DR11,
|
||||
ZYDIS_REGISTER_DR12,
|
||||
ZYDIS_REGISTER_DR13,
|
||||
ZYDIS_REGISTER_DR14,
|
||||
ZYDIS_REGISTER_DR15,
|
||||
// Mask registers
|
||||
ZYDIS_REGISTER_K0,
|
||||
ZYDIS_REGISTER_K1,
|
||||
ZYDIS_REGISTER_K2,
|
||||
ZYDIS_REGISTER_K3,
|
||||
ZYDIS_REGISTER_K4,
|
||||
ZYDIS_REGISTER_K5,
|
||||
ZYDIS_REGISTER_K6,
|
||||
ZYDIS_REGISTER_K7,
|
||||
// Bound registers
|
||||
ZYDIS_REGISTER_BND0,
|
||||
ZYDIS_REGISTER_BND1,
|
||||
ZYDIS_REGISTER_BND2,
|
||||
ZYDIS_REGISTER_BND3,
|
||||
ZYDIS_REGISTER_BNDCFG,
|
||||
ZYDIS_REGISTER_BNDSTATUS,
|
||||
// Uncategorized
|
||||
ZYDIS_REGISTER_MXCSR,
|
||||
ZYDIS_REGISTER_PKRU,
|
||||
ZYDIS_REGISTER_XCR0,
|
||||
|
||||
/**
|
||||
* Maximum value of this enum.
|
||||
*/
|
||||
ZYDIS_REGISTER_MAX_VALUE = ZYDIS_REGISTER_XCR0,
|
||||
/**
|
||||
* The minimum number of bits required to represent all values of this enum.
|
||||
*/
|
||||
ZYDIS_REGISTER_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGISTER_MAX_VALUE)
|
||||
} ZydisRegister;
|
@ -1,331 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Library (Zydis)
|
||||
|
||||
Original Author : Florian Bernd
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#ifndef ZYDIS_INTERNAL_DECODERDATA_H
|
||||
#define ZYDIS_INTERNAL_DECODERDATA_H
|
||||
|
||||
#include <Zycore/Defines.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Enums and types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
// MSVC does not like types other than (un-)signed int for bit-fields
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4214)
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder tree */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderTreeNodeType` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisDecoderTreeNodeType;
|
||||
|
||||
/**
|
||||
* Values that represent zydis decoder tree node types.
|
||||
*/
|
||||
enum ZydisDecoderTreeNodeTypes
|
||||
{
|
||||
ZYDIS_NODETYPE_INVALID = 0x00,
|
||||
/**
|
||||
* Reference to an instruction-definition.
|
||||
*/
|
||||
ZYDIS_NODETYPE_DEFINITION_MASK = 0x80,
|
||||
/**
|
||||
* Reference to an XOP-map filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_XOP = 0x01,
|
||||
/**
|
||||
* Reference to an VEX-map filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_VEX = 0x02,
|
||||
/**
|
||||
* Reference to an EVEX/MVEX-map filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_EMVEX = 0x03,
|
||||
/**
|
||||
* Reference to an opcode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_OPCODE = 0x04,
|
||||
/**
|
||||
* Reference to an instruction-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE = 0x05,
|
||||
/**
|
||||
* Reference to an compacted instruction-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_COMPACT = 0x06,
|
||||
/**
|
||||
* Reference to a ModRM.mod filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_MOD = 0x07,
|
||||
/**
|
||||
* Reference to a compacted ModRM.mod filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT = 0x08,
|
||||
/**
|
||||
* Reference to a ModRM.reg filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_REG = 0x09,
|
||||
/**
|
||||
* Reference to a ModRM.rm filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODRM_RM = 0x0A,
|
||||
/**
|
||||
* Reference to a PrefixGroup1 filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1 = 0x0B,
|
||||
/**
|
||||
* Reference to a mandatory-prefix filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX = 0x0C,
|
||||
/**
|
||||
* Reference to an operand-size filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_OPERAND_SIZE = 0x0D,
|
||||
/**
|
||||
* Reference to an address-size filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE = 0x0E,
|
||||
/**
|
||||
* Reference to a vector-length filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH = 0x0F,
|
||||
/**
|
||||
* Reference to an REX/VEX/EVEX.W filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_REX_W = 0x10,
|
||||
/**
|
||||
* Reference to an REX/VEX/EVEX.B filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_REX_B = 0x11,
|
||||
/**
|
||||
* Reference to an EVEX.b filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_EVEX_B = 0x12,
|
||||
/**
|
||||
* Reference to an MVEX.E filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MVEX_E = 0x13,
|
||||
/**
|
||||
* Reference to a AMD-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_AMD = 0x14,
|
||||
/**
|
||||
* Reference to a KNC-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_KNC = 0x15,
|
||||
/**
|
||||
* Reference to a MPX-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_MPX = 0x16,
|
||||
/**
|
||||
* Reference to a CET-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_CET = 0x17,
|
||||
/**
|
||||
* Reference to a LZCNT-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_LZCNT = 0x18,
|
||||
/**
|
||||
* Reference to a TZCNT-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_TZCNT = 0x19,
|
||||
/**
|
||||
* Reference to a WBNOINVD-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD = 0x1A,
|
||||
/**
|
||||
* Reference to a CLDEMOTE-mode filter.
|
||||
*/
|
||||
ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE = 0x1B
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderTreeNodeValue` data-type.
|
||||
*/
|
||||
typedef ZyanU16 ZydisDecoderTreeNodeValue;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisDecoderTreeNode` struct.
|
||||
*/
|
||||
typedef struct ZydisDecoderTreeNode_
|
||||
{
|
||||
ZydisDecoderTreeNodeType type;
|
||||
ZydisDecoderTreeNodeValue value;
|
||||
} ZydisDecoderTreeNode;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef ZYAN_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Physical instruction encoding info */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionEncodingFlags` data-type.
|
||||
*/
|
||||
typedef ZyanU8 ZydisInstructionEncodingFlags;
|
||||
|
||||
/**
|
||||
* The instruction has an optional modrm byte.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_MODRM 0x01
|
||||
|
||||
/**
|
||||
* The instruction has an optional displacement value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_DISP 0x02
|
||||
|
||||
/**
|
||||
* The instruction has an optional immediate value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM0 0x04
|
||||
|
||||
/**
|
||||
* The instruction has a second optional immediate value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM1 0x08
|
||||
|
||||
/**
|
||||
* The instruction ignores the value of `modrm.mod` and always assumes `modrm.mod == 3`
|
||||
* ("reg, reg" - form).
|
||||
*
|
||||
* Instructions with this flag can't have a SIB byte or a displacement value.
|
||||
*/
|
||||
#define ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM 0x10
|
||||
|
||||
/**
|
||||
* Defines the `ZydisInstructionEncodingInfo` struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionEncodingInfo_
|
||||
{
|
||||
/**
|
||||
* Contains flags with information about the physical instruction-encoding.
|
||||
*/
|
||||
ZydisInstructionEncodingFlags flags;
|
||||
/**
|
||||
* Displacement info.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The size of the displacement value.
|
||||
*/
|
||||
ZyanU8 size[3];
|
||||
} disp;
|
||||
/**
|
||||
* Immediate info.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The size of the immediate value.
|
||||
*/
|
||||
ZyanU8 size[3];
|
||||
/**
|
||||
* Signals, if the value is signed.
|
||||
*/
|
||||
ZyanBool is_signed;
|
||||
/**
|
||||
* Signals, if the value is a relative offset.
|
||||
*/
|
||||
ZyanBool is_relative;
|
||||
} imm[2];
|
||||
} ZydisInstructionEncodingInfo;
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
/* Decoder tree */
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
extern const ZydisDecoderTreeNode zydis_decoder_tree_root;
|
||||
|
||||
/**
|
||||
* Returns the root node of the instruction tree.
|
||||
*
|
||||
* @return The root node of the instruction tree.
|
||||
*/
|
||||
ZYAN_INLINE const ZydisDecoderTreeNode* ZydisDecoderTreeGetRootNode(void)
|
||||
{
|
||||
return &zydis_decoder_tree_root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child node of `parent` specified by `index`.
|
||||
*
|
||||
* @param parent The parent node.
|
||||
* @param index The index of the child node to retrieve.
|
||||
*
|
||||
* @return The specified child node.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode(
|
||||
const ZydisDecoderTreeNode* parent, ZyanU16 index);
|
||||
|
||||
/**
|
||||
* Returns information about optional instruction parts (like modrm, displacement or
|
||||
* immediates) for the instruction that is linked to the given `node`.
|
||||
*
|
||||
* @param node The instruction definition node.
|
||||
* @param info A pointer to the `ZydisInstructionParts` struct.
|
||||
*/
|
||||
ZYDIS_NO_EXPORT void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node,
|
||||
const ZydisInstructionEncodingInfo** info);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZYDIS_INTERNAL_DECODERDATA_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue