dep: Add Zydis

This commit is contained in:
Stenzek
2023-05-22 19:36:26 +10:00
parent 39e62ae948
commit c561400a47
77 changed files with 53849 additions and 0 deletions

View File

@ -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.

View File

@ -0,0 +1,29 @@
# Zyan Core Library for C
<a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
<a href="https://github.com/zyantific/zycore-c/actions"><img src="https://github.com/zyantific/zycore-c/workflows/GitHub%20Actions%20CI/badge.svg" alt="GitHub Actions"></a>
<a href="https://discord.zyantific.com/"><img src="https://img.shields.io/discord/390136917779415060.svg?logo=discord&label=Discord" alt="Discord"></a>
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.

View File

@ -0,0 +1,142 @@
/***************************************************************************************************
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 <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 */

View File

@ -0,0 +1,316 @@
/***************************************************************************************************
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 */

View File

@ -0,0 +1,527 @@
/***************************************************************************************************
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(__wasi__) || defined(__WASI__)
// via: https://reviews.llvm.org/D57155
# define ZYAN_WASI
#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__) || defined(__wasm__) || defined(__WASM__)
# define ZYAN_WASM
#elif defined(__powerpc64__)
# define ZYAN_PPC64
#elif defined(__powerpc__)
# define ZYAN_PPC
#elif defined(__riscv) && __riscv_xlen == 64
# define ZYAN_RISCV64
#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
/* ============================================================================================== */
/* Deprecation hint */
/* ============================================================================================== */
#if defined(ZYAN_GCC) || defined(ZYAN_CLANG)
# define ZYAN_DEPRECATED __attribute__((__deprecated__))
#elif defined(ZYAN_MSVC)
# define ZYAN_DEPRECATED __declspec(deprecated)
#else
# define ZYAN_DEPRECATED
#endif
/* ============================================================================================== */
/* Generic DLL import/export helpers */
/* ============================================================================================== */
#if defined(ZYAN_MSVC)
# define ZYAN_DLLEXPORT __declspec(dllexport)
# define ZYAN_DLLIMPORT __declspec(dllimport)
#else
# define ZYAN_DLLEXPORT
# define ZYAN_DLLIMPORT
#endif
/* ============================================================================================== */
/* Zycore dll{export,import} */
/* ============================================================================================== */
// This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To
// simplify builds without CMake, we define these things manually instead of relying on CMake
// to generate the header.
//
// For static builds, our CMakeList will define `ZYCORE_STATIC_BUILD`. For shared library builds,
// our CMake will define `ZYCORE_SHOULD_EXPORT` depending on whether the target is being imported or
// exported. If CMake isn't used, users can manually define these to fit their use-case.
// Backward compatibility: CMake would previously generate these variables names. However, because
// they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For
// backward compatibility for users that don't use CMake and previously manually defined these, we
// translate the old defines here and print a warning.
#if defined(ZYCORE_STATIC_DEFINE)
# pragma message("ZYCORE_STATIC_DEFINE was renamed to ZYCORE_STATIC_BUILD.")
# define ZYCORE_STATIC_BUILD
#endif
#if defined(Zycore_EXPORTS)
# pragma message("Zycore_EXPORTS was renamed to ZYCORE_SHOULD_EXPORT.")
# define ZYCORE_SHOULD_EXPORT
#endif
/**
* Symbol is exported in shared library builds.
*/
#if defined(ZYCORE_STATIC_BUILD)
# define ZYCORE_EXPORT
#else
# if defined(ZYCORE_SHOULD_EXPORT)
# define ZYCORE_EXPORT ZYAN_DLLEXPORT
# else
# define ZYCORE_EXPORT ZYAN_DLLIMPORT
# endif
#endif
/**
* Symbol is not exported and for internal use only.
*/
#define ZYCORE_NO_EXPORT
/* ============================================================================================== */
/* 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
#if defined(ZYAN_MSVC)
# define ZYAN_NOINLINE __declspec(noinline)
#elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
# define ZYAN_NOINLINE __attribute__((noinline))
#else
# define ZYAN_NOINLINE
#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 defined(__STDC_VERSION__) && __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 */

View File

@ -0,0 +1,285 @@
/***************************************************************************************************
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 <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

View File

@ -0,0 +1,511 @@
/***************************************************************************************************
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 */

View File

@ -0,0 +1,84 @@
/***************************************************************************************************
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 */

View File

@ -0,0 +1,287 @@
/***************************************************************************************************
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

View File

@ -0,0 +1,236 @@
/***************************************************************************************************
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
# if defined(ZYAN_MSVC)
# define ZYAN_INT8_MIN (-127i8 - 1)
# define ZYAN_INT16_MIN (-32767i16 - 1)
# define ZYAN_INT32_MIN (-2147483647i32 - 1)
# define ZYAN_INT64_MIN (-9223372036854775807i64 - 1)
# define ZYAN_INT8_MAX 127i8
# define ZYAN_INT16_MAX 32767i16
# define ZYAN_INT32_MAX 2147483647i32
# define ZYAN_INT64_MAX 9223372036854775807i64
# define ZYAN_UINT8_MAX 0xffui8
# define ZYAN_UINT16_MAX 0xffffui16
# define ZYAN_UINT32_MAX 0xffffffffui32
# define ZYAN_UINT64_MAX 0xffffffffffffffffui64
# else
# define ZYAN_INT8_MAX __INT8_MAX__
# define ZYAN_INT8_MIN (-ZYAN_INT8_MAX - 1)
# define ZYAN_INT16_MAX __INT16_MAX__
# define ZYAN_INT16_MIN (-ZYAN_INT16_MAX - 1)
# define ZYAN_INT32_MAX __INT32_MAX__
# define ZYAN_INT32_MIN (-ZYAN_INT32_MAX - 1)
# define ZYAN_INT64_MAX __INT64_MAX__
# define ZYAN_INT64_MIN (-ZYAN_INT64_MAX - 1)
# define ZYAN_UINT8_MAX __UINT8_MAX__
# define ZYAN_UINT16_MAX __UINT16_MAX__
# define ZYAN_UINT32_MAX __UINT32_MAX__
# define ZYAN_UINT64_MAX __UINT64_MAX__
# 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;
# define ZYAN_INT8_MIN INT8_MIN
# define ZYAN_INT16_MIN INT16_MIN
# define ZYAN_INT32_MIN INT32_MIN
# define ZYAN_INT64_MIN INT64_MIN
# define ZYAN_INT8_MAX INT8_MAX
# define ZYAN_INT16_MAX INT16_MAX
# define ZYAN_INT32_MAX INT32_MAX
# define ZYAN_INT64_MAX INT64_MAX
# define ZYAN_UINT8_MAX UINT8_MAX
# define ZYAN_UINT16_MAX UINT16_MAX
# define ZYAN_UINT32_MAX UINT32_MAX
# define ZYAN_UINT64_MAX UINT64_MAX
#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 void* ZyanVoidPointer;
/**
* Defines the `ZyanConstVoidPointer` data-type.
*/
typedef const void* ZyanConstVoidPointer;
#define ZYAN_NULL ((void*)0)
/* ============================================================================================== */
/* Logic types */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Boolean */
/* ---------------------------------------------------------------------------------------------- */
#define ZYAN_FALSE 0u
#define ZYAN_TRUE 1u
/**
* 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 */

View File

@ -0,0 +1,722 @@
/***************************************************************************************************
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 <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
/**
* The default shrink threshold for all vector instances.
*/
#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 4
/* ============================================================================================== */
/* 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.
*/
ZyanU8 growth_factor;
/**
* The shrink threshold.
*/
ZyanU8 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, \
/* shrink_threshold */ 0, \
/* 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 and the default shrink threshold.
*
* 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.
* @param shrink_threshold The shrink threshold.
*
* @return A zyan status code.
*
* A growth factor of `1` disables overallocation and a shrink threshold of `0` 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,
ZyanU8 growth_factor, ZyanU8 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 and the default shrink threshold.
*
* 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.
* @param shrink_threshold The shrink threshold.
*
* @return A zyan status code.
*
* A growth factor of `1` disables overallocation and a shrink threshold of `0` 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, ZyanU8 growth_factor, ZyanU8 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
* occurred.
*
* 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
* occurred.
*
* 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 occurred.
*
* 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 occurred.
*
* 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 occurred.
*
* 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 occurred.
*
* 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 */

View File

@ -0,0 +1,134 @@
/***************************************************************************************************
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
/* ============================================================================================== */

View File

@ -0,0 +1,507 @@
/***************************************************************************************************
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) || defined(ZYAN_WASM) || defined(ZYAN_PPC)
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) || defined(ZYAN_WASM) || defined(ZYAN_PPC)
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) || defined(ZYAN_PPC64) || defined(ZYAN_RISCV64)
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) || defined(ZYAN_PPC64) || defined(ZYAN_RISCV64)
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);
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,846 @@
/***************************************************************************************************
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) \
(((threshold) != 0) && ((size) * (threshold) < (capacity)))
/**
* 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);
const 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);
const 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, ZyanU8 growth_factor,
ZyanU8 shrink_threshold)
{
if (!vector || !element_size || !allocator || (growth_factor < 1))
{
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;
vector->shrink_threshold = 0;
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, ZyanU8 growth_factor, ZyanU8 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_ASSERT(vector->growth_factor >= 1);
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;
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */