mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-19 10:15:46 -04:00
dep: Add Zydis
This commit is contained in:
134
dep/zydis/dependencies/zycore/src/Allocator.c
Normal file
134
dep/zydis/dependencies/zycore/src/Allocator.c
Normal 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
|
||||
|
||||
/* ============================================================================================== */
|
507
dep/zydis/dependencies/zycore/src/Format.c
Normal file
507
dep/zydis/dependencies/zycore/src/Format.c
Normal 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);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
1098
dep/zydis/dependencies/zycore/src/String.c
Normal file
1098
dep/zydis/dependencies/zycore/src/String.c
Normal file
File diff suppressed because it is too large
Load Diff
846
dep/zydis/dependencies/zycore/src/Vector.c
Normal file
846
dep/zydis/dependencies/zycore/src/Vector.c
Normal 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;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
Reference in New Issue
Block a user