forked from IDontCode/Theodosius
parent
0c915c05d3
commit
4af07664ce
@ -0,0 +1 @@
|
||||
*.inc linguist-language=C
|
@ -0,0 +1 @@
|
||||
github: flobernd
|
@ -0,0 +1,69 @@
|
||||
name: GitHub Actions CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build Zydis (${{ matrix.image_name }}, ${{ matrix.no_libc }})"
|
||||
runs-on: "${{ matrix.image_name }}"
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
image_name: ["macOS-latest", "windows-2016", "ubuntu-18.04"]
|
||||
no_libc: ["", "-DZYAN_NO_LIBC=ON"]
|
||||
include:
|
||||
- image_name: "ubuntu-16.04"
|
||||
no_libc: "-DCMAKE_BUILD_TYPE=Release"
|
||||
dev_mode: "-DZYAN_DEV_MODE=ON"
|
||||
|
||||
steps:
|
||||
- uses: "actions/checkout@v1"
|
||||
- name: "Cloning submodules"
|
||||
run: |
|
||||
git submodule update --init
|
||||
- name: "Configuring"
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ${{ matrix.dev_mode }} ${{ matrix.no_libc }} ..
|
||||
- name: "Building"
|
||||
run: |
|
||||
cmake --build build --config Release
|
||||
- name: "Running regression tests"
|
||||
run: |
|
||||
cd tests
|
||||
python3 regression.py test ../build/ZydisInfo
|
||||
if: "!matrix.no_libc && matrix.image_name != 'windows-2016'"
|
||||
- name: "Running regression tests"
|
||||
run: |
|
||||
cd tests
|
||||
python regression.py test ..\\build\\Release\\ZydisInfo.exe
|
||||
if: "!matrix.no_libc && matrix.image_name == 'windows-2016'"
|
||||
|
||||
fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sanitizer: [address, undefined, memory]
|
||||
steps:
|
||||
- name: Build Fuzzers (${{ matrix.sanitizer }})
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'zydis'
|
||||
dry-run: false
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Run Fuzzers (${{ matrix.sanitizer }})
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'zydis'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: ${{ matrix.sanitizer }}-artifacts
|
||||
path: ./out/artifacts
|
@ -0,0 +1,101 @@
|
||||
# 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
|
@ -0,0 +1,3 @@
|
||||
[submodule "dependencies/zycore"]
|
||||
path = dependencies/zycore
|
||||
url = https://github.com/zyantific/zycore-c
|
@ -0,0 +1,296 @@
|
||||
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
@ -0,0 +1,7 @@
|
||||
@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
|
@ -0,0 +1,23 @@
|
||||
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.
|
||||
|
@ -0,0 +1,175 @@
|
||||
<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.
|
@ -0,0 +1,41 @@
|
||||
|
||||
#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.
After Width: | Height: | Size: 58 KiB |
@ -0,0 +1,4 @@
|
||||
- CMakeLists (VERSION)
|
||||
- Doxyfile
|
||||
- resources/VersionInfo.rc (4 locations)
|
||||
- include/Zydis/Zydis.h (ZYDIS_VERSION macro)
|
@ -0,0 +1,8 @@
|
||||
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)
|
@ -0,0 +1,100 @@
|
||||
# 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-*
|
@ -0,0 +1,266 @@
|
||||
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 ()
|
||||
|
||||
# =============================================================================================== #
|
@ -0,0 +1,15 @@
|
||||
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 ""
|
||||
)
|
@ -0,0 +1,23 @@
|
||||
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.
|
||||
|
@ -0,0 +1,25 @@
|
||||
# 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.
|
@ -0,0 +1,8 @@
|
||||
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)
|
@ -0,0 +1,192 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -0,0 +1,395 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
Binary file not shown.
@ -0,0 +1,128 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -0,0 +1,68 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
@ -0,0 +1,200 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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
|
||||
|
||||
/* ============================================================================================== */
|
@ -0,0 +1,156 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
@ -0,0 +1,194 @@
|
||||
/***************************************************************************************************
|
||||
|
||||
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
|
||||
|
||||
/* ============================================================================================== */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue