v1.4, added LLVM-Obfuscator and all demos now use it..

2.0
_xeroxz 4 years ago
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,10 +1,14 @@
#pragma once
#include "Theodosius.h"
#include <Windows.h>
#include <stdio.h>
void UsermodeMutateDemo();
void UsermodeNoObfuscation();
class VirtualFuncDemo
{
public:
MutateRoutine
explicit VirtualFuncDemo();
virtual ~VirtualFuncDemo();
virtual void PrintTest();
@ -13,7 +17,6 @@ public:
class Demo : public VirtualFuncDemo
{
public:
MutateRoutine
explicit Demo();
~Demo() override;
void PrintTest() override;
@ -22,7 +25,6 @@ public:
class Demo2 : public VirtualFuncDemo
{
public:
MutateRoutine
explicit Demo2();
~Demo2() override;
void PrintTest() override;

@ -33,7 +33,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>ClangCL</PlatformToolset>
<PlatformToolset>llvm</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
@ -60,6 +60,14 @@
<IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<ExecutablePath>$(LLVMInstallDir)\bin;$(ExecutablePath);</ExecutablePath>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClangClExecutable>$(ProjectDir)..\..\clang-cl.exe</ClangClExecutable>
<UseClangCl>true</UseClangCl>
<ClangClAdditionalOptions>-Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 </ClangClAdditionalOptions>
<LldLinkExecutable>
</LldLinkExecutable>
<UseLldLink>false</UseLldLink>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -85,10 +93,12 @@
<FunctionLevelLinking>false</FunctionLevelLinking>
<LanguageStandard_C>Default</LanguageStandard_C>
<CompileAs>Default</CompileAs>
<AdditionalOptions>-Xclang -mcmodel=large -Xclang -fno-jump-tables /Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
<DiagnosticsFormat />
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
<EntryPointSymbol>main</EntryPointSymbol>
</Link>
<BuildLog>
<Path>$(IntDir)ignore\$(MSBuildProjectName).log</Path>

@ -2,11 +2,18 @@
#define WINUSERAPI
#define _KERNEL32_
#define _ACRTIMP
#include <Windows.h>
#include <stdio.h>
#define NTKERNELAPI
#define ObfuscateRoutine __declspec(code_seg(".theo"), noinline)
#define MutateRoutine __declspec(code_seg(".theo1"), noinline)
#define THEO_OBFUSCATE(...) \
_Pragma("code_seg(\".theo\")") \
__VA_ARGS__ \
_Pragma("code_seg()")
void UsermodeNoObfuscation();
void UsermodeMutateDemo();
#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"))))

@ -1,7 +1,7 @@
#include "ClassDemo.hpp"
ObfuscateRoutine
extern "C" int main()
// ignore this warning... its VS...
THEO_OBFUSCATE(extern "C" int main()
{
AllocConsole();
freopen("conin$", "r", stdin);
@ -10,7 +10,7 @@ extern "C" int main()
printf("hello world\n");
getchar();
MessageBoxA(0, "Demo", "Hello From Obfuscated Routine!", 0);
MessageBoxA(0, "Demo", "Hello From main!", 0);
UsermodeMutateDemo();
UsermodeNoObfuscation();
@ -19,4 +19,4 @@ extern "C" int main()
VirtualFuncDemo Demo2Instance = Demo2();
Demo2Instance.PrintTest();
}
})

@ -33,7 +33,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>ClangCL</PlatformToolset>
<PlatformToolset>llvm</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
@ -57,8 +57,14 @@
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<IncludePath>$(IncludePath)</IncludePath>
<ExecutablePath>$(LLVMInstallDir)\bin;$(ExecutablePath);</ExecutablePath>
<ReferencePath>$(ReferencePath)</ReferencePath>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClangClExecutable>$(ProjectDir)..\..\clang-cl.exe</ClangClExecutable>
<UseLldLink>false</UseLldLink>
<ClangClAdditionalOptions>-Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 </ClangClAdditionalOptions>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@ -85,7 +91,8 @@
<FunctionLevelLinking>false</FunctionLevelLinking>
<LanguageStandard_C>Default</LanguageStandard_C>
<CompileAs>Default</CompileAs>
<AdditionalOptions>-Xclang -mcmodel=large -Xclang -fno-jump-tables /Zc:threadSafeInit- </AdditionalOptions>
<AdditionalOptions>/Zc:threadSafeInit- </AdditionalOptions>
<DiagnosticsFormat />
</ClCompile>
<Link>
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
@ -102,7 +109,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="Theodosius.h" />
<ClInclude Include="Types.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

@ -18,8 +18,5 @@
<ClInclude Include="Theodosius.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Types.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -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"))))

@ -18,7 +18,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>ClangCL</PlatformToolset>
<PlatformToolset>llvm</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -31,6 +31,11 @@
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<UseLldLink>false</UseLldLink>
<ClangClExecutable>$(ProjectDir)..\..\..\..\clang-cl.exe</ClangClExecutable>
<ClangClAdditionalOptions>-Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 </ClangClAdditionalOptions>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
@ -42,10 +47,11 @@
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
<ControlFlowGuard>false</ControlFlowGuard>
<AdditionalOptions>/Zc:threadSafeInit- -Xclang -mcmodel=large -Xclang -fno-jump-tables %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
<LanguageStandard>stdcpp17</LanguageStandard>
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<DiagnosticsFormat />
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -65,6 +71,7 @@
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="..\..\backends\imgui_impl_dx11.h" />
<ClInclude Include="..\..\backends\imgui_impl_win32.h" />
<ClInclude Include="Theodosius.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />

@ -24,6 +24,9 @@
<ClInclude Include="..\..\backends\imgui_impl_dx11.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="Theodosius.h">
<Filter>imgui</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">

@ -1,14 +1,7 @@
// Dear ImGui: standalone example application for DirectX 11
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#define WINUSERAPI
#define _KERNEL32_
#define _ACRTIMP
#define _NTSYSTEM_
#define _GDI32_
#define ObfuscateRoutine __declspec(code_seg(".theo"), noinline)
#define MutateRoutine __declspec(code_seg(".theo1"), noinline)
#include "Theodosius.h"
#include "imgui.h"
#include "imgui_impl_win32.h"
#include "imgui_impl_dx11.h"
@ -28,8 +21,7 @@ void CreateRenderTarget();
void CleanupRenderTarget();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
MutateRoutine
extern "C" int main(int, char**)
THEO_OBFUSCATE(LLVM_BCF LLVM_SUB extern "C" int main(int, char**)
{
// Create application window
//ImGui_ImplWin32_EnableDpiAwareness();
@ -164,7 +156,7 @@ extern "C" int main(int, char**)
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
})
// Helper functions

@ -271,73 +271,75 @@ int __cdecl main(int argc, char** argv)
[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t
{
std::uintptr_t result = 0u;
for (auto& [drv_name, drv_symbols] : extern_symbols)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
if (!result)
{
for (auto& [drv_name, drv_symbols] : extern_symbols)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
if (section_count == drv_symbols[symbol_name].first)
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
if (section_count == drv_symbols[symbol_name].first)
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
);
}
}
// keep looping over modules until we resolve the symbol...
return !result;
}
);
}
// keep looping over modules until we resolve the symbol...
return !result;
}
);
// if the symbol was not resolved in any of the map files then try
// to see if its an export from any other drivers...
if (!result)
{
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
// if we found the symbol then break out of the loop... else keep looping...
if (result) break;
}
}
// finally return the result...
return result;
};

@ -128,73 +128,75 @@ int main(int argc, char** argv)
[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t
{
std::uintptr_t result = 0u;
for (auto& [drv_name, drv_symbols] : extern_symbols)
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
if (!result)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
for (auto& [drv_name, drv_symbols] : extern_symbols)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
if (section_count == drv_symbols[symbol_name].first)
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
);
if (section_count == drv_symbols[symbol_name].first)
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
);
}
// keep looping over modules until we resolve the symbol...
return !result;
}
);
// keep looping over modules until we resolve the symbol...
return !result;
}
);
}
// if the symbol was not resolved in any of the map files then try
// to see if its an export from any other drivers...
if (!result)
{
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
// if we found the symbol then break out of the loop... else keep looping...
if (result) break;
}
}
// finally return the result...
return result;
};

@ -375,15 +375,9 @@ namespace utils
+ sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader);
for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx)
{
const auto _section_name =
reinterpret_cast<char*>(
section_header[idx].Name);
// keep looping until the callback returns false...
if (!callback(&section_header[idx], module_base))
return;
}
}
}

@ -124,73 +124,75 @@ int main(int argc, char** argv)
[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t
{
std::uintptr_t result = 0u;
for (auto& [drv_name, drv_symbols] : extern_symbols)
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
if (!result)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
for (auto& [drv_name, drv_symbols] : extern_symbols)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
if (section_count == drv_symbols[symbol_name].first)
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
);
if (section_count == drv_symbols[symbol_name].first)
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
);
}
// keep looping over modules until we resolve the symbol...
return !result;
}
);
// keep looping over modules until we resolve the symbol...
return !result;
}
);
}
// if the symbol was not resolved in any of the map files then try
// to see if its an export from any other drivers...
if (!result)
{
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
// if we found the symbol then break out of the loop... else keep looping...
if (result) break;
}
}
// finally return the result...
return result;
};

@ -54,8 +54,8 @@ int main(int argc, char** argv)
if (argc < 3 || strcmp(argv[1], "--libs"))
{
std::printf("[!] invalid usage... please use one of the following:\n");
std::printf(" > theo.exe --libs one.lib two.lib three.lib\n");
std::printf(" > theo.exe --libs one.lib --maps ntoskrnl.exe.map win32kbase.sys.map\n");
std::printf(" > theo.exe --libs one.lib two.lib three.lib --pid 1234\n");
std::printf(" > theo.exe --libs one.lib --pid 1234\n");
return -1;
}

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 */

@ -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…
Cancel
Save