mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-03 20:38:40 +00:00
linker
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal String8
|
||||
push_cstr(Arena *arena, String8 str)
|
||||
{
|
||||
U64 buffer_size = str.size + 1;
|
||||
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
|
||||
MemoryCopy(buffer, str.str, str.size);
|
||||
buffer[str.size] = 0;
|
||||
String8 result = str8(buffer, buffer_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U32 *
|
||||
push_u32(Arena *arena, U32 value)
|
||||
{
|
||||
U32 *result = push_array_no_zero(arena, U32, 1);
|
||||
*result = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64 *
|
||||
push_u64(Arena *arena, U64 value)
|
||||
{
|
||||
U64 *result = push_array_no_zero(arena, U64, 1);
|
||||
*result = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U32 *
|
||||
push_array_copy_u32(Arena *arena, U32 *v, U64 count)
|
||||
{
|
||||
U32 *result = push_array_no_zero(arena, U32, count);
|
||||
MemoryCopyTyped(result, v, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64 *
|
||||
push_array_copy_u64(Arena *arena, U64 *v, U64 count)
|
||||
{
|
||||
U64 *result = push_array_no_zero(arena, U64, count);
|
||||
MemoryCopyTyped(result, v, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64 **
|
||||
push_matrix_u64(Arena *arena, U64 rows, U64 columns)
|
||||
{
|
||||
U64 **result = push_array_no_zero(arena, U64 *, rows);
|
||||
for (U64 row_idx = 0; row_idx < rows; row_idx += 1) {
|
||||
result[row_idx] = push_array(arena, U64, columns);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Arena **
|
||||
alloc_fixed_size_arena_array(Arena *arena, U64 count, U64 res, U64 cmt)
|
||||
{
|
||||
U64 data_size = sizeof(count) + sizeof(Arena *) * count;
|
||||
U8 *data = push_array_no_zero(arena, U8, data_size);
|
||||
U64 *count_ptr = (U64 *)data;
|
||||
Arena **arr = (Arena **)(count_ptr + 1);
|
||||
*count_ptr = count;
|
||||
|
||||
ArenaParams params = {0};
|
||||
params.reserve_size = res;
|
||||
params.commit_size = cmt;
|
||||
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
Arena *fixed_arena = arena_alloc_(¶ms);
|
||||
arr[i] = fixed_arena;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
internal void
|
||||
release_arena_array(Arena **arr)
|
||||
{
|
||||
U64 *count_ptr = (U64 *)arr - 1;
|
||||
U64 count = *count_ptr;
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
arena_release(arr[i]);
|
||||
arr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
internal U32 * push_u32(Arena *arena, U32 value);
|
||||
internal U64 * push_u64(Arena *arena, U64 value);
|
||||
internal U32 * push_array_copy_u32(Arena *arena, U32 *v, U64 count);
|
||||
internal U64 * push_array_copy_u64(Arena *arena, U64 *v, U64 count);
|
||||
internal U64 ** push_matrix_u64(Arena *arena, U64 rows, U64 columns);
|
||||
internal String8 push_cstr(Arena *arena, String8 str);
|
||||
|
||||
internal Arena ** alloc_fixed_size_arena_array(Arena *arena, U64 count, U64 res, U64 cmt);
|
||||
internal void release_arena_array(Arena **arr);
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal U64
|
||||
void_list_count_nodes(VoidNode *head)
|
||||
{
|
||||
U64 node_count = 0;
|
||||
for (VoidNode *curr = head; curr != 0; curr = curr->next) {
|
||||
++node_count;
|
||||
}
|
||||
return node_count;
|
||||
}
|
||||
|
||||
internal void
|
||||
void_node_concat(VoidNode **head, VoidNode *node)
|
||||
{
|
||||
Assert(*head != node);
|
||||
node->next = *head;
|
||||
*head = node;
|
||||
}
|
||||
|
||||
internal void
|
||||
void_node_concat_atomic(VoidNode **head, VoidNode *node)
|
||||
{
|
||||
Assert(*head != node);
|
||||
node->next = ins_atomic_ptr_eval_assign(head, node);
|
||||
}
|
||||
|
||||
internal U64Node *
|
||||
u64_list_push(Arena *arena, U64List *list, U64 data)
|
||||
{
|
||||
U64Node *n = push_array(arena, U64Node, 1);
|
||||
n->next = 0;
|
||||
n->data = data;
|
||||
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
++list->count;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
internal void
|
||||
u64_list_concat_in_place(U64List *list, U64List *to_concat)
|
||||
{
|
||||
SLLConcatInPlace(list, to_concat);
|
||||
}
|
||||
|
||||
internal U64Array
|
||||
u64_array_from_list(Arena *arena, U64List *list)
|
||||
{
|
||||
U64Array result;
|
||||
result.count = 0;
|
||||
result.v = push_array(arena, U64, list->count);
|
||||
for (U64Node *n = list->first; n != NULL; n = n->next) {
|
||||
result.v[result.count++] = n->data;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
u32_array_sort(U64 count, U32 *v)
|
||||
{
|
||||
radsort(v, count, u32_is_before);
|
||||
}
|
||||
|
||||
internal void
|
||||
u32_pair_radix_sort(U64 count, PairU32 *arr)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
PairU32 *temp = push_array(scratch.arena, PairU32, count);
|
||||
|
||||
const U64 bit_count0 = 11;
|
||||
const U64 bit_count1 = 11;
|
||||
const U64 bit_count2 = 10;
|
||||
|
||||
U32 *count0 = push_array(scratch.arena, U32, (1 << bit_count0));
|
||||
U32 *count1 = push_array(scratch.arena, U32, (1 << bit_count1));
|
||||
U32 *count2 = push_array(scratch.arena, U32, (1 << bit_count2));
|
||||
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
U32 digit0 = (arr[i].v0 >> 0 ) % (1 << bit_count0);
|
||||
U32 digit1 = (arr[i].v0 >> bit_count0) % (1 << bit_count1);
|
||||
U32 digit2 = (arr[i].v0 >> bit_count1) % (1 << bit_count2);
|
||||
|
||||
++count0[digit0];
|
||||
++count1[digit1];
|
||||
++count2[digit2];
|
||||
}
|
||||
|
||||
counts_to_offsets_array_u32((1 << bit_count0), count0);
|
||||
counts_to_offsets_array_u32((1 << bit_count1), count1);
|
||||
counts_to_offsets_array_u32((1 << bit_count2), count2);
|
||||
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
U32 digit0 = (arr[i].v0 >> 0) % (1 << bit_count0);
|
||||
temp[count0[digit0]++] = arr[i];
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
U32 digit1 = (temp[i].v0 >> bit_count0) % (1 << bit_count1);
|
||||
arr[count1[digit1]++] = temp[i];
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
U32 digit2 = (arr[i].v0 >> bit_count1) % (1 << bit_count2);
|
||||
temp[count2[digit2]++] = arr[i];
|
||||
}
|
||||
|
||||
MemoryCopyTyped(arr, temp, count);
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal B32
|
||||
u32_array_compare(U32Array a, U32Array b)
|
||||
{
|
||||
B32 are_equal = 0;
|
||||
if (a.count == b.count) {
|
||||
int cmp = MemoryCompare(a.v, b.v, sizeof(a.v[0]) * a.count);
|
||||
are_equal = (cmp == 0);
|
||||
}
|
||||
return are_equal;
|
||||
}
|
||||
|
||||
internal U64Array
|
||||
u64_array_remove_duplicates(Arena *arena, U64Array in)
|
||||
{
|
||||
U64Array result;
|
||||
result.count = 0;
|
||||
result.v = push_array(arena, U64, in.count);
|
||||
|
||||
for (U64 i = 1; i < in.count; ++i) {
|
||||
B32 is_unique = in.v[i - 1] != in.v[i];
|
||||
if (is_unique) {
|
||||
result.v[result.count++] = in.v[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (in.count > 0 && result.count > 0) {
|
||||
B32 is_unique = result.v[result.count - 1] != in.v[in.count - 1];
|
||||
if (is_unique) {
|
||||
result.v[result.count++] = in.v[in.count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
U64 slack_size = (in.count - result.count) * sizeof(result.v[0]);
|
||||
arena_pop(arena, slack_size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
sum_array_u64(U64 count, U64 *v)
|
||||
{
|
||||
U64 result = 0;
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
result += v[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
sum_matrix_u64(U64 rows, U64 cols, U64 **v)
|
||||
{
|
||||
U64 result = 0;
|
||||
for (U64 i = 0; i < rows; ++i) {
|
||||
result += sum_array_u64(cols, v[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
max_array_u64(U64 count, U64 *v)
|
||||
{
|
||||
U64 result = 0;
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
result = Max(v[i], result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
min_array_u64(U64 count, U64 *v)
|
||||
{
|
||||
U64 result = max_U64;
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
result = Min(v[i], result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
counts_to_offsets_array_u32(U64 count, U32 *arr)
|
||||
{
|
||||
U32 next_offset = 0;
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
U32 current_offset = next_offset;
|
||||
next_offset += arr[i];
|
||||
arr[i] = current_offset;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
counts_to_offsets_array_u64(U64 count, U64 *arr)
|
||||
{
|
||||
U64 next_offset = 0;
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
U64 current_offset = next_offset;
|
||||
next_offset += arr[i];
|
||||
arr[i] = current_offset;
|
||||
}
|
||||
}
|
||||
|
||||
internal U32 *
|
||||
offsets_from_counts_array_u32(Arena *arena, U32 *v, U64 count)
|
||||
{
|
||||
U32 *result = push_array_copy_u32(arena, v, count);
|
||||
counts_to_offsets_array_u32(count, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64 *
|
||||
offsets_from_counts_array_u64(Arena *arena, U64 *v, U64 count)
|
||||
{
|
||||
U64 *result = push_array_copy_u64(arena, v, count);
|
||||
counts_to_offsets_array_u64(count, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct U32Array
|
||||
{
|
||||
U64 count;
|
||||
U32 *v;
|
||||
} U32Array;
|
||||
|
||||
typedef struct U64Array
|
||||
{
|
||||
U64 count;
|
||||
U64 *v;
|
||||
} U64Array;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 count;
|
||||
U128 *v;
|
||||
} U128Array;
|
||||
|
||||
typedef struct U64Node
|
||||
{
|
||||
struct U64Node *next;
|
||||
U64 data;
|
||||
} U64Node;
|
||||
|
||||
typedef struct U64List
|
||||
{
|
||||
U64 count;
|
||||
U64Node *first;
|
||||
U64Node *last;
|
||||
} U64List;
|
||||
|
||||
typedef struct VoidNode
|
||||
{
|
||||
struct VoidNode *next;
|
||||
void *v;
|
||||
} VoidNode;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64Node * u64_list_push(Arena *arena, U64List *list, U64 data);
|
||||
internal void u64_list_concat_in_place(U64List *list, U64List *to_concat);
|
||||
internal U64Array u64_array_from_list(Arena *arena, U64List *list);
|
||||
|
||||
internal U64Array u64_array_remove_duplicates(Arena *arena, U64Array in);
|
||||
|
||||
internal void u32_array_sort(U64 count, U32 *v);
|
||||
internal B32 u32_array_compare(U32Array a, U32Array b);
|
||||
|
||||
internal U64 sum_array_u64(U64 count, U64 *v);
|
||||
internal U64 max_array_u64(U64 count, U64 *v);
|
||||
internal U64 min_array_u64(U64 count, U64 *v);
|
||||
|
||||
internal void counts_to_offsets_array_u32(U64 count, U32 *arr);
|
||||
internal void counts_to_offsets_array_u64(U64 count, U64 *arr);
|
||||
|
||||
internal U32 * offsets_from_counts_array_u32(Arena *arena, U32 *v, U64 count);
|
||||
internal U64 * offsets_from_counts_array_u64(Arena *arena, U64 *v, U64 count);
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal U32Array
|
||||
bit_array_init32(Arena *arena, U64 word_count)
|
||||
{
|
||||
U32Array result;
|
||||
result.count = CeilIntegerDiv(word_count, 32);
|
||||
result.v = push_array(arena, U32, word_count);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
bit_array_scan_left_to_right32(U32Array bit_array, U64 lo, U64 hi, B32 state)
|
||||
{
|
||||
Assert(lo < bit_array.count*32);
|
||||
Assert(hi <= bit_array.count*32);
|
||||
Assert(lo <= hi);
|
||||
Assert(state == 0 || state == 1);
|
||||
|
||||
U64 word_lo = lo / 32;
|
||||
U64 word_hi = CeilIntegerDiv(hi, 32) - 1;
|
||||
|
||||
U64 word_idx = word_lo;
|
||||
U64 bit_idx = 0;
|
||||
|
||||
U64 scan_count = hi - lo;
|
||||
if (scan_count < 32) {
|
||||
U64 bit_lo = lo % 32;
|
||||
U64 bit_hi = hi % 32;
|
||||
U64 word = bit_array.v[word_idx];
|
||||
word ^= state - 1;
|
||||
word &= (1U << bit_hi) - (1U << bit_lo);
|
||||
if (word) {
|
||||
bit_idx = ctz32(word);
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
U32 first_word = bit_array.v[word_idx];
|
||||
first_word ^= state - 1;
|
||||
first_word &= ~0u << (lo % 32);
|
||||
if (first_word) {
|
||||
bit_idx = ctz32(first_word);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (word_idx += 1; word_idx < word_hi; word_idx += 1) {
|
||||
U32 word = bit_array.v[word_idx];
|
||||
word ^= state - 1;
|
||||
if (word != 0) {
|
||||
bit_idx = ctz32(word);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
U64 bit_hi = hi - (word_idx * 32);
|
||||
U32 last_word = bit_array.v[word_idx];
|
||||
last_word ^= state - 1;
|
||||
last_word &= (1 << bit_hi) - 1;
|
||||
if (last_word) {
|
||||
bit_idx = ctz32(last_word);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
word_idx = 0;
|
||||
bit_idx = max_U32;
|
||||
|
||||
exit:;
|
||||
|
||||
U64 result = word_idx * 32 + bit_idx;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
bit_array_scan_right_to_left32(U32Array bit_array, U64 lo, U64 hi, B32 state)
|
||||
{
|
||||
Assert(lo <= hi);
|
||||
Assert(state == 0 || state == 1);
|
||||
|
||||
S64 word_lo = lo / 32;
|
||||
S64 word_hi = CeilIntegerDiv(hi, 32) - 1;
|
||||
|
||||
S64 word_idx = word_hi;
|
||||
S64 bit_idx = -1;
|
||||
|
||||
U64 scan_count = hi - lo;
|
||||
if (scan_count < 32) {
|
||||
S64 bit_lo = lo % 32;
|
||||
S64 bit_hi = bit_lo + scan_count;
|
||||
U32 word = bit_array.v[word_idx];
|
||||
for (bit_idx = bit_hi; bit_idx >= bit_lo; bit_idx -= 1) {
|
||||
U32 bit = ExtractBit(word, bit_idx);
|
||||
if (bit == state) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
U32 last_word = bit_array.v[word_idx];
|
||||
S64 bit_hi = hi % 32;
|
||||
for (bit_idx = bit_hi; bit_idx >= 0; bit_idx -= 1) {
|
||||
U32 bit = ExtractBit(last_word, bit_idx);
|
||||
if (bit == state) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
for (word_idx -= 1; word_idx > word_lo; word_idx -= 1) {
|
||||
U32 word = bit_array.v[word_idx];
|
||||
for (bit_idx = 32 - 1; bit_idx >= 0; bit_idx -= 1) {
|
||||
U32 bit = ExtractBit(word, bit_idx);
|
||||
if (bit == state) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U32 first_word = bit_array.v[word_idx];
|
||||
S64 bit_lo = lo % 32;
|
||||
for (bit_idx = 32 - 1; bit_idx >= bit_lo; bit_idx -= 1) {
|
||||
U32 bit = ExtractBit(first_word, bit_idx);
|
||||
if (bit == state) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
word_idx = 0;
|
||||
bit_idx = max_U32;
|
||||
|
||||
exit:;
|
||||
|
||||
S64 result_s64 = word_idx * 32 + bit_idx;
|
||||
U64 result_u64 = (U64)result_s64;
|
||||
return result_u64;
|
||||
}
|
||||
|
||||
internal Rng1U64
|
||||
bit_array_scan_left_to_right32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count)
|
||||
{
|
||||
Rng1U64 result = rng_1u64(max_U64, max_U64);
|
||||
|
||||
U64 curr_count = 0, rover = lo;
|
||||
while (curr_count < in_row_count) {
|
||||
rover = bit_array_scan_left_to_right32(bit_array, rover, hi, state);
|
||||
|
||||
// no more bits in range
|
||||
if (rover >= hi) {
|
||||
break;
|
||||
}
|
||||
|
||||
// set first match
|
||||
if (result.v[0] == max_U64) {
|
||||
result = rng_1u64(rover, rover);
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset on non-contiguous range
|
||||
B32 is_bit_index_not_adjoined = (result.v[0] + 1 < rover);
|
||||
if (is_bit_index_not_adjoined) {
|
||||
curr_count = 0;
|
||||
result = rng_1u64(max_U64, max_U64);
|
||||
continue;
|
||||
}
|
||||
|
||||
// advance
|
||||
result.v[1] = rover;
|
||||
curr_count -= 1;
|
||||
}
|
||||
|
||||
// did we allocate enough bits?
|
||||
if (curr_count != in_row_count) {
|
||||
result = rng_1u64(max_U64, max_U64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Rng1U64
|
||||
bit_array_scan_right_to_left32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count)
|
||||
{
|
||||
Rng1U64 result = rng_1u64(max_U64, max_U64);
|
||||
|
||||
U64 curr_count = 0, rover = lo;
|
||||
while (curr_count < in_row_count) {
|
||||
rover = bit_array_scan_right_to_left32(bit_array, lo, rover, state);
|
||||
|
||||
// no more bits in range
|
||||
if (rover >= hi) {
|
||||
break;
|
||||
}
|
||||
|
||||
// set first match
|
||||
if (result.v[0] == max_U64) {
|
||||
result = rng_1u64(rover, rover);
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset on non-contiguous range
|
||||
B32 is_bit_index_not_adjoined = (result.v[0] + 1 < rover);
|
||||
if (is_bit_index_not_adjoined) {
|
||||
curr_count = 0;
|
||||
result = rng_1u64(max_U64, max_U64);
|
||||
continue;
|
||||
}
|
||||
|
||||
// advance
|
||||
result.v[0] = rover;
|
||||
curr_count -= 1;
|
||||
}
|
||||
|
||||
// did we allocate enough bits?
|
||||
if (curr_count != in_row_count) {
|
||||
result = rng_1u64(max_U64, max_U64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
bit_array_find_next_unset_bit32(U32Array bit_array)
|
||||
{
|
||||
U64 result = bit_array_scan_left_to_right32(bit_array, 0, bit_array.count*32, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
bit_array_find_next_set_bit32(U32Array bit_array)
|
||||
{
|
||||
U64 result = bit_array_scan_left_to_right32(bit_array, 0, bit_array.count*32, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
bit_array_set_bit32(U32Array bit_array, U64 idx, B32 state)
|
||||
{
|
||||
Assert(idx < bit_array.count*32);
|
||||
U64 word_idx = idx / 32;
|
||||
U64 bit_idx = idx % 32;
|
||||
if (state) {
|
||||
bit_array.v[word_idx] |= (1 << bit_idx);
|
||||
} else {
|
||||
bit_array.v[word_idx] &= ~(1 << bit_idx);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
bit_array_set_bit_range32(U32Array bit_array, Rng1U64 range, B32 state)
|
||||
{
|
||||
for (U64 idx = range.min ; idx < range.max; idx += 1) {
|
||||
bit_array_set_bit32(bit_array, idx, state);
|
||||
}
|
||||
}
|
||||
|
||||
internal U32
|
||||
bit_array_get_bit32(U32Array bit_array, U64 idx)
|
||||
{
|
||||
Assert(idx < bit_array.count*32);
|
||||
U64 word_idx = idx / 32;
|
||||
U64 bit_idx = idx % 32;
|
||||
U32 bit = (bit_array.v[word_idx] & (1 << bit_idx)) >> bit_idx;
|
||||
return bit;
|
||||
}
|
||||
|
||||
internal B32
|
||||
bit_array_is_bit_set(U32Array bit_arr, U64 bit_pos)
|
||||
{
|
||||
U64 word_idx = bit_pos / 32;
|
||||
Assert(word_idx < bit_arr.count);
|
||||
U32 word = bit_arr.v[word_idx];
|
||||
U64 bit_idx = bit_pos % 32;
|
||||
B32 is_set = !!(word & (1 << bit_idx));
|
||||
return is_set;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
internal U32Array bit_array_init32(Arena *arena, U64 word_count);
|
||||
internal U64 bit_array_scan_left_to_right32(U32Array bit_array, U64 lo, U64 hi, B32 state);
|
||||
internal U64 bit_array_scan_right_to_left32(U32Array bit_array, U64 lo, U64 hi, B32 state);
|
||||
internal Rng1U64 bit_array_scan_left_to_right32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count);
|
||||
internal Rng1U64 bit_array_scan_right_to_left32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count);
|
||||
internal B32 byte_scan_right_to_left(U8 *start, U8 *opl, U8 byte, U64 *offset_out);
|
||||
internal U64 bit_array_find_next_unset_bit32(U32Array bit_array);
|
||||
internal U64 bit_array_find_next_set_bit32(U32Array bit_array);
|
||||
internal void bit_array_set_bit32(U32Array bit_array, U64 idx, B32 state);
|
||||
internal void bit_array_set_bit_range32(U32Array bit_array, Rng1U64 range, B32 state);
|
||||
internal U32 bit_array_get_bit32(U32Array bit_array, U64 idx);
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmacro-redefined"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning (push, 0)
|
||||
#endif
|
||||
|
||||
#include "../third_party_ext/blake3/c/blake3_portable.c"
|
||||
|
||||
#if defined(_M_AMD64) || defined(__x86_64__)
|
||||
|
||||
#define round_fn sse2_round_fn
|
||||
#define compress_pre sse2_compress_pre
|
||||
|
||||
#include "../third_party_ext/blake3/c/blake3_sse2.c"
|
||||
|
||||
#define loadu sse41_loadu
|
||||
#define storeu sse41_storeu
|
||||
#define addv sse41_addv
|
||||
#define xorv sse41_xorv
|
||||
#define set1 sse41_set1
|
||||
#define set4 sse41_set4
|
||||
#define rot16 sse41_rot16
|
||||
#define rot12 sse41_rot12
|
||||
#define rot8 sse41_rot8
|
||||
#define rot7 sse41_rot7
|
||||
#define g1 sse41_g1
|
||||
#define g2 sse41_g2
|
||||
#define diagonalize sse41_diagonalize
|
||||
#define undiagonalize sse41_undiagonalize
|
||||
#define compress_pre sse41_compress_pre
|
||||
#define round_fn sse41_round_fn
|
||||
#define transpose_vecs sse41_transpose_vecs
|
||||
#define transpose_msg_vecs sse41_transpose_msg_vecs
|
||||
#define load_counters sse41_load_counters
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute push(__attribute__((target("sse4.1"))), apply_to=function)
|
||||
#endif
|
||||
#include "../third_party_ext/blake3/c/blake3_sse41.c"
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#define loadu avx2_loadu
|
||||
#define storeu avx2_storeu
|
||||
#define addv avx2_addv
|
||||
#define xorv avx2_xorv
|
||||
#define set1 avx2_set1
|
||||
#define rot7 avx2_rot7
|
||||
#define rot8 avx2_rot8
|
||||
#define rot12 avx2_rot12
|
||||
#define rot16 avx2_rot16
|
||||
#define round_fn avx2_round_fn
|
||||
#define transpose_vecs avx2_transpose_vecs
|
||||
#define transpose_msg_vecs avx2_transpose_msg_vecs
|
||||
#define load_counters avx2_load_counters
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute push(__attribute__((target("avx2"))), apply_to=function)
|
||||
#endif
|
||||
#include "../third_party_ext/blake3/c/blake3_avx2.c"
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#define set4 avx512_set4
|
||||
#define g1 avx512_g1
|
||||
#define g2 avx512_g2
|
||||
#define diagonalize avx512_diagonalize
|
||||
#define undiagonalize avx512_undiagonalize
|
||||
#define compress_pre avx512_compress_pre
|
||||
#define transpose_vecs avx512_transpose_vecs
|
||||
#define transpose_msg_vecs avx512_transpose_msg_vecs
|
||||
#define load_counters avx512_load_counters
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute push(__attribute__((target("avx512f,avx512vl"))), apply_to=function)
|
||||
#endif
|
||||
#include "../third_party_ext/blake3/c/blake3_avx512.c"
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
#include "../third_party_ext/blake3/c/blake3_neon.c"
|
||||
#endif
|
||||
|
||||
#include "../third_party_ext/blake3/c/blake3_dispatch.c"
|
||||
#include "../third_party_ext/blake3/c/blake3.c"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning (pop, 0)
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(__clang__) && defined(__x86_64__)
|
||||
# if defined(__IMMINTRIN_H)
|
||||
# error "include this header before immintrin.h / x86intrin.h / intrin.h"
|
||||
# endif
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wreserved-macro-identifier"
|
||||
# pragma push_macro("__AVX__")
|
||||
# pragma push_macro("__AVX2__")
|
||||
# pragma push_macro("__SSE4_1__")
|
||||
# pragma push_macro("__AVX512F__")
|
||||
# pragma push_macro("__AVX512VL__")
|
||||
# define __AVX__ 1
|
||||
# define __AVX2__ 1
|
||||
# define __SSE4_1__ 1
|
||||
# define __AVX512F__ 1
|
||||
# define __AVX512VL__ 1
|
||||
# include <immintrin.h>
|
||||
# pragma pop_macro("__AVX512VL__")
|
||||
# pragma pop_macro("__AVX512F__")
|
||||
# pragma pop_macro("__SSE4_1__")
|
||||
# pragma pop_macro("__AVX2__")
|
||||
# pragma pop_macro("__AVX__")
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "../third_party_ext/blake3/c/blake3.h"
|
||||
|
||||
static void
|
||||
blake3(void* out, size_t outlen, void* in, size_t inlen)
|
||||
{
|
||||
blake3_hasher hasher;
|
||||
blake3_hasher_init(&hasher);
|
||||
blake3_hasher_update(&hasher, in, inlen);
|
||||
blake3_hasher_finalize(&hasher, (uint8_t*)out, outlen);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "../third_party_ext/blake3/blake3_portable.c"
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
#include "../third_party_ext/blake3/blake3_neon.c"
|
||||
#endif
|
||||
|
||||
#include "../third_party_ext/blake3/blake3_dispatch.c"
|
||||
#include "../third_party_ext/blake3/blake3.c"
|
||||
|
||||
#pragma comment (lib, "blake3")
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_BLAKE3_H
|
||||
#define BASE_BLAKE3_H
|
||||
|
||||
#include "../third_party_ext/blake3/blake3.h"
|
||||
|
||||
static void
|
||||
blake3(void* out, size_t outlen, void* in, size_t inlen)
|
||||
{
|
||||
blake3_hasher hasher;
|
||||
blake3_hasher_init(&hasher);
|
||||
blake3_hasher_update(&hasher, in, inlen);
|
||||
blake3_hasher_finalize(&hasher, (uint8_t*)out, outlen);
|
||||
}
|
||||
|
||||
#endif // BASE_BLAKE3_H
|
||||
@@ -0,0 +1,227 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal U16
|
||||
safe_cast_u16x(U64 x)
|
||||
{
|
||||
AssertAlways(x <= max_U16);
|
||||
return (U16)x;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64
|
||||
u128_mod64(U128 a, U64 b)
|
||||
{
|
||||
return a.u64[1] % b;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal Version
|
||||
make_version(U64 major, U64 minor)
|
||||
{
|
||||
Version version;
|
||||
version.major = major;
|
||||
version.minor = minor;
|
||||
return version;
|
||||
}
|
||||
|
||||
internal int
|
||||
version_compar(Version a, Version b)
|
||||
{
|
||||
int cmp = 0;
|
||||
if (a.major < b.major) {
|
||||
cmp = -1;
|
||||
} else if (a.major > b.major) {
|
||||
cmp = +1;
|
||||
} else if (a.major == b.major) {
|
||||
if (a.minor < b.minor) {
|
||||
cmp = -1;
|
||||
} else if (a.minor > b.minor) {
|
||||
cmp = +1;
|
||||
}
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal ISectOff
|
||||
isect_off(U32 isect, U32 off)
|
||||
{
|
||||
ISectOff result = { isect, off };
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal int
|
||||
u16_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U16 a = *(U16*)raw_a;
|
||||
U16 b = *(U16*)raw_b;
|
||||
int result = a < b ? -1 :
|
||||
a > b ? +1 :
|
||||
0;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
u32_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U32 a = *(U32*)raw_a;
|
||||
U32 b = *(U32*)raw_b;
|
||||
int result = a < b ? -1 :
|
||||
a > b ? +1 :
|
||||
0;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
u64_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U64 a = *(const U64*)raw_a;
|
||||
U64 b = *(const U64*)raw_b;
|
||||
int result = a < b ? -1 : a > b ? +1 : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
u64_compar_inv(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U64 a = *(const U64*)raw_a;
|
||||
U64 b = *(const U64*)raw_b;
|
||||
int result = a < b ? +1 : a > b ? -1 : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
u16_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U16 *a = (U16 *)raw_a;
|
||||
U16 *b = (U16 *)raw_b;
|
||||
int is_before = *a < *b;
|
||||
return is_before;
|
||||
}
|
||||
|
||||
internal int
|
||||
u32_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U32 *a = (U32 *)raw_a;
|
||||
U32 *b = (U32 *)raw_b;
|
||||
int is_before = *a < *b;
|
||||
return is_before;
|
||||
}
|
||||
|
||||
internal int
|
||||
u64_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U64 *a = (U64 *)raw_a;
|
||||
U64 *b = (U64 *)raw_b;
|
||||
int is_before = *a < *b;
|
||||
return is_before;
|
||||
}
|
||||
|
||||
|
||||
internal int
|
||||
u8_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U8 *a = (U8 *) raw_a;
|
||||
U8 *b = (U8 *) raw_b;
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
u16_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U16 *a = (U16 *) raw_a;
|
||||
U16 *b = (U16 *) raw_b;
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
u32_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U32 *a = (U32 *) raw_a;
|
||||
U32 *b = (U32 *) raw_b;
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
u64_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U64 *a = (U64 *) raw_a;
|
||||
U64 *b = (U64 *) raw_b;
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u32_is_before_v0(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU32 *a = raw_a;
|
||||
PairU32 *b = raw_b;
|
||||
return a->v0 < b->v0;
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u32_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU32 *a = raw_a;
|
||||
PairU32 *b = raw_b;
|
||||
return a->v1 < b->v1;
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u64_is_before_v0(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU64 *a = raw_a;
|
||||
PairU64 *b = raw_b;
|
||||
return a->v0 < b->v0;
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u64_is_before_v1(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU64 *a = raw_a;
|
||||
PairU64 *b = raw_b;
|
||||
return a->v1 < b->v1;
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u32_compar_v0(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const PairU32 *a = raw_a;
|
||||
const PairU32 *b = raw_b;
|
||||
return u32_compar(&a->v0, &b->v0);
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u64_compar_v0(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const PairU64 *a = raw_a;
|
||||
const PairU64 *b = raw_b;
|
||||
return u64_compar(&a->v0, &b->v0);
|
||||
}
|
||||
|
||||
internal int
|
||||
pair_u64_compar_v1(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const PairU64 *a = raw_a;
|
||||
const PairU64 *b = raw_b;
|
||||
return u64_compar(&a->v1, &b->v1);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
str8_list_concat_in_place_array(String8List *list, String8List *arr, U64 count)
|
||||
{
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
str8_list_concat_in_place(list, &arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# define COMPILER_STRING "MSVC"
|
||||
#elif COMPILER_CLANG
|
||||
# define COMPILER_STRING "Clang"
|
||||
#elif COMPILER_GCC
|
||||
# define COMPILER_STRING "GCC"
|
||||
#else
|
||||
# error "undefined compiler string"
|
||||
#endif
|
||||
|
||||
#if BUILD_DEBUG
|
||||
# define BUILD_MODE_STRING "Debug"
|
||||
#else
|
||||
# define BUILD_MODE_STRING "Release"
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define BitExtract(x, count, shift) (((x) >> (shift)) & ((1 << (count)) - 1))
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#if OS_WINDOWS
|
||||
# define ins_atomic_ptr_eval_cond_assign(x,k,c) InterlockedCompareExchangePointer((volatile PVOID *)(x),(k),(c))
|
||||
# define ins_atomic_u32_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c)
|
||||
# define ins_atomic_u32_inc_eval(x) InterlockedIncrement((volatile LONG *)x)
|
||||
#else
|
||||
# error "atomics are not defined for this system"
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
// Linked List Helpers
|
||||
|
||||
#define DLLConcatInPlace(list, to_concat) do { \
|
||||
if ((to_concat)->count) { \
|
||||
if ((list)->count) { \
|
||||
(list)->last->next = (to_concat)->first; \
|
||||
(to_concat)->first->prev = (list)->last; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} else { \
|
||||
(list)->first = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} \
|
||||
(list)->count += (to_concat)->count; \
|
||||
MemoryZeroStruct(to_concat); \
|
||||
} \
|
||||
} while (0)
|
||||
#define DLLConcatInPlaceArray(list, to_concat_arr, count) for (U64 i = 0; i < (count); i += 1) { DLLConcatInPlace(list, &(to_concat_arr)[i]); }
|
||||
|
||||
#define SLLQueuePushCount(list, node) do { \
|
||||
SLLQueuePush((list)->first, (list)->last, node); \
|
||||
++(list)->count; \
|
||||
} while (0)
|
||||
|
||||
#define SLLConcatInPlaceNoCount(list, to_concat) do { \
|
||||
if ((to_concat)->first) { \
|
||||
if ((list)->first) { \
|
||||
(list)->last->next = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} else { \
|
||||
(list)->first = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} \
|
||||
MemoryZeroStruct(to_concat); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLLConcatInPlace(list, to_concat) do { \
|
||||
if ((to_concat)->count) { \
|
||||
if ((list)->count) { \
|
||||
(list)->last->next = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} else { \
|
||||
(list)->first = (to_concat)->first; \
|
||||
(list)->last = (to_concat)->last; \
|
||||
} \
|
||||
(list)->count += (to_concat)->count; \
|
||||
MemoryZeroStruct(to_concat); \
|
||||
} \
|
||||
} while (0)
|
||||
#define SLLConcatInPlaceArray(list, to_concat_arr, count) for (U64 i = 0; i < (count); ++i) { SLLConcatInPlace(list, &(to_concat_arr)[i]); }
|
||||
|
||||
#define SLLConcatInPlaceChunkList(list, to_concat, chunk_type) do { \
|
||||
if ((list)->last != 0) { \
|
||||
U64 base_cursor = (list)->last->base + (list)->last->count; \
|
||||
for (chunk_type *c = (to_concat)->first; c != 0; c = c->next) { \
|
||||
c->base = base_cursor; \
|
||||
base_cursor += c->count; \
|
||||
} \
|
||||
} \
|
||||
SLLConcatInPlace(list, to_concat); \
|
||||
} while (0)
|
||||
|
||||
#define SLLConcatInPlaceChunkListArray(list, to_concat_arr, type, count) for (U64 i = 0; i < (count); ++i) { SLLConcatInPlaceChunkList(list, &(to_concat_arr)[i], type); }
|
||||
|
||||
#define SLLChunkListPush(_arena, _list, _cap, _value_type) do { \
|
||||
if ((_list)->last == 0 || (_list)->last->count >= (_list)->last->cap) { \
|
||||
_value_type##Chunk *new_chunk = push_array(_arena, _value_type##Chunk, 1); \
|
||||
new_chunk->v = push_array(_arena, _value_type, _cap); \
|
||||
new_chunk->cap = _cap; \
|
||||
new_chunk->base = (_list)->last ? (_list)->last->base + (_list)->last->cap : 0; \
|
||||
SLLQueuePushCount(_list, new_chunk); \
|
||||
} \
|
||||
_value_type *v = &(_list)->last->v[(_list)->last->count++]; \
|
||||
v->chunk = (_list)->last; \
|
||||
} while (0)
|
||||
|
||||
#define SLLChunkListPushZero(_arena, _list, _cap, _value_type) do { \
|
||||
SLLChunkListPush(_arena, _list, _cap, _value_type); \
|
||||
MemoryZeroStruct(SLLChunkListLastItem(_list)); \
|
||||
SLLChunkListLastItem(_list)->chunk = (_list)->last; \
|
||||
} while(0)
|
||||
|
||||
#define SLLChunkListLastItem(_list) (&(_list)->last->v[(_list)->last->count - 1])
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define MemoryIsZeroStruct(p) memory_is_zero(p, sizeof(*p))
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#if ARCH_LITTLE_ENDIAN
|
||||
# define BE_U32(x) bswap_u32(x)
|
||||
#else
|
||||
# define BE_U32(x) (x)
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 major;
|
||||
U64 minor;
|
||||
} Version;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct ISectOff
|
||||
{
|
||||
U32 isect;
|
||||
U32 off;
|
||||
} ISectOff;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct PairU32
|
||||
{
|
||||
U32 v0;
|
||||
U32 v1;
|
||||
} PairU32;
|
||||
|
||||
typedef struct PairU64
|
||||
{
|
||||
U64 v0;
|
||||
U64 v1;
|
||||
} PairU64;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U16 safe_cast_u16x(U64 x);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64 u128_mod64(U128 a, U64 b);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal Version make_version(U64 major, U64 minor);
|
||||
internal int version_compar(Version a, Version b);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal ISectOff isect_off(U32 isect, U32 off);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal int u16_compar(const void *raw_a, const void *raw_b);
|
||||
internal int u32_compar(const void *raw_a, const void *raw_b);
|
||||
internal int u64_compar(const void *raw_a, const void *raw_b);
|
||||
|
||||
internal int u8_is_before(void *raw_a, void *raw_b);
|
||||
internal int u16_is_before(void *raw_a, void *raw_b);
|
||||
internal int u32_is_before(void *raw_a, void *raw_b);
|
||||
internal int u64_is_before(void *raw_a, void *raw_b);
|
||||
|
||||
internal int pair_u32_is_before_v0(void *raw_a, void *raw_b);
|
||||
internal int pair_u32_is_before_v1(void *raw_a, void *raw_b);
|
||||
internal int pair_u64_is_before_v0(void *raw_a, void *raw_b);
|
||||
internal int pair_u64_is_before_v1(void *raw_a, void *raw_b);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void str8_list_concat_in_place_array(String8List *list, String8List *arr, U64 count);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal U32
|
||||
update_crc32(U32 crc, U8 *ptr, U64 size)
|
||||
{
|
||||
// CRC-32 algo borrowed from stb.h
|
||||
|
||||
local_persist U32 crc_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
|
||||
0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
|
||||
0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
|
||||
0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
|
||||
0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
|
||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,
|
||||
0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
|
||||
0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,
|
||||
0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,
|
||||
0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,
|
||||
0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,
|
||||
0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
|
||||
0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
|
||||
0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
|
||||
0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
|
||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,
|
||||
0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
|
||||
0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
|
||||
0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
|
||||
0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
#if 0
|
||||
for (U32 i = 0; i < 256; ++i) {
|
||||
U32 s = i;
|
||||
for (U32 j = 0; j < 8; ++j) {
|
||||
s = (s >> 1) ^ (s & 1 ? 0xedb88320 : 0);
|
||||
}
|
||||
crc_table[i] = s;
|
||||
}
|
||||
#endif
|
||||
|
||||
crc = ~crc;
|
||||
for (U32 i = 0; i < size; ++i) {
|
||||
crc = (crc >> 8) ^ crc_table[(ptr[i] ^ crc) & 0xff];
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
internal U32
|
||||
crc32_from_string(String8 string)
|
||||
{
|
||||
return update_crc32(0, string.str, string.size);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
internal U32 update_crc32(U32 crc, U8 *ptr, U64 size);
|
||||
internal U32 crc32_from_string(String8 string);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "base_core.c"
|
||||
#include "base_strings.c"
|
||||
#include "base_arena.c"
|
||||
#include "base_math.c"
|
||||
#include "base_arrays.c"
|
||||
#include "base_bit_array.c"
|
||||
#include "base_crc32.c"
|
||||
#include "base_md5.c"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base_core.h"
|
||||
#include "base_strings.h"
|
||||
#include "base_arena.h"
|
||||
#include "base_math.h"
|
||||
#include "base_arrays.h"
|
||||
#include "base_blake3.h"
|
||||
#include "base_bit_array.h"
|
||||
#include "base_crc32.h"
|
||||
#include "base_md5.h"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
rng_1u64_list_push_node(Rng1U64List *list, Rng1U64Node *node)
|
||||
{
|
||||
SLLQueuePush(list->first, list->last, node);
|
||||
++list->count;
|
||||
}
|
||||
|
||||
internal Rng1U64Node *
|
||||
rng_1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 range)
|
||||
{
|
||||
Rng1U64Node *node = push_array(arena, Rng1U64Node, 1);
|
||||
node->v = range;
|
||||
rng_1u64_list_push_node(list, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct Rng1U64Node
|
||||
{
|
||||
struct Rng1U64Node *next;
|
||||
Rng1U64 v;
|
||||
} Rng1U64Node;
|
||||
|
||||
typedef struct Rng1U64List
|
||||
{
|
||||
U64 count;
|
||||
Rng1U64Node *first;
|
||||
Rng1U64Node *last;
|
||||
} Rng1U64List;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void rng_1u64_list_push_node(Rng1U64List *list, Rng1U64Node *node);
|
||||
internal Rng1U64Node * rng_1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 range);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal MD5Hash
|
||||
md5_hash_from_string(String8 data)
|
||||
{
|
||||
MD5_CTX ctx; MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, (void*)data.str, safe_cast_u32(data.size));
|
||||
MD5Hash hash; MD5_Final((unsigned char*)&hash, &ctx);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct MD5Hash
|
||||
{
|
||||
U8 value[16];
|
||||
} MD5Hash;
|
||||
|
||||
internal MD5Hash md5_hash_from_string(String8 data);
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
global read_only String8 g_null_string;
|
||||
|
||||
internal String8
|
||||
str8_cstring_capped_reverse(void *start, void *cap)
|
||||
{
|
||||
char *ptr = cap;
|
||||
while (ptr > (char *)start) {
|
||||
--ptr;
|
||||
if (*ptr == '\0') break;
|
||||
}
|
||||
U64 null_offset = (U64)(ptr - (char *) start);
|
||||
String8 result = str8((U8 *) start, null_offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags)
|
||||
{
|
||||
for (S64 i = string.size - start_pos - needle.size; i >= 0; --i) {
|
||||
String8 haystack = str8_substr(string, rng_1u64(i, i + needle.size));
|
||||
if (str8_match(haystack, needle, flags)) {
|
||||
return (U64)i + needle.size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal int
|
||||
str8_compar(String8 a, String8 b, B32 ignore_case)
|
||||
{
|
||||
int cmp = 0;
|
||||
U64 size = Min(a.size, b.size);
|
||||
if (ignore_case) {
|
||||
for (U64 i = 0; i < size; ++i) {
|
||||
U8 la = char_to_lower(a.str[i]);
|
||||
U8 lb = char_to_lower(b.str[i]);
|
||||
if (la < lb) {
|
||||
cmp = -1;
|
||||
break;
|
||||
} else if (la > lb) {
|
||||
cmp = +1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (U64 i = 0; i < size; ++i) {
|
||||
if (a.str[i] < b.str[i]) {
|
||||
cmp = -1;
|
||||
break;
|
||||
} else if (a.str[i] > b.str[i]) {
|
||||
cmp = +1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cmp == 0) {
|
||||
// shorter prefix must precede longer prefixes
|
||||
if (a.size > b.size) {
|
||||
cmp = +1;
|
||||
} else if (b.size > a.size) {
|
||||
cmp = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
internal int
|
||||
str8_compar_ignore_case(const void *a, const void *b)
|
||||
{
|
||||
return str8_compar(*(String8*)a, *(String8*)b, 1);
|
||||
}
|
||||
|
||||
internal int
|
||||
str8_compar_case_sensetive(const void *a, const void *b)
|
||||
{
|
||||
return str8_compar(*(String8*)a, *(String8*)b, 0);
|
||||
}
|
||||
|
||||
internal int
|
||||
str8_is_before_case_sensetive(const void *a, const void *b)
|
||||
{
|
||||
int cmp = str8_compar_case_sensetive(a, b);
|
||||
return cmp < 0;
|
||||
}
|
||||
|
||||
internal String8Node *
|
||||
str8_list_push_raw(Arena *arena, String8List *list, void *data_ptr, U64 data_size)
|
||||
{
|
||||
String8 data = str8((U8 *)data_ptr, data_size);
|
||||
String8Node *node = str8_list_push(arena, list, data);
|
||||
return node;
|
||||
}
|
||||
|
||||
internal U64
|
||||
str8_list_push_pad(Arena *arena, String8List *list, U64 offset, U64 align)
|
||||
{
|
||||
U64 pad_size = AlignPow2(offset, align) - offset;
|
||||
U8 *pad = push_array(arena, U8, pad_size);
|
||||
MemorySet(pad, 0, pad_size);
|
||||
str8_list_push(arena, list, str8(pad, pad_size));
|
||||
return pad_size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
str8_list_push_pad_front(Arena *arena, String8List *list, U64 offset, U64 align)
|
||||
{
|
||||
U64 pad_size = AlignPow2(offset, align) - offset;
|
||||
U8 *pad = push_array(arena, U8, pad_size);
|
||||
MemorySet(pad, 0, pad_size);
|
||||
str8_list_push_front(arena, list, str8(pad, pad_size));
|
||||
return pad_size;
|
||||
}
|
||||
|
||||
internal String8List
|
||||
str8_list_arr_concat(String8List *v, U64 count)
|
||||
{
|
||||
String8List result = {0};
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
str8_list_concat_in_place(&result, &v[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8Node *
|
||||
str8_list_push_many(Arena *arena, String8List *list, U64 count)
|
||||
{
|
||||
String8Node *arr = push_array(arena, String8Node, count);
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
str8_list_push_node(list, arr + i);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_bits_u32(Arena *arena, U32 x)
|
||||
{
|
||||
U8 c0 = 'a' + ((x >> 28) & 0xf);
|
||||
U8 c1 = 'a' + ((x >> 24) & 0xf);
|
||||
U8 c2 = 'a' + ((x >> 20) & 0xf);
|
||||
U8 c3 = 'a' + ((x >> 16) & 0xf);
|
||||
U8 c4 = 'a' + ((x >> 12) & 0xf);
|
||||
U8 c5 = 'a' + ((x >> 8) & 0xf);
|
||||
U8 c6 = 'a' + ((x >> 4) & 0xf);
|
||||
U8 c7 = 'a' + ((x >> 0) & 0xf);
|
||||
String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_bits_u64(Arena *arena, U64 x)
|
||||
{
|
||||
U8 c0 = 'a' + ((x >> 60) & 0xf);
|
||||
U8 c1 = 'a' + ((x >> 56) & 0xf);
|
||||
U8 c2 = 'a' + ((x >> 52) & 0xf);
|
||||
U8 c3 = 'a' + ((x >> 48) & 0xf);
|
||||
U8 c4 = 'a' + ((x >> 44) & 0xf);
|
||||
U8 c5 = 'a' + ((x >> 40) & 0xf);
|
||||
U8 c6 = 'a' + ((x >> 36) & 0xf);
|
||||
U8 c7 = 'a' + ((x >> 32) & 0xf);
|
||||
U8 c8 = 'a' + ((x >> 28) & 0xf);
|
||||
U8 c9 = 'a' + ((x >> 24) & 0xf);
|
||||
U8 ca = 'a' + ((x >> 20) & 0xf);
|
||||
U8 cb = 'a' + ((x >> 16) & 0xf);
|
||||
U8 cc = 'a' + ((x >> 12) & 0xf);
|
||||
U8 cd = 'a' + ((x >> 8) & 0xf);
|
||||
U8 ce = 'a' + ((x >> 4) & 0xf);
|
||||
U8 cf = 'a' + ((x >> 0) & 0xf);
|
||||
String8 result = push_str8f(arena,
|
||||
"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8Node *
|
||||
str8_list_pop_front(String8List *list)
|
||||
{
|
||||
String8Node *node = 0;
|
||||
if (list->node_count) {
|
||||
node = list->first;
|
||||
Assert(list->total_size >= list->first->string.size);
|
||||
list->node_count -= 1;
|
||||
list->total_size -= list->first->string.size;
|
||||
SLLQueuePop(list->first, list->last);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_memory_size2(Arena *arena, U64 size)
|
||||
{
|
||||
String8 result;
|
||||
if (size < KB(1)) {
|
||||
result = push_str8f(arena, "%llu Bytes", size);
|
||||
} else if (size < MB(1)) {
|
||||
result = push_str8f(arena, "%llu.%02llu KiB", size / KB(1), ((size * 100) / KB(1)) % 100);
|
||||
} else if (size < GB(1)) {
|
||||
result = push_str8f(arena, "%llu.%02llu MiB", size / MB(1), ((size * 100) / MB(1)) % 100);
|
||||
} else if (size < TB(1)) {
|
||||
result = push_str8f(arena, "%llu.%02llu GiB", size / GB(1), ((size * 100) / GB(1)) % 100);
|
||||
} else {
|
||||
result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_count(Arena *arena, U64 count)
|
||||
{
|
||||
String8 result;
|
||||
if (count < 1000) {
|
||||
result = push_str8f(arena, "%llu", count);
|
||||
} else if (count < 1000000) {
|
||||
U64 frac = ((count * 100) / 1000) % 100;
|
||||
if (frac) {
|
||||
result = push_str8f(arena, "%llu.%02lluK", count / 1000, frac);
|
||||
} else {
|
||||
result = push_str8f(arena, "%lluK", count / 1000);
|
||||
}
|
||||
} else if (count < 1000000000) {
|
||||
U64 frac = ((count * 100) / 1000000) % 100;
|
||||
if (frac) {
|
||||
result = push_str8f(arena, "%llu.%02lluM", count / 1000000, frac);
|
||||
} else {
|
||||
result = push_str8f(arena, "%lluM", count / 1000000);
|
||||
}
|
||||
} else {
|
||||
U64 frac = ((count * 100) * 1000000000) % 100;
|
||||
if (frac) {
|
||||
result = push_str8f(arena, "%llu.%02lluB", count / 1000000000, frac);
|
||||
} else {
|
||||
result = push_str8f(arena, "%lluB", count / 1000000000, frac);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
hash_from_str8(String8 string)
|
||||
{
|
||||
XXH64_hash_t hash64 = XXH3_64bits(string.str, string.size);
|
||||
return hash64;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MemoryCopyStr8(dst, s) MemoryCopy(dst, (s).str, (s).size)
|
||||
|
||||
internal String8 str8_cstring_capped_reverse(void *start, void *cap);
|
||||
|
||||
internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
|
||||
|
||||
internal int str8_compar(String8 a, String8 b, B32 ignore_case);
|
||||
internal int str8_compar_ignore_case(const void *a, const void *b);
|
||||
internal int str8_compar_case_sensetive(const void *a, const void *b);
|
||||
|
||||
#define str8_list_push_struct(a,l,d) str8_list_push_raw(a, l, d, sizeof(*d))
|
||||
internal String8Node * str8_list_push_raw(Arena *arena, String8List *list, void *data_ptr, U64 data_size);
|
||||
internal U64 str8_list_push_pad(Arena *arena, String8List *list, U64 offset, U64 align);
|
||||
internal U64 str8_list_push_pad_front(Arena *arena, String8List *list, U64 offset, U64 align);
|
||||
internal String8List str8_list_arr_concat(String8List *v, U64 count);
|
||||
internal String8Node * str8_list_push_many(Arena *arena, String8List *list, U64 count);
|
||||
|
||||
internal String8 str8_from_bits_u32(Arena *arena, U32 x);
|
||||
internal String8 str8_from_bits_u64(Arena *arena, U64 x);
|
||||
|
||||
// TODO: remove
|
||||
internal String8Node * str8_list_pop_front(String8List *list);
|
||||
|
||||
internal String8 str8_from_memory_size2(Arena *arena, U64 size);
|
||||
internal String8 str8_from_count(Arena *arena, U64 count);
|
||||
|
||||
internal U64 hash_from_str8(String8 string);
|
||||
|
||||
Reference in New Issue
Block a user