Files
raddebugger/src/base/base_core.c
T

677 lines
14 KiB
C

// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Safe Casts
internal U16
safe_cast_u16(U32 x)
{
AssertAlways(x <= max_U16);
U16 result = (U16)x;
return result;
}
internal U32
safe_cast_u32(U64 x)
{
AssertAlways(x <= max_U32);
U32 result = (U32)x;
return result;
}
internal S32
safe_cast_s32(S64 x)
{
AssertAlways(x <= max_S32);
S32 result = (S32)x;
return result;
}
////////////////////////////////
//~ rjf: Large Base Type Functions
internal U128
u128_zero(void)
{
U128 v = {0};
return v;
}
internal U128
u128_make(U64 v0, U64 v1)
{
U128 v = {v0, v1};
return v;
}
internal B32
u128_match(U128 a, U128 b)
{
return MemoryMatchStruct(&a, &b);
}
////////////////////////////////
//~ rjf: Bit Patterns
internal U32
u32_from_u64_saturate(U64 x){
U32 x32 = (x > max_U32)?max_U32:(U32)x;
return(x32);
}
internal U64
u64_up_to_pow2(U64 x){
if (x == 0){
x = 1;
}
else{
x -= 1;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
x |= (x >> 32);
x += 1;
}
return(x);
}
internal S32
extend_sign32(U32 x, U32 size){
U32 high_bit = size * 8;
U32 shift = 32 - high_bit;
S32 result = ((S32)x << shift) >> shift;
return result;
}
internal S64
extend_sign64(U64 x, U64 size){
U64 high_bit = size * 8;
U64 shift = 64 - high_bit;
S64 result = ((S64)x << shift) >> shift;
return result;
}
internal F32
inf32(void){
union { U32 u; F32 f; } x;
x.u = exponent32;
return(x.f);
}
internal F32
neg_inf32(void){
union { U32 u; F32 f; } x;
x.u = sign32 | exponent32;
return(x.f);
}
internal U16
bswap_u16(U16 x)
{
U16 result = (((x & 0xFF00) >> 8) |
((x & 0x00FF) << 8));
return result;
}
internal U32
bswap_u32(U32 x)
{
U32 result = (((x & 0xFF000000) >> 24) |
((x & 0x00FF0000) >> 8) |
((x & 0x0000FF00) << 8) |
((x & 0x000000FF) << 24));
return result;
}
internal U64
bswap_u64(U64 x)
{
// TODO(nick): naive bswap, replace with something that is faster like an intrinsic
U64 result = (((x & 0xFF00000000000000ULL) >> 56) |
((x & 0x00FF000000000000ULL) >> 40) |
((x & 0x0000FF0000000000ULL) >> 24) |
((x & 0x000000FF00000000ULL) >> 8) |
((x & 0x00000000FF000000ULL) << 8) |
((x & 0x0000000000FF0000ULL) << 24) |
((x & 0x000000000000FF00ULL) << 40) |
((x & 0x00000000000000FFULL) << 56));
return result;
}
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
internal U64
count_bits_set32(U32 val)
{
return __popcnt(val);
}
internal U64
count_bits_set64(U64 val)
{
return __popcnt64(val);
}
internal U64
ctz32(U32 mask)
{
unsigned long idx;
_BitScanForward(&idx, mask);
return idx;
}
internal U64
ctz64(U64 mask)
{
unsigned long idx;
_BitScanForward64(&idx, mask);
return idx;
}
internal U64
clz32(U32 mask)
{
unsigned long idx;
_BitScanReverse(&idx, mask);
return 31 - idx;
}
internal U64
clz64(U64 mask)
{
unsigned long idx;
_BitScanReverse64(&idx, mask);
return 63 - idx;
}
#elif COMPILER_CLANG || COMPILER_GCC
internal U64
count_bits_set32(U32 val)
{
return __builtin_popcount(val);
}
internal U64
count_bits_set64(U64 val)
{
return __builtin_popcountll(val);
}
internal U64
ctz32(U32 val)
{
return __builtin_ctz(val);
}
internal U64
clz32(U32 val)
{
return __builtin_clz(val);
}
internal U64
ctz64(U64 val)
{
return __builtin_ctzll(val);
}
internal U64
clz64(U64 val)
{
return __builtin_clzll(val);
}
#else
# error "Bit intrinsic functions not defined for this compiler."
#endif
////////////////////////////////
//~ rjf: Enum -> Sign
internal S32
sign_from_side_S32(Side side){
return((side == Side_Min)?-1:1);
}
internal F32
sign_from_side_F32(Side side){
return((side == Side_Min)?-1.f:1.f);
}
////////////////////////////////
//~ rjf: Memory Functions
internal B32
memory_is_zero(void *ptr, U64 size)
{
B32 result = 1;
// break down size
U64 extra = (size&0x7);
U64 count8 = (size >> 3);
// check with 8-byte stride
U64 *p64 = (U64*)ptr;
if(result)
{
for(U64 i = 0; i < count8; i += 1, p64 += 1)
{
if(*p64 != 0)
{
result = 0;
goto done;
}
}
}
// check extra
if(result)
{
U8 *p8 = (U8*)p64;
for(U64 i = 0; i < extra; i += 1, p8 += 1)
{
if(*p8 != 0)
{
result = 0;
goto done;
}
}
}
done:;
return result;
}
////////////////////////////////
//~ rjf: Text 2D Coordinate/Range Functions
internal TxtPt
txt_pt(S64 line, S64 column)
{
TxtPt p = {0};
p.line = line;
p.column = column;
return p;
}
internal B32
txt_pt_match(TxtPt a, TxtPt b)
{
return a.line == b.line && a.column == b.column;
}
internal B32
txt_pt_less_than(TxtPt a, TxtPt b)
{
B32 result = 0;
if(a.line < b.line)
{
result = 1;
}
else if(a.line == b.line)
{
result = a.column < b.column;
}
return result;
}
internal TxtPt
txt_pt_min(TxtPt a, TxtPt b)
{
TxtPt result = b;
if(txt_pt_less_than(a, b))
{
result = a;
}
return result;
}
internal TxtPt
txt_pt_max(TxtPt a, TxtPt b)
{
TxtPt result = a;
if(txt_pt_less_than(a, b))
{
result = b;
}
return result;
}
internal TxtRng
txt_rng(TxtPt min, TxtPt max)
{
TxtRng range = {0};
if(txt_pt_less_than(min, max))
{
range.min = min;
range.max = max;
}
else
{
range.min = max;
range.max = min;
}
return range;
}
internal TxtRng
txt_rng_intersect(TxtRng a, TxtRng b)
{
TxtRng result = {0};
result.min = txt_pt_max(a.min, b.min);
result.max = txt_pt_min(a.max, b.max);
if(txt_pt_less_than(result.max, result.min))
{
MemoryZeroStruct(&result);
}
return result;
}
internal TxtRng
txt_rng_union(TxtRng a, TxtRng b)
{
TxtRng result = {0};
result.min = txt_pt_min(a.min, b.min);
result.max = txt_pt_max(a.max, b.max);
return result;
}
internal B32
txt_rng_contains(TxtRng r, TxtPt pt)
{
B32 result = ((txt_pt_less_than(r.min, pt) || txt_pt_match(r.min, pt)) &&
txt_pt_less_than(pt, r.max));
return result;
}
////////////////////////////////
//~ rjf: Toolchain/Environment Enum Functions
internal U64
bit_size_from_arch(Arch arch)
{
// TODO(rjf): metacode
U64 arch_bitsize = 0;
switch(arch)
{
case Arch_x64: arch_bitsize = 64; break;
case Arch_x86: arch_bitsize = 32; break;
case Arch_arm64: arch_bitsize = 64; break;
case Arch_arm32: arch_bitsize = 32; break;
default: break;
}
return arch_bitsize;
}
internal U64
max_instruction_size_from_arch(Arch arch)
{
// TODO(rjf): make this real
return 64;
}
////////////////////////////////
//~ rjf: Time Functions
internal DenseTime
dense_time_from_date_time(DateTime date_time){
DenseTime result = 0;
result += date_time.year;
result *= 12;
result += date_time.mon;
result *= 31;
result += date_time.day;
result *= 24;
result += date_time.hour;
result *= 60;
result += date_time.min;
result *= 61;
result += date_time.sec;
result *= 1000;
result += date_time.msec;
return(result);
}
internal DateTime
date_time_from_dense_time(DenseTime time){
DateTime result = {0};
result.msec = time%1000;
time /= 1000;
result.sec = time%61;
time /= 61;
result.min = time%60;
time /= 60;
result.hour = time%24;
time /= 24;
result.day = time%31;
time /= 31;
result.mon = time%12;
time /= 12;
Assert(time <= max_U32);
result.year = (U32)time;
return(result);
}
internal DateTime
date_time_from_micro_seconds(U64 time){
DateTime result = {0};
result.micro_sec = time%1000;
time /= 1000;
result.msec = time%1000;
time /= 1000;
result.sec = time%60;
time /= 60;
result.min = time%60;
time /= 60;
result.hour = time%24;
time /= 24;
result.day = time%31;
time /= 31;
result.mon = time%12;
time /= 12;
Assert(time <= max_U32);
result.year = (U32)time;
return(result);
}
internal DateTime
date_time_from_unix_time(U64 unix_time)
{
DateTime date = {0};
date.year = 1970;
date.day = 1 + (unix_time / 86400);
date.sec = (U32)unix_time % 60;
date.min = (U32)(unix_time / 60) % 60;
date.hour = (U32)(unix_time / 3600) % 24;
for(;;)
{
for(date.month = 0; date.month < 12; ++date.month)
{
U64 c = 0;
switch(date.month)
{
case Month_Jan: c = 31; break;
case Month_Feb:
{
if((date.year % 4 == 0) && ((date.year % 100) != 0 || (date.year % 400) == 0))
{
c = 29;
}
else
{
c = 28;
}
} break;
case Month_Mar: c = 31; break;
case Month_Apr: c = 30; break;
case Month_May: c = 31; break;
case Month_Jun: c = 30; break;
case Month_Jul: c = 31; break;
case Month_Aug: c = 31; break;
case Month_Sep: c = 30; break;
case Month_Oct: c = 31; break;
case Month_Nov: c = 30; break;
case Month_Dec: c = 31; break;
default: InvalidPath;
}
if(date.day <= c)
{
goto exit;
}
date.day -= c;
}
++date.year;
}
exit:;
return date;
}
////////////////////////////////
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
internal U64
ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size)
{
Assert(src_data_size <= ring_size);
{
U64 ring_off = ring_pos%ring_size;
U64 bytes_before_split = ring_size-ring_off;
U64 pre_split_bytes = Min(bytes_before_split, src_data_size);
U64 pst_split_bytes = src_data_size-pre_split_bytes;
void *pre_split_data = src_data;
void *pst_split_data = ((U8 *)src_data + pre_split_bytes);
MemoryCopy(ring_base+ring_off, pre_split_data, pre_split_bytes);
MemoryCopy(ring_base+0, pst_split_data, pst_split_bytes);
}
return src_data_size;
}
internal U64
ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size)
{
Assert(read_size <= ring_size);
{
U64 ring_off = ring_pos%ring_size;
U64 bytes_before_split = ring_size-ring_off;
U64 pre_split_bytes = Min(bytes_before_split, read_size);
U64 pst_split_bytes = read_size-pre_split_bytes;
MemoryCopy(dst_data, ring_base+ring_off, pre_split_bytes);
MemoryCopy((U8 *)dst_data + pre_split_bytes, ring_base+0, pst_split_bytes);
}
return read_size;
}
////////////////////////////////
internal U64
u64_array_bsearch(U64 *arr, U64 count, U64 value)
{
if(count > 1 && arr[0] <= value && value < arr[count-1])
{
U64 l = 0;
U64 r = count - 1;
for(; l <= r; )
{
U64 m = l + (r - l) / 2;
if(arr[m] == value)
{
return m;
}
else if(arr[m] < value)
{
l = m + 1;
}
else
{
r = m - 1;
}
}
}
else if (count == 1 && arr[0] == value)
{
return 0;
}
return max_U64;
}
////////////////////////////////
internal U64
index_of_zero_u32(U32 *ptr, U64 count)
{
for (U64 i = 0; i < count; i += 1) {
if (ptr[i] == 0) {
return i;
}
}
return max_U64;
}
internal U64
index_of_zero_u64(U64 *ptr, U64 count)
{
for (U64 i = 0; i < count; i += 1) {
if (ptr[i] == 0) {
return i;
}
}
return max_U64;
}
////////////////////////////////
//~ rjf: Third Party Includes
#if !BUILD_SUPPLEMENTARY_UNIT
# define STB_SPRINTF_IMPLEMENTATION
# include "third_party/stb/stb_sprintf.h"
#endif
////////////////////////////////
//~ rjf: String <-> Integer Tables
read_only global U8 integer_symbols[16] =
{
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',
};
// NOTE(rjf): Includes reverses for uppercase and lowercase hex.
read_only global U8 integer_symbol_reverse[128] =
{
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
read_only global U8 base64[64] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'_', '$',
};
read_only global U8 base64_reverse[128] =
{
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
0xFF,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,
0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0xFF,0xFF,0xFF,0xFF,0x3E,
0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,
};