reinit repo after broken git

This commit is contained in:
krzosa
2024-12-29 10:10:09 +01:00
commit a30a897272
40 changed files with 13769 additions and 0 deletions

132
src/core/arena.c Normal file
View File

@@ -0,0 +1,132 @@
b32 is_pow2(usize x) {
b32 result = (((x) & ((x)-1)) == 0);
return result;
}
usize get_align_offset(usize size, usize align) {
assert(is_pow2(align));
if (align == 0) return 0;
usize mask = align - 1;
usize val = size & mask;
if (val) {
val = align - val;
}
return val;
}
usize align_up(usize size, usize align) {
usize result = size + get_align_offset(size, align);
return result;
}
usize align_down(usize size, usize align) {
size += 1; // Make sure when align is 8 doesn't get rounded down to 0
usize result = size - (align - get_align_offset(size, align));
return result;
}
void ma_init(ma_arena_t *arena, usize reserve) {
reserve = align_up(reserve, ma_page_size);
arena->align = ma_default_alignment;
arena->data = (u8 *)vmem_reserve(reserve);
if (arena->data) {
arena->reserve = reserve;
}
}
ma_arena_t *ma_create(usize reserve) {
ma_arena_t *result = NULL;
void *data = vmem_reserve(reserve);
if (!data) return result;
b32 success = vmem_commit(data, ma_page_size);
if (!success) {
vmem_release(data);
return result;
}
result = (ma_arena_t *)data;
result->data = (u8 *)data;
result->reserve = reserve;
result->commit = ma_page_size;
result->len = result->base_len = sizeof(ma_arena_t);
result->align = ma_default_alignment;
return result;
}
void *ma_push_size_ex(ma_arena_t *arena, usize size) {
// base_len is used for bootstraping arenas, it denotes the
// space occupied by the arena. If len is smaller then base_len then
// we start to overwrite the arena itself - pure barbarism.
assert(arena->len >= arena->base_len);
usize align_offset = 0;
if (arena->align) {
align_offset = get_align_offset((usize)arena->data + arena->len, arena->align);
}
usize size_with_alignment = size + align_offset;
usize new_len = arena->len + size_with_alignment;
if (new_len > arena->commit) {
if (arena->reserve == 0) {
ma_init(arena, ma_default_reserve_size);
}
usize new_len_aligned_to_page_size = align_up(new_len, ma_page_size);
usize to_commit = new_len_aligned_to_page_size - arena->commit;
usize to_commit_clamped = CLAMP_TOP(to_commit, arena->reserve);
if (to_commit_clamped > 0) {
b32 success = vmem_commit(arena->data + arena->commit, to_commit_clamped);
if (success) {
MA_ASAN_UNPOISON_MEMORY_REGION(arena->data + arena->commit, to_commit_clamped);
arena->commit += to_commit_clamped;
}
}
if (new_len > arena->commit) {
return NULL;
}
}
u8 *result = arena->data + arena->len + align_offset;
arena->len = new_len;
MA_ASAN_UNPOISON_MEMORY_REGION(result, size);
return (void *)result;
}
void *ma_push_size(ma_arena_t *arena, usize size) {
void *result = ma_push_size_ex(arena, size);
if (result) memory_zero(result, size);
return result;
}
ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size) {
ma_arena_t *result = ma_push_type(allocator, ma_arena_t);
result->data = (u8 *)ma_push_size(allocator, size);
result->reserve = size;
result->commit = size;
result->align = ma_default_alignment;
return result;
}
void ma_destroy(ma_arena_t *arena) {
if (arena == NULL || arena->data == NULL) return;
b32 zero_memory = (u8 *)arena != arena->data;
vmem_release(arena->data);
if (zero_memory) memory_zero(arena, sizeof(ma_arena_t));
}
void ma_set_len(ma_arena_t *arena, usize pos) {
// base_len is used for bootstraping arenas, it denotes the
// space occupied by the arena. If len is smaller then base_len then
// we start to overwrite the arena itself - pure barbarism.
assert(arena->len >= arena->base_len);
pos = CLAMP(pos, arena->base_len, arena->len);
usize size = arena->len - pos;
arena->len = pos;
MA_ASAN_POISON_MEMORY_REGION(arena->data + arena->len, size);
}
void ma_pop(ma_arena_t *arena, usize size) { ma_set_len(arena, arena->len - size); }
ma_temp_t ma_begin_temp(ma_arena_t *arena) { return (ma_temp_t){arena, arena->len}; }
void ma_end_temp(ma_temp_t temp) { ma_set_len(temp.arena, temp.len); }
void ma_set0(ma_arena_t *arena) { ma_set_len(arena, 0); }

41
src/core/core.c Normal file
View File

@@ -0,0 +1,41 @@
#include <stdarg.h>
#if PLATFORM_WINDOWS
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#if PLATFORM_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
#if !defined(ASAN_POISON_MEMORY_REGION)
#define MA_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#else
#define MA_ASAN_POISON_MEMORY_REGION(addr, size) ASAN_POISON_MEMORY_REGION(addr, size)
#define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size)
#endif
#if PLATFORM_CL
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#endif
#include "intrinsics.c"
#include "unicode.c"
#include "mathx.c"
#include "mathx.gen.c"
#include "arena.c"
#define STB_SPRINTF_IMPLEMENTATION
#include "stb_sprintf.h"
#include "string.c"
#include "string8.c"
#include "scratch.c"
#include "log.c"
#include "lexer.c"
#include "type_info.c"

5
src/core/core.h Normal file
View File

@@ -0,0 +1,5 @@
#include "platform_defines.h"
#include <stdint.h>
#include <stddef.h>
#include "types.h"
#include "type_info.h"

126
src/core/intrinsics.c Normal file
View File

@@ -0,0 +1,126 @@
void memory_copy(void *dst, void *src, size_t n) {
#if PLATFORM_CLANG
__builtin_memcpy(dst, src, n);
#else
memcpy(dst, src, n);
#endif
}
void memory_move(void *dest, const void *src, size_t n) {
#if PLATFORM_CLANG
__builtin_memmove(dest, src, n);
#else
memmove(dest, src, n);
#endif
}
void memory_set(void *dst, int c, size_t size) {
#if PLATFORM_CLANG
__builtin_memset(dst, c, size);
#else
memset(dst, c, size);
#endif
}
void memory_zero(void *dst, usize size) { memory_set(dst, 0, size); }
#if PLATFORM_CLANG
f32 f32_sqrt(f32 x) { return __builtin_sqrtf(x); }
f64 f64_sqrt(f64 x) { return __builtin_sqrt(x); }
f32 f32_ceil(f32 x) { return __builtin_ceilf(x); }
f64 f64_ceil(f64 x) { return __builtin_ceil(x); }
f32 f32_floor(f32 x) { return __builtin_floorf(x); }
f64 f64_floor(f64 x) { return __builtin_floor(x); }
f32 f32_abs(f32 x) { return __builtin_fabsf(x); }
f64 f64_abs(f64 x) { return __builtin_fabs(x); }
f32 f32_round(f32 x) { return __builtin_roundf(x); }
f64 f64_round(f64 x) { return __builtin_round(x); }
f64 f64_mod(f64 a, f64 b) { return __builtin_fmod(a, b); }
f32 f32_mod(f32 a, f32 b) { return __builtin_fmodf(a, b); }
#else
f32 f32_sqrt(f32 x) { return sqrtf(x); }
f64 f64_sqrt(f64 x) { return sqrt(x); }
f32 f32_ceil(f32 x) { return ceilf(x); }
f64 f64_ceil(f64 x) { return ceil(x); }
f32 f32_floor(f32 x) { return floorf(x); }
f64 f64_floor(f64 x) { return floor(x); }
f32 f32_abs(f32 x) { return fabsf(x); }
f64 f64_abs(f64 x) { return fabs(x); }
f32 f32_round(f32 x) { return roundf(x); }
f64 f64_round(f64 x) { return round(x); }
f64 f64_mod(f64 a, f64 b) { return fmod(a, b); }
f32 f32_mod(f32 a, f32 b) { return fmodf(a, b); }
#endif
#if PLATFORM_WINDOWS
void *vmem_reserve(size_t size) {
void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
return result;
}
b32 vmem_commit(void *p, size_t size) {
void *result = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
return result ? true : false;
}
b32 vmem_release(void *p) {
BOOL result = VirtualFree(p, 0, MEM_RELEASE);
return result ? true : false;
}
b32 vmem_decommit(void *p, size_t size) {
BOOL result = VirtualFree(p, size, MEM_DECOMMIT);
return result ? true : false;
}
#else
void *vmem_reserve(size_t size) { return NULL; }
b32 vmem_commit(void *p, size_t size) { return false; }
b32 vmem_release(void *p) { return true; }
b32 vmem_decommit(void *p, size_t size) { return true; }
#endif
#if PLATFORM_WASM
f64 s8_deserial_f64(s8_t string);
#else
f64 s8_deserial_f64(s8_t string) { return strtod(string.str, NULL); }
#endif
#if PLATFORM_WINDOWS
void core_log_message(char *string) {
if (IsDebuggerPresent()) {
OutputDebugStringA(string);
}
printf("%s", string);
fflush(stdout);
}
void core_panic(void) {
if (core_desc.on_exit) core_desc.on_exit();
ExitProcess(1);
}
#elif PLATFORM_WASM
void write_to_console(char *string);
void core_log_message(char *string) {
write_to_console(string);
}
void core_panic(void) {
if (core_desc.on_exit) core_desc.on_exit();
debug_break();
}
#else
void core_log_message(char *string) {
printf("%s");
fflush(stdout);
}
void core_panic(void) {
if (core_desc.on_exit) core_desc.on_exit();
debug_break();
}
#endif
void core_on_exit(void) {
debugf("program panicked! exiting...");
}
THREAD_LOCAL core_desc_t core_desc = {
.print = core_log_message,
.panic = core_panic,
.break_on_panic = true,
};

493
src/core/lexer.c Normal file
View File

@@ -0,0 +1,493 @@
typedef enum lex_kind_t lex_kind_t;
enum lex_kind_t {
#define LEX_KIND_XLIST\
X(eof, "end of file", "---")\
X(int, "integer", "---")\
X(real, "real", "---")\
X(ident, "identifier", "---")\
X(string, "string", "---")\
X(comment, "comment", "---")\
X(open_brace, "'{' open brace", "{")\
X(close_brace, "'}' close brace", "}")\
X(open_paren, "'(' open parenthesis", "(")\
X(close_paren, "')' close parenthesis", ")")\
X(open_bracket, "'[' open bracket", "[")\
X(close_bracket, "']' close bracket", "]")\
X(plus, "'+' plus", "+")\
X(minus, "'-' minus", "-")\
X(divide, "'/' division sign", "/")\
X(multiply, "'*' multiplication sign", "*")\
X(modulo, "'%' modulo", "%")\
X(or, "'||' logical or", "||")\
X(and, "'&&' logical and", "&&")\
X(negation, "'!' logical negation", "!")\
X(bit_negation, "'~' bit negation", "~")\
X(bit_left_shift, "'<<' bit left shift", "<<")\
X(bit_right_shift, "'>>' bit right shift", ">>")\
X(bit_or, "'|' bit or", "|")\
X(bit_and, "'&' bit and", "&")\
X(bit_xor, "'^' bit xor", "^")\
X(decrement, "'--' decrement", "--")\
X(increment, "'++' increment", "++")\
X(post_decrement, "'--' post decrement", "--")\
X(post_increment, "'++' post increment", "++")\
X(assign, "'=' assignment", "=")\
X(divide_assign, "'/=' divide assignment", "/=")\
X(multiply_assign, "'*=' multiply assignment", "*=")\
X(plus_assign, "'+=' plus assignment", "+=")\
X(minus_assign, "'-=' minus assignment", "-=")\
X(modulo_assign, "'%=' modulo assignment", "%=")\
X(bit_and_assign, "&=", "&=")\
X(bit_or_assign, "'|=' bit or assignment", "|=")\
X(bit_xor_assign, "'^=' bit xor assignment", "^=")\
X(bit_left_shift_assign, "'<<=' bit left shift assignment", "<<=")\
X(bit_right_shift_assign, "'>>=' bit right shift assignment", ">>=")\
X(equals, "'==' equals sign", "==")\
X(not_equals, "'!=' not equals sign", "!=")\
X(lesser, "'<' lesser then", "<")\
X(greater, "'>' greater then", ">")\
X(lesser_or_equal, "'<=' lesser then or equal", "<=")\
X(greater_or_equal, "'>=' greater then or equal", ">=")\
X(comma, "',' comma", ",")\
X(dot, "'.' dot", ".")\
X(three_dots, "'...' three dots", "...")\
X(semicolon, "';' semicolon", ";")\
X(colon, "':' colon", ":")\
X(arrow, "'->' arrow", "->")\
X(question, "'?' question mark", "?")\
#define X(KIND, STR, SIMPLE) lex_kind_##KIND,
LEX_KIND_XLIST
#undef X
lex_kind_count,
};
typedef enum lex_suffix_t lex_suffix_t;
enum lex_suffix_t {
#define LEX_SUFFIX_XLIST X(none) X(f) X(d) X(u) X(ul) X(ull) X(l) X(ll)
#define X(KIND) lex_suffix_##KIND,
LEX_SUFFIX_XLIST
#undef X
lex_suffix_count,
};
typedef struct lex_t lex_t;
struct lex_t {
lex_kind_t kind;
lex_suffix_t suffix;
union {
struct {char *str; i64 len;};
s8_t s8;
};
int line;
int column;
char *file_name;
union {
u64 integer;
f64 real;
char *error;
};
};
typedef struct lexer_t lexer_t;
struct lexer_t {
char *at;
char *file_name;
int line;
int column;
};
typedef struct lex_array_t lex_array_t;
struct lex_array_t {
lex_t *data;
int len;
};
void lex_panicf(lex_t *token, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch();
S8_FMT(scratch.arena, str, str8);
panicf("%s(%d:%d): error: %S", token->file_name, token->line, token->column, str8);
ma_end_scratch(scratch);
}
lexer_t lex_make(char *begin, char *file_name) {
lexer_t result = {.at = begin, .file_name = file_name};
return result;
}
void lex_advance(lexer_t *lex) {
if (lex->at[0] == 0) return;
if (lex->at[0] == '\n') { lex->column = 0; lex->line += 1; }
lex->column += 1;
lex->at += 1;
}
b32 lex_match(lexer_t *lex, char c) {
if (lex->at[0] == c) {
lex_advance(lex);
return true;
}
return false;
}
void lex_eat_whitespace(lexer_t *lex) {
while (char_is_whitespace(lex->at[0])) lex_advance(lex);
}
u64 lex_map_char_to_int(char c) {
switch (c) {
case '0': return 0; break;
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
case 'a':
case 'A': return 10; break;
case 'b':
case 'B': return 11; break;
case 'c':
case 'C': return 12; break;
case 'd':
case 'D': return 13; break;
case 'e':
case 'E': return 14; break;
case 'f':
case 'F': return 15; break;
default: return 255;
}
}
u64 lex_deserial_u64(char *string, i64 len, u64 base) {
assert(base >= 2 && base <= 16);
u64 acc = 0;
for (i64 i = 0; i < len; i++) {
u64 num = lex_map_char_to_int(string[i]);
if (num >= base) {
panicf("invalid number");
break;
}
acc *= base;
acc += num;
}
return acc;
}
void lex_eat_number(lexer_t *lex, lex_t *token) {
token->kind = lex_kind_int;
for (;;) {
if (char_is_digit(lex->at[0])) {
lex_advance(lex);
continue;
}
if (lex_match(lex, '.')) {
if (token->kind == lex_kind_real) {
lex_panicf(token, "multiple '.' periods in floating point number literal");
}
token->kind = lex_kind_real;
continue;
}
break;
}
if (lex_match(lex, 'f')) {
token->kind = lex_kind_real;
token->suffix = lex_suffix_f;
} else if (lex_match(lex, 'd')) {
token->kind = lex_kind_real;
token->suffix = lex_suffix_d;
} else if (token->kind == lex_kind_int && ((lex->at[0] == 'u' && lex->at[1] == 'l' && lex->at[2] == 'l') || (lex->at[0] == 'U' && lex->at[1] == 'L' && lex->at[2] == 'L'))) {
token->suffix = lex_suffix_ull;
lex_advance(lex); lex_advance(lex); lex_advance(lex);
} else if (token->kind == lex_kind_int && ((lex->at[0] == 'u' && lex->at[1] == 'l') || (lex->at[0] == 'U' && lex->at[1] == 'L'))) {
token->suffix = lex_suffix_ul;
lex_advance(lex); lex_advance(lex);
} else if (token->kind == lex_kind_int && (lex->at[0] == 'l' || lex->at[0] == 'L')) {
token->suffix = lex_suffix_l;
lex_advance(lex);
} else if (token->kind == lex_kind_int && ((lex->at[0] == 'l' && lex->at[1] == 'l') || (lex->at[0] == 'L' && lex->at[1] == 'L'))) {
token->suffix = lex_suffix_ll;
lex_advance(lex); lex_advance(lex);
}
}
void lex_eat_until(lexer_t *lex, char c) {
while (lex->at[0] != c && lex->at[0] != 0) lex_advance(lex);
}
void lex_eat_string(lexer_t *lex, lex_t *token) {
token->kind = lex_kind_string;
for (;;) {
if (lex_match(lex, token->str[0])) {
break;
}
if (lex->at[0] == 0) {
lex_panicf(token, "unclosed string");
}
lex_advance(lex);
}
}
#define LEX_CASE3(C1, K1, C2, K2, C3, K3)\
case C1: {\
token->kind = K1;\
if (lex_match(lex, C2)) {\
lex_advance(lex);\
token->kind = K2;\
} else if (lex_match(lex, C3)) {\
lex_advance(lex);\
token->kind = K3;\
}\
} break
void lex_token_ex(lexer_t *lex, lex_t *token) {
lex_eat_whitespace(lex);
*token = (lex_t){.str = lex->at, .file_name = lex->file_name, .line = lex->line, .column = lex->column};
lex_advance(lex);
switch (token->str[0]) {
case '\0': token->kind = lex_kind_eof; break;
case '{': token->kind = lex_kind_open_brace; break;
case '}': token->kind = lex_kind_close_brace; break;
case '(': token->kind = lex_kind_open_paren; break;
case ')': token->kind = lex_kind_close_paren; break;
case '[': token->kind = lex_kind_open_bracket; break;
case ']': token->kind = lex_kind_close_bracket; break;
case '~': token->kind = lex_kind_bit_negation; break;
case ';': token->kind = lex_kind_semicolon; break;
case ':': token->kind = lex_kind_colon; break;
case ',': token->kind = lex_kind_comma; break;
case '"': lex_eat_string(lex, token); break;
case '`': lex_eat_string(lex, token); break;
case '\'': lex_eat_string(lex, token); break;
case '.': {
token->kind = lex_kind_dot;
if (lex->at[0] == '.' && lex->at[1] == '.') {
lex_advance(lex);
lex_advance(lex);
token->kind = lex_kind_three_dots;
}
} break;
case '/': {
token->kind = lex_kind_divide;
if (lex_match(lex, '/')) {
token->kind = lex_kind_comment;
lex_eat_until(lex, '\n');
} else if (lex_match(lex, '*')) {
token->kind = lex_kind_comment;
for (;;) {
if (lex->at[0] == '*' && lex->at[1] == '/') {
break;
}
if (lex->at[0] == 0) {
lex_panicf(token, "Unclosed block comment");
return;
}
lex_advance(lex);
}
lex_advance(lex);
lex_advance(lex);
} else if (lex_match(lex, '=')) {
token->kind = lex_kind_divide_assign;
lex_advance(lex);
}
} break;
LEX_CASE3('^', lex_kind_bit_xor, '=', lex_kind_bit_xor_assign, /*ignored option*/'=', lex_kind_bit_xor_assign);
LEX_CASE3('=', lex_kind_assign, '=', lex_kind_equals, /*ignored option*/'=', lex_kind_equals);
LEX_CASE3('!', lex_kind_negation, '=', lex_kind_not_equals, /*ignored option*/'=', lex_kind_not_equals);
LEX_CASE3('%', lex_kind_modulo, '=', lex_kind_modulo_assign, /*ignored option*/'=', lex_kind_modulo_assign);
LEX_CASE3('*', lex_kind_multiply, '=', lex_kind_multiply_assign, /*ignored option*/'=', lex_kind_multiply_assign);
LEX_CASE3('+', lex_kind_plus, '+', lex_kind_increment, '=', lex_kind_plus_assign);
LEX_CASE3('-', lex_kind_minus, '-', lex_kind_decrement, '=', lex_kind_minus_assign);
LEX_CASE3('&', lex_kind_bit_and, '&', lex_kind_and, '=', lex_kind_bit_and_assign);
LEX_CASE3('|', lex_kind_bit_or, '|', lex_kind_or, '=', lex_kind_bit_or_assign);
case '>': {
token->kind = lex_kind_greater;
if (lex_match(lex, '=')) {
token->kind = lex_kind_greater_or_equal;
} else if (lex_match(lex, '>')) {
token->kind = lex_kind_bit_right_shift;
if (lex_match(lex, '=')) {
token->kind = lex_kind_bit_right_shift_assign;
}
}
} break;
case '<': {
token->kind = lex_kind_lesser;
if (lex_match(lex, '=')) {
token->kind = lex_kind_lesser_or_equal;
}
else if (lex_match(lex, '<')) {
token->kind = lex_kind_bit_left_shift;
if (lex_match(lex, '=')) {
token->kind = lex_kind_bit_left_shift_assign;
}
}
} break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': {
lex_eat_number(lex, token);
} break;
case 'A': case 'a': case 'B': case 'b': case 'C': case 'c':
case 'D': case 'd': case 'E': case 'e': case 'F': case 'f':
case 'G': case 'g': case 'H': case 'h': case 'I': case 'i':
case 'J': case 'j': case 'K': case 'k': case 'L': case 'l':
case 'M': case 'm': case 'N': case 'n': case 'O': case 'o':
case 'P': case 'p': case 'Q': case 'q': case 'R': case 'r':
case 'S': case 's': case 'T': case 't': case 'U': case 'u':
case 'V': case 'v': case 'W': case 'w': case 'X': case 'x':
case 'Y': case 'y': case 'Z': case 'z': case '_': {
token->kind = lex_kind_ident;
while (char_is_alphanumeric(lex->at[0]) || lex->at[0] == '_') lex_advance(lex);
} break;
default: {
lex_panicf(token, "found invalid character in the token stream (%d)", token->str[0]);
}
}
token->len = (int)(lex->at - token->str);
if (token->kind == lex_kind_int) {
token->integer = lex_deserial_u64(token->str, token->len, 10);
} else if (token->kind == lex_kind_real) {
token->real = s8_deserial_f64(token->s8);
} else if (token->kind == lex_kind_string) {
token->str += 1;
token->len -= 2;
}
}
lex_t lex_token(lexer_t *lex) {
lex_t result = {0};
lex_token_ex(lex, &result);
return result;
}
// @todo: use s8_t instead
lex_array_t lex_tokens(ma_arena_t *arena, char *file_name, char *stream) {
usize align = arena->align;
arena->align = 0;
lex_array_t token_array = {0};
lexer_t l = lex_make(stream, file_name);
for (;;) {
lex_t *token = ma_push_type(arena, lex_t);
if (token_array.data == NULL) {
token_array.data = token;
}
token_array.len += 1;
do {
lex_token_ex(&l, token);
} while (token->kind == lex_kind_comment);
if (token->kind == lex_kind_eof) break;
}
arena->align = align;
return token_array;
}
s8_t global_lex_kind_simple_strings[] = {
#define X(KIND, STR, SIMPLE) s8_const_lit(SIMPLE),
LEX_KIND_XLIST
#undef X
};
s8_t s8_serial_simple_lex_kind_t(lex_kind_t kind) {
assert(kind >= 0 && kind < lex_kind_count);
return global_lex_kind_simple_strings[kind];
}
s8_t global_lex_kind_strings[] = {
#define X(KIND, STR, SIMPLE) s8_const_lit(STR),
LEX_KIND_XLIST
#undef X
};
s8_t s8_serial_lex_kind_t(lex_kind_t kind) {
assert(kind >= 0 && kind < lex_kind_count);
return global_lex_kind_strings[kind];
}
type_member_t members__lex_kind_t[] = {
#define X(KIND, STR, SIMPLE) {.name = s8_const_lit("lex_kind_" #KIND), .value = lex_kind_##KIND},
LEX_KIND_XLIST
#undef X
};
DEFINE_ENUM(lex_kind_t);
type_member_t members__lex_suffix_t[] = {
#define X(KIND) {.name = s8_const_lit("lex_suffix_" #KIND), .value = lex_suffix_##KIND},
LEX_SUFFIX_XLIST
#undef X
};
DEFINE_ENUM(lex_suffix_t);
//
//
typedef struct parser_t parser_t;
struct parser_t {
ma_arena_t *arena;
lex_t *at;
};
#define parser_make(ARENA, TOKEN) &(parser_t){.arena = ARENA, .at = TOKEN}
lex_t *parser_next(parser_t *par) {
lex_t *result = par->at;
if (result->kind != lex_kind_eof) par->at += 1;
return result;
}
lex_t *parser_match(parser_t *par, lex_kind_t kind) {
if (par->at->kind == kind) {
return parser_next(par);
} else {
return NULL;
}
}
lex_t *parser_matchi(parser_t *par, s8_t str) {
if (par->at->kind == lex_kind_ident && s8_equal(par->at->s8, str)) {
return parser_next(par);
} else {
return NULL;
}
}
lex_t *parser_expect(parser_t *par, lex_kind_t kind) {
lex_t *token = parser_match(par, kind);
if (!token) lex_panicf(par->at, "expected token kind: %S, got instead: %S", s8_serial_lex_kind_t(kind), s8_serial_lex_kind_t(par->at->kind));
return token;
}
void parser_eat_until(parser_t *par, lex_kind_t kind) {
while (par->at->kind != kind && par->at->kind != lex_kind_eof) {
parser_next(par);
}
}
void parser_eat_including(parser_t *par, lex_kind_t kind) {
parser_eat_until(par, kind);
parser_next(par);
}

27
src/core/log.c Normal file
View File

@@ -0,0 +1,27 @@
void panicf(const char *_str, ...) {
ma_temp_t scratch = ma_begin_scratch();
S8_FMT(scratch.arena, _str, str);
core_desc.print(str.str);
core_desc.print("\n");
if (core_desc.break_on_panic) {
debug_break();
} else {
core_desc.panic();
}
ma_end_scratch(scratch);
}
void debugexf(const char *_str, ...) {
ma_temp_t scratch = ma_begin_scratch();
S8_FMT(scratch.arena, _str, str);
core_desc.print(str.str);
ma_end_scratch(scratch);
}
void debugf(const char *_str, ...) {
ma_temp_t scratch = ma_begin_scratch();
S8_FMT(scratch.arena, _str, str);
core_desc.print(str.str);
core_desc.print("\n");
ma_end_scratch(scratch);
}

291
src/core/math_gen.py Normal file
View File

@@ -0,0 +1,291 @@
import sys
op_idx = 0
opname_idx = 1
symbols = [
["+", "add"],
["-", "sub"],
["*", "mul"],
["/", "div"],
]
basic_types = [
"f32",
"f64",
"i32",
"i64",
]
name_idx = 0
member_idx = 1
vec_types = [
["v2", ["x", "y"]],
["v3", ["x", "y", "z"]],
["v4", ["x", "y", "z", "w"]],
]
rect_types = [
["r2", ["x0", "y0", "x1", "y1"]],
["r3", ["x0", "y0", "z0", "x1", "y1", "z1"]],
]
struct_types = vec_types + rect_types
# fd = open("mathx.gen.h", "w")
# sys.stdout = fd
# print("// auto generated using:", __file__)
# for bt in basic_types:
# s = """
# typedef union v2f64_t v2f64_t;
# union v2f64_t {
# struct { f64 x, y; };
# f64 e[2];
# };
# typedef union v3f64_t v3f64_t;
# union v3f64_t {
# struct { f64 x, y, z; };
# struct { v2f64_t xy; };
# struct { f64 _x0; v2f64_t zw; };
# struct { f64 r, g, b; };
# struct { f64 h, s, l; };
# f64 e[3];
# };
# typedef union v4f64_t v4f64_t;
# union v4f64_t {
# struct { f64 x, y, z, w; };
# struct { v2f64_t xy; v2f64_t zw; };
# struct { v3f64_t xyz; };
# struct { f64 _x0; f64 yzw; };
# struct { f64 r, g, b, a; };
# struct { f64 h, s, l, _a; };
# f64 e[4];
# };
# typedef union r1f64_t r1f64_t;
# union r1f64_t {
# struct { f64 min, max; };
# struct { f64 x0, x1; };
# f64 e[2];
# };
# typedef union r2f64_t r2f64_t;
# union r2f64_t {
# struct { v2f64_t min, max; };
# struct { f64 x0, y0, x1, y1; };
# v4f64_t e4;
# f64 e[4];
# };
# typedef union r3f64_t r3f64_t;
# union r3f64_t {
# struct { v3f64_t min, max; };
# struct { f64 x0, y0, z0, x1, y1, z1; };
# f64 e[6];
# };
#
#
# type_t type__v2f64_t = { type_kind_struct, s8_const_lit("v2f64_t"), sizeof(v2f64_t), .count = 2,
# .members = (type_member_t[]){
# {s8_const_lit("x"), &type__f64, .offset = offsetof(v2f64_t, x)},
# {s8_const_lit("y"), &type__f64, .offset = offsetof(v2f64_t, y)},
# }
# };
# type_t type__v3f64_t = { type_kind_struct, s8_const_lit("v3f64_t"), sizeof(v3f64_t), .count = 3,
# .members = (type_member_t[]){
# {s8_const_lit("x"), &type__f64, .offset = offsetof(v3f64_t, x)},
# {s8_const_lit("y"), &type__f64, .offset = offsetof(v3f64_t, y)},
# {s8_const_lit("z"), &type__f64, .offset = offsetof(v3f64_t, z)},
# }
# };
# type_t type__v4f64_t = { type_kind_struct, s8_const_lit("v4f64_t"), sizeof(v4f64_t), .count = 4,
# .members = (type_member_t[]){
# {s8_const_lit("x"), &type__f64, .offset = offsetof(v4f64_t, x)},
# {s8_const_lit("y"), &type__f64, .offset = offsetof(v4f64_t, y)},
# {s8_const_lit("z"), &type__f64, .offset = offsetof(v4f64_t, z)},
# {s8_const_lit("w"), &type__f64, .offset = offsetof(v4f64_t, w)},
# }
# };
# type_t type__r3f64_t = { type_kind_struct, s8_const_lit("r3f64_t"), sizeof(r3f64_t), .count = 6,
# .members = (type_member_t[]){
# {s8_const_lit("x0"), &type__f64, .offset = offsetof(r3f64_t, x0)},
# {s8_const_lit("y0"), &type__f64, .offset = offsetof(r3f64_t, y0)},
# {s8_const_lit("x0"), &type__f64, .offset = offsetof(r3f64_t, z0)},
# {s8_const_lit("x1"), &type__f64, .offset = offsetof(r3f64_t, x1)},
# {s8_const_lit("y1"), &type__f64, .offset = offsetof(r3f64_t, y1)},
# {s8_const_lit("x1"), &type__f64, .offset = offsetof(r3f64_t, z1)},
# }
# };
# type_member_t members__r2f64_t[] = {
# {s8_const_lit("x0"), &type__f64, .offset = offsetof(r2f64_t, x0)},
# {s8_const_lit("y0"), &type__f64, .offset = offsetof(r2f64_t, y0)},
# {s8_const_lit("x1"), &type__f64, .offset = offsetof(r2f64_t, x1)},
# {s8_const_lit("y1"), &type__f64, .offset = offsetof(r2f64_t, y1)},
# };
# DEFINE_STRUCT(r2f64_t);
# type_member_t members__r1f64_t[] = {
# {s8_const_lit("x0"), &type__f64, .offset = offsetof(r1f64_t, x0)},
# {s8_const_lit("x1"), &type__f64, .offset = offsetof(r1f64_t, x1)},
# };
# DEFINE_STRUCT(r1f64_t);
# """
# s = s.replace("f64", bt)
# print(s)
fd = open("mathx.gen.c", "w")
sys.stdout = fd
print("// auto generated using:", __file__)
for basic_type in basic_types:
for st in struct_types:
type = f"{st[name_idx]}{basic_type}"
typedef = f"{type}_t"
members = st[member_idx]
def members_as_func_params(members, basic_type):
result = ""
for i, m in enumerate(members):
result += f"{basic_type} {m}"
if i != len(members) - 1:
result += ", "
return result
print(f"""{type}_t {type}({members_as_func_params(members, basic_type)}) {{ return ({type}_t){{ {members_as_func_params(members, "")} }}; }}""")
for sym in symbols:
op = sym[op_idx]
opname = sym[opname_idx]
def op_str(members, op, skip_right = False):
result = ""
for i in range(len(members)):
mem = members[i]
if skip_right:
result += f"a.{mem} {op} b"
else:
result += f"a.{mem} {op} b.{mem}"
if i != len(members) - 1:
result += ", "
return result
print(f"{type}_t {type}_{opname}({type}_t a, {type}_t b) {{ return ({type}_t){{ {op_str(members, op)} }}; }}")
print(f"{type}_t {type}_{opname}s({type}_t a, {basic_type} b) {{ return ({type}_t){{ {op_str(members, op, skip_right = True)} }}; }}")
for basic_type in basic_types:
for i in range(len(rect_types)):
vec_type = vec_types[i]
rect_type = rect_types[i]
vec_name = vec_type[name_idx] + basic_type
vec_members = vec_type[member_idx]
rect_name = rect_type[name_idx] + basic_type
rect_members = rect_type[member_idx]
print(f"{rect_name}_t {rect_name}_mindim({vec_name}_t pos, {vec_name}_t size) {{ return ({rect_name}_t){{ pos, {vec_name}_add(pos, size) }}; }}")
print(f"{rect_name}_t {rect_name}_center_halfdim({vec_name}_t center, {vec_name}_t halfdim) {{ return ({rect_name}_t){{ {vec_name}_sub(center, halfdim), {vec_name}_add(center, halfdim) }}; }}")
for basic_type in basic_types:
s = """
r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
return (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
}
r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
return (r2f64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
}
r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
return (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
}
r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
return (r2f64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
}
// get past left
r2f64_t r2f64_getp_left(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
r2f64_t r2f64_getp_right(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
r2f64_t r2f64_getp_bottom(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
r2f64_t r2f64_getp_top(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
r2f64_t r2f64_get_left(const r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r2f64_t result = (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
r2f64_t r2f64_get_right(const r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r2f64_t result = (r2f64_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
r2f64_t r2f64_get_top(const r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
v2f64_t r2f64_get_mid(r2f64_t r) { return v2f64_add(r.min, v2f64_divs(r2f64_get_size(r), 2)); }
b32 r2f64_contains(r2f64_t rec, v2f64_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
"""
s = s.replace("r2f64", f"r2{basic_type}")
s = s.replace("f64", basic_type)
s = s.replace("v2f64", f"v2{basic_type}")
print(s)
for at in basic_types:
for bt in basic_types:
if at == bt: continue
for st in struct_types:
atype = f"{st[name_idx]}{at}"
btype = f"{st[name_idx]}{bt}"
members = st[member_idx]
def cast_members(members, type):
result = ""
for i in range(len(members)):
result += f"({type})v.{members[i]}"
if i != len(members) - 1:
result += ", "
return result
print(f"{btype}_t {atype}_to_{btype}({atype}_t v) {{ return ({btype}_t){{ {cast_members(members, bt)} }}; }}")

520
src/core/mathx.c Normal file
View File

@@ -0,0 +1,520 @@
#define F64_PI (3.1415926535897932384626433832795028841971693994)
#define F64_DEG2RAD (F64_PI / 180.0); // @Usage: degree * DEG2RAD = radians;
#define F64_RAD2DEG (180.0 / F64_PI);
#define F32_PI ((f32)F64_PI)
#define rgba_macro_const(r, g, b, a) { r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f }
v4f32_t primary_color_global = rgba_macro_const(245, 238, 230, 255);
v4f32_t secondary_color_global = rgba_macro_const(255, 248, 227, 255);
v4f32_t accent1_color_global = rgba_macro_const(243, 215, 202, 255);
v4f32_t accent2_color_global = rgba_macro_const(230, 164, 180, 255);
v4f32_t white_color_global = rgba_macro_const(255, 255, 255, 255);
v4f32_t black_color_global = rgba_macro_const(0, 0, 0, 255);
/*
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* also https://gist.github.com/ciembor/1494530
* alpha is ignored
*/
v3f32_t v3f32_rgb_to_hsl(v3f32_t color) {
v3f32_t result;
f32 max = MAX(MAX(color.r, color.g), color.b);
f32 min = MIN(MIN(color.r, color.g), color.b);
result.h = result.s = result.l = (max + min) / 2.f;
if (max == min) {
result.h = result.s = 0.f; // achromatic
} else {
f32 d = max - min;
result.s = (result.l > 0.5f) ? d / (2.f - max - min) : d / (max + min);
if (max == color.r) {
result.h = (color.g - color.b) / d + (color.g < color.b ? 6.f : 0.f);
} else if (max == color.g) {
result.h = (color.b - color.r) / d + 2.f;
} else if (max == color.b) {
result.h = (color.r - color.g) / d + 4.f;
}
result.h /= 6.f;
}
return result;
}
/*
* Converts an HUE to r, g or b.
* returns f32 in the set [0, 1].
*/
f32 f32_hue_to_rgb(f32 p, f32 q, f32 t) {
if (t < 0.f)
t += 1.f;
if (t > 1.f)
t -= 1.f;
if (t < 1.f / 6.f)
return p + (q - p) * 6.f * t;
if (t < 1.f / 2.f)
return q;
if (t < 2.f / 3.f)
return p + (q - p) * (2.f / 3.f - t) * 6.f;
return p;
}
v3f32_t v3f32_hsl_to_rgb(v3f32_t color) {
v3f32_t result;
if (0 == color.s) {
result.r = result.g = result.b = color.l; // achromatic
} else {
f32 q = color.l < 0.5f ? color.l * (1.f + color.s)
: color.l + color.s - color.l * color.s;
f32 p = 2.f * color.l - q;
result.r = f32_hue_to_rgb(p, q, color.h + 1.f / 3.f);
result.g = f32_hue_to_rgb(p, q, color.h);
result.b = f32_hue_to_rgb(p, q, color.h - 1.f / 3.f);
}
return result;
}
v4f32_t v4f32_rgba_to_hsla(v4f32_t rgba) {
v3f32_t result = v3f32_rgb_to_hsl(rgba.xyz);
return (v4f32_t){result.r, result.g, result.b, rgba.a};
}
v4f32_t v4f32_hsl_to_rgb(v4f32_t color) {
v3f32_t result = v3f32_hsl_to_rgb(color.xyz);
return (v4f32_t){result.r, result.g, result.b, color.a};
}
/*
https://git.musl-libc.org/cgit/musl/tree/src/math
https://gitlab.com/nakst/essence/-/blob/master/shared/math.cpp
*/
f64 f64_lerp(f64 a, f64 b, f64 t) { return (1 - t) * a + t * b; }
f64 f64_smooth_step(f64 t) { return t*t*(3-2*t); }
f64 f64_ease_in_quint(f64 x) { return x * x * x * x * x; }
f64 f64_ease_in_cubic(f64 x) { return x * x * x; }
f64 f64_ping_pong(f64 x) { return 1.0 - f64_abs(1.0 - f64_mod(x,2)); }
f32 f32_lerp(f32 a, f32 b, f32 t) { return (1 - t) * a + t * b; }
f32 f32_smooth_step(f32 t) { return t*t*(3-2*t); }
f32 f32_ease_in_quint(f32 x) { return x * x * x * x * x; }
f32 f32_ease_in_cubic(f32 x) { return x * x * x; }
f32 f32_ping_pong(f32 x) { return 1.0f - f32_abs(1.0f - f32_mod(x,2)); }
v4f32_t v4f32_lerp(v4f32_t a, v4f32_t b, f32 t) {
return (v4f32_t){f32_lerp(a.x, a.y, t), f32_lerp(a.y, b.y, t), f32_lerp(a.z, b.z, t), f32_lerp(a.w, b.w, t)};
}
#if PLATFORM_CL
#pragma warning(disable: 4116)
#endif
#define U64ToF64(x) (((union { f64 d; u64 i; }) { .i = (x) }).d)
#define U32ToF32(x) (((union { f32 f; u32 i; }) { .i = (x) }).f)
f64 _Sine(f64 x) {
// Calculates sin(x) for x in [0, pi/4].
f64 x2 = x * x;
return x * (U64ToF64(0x3FF0000000000000) + x2 * (U64ToF64(0xBFC5555555555540) + x2 * (U64ToF64(0x3F8111111110ED80) + x2 * (U64ToF64(0xBF2A01A019AE6000)
+ x2 * (U64ToF64(0x3EC71DE349280000) + x2 * (U64ToF64(0xBE5AE5DC48000000) + x2 * U64ToF64(0x3DE5D68200000000)))))));
}
f32 _SineFloat(f32 x) {
// Calculates sin(x) for x in [0, pi/4].
f32 x2 = x * x;
return x * (U32ToF32(0x3F800000) + x2 * (U32ToF32(0xBE2AAAA0) + x2 * (U32ToF32(0x3C0882C0) + x2 * U32ToF32(0xB94C6000))));
}
f64 _ArcSine(f64 x) {
// Calculates arcsin(x) for x in [0, 0.5].
f64 x2 = x * x;
return x * (U64ToF64(0x3FEFFFFFFFFFFFE6) + x2 * (U64ToF64(0x3FC555555555FE00) + x2 * (U64ToF64(0x3FB333333292DF90) + x2 * (U64ToF64(0x3FA6DB6DFD3693A0)
+ x2 * (U64ToF64(0x3F9F1C608DE51900) + x2 * (U64ToF64(0x3F96EA0659B9A080) + x2 * (U64ToF64(0x3F91B4ABF1029100)
+ x2 * (U64ToF64(0x3F8DA8DAF31ECD00) + x2 * (U64ToF64(0x3F81C01FD5000C00) + x2 * (U64ToF64(0x3F94BDA038CF6B00)
+ x2 * (U64ToF64(0xBF8E849CA75B1E00) + x2 * U64ToF64(0x3FA146C2D37F2C60))))))))))));
}
f32 _ArcSineFloat(f32 x) {
// Calculates arcsin(x) for x in [0, 0.5].
f32 x2 = x * x;
return x * (U32ToF32(0x3F800004) + x2 * (U32ToF32(0x3E2AA130) + x2 * (U32ToF32(0x3D9B2C28) + x2 * (U32ToF32(0x3D1C1800) + x2 * U32ToF32(0x3D5A97C0)))));
}
f64 _ArcTangent(f64 x) {
// Calculates arctan(x) for x in [0, 0.5].
f64 x2 = x * x;
return x * (U64ToF64(0x3FEFFFFFFFFFFFF8) + x2 * (U64ToF64(0xBFD5555555553B44) + x2 * (U64ToF64(0x3FC9999999803988) + x2 * (U64ToF64(0xBFC249248C882E80)
+ x2 * (U64ToF64(0x3FBC71C5A4E4C220) + x2 * (U64ToF64(0xBFB745B3B75243F0) + x2 * (U64ToF64(0x3FB3AFAE9A2939E0)
+ x2 * (U64ToF64(0xBFB1030C4A4A1B90) + x2 * (U64ToF64(0x3FAD6F65C35579A0) + x2 * (U64ToF64(0xBFA805BCFDAFEDC0)
+ x2 * (U64ToF64(0x3F9FC6B5E115F2C0) + x2 * U64ToF64(0xBF87DCA5AB25BF80))))))))))));
}
f32 _ArcTangentFloat(f32 x) {
// Calculates arctan(x) for x in [0, 0.5].
f32 x2 = x * x;
return x * (U32ToF32(0x3F7FFFF8) + x2 * (U32ToF32(0xBEAAA53C) + x2 * (U32ToF32(0x3E4BC990) + x2 * (U32ToF32(0xBE084A60) + x2 * U32ToF32(0x3D8864B0)))));
}
f64 _Cosine(f64 x) {
// Calculates cos(x) for x in [0, pi/4].
f64 x2 = x * x;
return U64ToF64(0x3FF0000000000000) + x2 * (U64ToF64(0xBFDFFFFFFFFFFFA0) + x2 * (U64ToF64(0x3FA555555554F7C0) + x2 * (U64ToF64(0xBF56C16C16475C00)
+ x2 * (U64ToF64(0x3EFA019F87490000) + x2 * (U64ToF64(0xBE927DF66B000000) + x2 * U64ToF64(0x3E21B949E0000000))))));
}
f32 _CosineFloat(f32 x) {
// Calculates cos(x) for x in [0, pi/4].
f32 x2 = x * x;
return U32ToF32(0x3F800000) + x2 * (U32ToF32(0xBEFFFFDA) + x2 * (U32ToF32(0x3D2A9F60) + x2 * U32ToF32(0xBAB22C00)));
}
f64 _Tangent(f64 x) {
// Calculates tan(x) for x in [0, pi/4].
f64 x2 = x * x;
return x * (U64ToF64(0x3FEFFFFFFFFFFFE8) + x2 * (U64ToF64(0x3FD5555555558000) + x2 * (U64ToF64(0x3FC1111110FACF90) + x2 * (U64ToF64(0x3FABA1BA266BFD20)
+ x2 * (U64ToF64(0x3F9664F30E56E580) + x2 * (U64ToF64(0x3F822703B08BDC00) + x2 * (U64ToF64(0x3F6D698D2E4A4C00)
+ x2 * (U64ToF64(0x3F57FF4F23EA4400) + x2 * (U64ToF64(0x3F424F3BEC845800) + x2 * (U64ToF64(0x3F34C78CA9F61000)
+ x2 * (U64ToF64(0xBF042089F8510000) + x2 * (U64ToF64(0x3F29D7372D3A8000) + x2 * (U64ToF64(0xBF19D1C5EF6F0000)
+ x2 * (U64ToF64(0x3F0980BDF11E8000)))))))))))))));
}
f32 _TangentFloat(f32 x) {
// Calculates tan(x) for x in [0, pi/4].
f32 x2 = x * x;
return x * (U32ToF32(0x3F800001) + x2 * (U32ToF32(0x3EAAA9AA) + x2 * (U32ToF32(0x3E08ABA8) + x2 * (U32ToF32(0x3D58EC90)
+ x2 * (U32ToF32(0x3CD24840) + x2 * (U32ToF32(0x3AC3CA00) + x2 * U32ToF32(0x3C272F00)))))));
}
f64 f64_sin(f64 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = true;
}
// x in 0, infty
x -= 2 * F64_PI * f64_floor(x / (2 * F64_PI));
// x in 0, 2*pi
if (x < F64_PI / 2) {
} else if (x < F64_PI) {
x = F64_PI - x;
} else if (x < 3 * F64_PI / 2) {
x = x - F64_PI;
negate = !negate;
} else {
x = F64_PI * 2 - x;
negate = !negate;
}
// x in 0, pi/2
f64 y = x < F64_PI / 4 ? _Sine(x) : _Cosine(F64_PI / 2 - x);
return negate ? -y : y;
}
f32 f32_sin(f32 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = true;
}
// x in 0, infty
x -= 2 * F32_PI * f32_floor(x / (2 * F32_PI));
// x in 0, 2*pi
if (x < F32_PI / 2) {
} else if (x < F32_PI) {
x = F32_PI - x;
} else if (x < 3 * F32_PI / 2) {
x = x - F32_PI;
negate = !negate;
} else {
x = F32_PI * 2 - x;
negate = !negate;
}
// x in 0, pi/2
f32 y = x < F32_PI / 4 ? _SineFloat(x) : _CosineFloat(F32_PI / 2 - x);
return negate ? -y : y;
}
f64 f64_cos(f64 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
}
// x in 0, infty
x -= 2 * F64_PI * f64_floor(x / (2 * F64_PI));
// x in 0, 2*pi
if (x < F64_PI / 2) {
} else if (x < F64_PI) {
x = F64_PI - x;
negate = !negate;
} else if (x < 3 * F64_PI / 2) {
x = x - F64_PI;
negate = !negate;
} else {
x = F64_PI * 2 - x;
}
// x in 0, pi/2
f64 y = x < F64_PI / 4 ? _Cosine(x) : _Sine(F64_PI / 2 - x);
return negate ? -y : y;
}
f32 f32_cos(f32 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
}
// x in 0, infty
x -= 2 * F32_PI * f32_floor(x / (2 * F32_PI));
// x in 0, 2*pi
if (x < F32_PI / 2) {
} else if (x < F32_PI) {
x = F32_PI - x;
negate = !negate;
} else if (x < 3 * F32_PI / 2) {
x = x - F32_PI;
negate = !negate;
} else {
x = F32_PI * 2 - x;
}
// x in 0, pi/2
f32 y = x < F32_PI / 4 ? _CosineFloat(x) : _SineFloat(F32_PI / 2 - x);
return negate ? -y : y;
}
f64 f64_tan(f64 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = !negate;
}
// x in 0, infty
x -= F64_PI * f64_floor(x / F64_PI);
// x in 0, pi
if (x > F64_PI / 2) {
x = F64_PI - x;
negate = !negate;
}
// x in 0, pi/2
f64 y = x < F64_PI / 4 ? _Tangent(x) : (1.0 / _Tangent(F64_PI / 2 - x));
return negate ? -y : y;
}
f32 f32_tan(f32 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = !negate;
}
// x in 0, infty
x -= F32_PI * f32_floor(x / F32_PI);
// x in 0, pi
if (x > F32_PI / 2) {
x = F32_PI - x;
negate = !negate;
}
// x in 0, pi/2
f32 y = x < F32_PI / 4 ? _TangentFloat(x) : (1.0f / _TangentFloat(F32_PI / 2 - x));
return negate ? -y : y;
}
f64 f64_asin(f64 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
f64 y;
if (x < 0.5) {
y = _ArcSine(x);
} else {
y = F64_PI / 2 - 2 * _ArcSine(f64_sqrt(0.5 - 0.5 * x));
}
return negate ? -y : y;
}
f32 f32_asin(f32 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
f32 y;
if (x < 0.5) {
y = _ArcSineFloat(x);
} else {
y = F32_PI / 2 - 2 * _ArcSineFloat(f32_sqrt(0.5f - 0.5f * x));
}
return negate ? -y : y;
}
f64 f64_acos(f64 x) {
return f64_asin(-x) + F64_PI / 2;
}
f32 f32_acos(f32 x) {
return f32_asin(-x) + F32_PI / 2;
}
f64 f64_atan(f64 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
b32 reciprocalTaken = false;
if (x > 1) {
x = 1 / x;
reciprocalTaken = true;
}
f64 y;
if (x < 0.5) {
y = _ArcTangent(x);
} else {
y = 0.463647609000806116 + _ArcTangent((2 * x - 1) / (2 + x));
}
if (reciprocalTaken) {
y = F64_PI / 2 - y;
}
return negate ? -y : y;
}
f32 f32_atan(f32 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
b32 reciprocalTaken = false;
if (x > 1) {
x = 1 / x;
reciprocalTaken = true;
}
f32 y;
if (x < 0.5f) {
y = _ArcTangentFloat(x);
} else {
y = 0.463647609000806116f + _ArcTangentFloat((2 * x - 1) / (2 + x));
}
if (reciprocalTaken) {
y = F32_PI / 2 - y;
}
return negate ? -y : y;
}
f64 f64_atan2(f64 y, f64 x) {
if (x == 0) return y > 0 ? F64_PI / 2 : -F64_PI / 2;
else if (x > 0) return f64_atan(y / x);
else if (y >= 0) return F64_PI + f64_atan(y / x);
else return -F64_PI + f64_atan(y / x);
}
f32 f32_atan2(f32 y, f32 x) {
if (x == 0) return y > 0 ? F32_PI / 2 : -F32_PI / 2;
else if (x > 0) return f32_atan(y / x);
else if (y >= 0) return F32_PI + f32_atan(y / x);
else return -F32_PI + f32_atan(y / x);
}

519
src/core/mathx.gen.c Normal file
View File

@@ -0,0 +1,519 @@
// auto generated using: D:\dev\wasm\src\core\math_gen.py
v2f32_t v2f32(f32 x, f32 y) { return (v2f32_t){ x, y }; }
v2f32_t v2f32_add(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x + b.x, a.y + b.y }; }
v2f32_t v2f32_adds(v2f32_t a, f32 b) { return (v2f32_t){ a.x + b, a.y + b }; }
v2f32_t v2f32_sub(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x - b.x, a.y - b.y }; }
v2f32_t v2f32_subs(v2f32_t a, f32 b) { return (v2f32_t){ a.x - b, a.y - b }; }
v2f32_t v2f32_mul(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x * b.x, a.y * b.y }; }
v2f32_t v2f32_muls(v2f32_t a, f32 b) { return (v2f32_t){ a.x * b, a.y * b }; }
v2f32_t v2f32_div(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x / b.x, a.y / b.y }; }
v2f32_t v2f32_divs(v2f32_t a, f32 b) { return (v2f32_t){ a.x / b, a.y / b }; }
v3f32_t v3f32(f32 x, f32 y, f32 z) { return (v3f32_t){ x, y, z }; }
v3f32_t v3f32_add(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
v3f32_t v3f32_adds(v3f32_t a, f32 b) { return (v3f32_t){ a.x + b, a.y + b, a.z + b }; }
v3f32_t v3f32_sub(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
v3f32_t v3f32_subs(v3f32_t a, f32 b) { return (v3f32_t){ a.x - b, a.y - b, a.z - b }; }
v3f32_t v3f32_mul(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
v3f32_t v3f32_muls(v3f32_t a, f32 b) { return (v3f32_t){ a.x * b, a.y * b, a.z * b }; }
v3f32_t v3f32_div(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
v3f32_t v3f32_divs(v3f32_t a, f32 b) { return (v3f32_t){ a.x / b, a.y / b, a.z / b }; }
v4f32_t v4f32(f32 x, f32 y, f32 z, f32 w) { return (v4f32_t){ x, y, z, w }; }
v4f32_t v4f32_add(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
v4f32_t v4f32_adds(v4f32_t a, f32 b) { return (v4f32_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
v4f32_t v4f32_sub(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
v4f32_t v4f32_subs(v4f32_t a, f32 b) { return (v4f32_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
v4f32_t v4f32_mul(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
v4f32_t v4f32_muls(v4f32_t a, f32 b) { return (v4f32_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
v4f32_t v4f32_div(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
v4f32_t v4f32_divs(v4f32_t a, f32 b) { return (v4f32_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
r2f32_t r2f32(f32 x0, f32 y0, f32 x1, f32 y1) { return (r2f32_t){ x0, y0, x1, y1 }; }
r2f32_t r2f32_add(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
r2f32_t r2f32_adds(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
r2f32_t r2f32_sub(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
r2f32_t r2f32_subs(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
r2f32_t r2f32_mul(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
r2f32_t r2f32_muls(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
r2f32_t r2f32_div(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
r2f32_t r2f32_divs(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
r3f32_t r3f32(f32 x0, f32 y0, f32 z0, f32 x1, f32 y1, f32 z1) { return (r3f32_t){ x0, y0, z0, x1, y1, z1 }; }
r3f32_t r3f32_add(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
r3f32_t r3f32_adds(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
r3f32_t r3f32_sub(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
r3f32_t r3f32_subs(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
r3f32_t r3f32_mul(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
r3f32_t r3f32_muls(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
r3f32_t r3f32_div(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
r3f32_t r3f32_divs(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
v2f64_t v2f64(f64 x, f64 y) { return (v2f64_t){ x, y }; }
v2f64_t v2f64_add(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x + b.x, a.y + b.y }; }
v2f64_t v2f64_adds(v2f64_t a, f64 b) { return (v2f64_t){ a.x + b, a.y + b }; }
v2f64_t v2f64_sub(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x - b.x, a.y - b.y }; }
v2f64_t v2f64_subs(v2f64_t a, f64 b) { return (v2f64_t){ a.x - b, a.y - b }; }
v2f64_t v2f64_mul(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x * b.x, a.y * b.y }; }
v2f64_t v2f64_muls(v2f64_t a, f64 b) { return (v2f64_t){ a.x * b, a.y * b }; }
v2f64_t v2f64_div(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x / b.x, a.y / b.y }; }
v2f64_t v2f64_divs(v2f64_t a, f64 b) { return (v2f64_t){ a.x / b, a.y / b }; }
v3f64_t v3f64(f64 x, f64 y, f64 z) { return (v3f64_t){ x, y, z }; }
v3f64_t v3f64_add(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
v3f64_t v3f64_adds(v3f64_t a, f64 b) { return (v3f64_t){ a.x + b, a.y + b, a.z + b }; }
v3f64_t v3f64_sub(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
v3f64_t v3f64_subs(v3f64_t a, f64 b) { return (v3f64_t){ a.x - b, a.y - b, a.z - b }; }
v3f64_t v3f64_mul(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
v3f64_t v3f64_muls(v3f64_t a, f64 b) { return (v3f64_t){ a.x * b, a.y * b, a.z * b }; }
v3f64_t v3f64_div(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
v3f64_t v3f64_divs(v3f64_t a, f64 b) { return (v3f64_t){ a.x / b, a.y / b, a.z / b }; }
v4f64_t v4f64(f64 x, f64 y, f64 z, f64 w) { return (v4f64_t){ x, y, z, w }; }
v4f64_t v4f64_add(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
v4f64_t v4f64_adds(v4f64_t a, f64 b) { return (v4f64_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
v4f64_t v4f64_sub(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
v4f64_t v4f64_subs(v4f64_t a, f64 b) { return (v4f64_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
v4f64_t v4f64_mul(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
v4f64_t v4f64_muls(v4f64_t a, f64 b) { return (v4f64_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
v4f64_t v4f64_div(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
v4f64_t v4f64_divs(v4f64_t a, f64 b) { return (v4f64_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
r2f64_t r2f64(f64 x0, f64 y0, f64 x1, f64 y1) { return (r2f64_t){ x0, y0, x1, y1 }; }
r2f64_t r2f64_add(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
r2f64_t r2f64_adds(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
r2f64_t r2f64_sub(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
r2f64_t r2f64_subs(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
r2f64_t r2f64_mul(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
r2f64_t r2f64_muls(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
r2f64_t r2f64_div(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
r2f64_t r2f64_divs(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
r3f64_t r3f64(f64 x0, f64 y0, f64 z0, f64 x1, f64 y1, f64 z1) { return (r3f64_t){ x0, y0, z0, x1, y1, z1 }; }
r3f64_t r3f64_add(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
r3f64_t r3f64_adds(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
r3f64_t r3f64_sub(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
r3f64_t r3f64_subs(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
r3f64_t r3f64_mul(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
r3f64_t r3f64_muls(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
r3f64_t r3f64_div(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
r3f64_t r3f64_divs(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
v2i32_t v2i32(i32 x, i32 y) { return (v2i32_t){ x, y }; }
v2i32_t v2i32_add(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x + b.x, a.y + b.y }; }
v2i32_t v2i32_adds(v2i32_t a, i32 b) { return (v2i32_t){ a.x + b, a.y + b }; }
v2i32_t v2i32_sub(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x - b.x, a.y - b.y }; }
v2i32_t v2i32_subs(v2i32_t a, i32 b) { return (v2i32_t){ a.x - b, a.y - b }; }
v2i32_t v2i32_mul(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x * b.x, a.y * b.y }; }
v2i32_t v2i32_muls(v2i32_t a, i32 b) { return (v2i32_t){ a.x * b, a.y * b }; }
v2i32_t v2i32_div(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x / b.x, a.y / b.y }; }
v2i32_t v2i32_divs(v2i32_t a, i32 b) { return (v2i32_t){ a.x / b, a.y / b }; }
v3i32_t v3i32(i32 x, i32 y, i32 z) { return (v3i32_t){ x, y, z }; }
v3i32_t v3i32_add(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
v3i32_t v3i32_adds(v3i32_t a, i32 b) { return (v3i32_t){ a.x + b, a.y + b, a.z + b }; }
v3i32_t v3i32_sub(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
v3i32_t v3i32_subs(v3i32_t a, i32 b) { return (v3i32_t){ a.x - b, a.y - b, a.z - b }; }
v3i32_t v3i32_mul(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
v3i32_t v3i32_muls(v3i32_t a, i32 b) { return (v3i32_t){ a.x * b, a.y * b, a.z * b }; }
v3i32_t v3i32_div(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
v3i32_t v3i32_divs(v3i32_t a, i32 b) { return (v3i32_t){ a.x / b, a.y / b, a.z / b }; }
v4i32_t v4i32(i32 x, i32 y, i32 z, i32 w) { return (v4i32_t){ x, y, z, w }; }
v4i32_t v4i32_add(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
v4i32_t v4i32_adds(v4i32_t a, i32 b) { return (v4i32_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
v4i32_t v4i32_sub(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
v4i32_t v4i32_subs(v4i32_t a, i32 b) { return (v4i32_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
v4i32_t v4i32_mul(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
v4i32_t v4i32_muls(v4i32_t a, i32 b) { return (v4i32_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
v4i32_t v4i32_div(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
v4i32_t v4i32_divs(v4i32_t a, i32 b) { return (v4i32_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
r2i32_t r2i32(i32 x0, i32 y0, i32 x1, i32 y1) { return (r2i32_t){ x0, y0, x1, y1 }; }
r2i32_t r2i32_add(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
r2i32_t r2i32_adds(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
r2i32_t r2i32_sub(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
r2i32_t r2i32_subs(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
r2i32_t r2i32_mul(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
r2i32_t r2i32_muls(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
r2i32_t r2i32_div(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
r2i32_t r2i32_divs(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
r3i32_t r3i32(i32 x0, i32 y0, i32 z0, i32 x1, i32 y1, i32 z1) { return (r3i32_t){ x0, y0, z0, x1, y1, z1 }; }
r3i32_t r3i32_add(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
r3i32_t r3i32_adds(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
r3i32_t r3i32_sub(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
r3i32_t r3i32_subs(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
r3i32_t r3i32_mul(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
r3i32_t r3i32_muls(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
r3i32_t r3i32_div(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
r3i32_t r3i32_divs(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
v2i64_t v2i64(i64 x, i64 y) { return (v2i64_t){ x, y }; }
v2i64_t v2i64_add(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x + b.x, a.y + b.y }; }
v2i64_t v2i64_adds(v2i64_t a, i64 b) { return (v2i64_t){ a.x + b, a.y + b }; }
v2i64_t v2i64_sub(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x - b.x, a.y - b.y }; }
v2i64_t v2i64_subs(v2i64_t a, i64 b) { return (v2i64_t){ a.x - b, a.y - b }; }
v2i64_t v2i64_mul(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x * b.x, a.y * b.y }; }
v2i64_t v2i64_muls(v2i64_t a, i64 b) { return (v2i64_t){ a.x * b, a.y * b }; }
v2i64_t v2i64_div(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x / b.x, a.y / b.y }; }
v2i64_t v2i64_divs(v2i64_t a, i64 b) { return (v2i64_t){ a.x / b, a.y / b }; }
v3i64_t v3i64(i64 x, i64 y, i64 z) { return (v3i64_t){ x, y, z }; }
v3i64_t v3i64_add(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
v3i64_t v3i64_adds(v3i64_t a, i64 b) { return (v3i64_t){ a.x + b, a.y + b, a.z + b }; }
v3i64_t v3i64_sub(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
v3i64_t v3i64_subs(v3i64_t a, i64 b) { return (v3i64_t){ a.x - b, a.y - b, a.z - b }; }
v3i64_t v3i64_mul(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
v3i64_t v3i64_muls(v3i64_t a, i64 b) { return (v3i64_t){ a.x * b, a.y * b, a.z * b }; }
v3i64_t v3i64_div(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
v3i64_t v3i64_divs(v3i64_t a, i64 b) { return (v3i64_t){ a.x / b, a.y / b, a.z / b }; }
v4i64_t v4i64(i64 x, i64 y, i64 z, i64 w) { return (v4i64_t){ x, y, z, w }; }
v4i64_t v4i64_add(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
v4i64_t v4i64_adds(v4i64_t a, i64 b) { return (v4i64_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
v4i64_t v4i64_sub(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
v4i64_t v4i64_subs(v4i64_t a, i64 b) { return (v4i64_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
v4i64_t v4i64_mul(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
v4i64_t v4i64_muls(v4i64_t a, i64 b) { return (v4i64_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
v4i64_t v4i64_div(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
v4i64_t v4i64_divs(v4i64_t a, i64 b) { return (v4i64_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
r2i64_t r2i64(i64 x0, i64 y0, i64 x1, i64 y1) { return (r2i64_t){ x0, y0, x1, y1 }; }
r2i64_t r2i64_add(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
r2i64_t r2i64_adds(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
r2i64_t r2i64_sub(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
r2i64_t r2i64_subs(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
r2i64_t r2i64_mul(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
r2i64_t r2i64_muls(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
r2i64_t r2i64_div(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
r2i64_t r2i64_divs(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
r3i64_t r3i64(i64 x0, i64 y0, i64 z0, i64 x1, i64 y1, i64 z1) { return (r3i64_t){ x0, y0, z0, x1, y1, z1 }; }
r3i64_t r3i64_add(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
r3i64_t r3i64_adds(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
r3i64_t r3i64_sub(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
r3i64_t r3i64_subs(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
r3i64_t r3i64_mul(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
r3i64_t r3i64_muls(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
r3i64_t r3i64_div(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
r3i64_t r3i64_divs(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
r2f32_t r2f32_mindim(v2f32_t pos, v2f32_t size) { return (r2f32_t){ pos, v2f32_add(pos, size) }; }
r2f32_t r2f32_center_halfdim(v2f32_t center, v2f32_t halfdim) { return (r2f32_t){ v2f32_sub(center, halfdim), v2f32_add(center, halfdim) }; }
r3f32_t r3f32_mindim(v3f32_t pos, v3f32_t size) { return (r3f32_t){ pos, v3f32_add(pos, size) }; }
r3f32_t r3f32_center_halfdim(v3f32_t center, v3f32_t halfdim) { return (r3f32_t){ v3f32_sub(center, halfdim), v3f32_add(center, halfdim) }; }
r2f64_t r2f64_mindim(v2f64_t pos, v2f64_t size) { return (r2f64_t){ pos, v2f64_add(pos, size) }; }
r2f64_t r2f64_center_halfdim(v2f64_t center, v2f64_t halfdim) { return (r2f64_t){ v2f64_sub(center, halfdim), v2f64_add(center, halfdim) }; }
r3f64_t r3f64_mindim(v3f64_t pos, v3f64_t size) { return (r3f64_t){ pos, v3f64_add(pos, size) }; }
r3f64_t r3f64_center_halfdim(v3f64_t center, v3f64_t halfdim) { return (r3f64_t){ v3f64_sub(center, halfdim), v3f64_add(center, halfdim) }; }
r2i32_t r2i32_mindim(v2i32_t pos, v2i32_t size) { return (r2i32_t){ pos, v2i32_add(pos, size) }; }
r2i32_t r2i32_center_halfdim(v2i32_t center, v2i32_t halfdim) { return (r2i32_t){ v2i32_sub(center, halfdim), v2i32_add(center, halfdim) }; }
r3i32_t r3i32_mindim(v3i32_t pos, v3i32_t size) { return (r3i32_t){ pos, v3i32_add(pos, size) }; }
r3i32_t r3i32_center_halfdim(v3i32_t center, v3i32_t halfdim) { return (r3i32_t){ v3i32_sub(center, halfdim), v3i32_add(center, halfdim) }; }
r2i64_t r2i64_mindim(v2i64_t pos, v2i64_t size) { return (r2i64_t){ pos, v2i64_add(pos, size) }; }
r2i64_t r2i64_center_halfdim(v2i64_t center, v2i64_t halfdim) { return (r2i64_t){ v2i64_sub(center, halfdim), v2i64_add(center, halfdim) }; }
r3i64_t r3i64_mindim(v3i64_t pos, v3i64_t size) { return (r3i64_t){ pos, v3i64_add(pos, size) }; }
r3i64_t r3i64_center_halfdim(v3i64_t center, v3i64_t halfdim) { return (r3i64_t){ v3i64_sub(center, halfdim), v3i64_add(center, halfdim) }; }
r2f32_t r2f32_cut_left(r2f32_t *r, f32 value) {
f32 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
return (r2f32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
}
r2f32_t r2f32_cut_right(r2f32_t *r, f32 value) {
f32 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
return (r2f32_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
}
r2f32_t r2f32_cut_top(r2f32_t *r, f32 value) { /* Y is down */
f32 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
return (r2f32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
}
r2f32_t r2f32_cut_bottom(r2f32_t *r, f32 value) { /* Y is down */
f32 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
return (r2f32_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
}
// get past left
r2f32_t r2f32_getp_left(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
r2f32_t r2f32_getp_right(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
r2f32_t r2f32_getp_bottom(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
r2f32_t r2f32_getp_top(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
r2f32_t r2f32_get_left(const r2f32_t *r, f32 value) {
f32 minx = r->min.x;
r2f32_t result = (r2f32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
r2f32_t r2f32_get_right(const r2f32_t *r, f32 value) {
f32 maxx = r->max.x;
r2f32_t result = (r2f32_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
r2f32_t r2f32_get_top(const r2f32_t *r, f32 value) { /* Y is down */
f32 miny = r->min.y;
r2f32_t result = (r2f32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
r2f32_t r2f32_get_bottom(const r2f32_t *r, f32 value) { /* Y is down */
f32 maxy = r->max.y;
r2f32_t result = (r2f32_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
r2f32_t r2f32_shrink(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_add(rect.min, value), v2f32_sub(rect.max, value) }; }
v2f32_t r2f32_get_size(r2f32_t r) { return (v2f32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
v2f32_t r2f32_get_mid(r2f32_t r) { return v2f32_add(r.min, v2f32_divs(r2f32_get_size(r), 2)); }
b32 r2f32_contains(r2f32_t rec, v2f32_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
return (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
}
r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
return (r2f64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
}
r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
return (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
}
r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
return (r2f64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
}
// get past left
r2f64_t r2f64_getp_left(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
r2f64_t r2f64_getp_right(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
r2f64_t r2f64_getp_bottom(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
r2f64_t r2f64_getp_top(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
r2f64_t r2f64_get_left(const r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r2f64_t result = (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
r2f64_t r2f64_get_right(const r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r2f64_t result = (r2f64_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
r2f64_t r2f64_get_top(const r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
v2f64_t r2f64_get_mid(r2f64_t r) { return v2f64_add(r.min, v2f64_divs(r2f64_get_size(r), 2)); }
b32 r2f64_contains(r2f64_t rec, v2f64_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
r2i32_t r2i32_cut_left(r2i32_t *r, i32 value) {
i32 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
return (r2i32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
}
r2i32_t r2i32_cut_right(r2i32_t *r, i32 value) {
i32 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
return (r2i32_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
}
r2i32_t r2i32_cut_top(r2i32_t *r, i32 value) { /* Y is down */
i32 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
return (r2i32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
}
r2i32_t r2i32_cut_bottom(r2i32_t *r, i32 value) { /* Y is down */
i32 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
return (r2i32_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
}
// get past left
r2i32_t r2i32_getp_left(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
r2i32_t r2i32_getp_right(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
r2i32_t r2i32_getp_bottom(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
r2i32_t r2i32_getp_top(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
r2i32_t r2i32_get_left(const r2i32_t *r, i32 value) {
i32 minx = r->min.x;
r2i32_t result = (r2i32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
r2i32_t r2i32_get_right(const r2i32_t *r, i32 value) {
i32 maxx = r->max.x;
r2i32_t result = (r2i32_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
r2i32_t r2i32_get_top(const r2i32_t *r, i32 value) { /* Y is down */
i32 miny = r->min.y;
r2i32_t result = (r2i32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
r2i32_t r2i32_get_bottom(const r2i32_t *r, i32 value) { /* Y is down */
i32 maxy = r->max.y;
r2i32_t result = (r2i32_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
r2i32_t r2i32_shrink(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_add(rect.min, value), v2i32_sub(rect.max, value) }; }
v2i32_t r2i32_get_size(r2i32_t r) { return (v2i32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
v2i32_t r2i32_get_mid(r2i32_t r) { return v2i32_add(r.min, v2i32_divs(r2i32_get_size(r), 2)); }
b32 r2i32_contains(r2i32_t rec, v2i32_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
r2i64_t r2i64_cut_left(r2i64_t *r, i64 value) {
i64 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
return (r2i64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
}
r2i64_t r2i64_cut_right(r2i64_t *r, i64 value) {
i64 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
return (r2i64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
}
r2i64_t r2i64_cut_top(r2i64_t *r, i64 value) { /* Y is down */
i64 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
return (r2i64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
}
r2i64_t r2i64_cut_bottom(r2i64_t *r, i64 value) { /* Y is down */
i64 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
return (r2i64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
}
// get past left
r2i64_t r2i64_getp_left(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
r2i64_t r2i64_getp_right(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
r2i64_t r2i64_getp_bottom(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
r2i64_t r2i64_getp_top(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
r2i64_t r2i64_get_left(const r2i64_t *r, i64 value) {
i64 minx = r->min.x;
r2i64_t result = (r2i64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
r2i64_t r2i64_get_right(const r2i64_t *r, i64 value) {
i64 maxx = r->max.x;
r2i64_t result = (r2i64_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
r2i64_t r2i64_get_top(const r2i64_t *r, i64 value) { /* Y is down */
i64 miny = r->min.y;
r2i64_t result = (r2i64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
r2i64_t r2i64_get_bottom(const r2i64_t *r, i64 value) { /* Y is down */
i64 maxy = r->max.y;
r2i64_t result = (r2i64_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
r2i64_t r2i64_shrink(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_add(rect.min, value), v2i64_sub(rect.max, value) }; }
v2i64_t r2i64_get_size(r2i64_t r) { return (v2i64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
v2i64_t r2i64_get_mid(r2i64_t r) { return v2i64_add(r.min, v2i64_divs(r2i64_get_size(r), 2)); }
b32 r2i64_contains(r2i64_t rec, v2i64_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
v2f64_t v2f32_to_v2f64(v2f32_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; }
v3f64_t v3f32_to_v3f64(v3f32_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; }
v4f64_t v4f32_to_v4f64(v4f32_t v) { return (v4f64_t){ (f64)v.x, (f64)v.y, (f64)v.z, (f64)v.w }; }
r2f64_t r2f32_to_r2f64(r2f32_t v) { return (r2f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.x1, (f64)v.y1 }; }
r3f64_t r3f32_to_r3f64(r3f32_t v) { return (r3f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.z0, (f64)v.x1, (f64)v.y1, (f64)v.z1 }; }
v2i32_t v2f32_to_v2i32(v2f32_t v) { return (v2i32_t){ (i32)v.x, (i32)v.y }; }
v3i32_t v3f32_to_v3i32(v3f32_t v) { return (v3i32_t){ (i32)v.x, (i32)v.y, (i32)v.z }; }
v4i32_t v4f32_to_v4i32(v4f32_t v) { return (v4i32_t){ (i32)v.x, (i32)v.y, (i32)v.z, (i32)v.w }; }
r2i32_t r2f32_to_r2i32(r2f32_t v) { return (r2i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.x1, (i32)v.y1 }; }
r3i32_t r3f32_to_r3i32(r3f32_t v) { return (r3i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.z0, (i32)v.x1, (i32)v.y1, (i32)v.z1 }; }
v2i64_t v2f32_to_v2i64(v2f32_t v) { return (v2i64_t){ (i64)v.x, (i64)v.y }; }
v3i64_t v3f32_to_v3i64(v3f32_t v) { return (v3i64_t){ (i64)v.x, (i64)v.y, (i64)v.z }; }
v4i64_t v4f32_to_v4i64(v4f32_t v) { return (v4i64_t){ (i64)v.x, (i64)v.y, (i64)v.z, (i64)v.w }; }
r2i64_t r2f32_to_r2i64(r2f32_t v) { return (r2i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.x1, (i64)v.y1 }; }
r3i64_t r3f32_to_r3i64(r3f32_t v) { return (r3i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.z0, (i64)v.x1, (i64)v.y1, (i64)v.z1 }; }
v2f32_t v2f64_to_v2f32(v2f64_t v) { return (v2f32_t){ (f32)v.x, (f32)v.y }; }
v3f32_t v3f64_to_v3f32(v3f64_t v) { return (v3f32_t){ (f32)v.x, (f32)v.y, (f32)v.z }; }
v4f32_t v4f64_to_v4f32(v4f64_t v) { return (v4f32_t){ (f32)v.x, (f32)v.y, (f32)v.z, (f32)v.w }; }
r2f32_t r2f64_to_r2f32(r2f64_t v) { return (r2f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.x1, (f32)v.y1 }; }
r3f32_t r3f64_to_r3f32(r3f64_t v) { return (r3f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.z0, (f32)v.x1, (f32)v.y1, (f32)v.z1 }; }
v2i32_t v2f64_to_v2i32(v2f64_t v) { return (v2i32_t){ (i32)v.x, (i32)v.y }; }
v3i32_t v3f64_to_v3i32(v3f64_t v) { return (v3i32_t){ (i32)v.x, (i32)v.y, (i32)v.z }; }
v4i32_t v4f64_to_v4i32(v4f64_t v) { return (v4i32_t){ (i32)v.x, (i32)v.y, (i32)v.z, (i32)v.w }; }
r2i32_t r2f64_to_r2i32(r2f64_t v) { return (r2i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.x1, (i32)v.y1 }; }
r3i32_t r3f64_to_r3i32(r3f64_t v) { return (r3i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.z0, (i32)v.x1, (i32)v.y1, (i32)v.z1 }; }
v2i64_t v2f64_to_v2i64(v2f64_t v) { return (v2i64_t){ (i64)v.x, (i64)v.y }; }
v3i64_t v3f64_to_v3i64(v3f64_t v) { return (v3i64_t){ (i64)v.x, (i64)v.y, (i64)v.z }; }
v4i64_t v4f64_to_v4i64(v4f64_t v) { return (v4i64_t){ (i64)v.x, (i64)v.y, (i64)v.z, (i64)v.w }; }
r2i64_t r2f64_to_r2i64(r2f64_t v) { return (r2i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.x1, (i64)v.y1 }; }
r3i64_t r3f64_to_r3i64(r3f64_t v) { return (r3i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.z0, (i64)v.x1, (i64)v.y1, (i64)v.z1 }; }
v2f32_t v2i32_to_v2f32(v2i32_t v) { return (v2f32_t){ (f32)v.x, (f32)v.y }; }
v3f32_t v3i32_to_v3f32(v3i32_t v) { return (v3f32_t){ (f32)v.x, (f32)v.y, (f32)v.z }; }
v4f32_t v4i32_to_v4f32(v4i32_t v) { return (v4f32_t){ (f32)v.x, (f32)v.y, (f32)v.z, (f32)v.w }; }
r2f32_t r2i32_to_r2f32(r2i32_t v) { return (r2f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.x1, (f32)v.y1 }; }
r3f32_t r3i32_to_r3f32(r3i32_t v) { return (r3f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.z0, (f32)v.x1, (f32)v.y1, (f32)v.z1 }; }
v2f64_t v2i32_to_v2f64(v2i32_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; }
v3f64_t v3i32_to_v3f64(v3i32_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; }
v4f64_t v4i32_to_v4f64(v4i32_t v) { return (v4f64_t){ (f64)v.x, (f64)v.y, (f64)v.z, (f64)v.w }; }
r2f64_t r2i32_to_r2f64(r2i32_t v) { return (r2f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.x1, (f64)v.y1 }; }
r3f64_t r3i32_to_r3f64(r3i32_t v) { return (r3f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.z0, (f64)v.x1, (f64)v.y1, (f64)v.z1 }; }
v2i64_t v2i32_to_v2i64(v2i32_t v) { return (v2i64_t){ (i64)v.x, (i64)v.y }; }
v3i64_t v3i32_to_v3i64(v3i32_t v) { return (v3i64_t){ (i64)v.x, (i64)v.y, (i64)v.z }; }
v4i64_t v4i32_to_v4i64(v4i32_t v) { return (v4i64_t){ (i64)v.x, (i64)v.y, (i64)v.z, (i64)v.w }; }
r2i64_t r2i32_to_r2i64(r2i32_t v) { return (r2i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.x1, (i64)v.y1 }; }
r3i64_t r3i32_to_r3i64(r3i32_t v) { return (r3i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.z0, (i64)v.x1, (i64)v.y1, (i64)v.z1 }; }
v2f32_t v2i64_to_v2f32(v2i64_t v) { return (v2f32_t){ (f32)v.x, (f32)v.y }; }
v3f32_t v3i64_to_v3f32(v3i64_t v) { return (v3f32_t){ (f32)v.x, (f32)v.y, (f32)v.z }; }
v4f32_t v4i64_to_v4f32(v4i64_t v) { return (v4f32_t){ (f32)v.x, (f32)v.y, (f32)v.z, (f32)v.w }; }
r2f32_t r2i64_to_r2f32(r2i64_t v) { return (r2f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.x1, (f32)v.y1 }; }
r3f32_t r3i64_to_r3f32(r3i64_t v) { return (r3f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.z0, (f32)v.x1, (f32)v.y1, (f32)v.z1 }; }
v2f64_t v2i64_to_v2f64(v2i64_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; }
v3f64_t v3i64_to_v3f64(v3i64_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; }
v4f64_t v4i64_to_v4f64(v4i64_t v) { return (v4f64_t){ (f64)v.x, (f64)v.y, (f64)v.z, (f64)v.w }; }
r2f64_t r2i64_to_r2f64(r2i64_t v) { return (r2f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.x1, (f64)v.y1 }; }
r3f64_t r3i64_to_r3f64(r3i64_t v) { return (r3f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.z0, (f64)v.x1, (f64)v.y1, (f64)v.z1 }; }
v2i32_t v2i64_to_v2i32(v2i64_t v) { return (v2i32_t){ (i32)v.x, (i32)v.y }; }
v3i32_t v3i64_to_v3i32(v3i64_t v) { return (v3i32_t){ (i32)v.x, (i32)v.y, (i32)v.z }; }
v4i32_t v4i64_to_v4i32(v4i64_t v) { return (v4i32_t){ (i32)v.x, (i32)v.y, (i32)v.z, (i32)v.w }; }
r2i32_t r2i64_to_r2i32(r2i64_t v) { return (r2i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.x1, (i32)v.y1 }; }
r3i32_t r3i64_to_r3i32(r3i64_t v) { return (r3i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.z0, (i32)v.x1, (i32)v.y1, (i32)v.z1 }; }

View File

@@ -0,0 +1,69 @@
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#if defined(__APPLE__) && defined(__MACH__)
#define PLATFORM_MAC_OS 1
#define PLATFORM_POSIX 1
#elif defined(_WIN32)
#define PLATFORM_WINDOWS 1
#elif defined(__linux__)
#define PLATFORM_POSIX 1
#define PLATFORM_LINUX 1
#elif defined(__wasm)
#define PLATFORM_WASM 1
#endif
#if defined(__clang__)
#define PLATFORM_CLANG 1
#elif defined(__GNUC__) || defined(__GNUG__)
#define PLATFORM_GCC 1
#elif defined(_MSC_VER)
#define PLATFORM_CL 1
#elif defined(__TINYC__)
#define PLATFORM_TCC 1
#endif
#ifndef PLATFORM_WASM
#define PLATFORM_WASM 0
#endif
#ifndef PLATFORM_WINDOWS
#define PLATFORM_WINDOWS 0
#endif
#ifndef PLATFORM_LINUX
#define PLATFORM_LINUX 0
#endif
#ifndef PLATFORM_POSIX
#define PLATFORM_POSIX 0
#endif
#ifndef PLATFORM_MAC_OS
#define PLATFORM_MAC_OS 0
#endif
#ifndef PLATFORM_CLANG
#define PLATFORM_CLANG 0
#endif
#ifndef PLATFORM_GCC
#define PLATFORM_GCC 0
#endif
#ifndef PLATFORM_CL
#define PLATFORM_CL 0
#endif
#ifndef PLATFORM_TCC
#define PLATFORM_TCC 0
#endif
#ifndef PLATFORM_ASSERT
#define PLATFORM_ASSERT 1
#endif
#ifndef PLATFORM_ADDRESS_SANITIZER
#define PLATFORM_ADDRESS_SANITIZER 0
#endif

36
src/core/scratch.c Normal file
View File

@@ -0,0 +1,36 @@
ma_temp_t ma_begin_scratch_ex(ma_arena_t **conflicts, int conflict_count) {
ma_arena_t *unoccupied = 0;
for (int i = 0; i < lengthof(core_desc.scratch); i += 1) {
ma_arena_t *from_pool = core_desc.scratch + i;
unoccupied = from_pool;
for (int conflict_i = 0; conflict_i < conflict_count; conflict_i += 1) {
ma_arena_t *from_conflict = conflicts[conflict_i];
if (from_pool == from_conflict) {
unoccupied = 0;
break;
}
}
if (unoccupied) {
break;
}
}
assertf(unoccupied, "Failed to get free scratch memory, this is a fatal error, this shouldnt happen");
ma_temp_t result = ma_begin_temp(unoccupied);
return result;
}
ma_temp_t ma_begin_scratch(void) {
ma_temp_t result = ma_begin_temp(core_desc.scratch + 0);
return result;
}
ma_temp_t ma_begin_scratch1(ma_arena_t *conflict) {
ma_arena_t *conflicts[] = {conflict};
return ma_begin_scratch_ex(conflicts, 1);
}
#define ma_end_scratch(x) ma_end_temp(x)
#define ma_temp_scope(name, InArena) for (ma_temp_t name = ma_begin_temp(InArena); name.arena; (ma_end_temp(name), name.arena = 0))
#define ma_scratch_scope(x) for (ma_temp_t x = ma_begin_scratch(); x.arena; (ma_end_temp(x), x.arena = 0))

1961
src/core/stb_sprintf.h Normal file

File diff suppressed because it is too large Load Diff

59
src/core/string.c Normal file
View File

@@ -0,0 +1,59 @@
#define STR_FMT(buff, str) \
va_list args1; \
va_start(args1, str); \
int len = stbsp_vsnprintf(buff, sizeof(buff), str, args1); \
va_end(args1)
int str_len(char *str) {
int i = 0;
while (str[i]) i += 1;
return i;
}
b32 s8_equal(s8_t a, s8_t b);
s8_t s8_from_char(char *string);
b32 str_eq(char *a, char *b) {
return s8_equal(s8_from_char(a), s8_from_char(b));
}
char char_to_lower_case(char a) {
if (a >= 'A' && a <= 'Z') a += 32;
return a;
}
char char_to_upper_case(char a) {
if (a >= 'a' && a <= 'z') a -= 32;
return a;
}
b32 char_is_whitespace(char w) {
b32 result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
return result;
}
b32 char_is_alphabetic(char a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
return result;
}
b32 char_is_ident(char a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') || a == '_';
return result;
}
b32 char_is_digit(char a) {
b32 result = a >= '0' && a <= '9';
return result;
}
b32 char_is_alphanumeric(char a) {
b32 result = char_is_digit(a) || char_is_alphabetic(a);
return result;
}
i64 wstr_len(wchar_t *string) {
i64 len = 0;
while (*string++ != 0)
len++;
return len;
}

454
src/core/string8.c Normal file
View File

@@ -0,0 +1,454 @@
#define s8_vsnprintf stbsp_vsnprintf
#define S8_FMT(ma, str, result) \
va_list args1; \
va_start(args1, str); \
s8_t result = s8_vfmt(ma, str, args1); \
va_end(args1)
s8_t s8_range(char *begin, char *end) {
assert(end >= begin);
intptr_t size = (intptr_t)end - (intptr_t)begin;
s8_t result = {begin, size};
return result;
}
b32 s8_equal_ex(s8_t a, s8_t b, b32 ignore_case) {
if (a.len != b.len) return false;
for (int64_t i = 0; i < a.len; i++) {
char A = a.str[i];
char B = b.str[i];
if (ignore_case) {
A = char_to_lower_case(A);
B = char_to_lower_case(B);
}
if (A != B)
return false;
}
return true;
}
b32 s8_equal(s8_t a, s8_t b) {return s8_equal_ex(a, b, false);}
s8_t s8_get_postfix(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
int64_t remain_len = string.len - len;
s8_t result = s8(string.str + remain_len, len);
return result;
}
s8_t s8_get_prefix(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
s8_t result = s8(string.str, len);
return result;
}
s8_t s8_chop(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
s8_t result = s8(string.str, string.len - len);
return result;
}
s8_t s8_skip(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
int64_t remain = string.len - len;
s8_t result = s8(string.str + len, remain);
return result;
}
b32 s8_ends_with(s8_t a, s8_t end, b32 ignore_case) {
s8_t a_end = s8_get_postfix(a, end.len);
b32 result = s8_equal_ex(end, a_end, ignore_case);
return result;
}
b32 s8_starts_with(s8_t a, s8_t start, b32 ignore_case) {
s8_t a_start = s8_get_prefix(a, start.len);
b32 result = s8_equal_ex(start, a_start, ignore_case);
return result;
}
void s8_normalize_path_unsafe(s8_t s) {
for (int64_t i = 0; i < s.len; i++) {
if (s.str[i] == '\\')
s.str[i] = '/';
}
}
b32 s8_is_pointer_inside(s8_t string, char *p) {
uintptr_t pointer = (uintptr_t)p;
uintptr_t start = (uintptr_t)string.str;
uintptr_t stop = start + (uintptr_t)string.len;
b32 result = pointer >= start && pointer < stop;
return result;
}
s8_t s8_skip_to_p(s8_t string, char *p) {
if (s8_is_pointer_inside(string, p)) {
s8_t result = s8(p, p - string.str);
return result;
}
return string;
}
s8_t s8_skip_past(s8_t string, s8_t a) {
if (s8_is_pointer_inside(string, a.str)) {
s8_t on_p = s8(a.str, a.str - string.str);
s8_t result = s8_skip(on_p, a.len);
return result;
}
return string;
}
s8_t s8_slice(s8_t string, int64_t first_index, int64_t one_past_last_index) {
if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1;
if (first_index < 0) first_index = string.len + first_index;
assert(first_index < one_past_last_index && "s8_slice, first_index is bigger then one_past_last_index");
assert(string.len > 0 && "Slicing string of length 0! Might be an error!");
s8_t result = string;
if (string.len > 0) {
if (one_past_last_index > first_index) {
first_index = CLAMP_TOP(first_index, string.len - 1);
one_past_last_index = CLAMP_TOP(one_past_last_index, string.len);
result.str += first_index;
result.len = one_past_last_index - first_index;
}
else {
result.len = 0;
}
}
return result;
}
s8_t s8_trim(s8_t string) {
if (string.len == 0)
return string;
int64_t whitespace_begin = 0;
for (; whitespace_begin < string.len; whitespace_begin++) {
if (!char_is_whitespace(string.str[whitespace_begin])) {
break;
}
}
int64_t whitespace_end = string.len;
for (; whitespace_end != whitespace_begin; whitespace_end--) {
if (!char_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
if (whitespace_begin == whitespace_end) {
string.len = 0;
}
else {
string = s8_slice(string, whitespace_begin, whitespace_end);
}
return string;
}
s8_t s8_trim_end(s8_t string) {
int64_t whitespace_end = string.len;
for (; whitespace_end != 0; whitespace_end--) {
if (!char_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
s8_t result = s8_get_prefix(string, whitespace_end);
return result;
}
typedef int s8_seek_t;
enum {
s8_seek_none = 0,
s8_seek_ignore_case = 1,
s8_seek_match_find_last = 2,
};
b32 s8_seek(s8_t string, s8_t find, s8_seek_t flags, int64_t *index_out) {
b32 ignore_case = flags & s8_seek_ignore_case ? true : false;
b32 result = false;
if (flags & s8_seek_match_find_last) {
for (int64_t i = string.len; i != 0; i--) {
int64_t index = i - 1;
s8_t substring = s8_slice(string, index, index + find.len);
if (s8_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = index;
result = true;
break;
}
}
}
else {
for (int64_t i = 0; i < string.len; i++) {
s8_t substring = s8_slice(string, i, i + find.len);
if (s8_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = i;
result = true;
break;
}
}
}
return result;
}
int64_t s8_find(s8_t string, s8_t find, s8_seek_t flag) {
int64_t result = -1;
s8_seek(string, find, flag, &result);
return result;
}
s8_t s8_chop_last_slash(s8_t s) {
s8_t result = s;
s8_seek(s, s8_lit("/"), s8_seek_match_find_last, &result.len);
return result;
}
s8_t s8_chop_last_period(s8_t s) {
s8_t result = s;
s8_seek(s, s8_lit("."), s8_seek_match_find_last, &result.len);
return result;
}
s8_t s8_skip_to_last_slash(s8_t s) {
int64_t pos;
s8_t result = s;
if (s8_seek(s, s8_lit("/"), s8_seek_match_find_last, &pos)) {
result = s8_skip(result, pos + 1);
}
return result;
}
s8_t s8_skip_to_last_period(s8_t s) {
int64_t pos;
s8_t result = s;
if (s8_seek(s, s8_lit("."), s8_seek_match_find_last, &pos)) {
result = s8_skip(result, pos + 1);
}
return result;
}
s8_t s8_from_char(char *string) {
s8_t result;
result.str = (char *)string;
result.len = str_len(string);
return result;
}
s8_t s8_get_name_no_ext(s8_t s) {
return s8_skip_to_last_slash(s8_chop_last_period(s));
}
s8_t s8_copy(ma_arena_t *ma, s8_t string) {
char *copy = (char *)ma_push_size(ma, sizeof(char) * (string.len + 1));
if (copy) {
memory_copy(copy, string.str, string.len);
copy[string.len] = 0;
s8_t result = s8(copy, string.len);
return result;
}
return (s8_t){0};
}
s8_t s8_copy_char(ma_arena_t *ma, char *s) {
int64_t len = str_len(s);
char *copy = (char *)ma_push_size(ma, sizeof(char) * (len + 1));
memory_copy(copy, s, len);
copy[len] = 0;
s8_t result = s8(copy, len);
return result;
}
s8_t s8_normalize_path(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
if (copy.str[i] == '\\')
copy.str[i] = '/';
}
return copy;
}
s8_t s8_to_lower_case(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = char_to_lower_case(copy.str[i]);
}
return copy;
}
s8_t s8_to_upper_case(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = char_to_upper_case(copy.str[i]);
}
return copy;
}
s8_t s8_vfmt(ma_arena_t *ma, const char *str, va_list args1) {
va_list args2;
va_copy(args2, args1);
int64_t len = s8_vsnprintf(0, 0, str, args2);
va_end(args2);
char *result = (char *)ma_push_size(ma, sizeof(char) * (len + 1));
s8_vsnprintf(result, (int)(len + 1), str, args1);
s8_t res = s8(result, len);
return res;
}
s8_t s8_fmt(ma_arena_t *ma, const char *str, ...) {
S8_FMT(ma, str, result);
return result;
}
//
// sb8_t
//
sb8_node_t *sb8_node(ma_arena_t *ma, s8_t str) {
sb8_node_t *node = ma_push_type(ma, sb8_node_t);
node->s = str;
return node;
}
sb8_node_t *sb8_append(sb8_t *list, s8_t string) {
sb8_node_t *node = sb8_node(list->arena, string);
SLLQ_APPEND(list->first, list->last, node);
return node;
}
s8_t sb8_printf(sb8_t *sb, const char *str, ...) {
S8_FMT(sb->arena, str, result);
sb8_append(sb, result);
return result;
}
void sb8_indent(sb8_t *sb) {
sb8_printf(sb, "\n%.*s", sb->indent*4, " ");
}
s8_t sb8_stmtf(sb8_t *sb, const char *str, ...) {
S8_FMT(sb->arena, str, result);
sb8_indent(sb);
sb8_append(sb, result);
return result;
}
int64_t sb8_char_size(sb8_t *sb) {
int64_t result = 0;
for (sb8_node_t *it = sb->first; it; it = it->next) {
result += it->len;
}
return result;
}
s8_t sb8_merge(sb8_t *sb) {
int64_t size = sb8_char_size(sb) + 1;
char *str = ma_push_size(sb->arena, size);
s8_t result = {str, 0};
for (sb8_node_t *it = sb->first; it; it = it->next) {
memory_copy(result.str + result.len, it->str, it->len);
result.len += it->len;
}
result.str[result.len] = 0;
return result;
}
typedef int s8_split_t;
enum {
s8_split_none = 0,
s8_split_ignore_case = 1,
s8_split_inclusive = 2,
};
sb8_t s8_split(ma_arena_t *ma, s8_t string, s8_t find, s8_split_t flags) {
sb8_t result = (sb8_t){ma};
int64_t index = 0;
s8_seek_t find_flag = flags & s8_split_ignore_case ? s8_seek_ignore_case : s8_seek_none;
while (s8_seek(string, find, find_flag, &index)) {
s8_t before_match = s8(string.str, index);
sb8_append(&result, before_match);
if (flags & s8_split_inclusive) {
s8_t match = s8(string.str + index, find.len);
sb8_append(&result, match);
}
string = s8_skip(string, index + find.len);
}
if (string.len) sb8_append(&result, string);
return result;
}
s16_t s16_from_s8(ma_arena_t *ma, s8_t string) {
u16 *buffer = ma_push_array(ma, u16, string.len + 1);
i64 len = wstr_from_str(buffer, string.len + 1, string.str, string.len);
assert(len < string.len);
return (s16_t){buffer,len};
}
s8_t s8_from_s16(ma_arena_t *ma, s16_t string) {
i64 buffer_size = (string.len + 1) * 2;
char *buffer = ma_push_array(ma, char, buffer_size);
i64 len = str_from_wstr(buffer, buffer_size, string.str, string.len);
assert(len < buffer_size);
return (s8_t){buffer,len};
}
#if 0
s8_t S8_MergeWithSeparator(ma_arena_t *ma, S8_List list, s8_t separator) {
if (list.node_count == 0) return s8_makeEmpty();
if (list.char_count == 0) return s8_makeEmpty();
int64_t base_size = (list.char_count + 1);
int64_t sep_size = (list.node_count - 1) * separator.len;
int64_t size = base_size + sep_size;
char *buff = (char *)ma_push_size(ma, sizeof(char) * (size + 1));
s8_t string = s8(buff, 0);
for (S8_Node *it = list.first; it; it = it->next) {
assert(string.len + it->string.len <= size);
memory_copy(string.str + string.len, it->string.str, it->string.len);
string.len += it->string.len;
if (it != list.last) {
memory_copy(string.str + string.len, separator.str, separator.len);
string.len += separator.len;
}
}
assert(string.len == size - 1);
string.str[size] = 0;
return string;
}
s8_t S8_Merge(ma_arena_t *ma, S8_List list) {
return S8_MergeWithSeparator(ma, list, s8_lit(""));
}
s8_t S8_ReplaceAll(ma_arena_t *ma, s8_t string, s8_t replace, s8_t with, b32 ignore_case) {
s8_split_flag split_flag = ignore_case ? S8_SplitFlag_IgnoreCase : S8_SplitFlag_None;
S8_List list = S8_Split(ma, string, replace, split_flag | S8_SplitFlag_SplitInclusive);
for (S8_Node *it = list.first; it; it = it->next) {
if (s8_equal_ex(it->string, replace, ignore_case)) {
S8_ReplaceNodeString(&list, it, with);
}
}
s8_t result = S8_Merge(ma, list);
return result;
}
S8_List S8_FindAll(ma_arena_t *ma, s8_t string, s8_t find, b32 ignore_case) { // @untested
S8_List result = s8_makeEmptyList();
int64_t index = 0;
s8_seek find_flag = ignore_case ? s8_seek_ignore_case : 0;
while (s8_seek(string, find, find_flag, &index)) {
s8_t match = s8(string.str + index, find.len);
S8_AddNode(ma, &result, match);
string = s8_skip(string, index + find.len);
}
return result;
}
#endif

403
src/core/type_info.c Normal file
View File

@@ -0,0 +1,403 @@
s8_t ti_enum_value_to_name(type_t *type, i64 value) {
assert(type->kind == type_kind_enum);
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (value == it->value) {
return it->name;
}
}
return s8_lit("invalid");
}
i64 ti_enum_name_to_value(type_t *type, s8_t name) {
assert(type->kind == type_kind_enum);
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (s8_equal(it->name, name)) {
return it->value;
}
}
return -1;
}
type_member_t *ti_get_member(type_t *type, s8_t name) {
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (s8_equal(it->name, name)) {
return it;
}
}
return NULL;
}
void sb8_serial_data(sb8_t *sb, void *p, type_t *type) {
assert(type->kind != type_kind_invalid);
switch(type->kind) {
case type_kind_i8: {
i8 n = *(i8 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_i16: {
i16 n = *(i16 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_i32: {
i32 n = *(i32 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_i64: {
i64 n = *(i64 *)p;
sb8_printf(sb, "%lld", (long long)n);
return;
} break;
case type_kind_u8: {
u8 n = *(u8 *)p;
sb8_printf(sb, "%u", n);
return;
} break;
case type_kind_u16: {
u16 n = *(u16 *)p;
sb8_printf(sb, "%u", n);
return;
} break;
case type_kind_u32: {
u32 n = *(u32 *)p;
sb8_printf(sb, "%u", n);
return;
} break;
case type_kind_u64: {
u64 n = *(u64 *)p;
sb8_printf(sb, "%llu", (unsigned long long)n);
return;
} break;
case type_kind_b8: {
b8 n = *(b8 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_b16: {
b16 n = *(b16 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_b32: {
b32 n = *(b32 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_b64: {
b64 n = *(b64 *)p;
sb8_printf(sb, "%lld", (long long)n);
return;
} break;
case type_kind_f32: {
f32 n = *(f32 *)p;
sb8_printf(sb, "%f", n);
return;
} break;
case type_kind_f64: {
f64 n = *(f64 *)p;
sb8_printf(sb, "%f", n);
return;
} break;
case type_kind_isize: {
isize n = *(isize *)p;
sb8_printf(sb, "%lld", (long long)n);
return;
} break;
case type_kind_usize: {
usize n = *(usize *)p;
sb8_printf(sb, "%llu", (unsigned long long)n);
return;
} break;
case type_kind_int: {
int n = *(int *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_char: {
char n = *(char *)p;
sb8_printf(sb, "%c", n);
return;
} break;
}
if (type == &type__s8_t) {
s8_t n = *(s8_t *)p;
sb8_printf(sb, "\"%S\"", n);
return;
}
if (type->kind == type_kind_pointer) {
sb8_printf(sb, "0x%x", p);
return;
}
if (type->kind == type_kind_enum) {
i64 value = 0;
if (type->size == 1) {
value = *(i8 *)p;
} else if (type->size == 2) {
value = *(i16 *)p;
} else if (type->size == 4) {
value = *(i32 *)p;
} else if (type->size == 8) {
value = *(i64 *)p;
} else {
panicf("invalid size of enum: %d", type->size);
}
s8_t s = ti_enum_value_to_name(type, value);
sb8_append(sb, s);
return;
}
if (type->kind == type_kind_array) {
u8 *p8 = (u8 *)p;
sb8_printf(sb, "{");
sb->indent += 1;
for (i32 i = 0; i < type->count; i += 1) {
type_t *base = type->base;
u8 *mem_p = p8 + base->size * i;
sb8_indent(sb);
sb8_serial_data(sb, mem_p, base);
sb8_printf(sb, ",");
}
sb->indent -= 1;
sb8_stmtf(sb, "}");
return;
}
if (type->kind == type_kind_struct) {
u8 *p8 = (u8 *)p;
sb8_printf(sb, "{");
sb->indent += 1;
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *mem = type->members + i;
u8 *mem_p = p8 + mem->offset;
sb8_indent(sb);
sb8_printf(sb, "%S: ", mem->name);
sb8_serial_data(sb, mem_p, mem->type);
sb8_printf(sb, ",");
}
sb->indent -= 1;
sb8_stmtf(sb, "}");
return;
}
panicf("can't serialize: unhandled type");
}
s8_t s8_serial_data(ma_arena_t *arena, void *p, type_t *type) {
sb8_t *sb = sb8_serial_begin(arena);
sb8_serial_data(sb, p, type);
s8_t string = sb8_serial_end(sb);
return string;
}
i64 parser__match_i64(parser_t *par) {
i64 minus = 1;
if (parser_match(par, lex_kind_minus)) {
minus = -1;
}
lex_t *token = parser_expect(par, lex_kind_int);
i64 result = (i64)token->integer * minus;
return result;
}
void s8_deserial_data_ex(ma_arena_t *arena, parser_t *par, void *p, type_t *type) {
switch(type->kind) {
case type_kind_i8: {
i8 *n = (i8 *)p;
n[0] = (i8)parser__match_i64(par);
return;
} break;
case type_kind_i16: {
i16 *n = (i16 *)p;
n[0] = (i16)parser__match_i64(par);
return;
} break;
case type_kind_i32: {
i32 *n = (i32 *)p;
n[0] = (i32)parser__match_i64(par);
return;
} break;
case type_kind_i64: {
i64 *n = (i64 *)p;
n[0] = (i64)parser__match_i64(par);
return;
} break;
case type_kind_b8: {
b8 *n = (b8 *)p;
n[0] = (b8)parser__match_i64(par);
return;
} break;
case type_kind_b16: {
b16 *n = (b16 *)p;
n[0] = (b16)parser__match_i64(par);
return;
} break;
case type_kind_b32: {
b32 *n = (b32 *)p;
n[0] = (b32)parser__match_i64(par);
return;
} break;
case type_kind_b64: {
b64 *n = (b64 *)p;
n[0] = (b64)parser__match_i64(par);
return;
} break;
case type_kind_u8: {
lex_t *token = parser_expect(par, lex_kind_int);
u8 *n = (u8 *)p;
n[0] = (u8)token->integer;
return;
} break;
case type_kind_u16: {
lex_t *token = parser_expect(par, lex_kind_int);
u16 *n = (u16 *)p;
n[0] = (u16)token->integer;
return;
} break;
case type_kind_u32: {
lex_t *token = parser_expect(par, lex_kind_int);
u32 *n = (u32 *)p;
n[0] = (u32)token->integer;
return;
} break;
case type_kind_u64: {
lex_t *token = parser_expect(par, lex_kind_int);
u64 *n = (u64 *)p;
n[0] = (u64)token->integer;
return;
} break;
case type_kind_f32: {
lex_t *token = parser_expect(par, lex_kind_real);
f32 *n = (f32 *)p;
n[0] = (f32)token->real;
return;
} break;
case type_kind_f64: {
lex_t *token = parser_expect(par, lex_kind_real);
f64 *n = (f64 *)p;
n[0] = token->real;
return;
} break;
case type_kind_isize: {
isize *n = (isize *)p;
n[0] = (isize)parser__match_i64(par);
return;
} break;
case type_kind_usize: {
lex_t *token = parser_expect(par, lex_kind_int);
usize *n = (usize *)p;
n[0] = (usize)token->integer;
return;
} break;
case type_kind_int: {
int *n = (int *)p;
n[0] = (int)parser__match_i64(par);
return;
} break;
case type_kind_char: {
char *n = (char *)p;
n[0] = (char)parser__match_i64(par);
return;
} break;
}
if (type == &type__s8_t) {
lex_t *token = parser_expect(par, lex_kind_string);
s8_t *n = (s8_t *)p;
n[0] = s8_copy(arena, token->s8);
return;
}
if (type->kind == type_kind_enum) {
lex_t *token = parser_expect(par, lex_kind_ident);
i64 value = ti_enum_name_to_value(type, token->s8);
if (value == -1) {
panicf("invalid enum value: %S", token->s8);
}
if (type->size == 1) {
*(i8 *)p = (i8)value;
} else if (type->size == 2) {
*(i16 *)p = (i16)value;
} else if (type->size == 4) {
*(i32 *)p = (i32)value;
} else if (type->size == 8) {
*(i64 *)p = (i64)value;
} else {
panicf("invalid size of enum: %d", type->size);
}
return;
}
if (type->kind == type_kind_struct) {
u8 *p8 = (u8 *)p;
#if 0
parser_expect(par, lex_kind_open_brace);
while (!parser_match(par, lex_kind_close_brace)) {
lex_t *ident = parser_expect(par, lex_kind_ident);
parser_expect(par, lex_kind_colon);
type_member_t *mem = ti_get_member(type, ident->s8);
if (mem) {
u8 *mem_p = p8 + mem->offset;
s8_deserial_data_ex(arena, par, mem_p, mem->type);
} else {
debugf("deserial - skipping field: %S", ident->s8);
parser_eat_until(par, lex_kind_comma);
}
parser_expect(par, lex_kind_comma);
}
#else // strict
parser_expect(par, lex_kind_open_brace);
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *mem = type->members + i;
u8 *mem_p = p8 + mem->offset;
lex_t *ident = parser_expect(par, lex_kind_ident);
parser_expect(par, lex_kind_colon);
assert(s8_equal(ident->s8, mem->name));
s8_deserial_data_ex(arena, par, mem_p, mem->type);
parser_expect(par, lex_kind_comma);
}
parser_expect(par, lex_kind_close_brace);
#endif
}
if (type->kind == type_kind_array) {
u8 *p8 = (u8 *)p;
parser_expect(par, lex_kind_open_brace);
for (i32 i = 0; i < type->count; i += 1) {
type_t *base = type->base;
u8 *mem_p = p8 + base->size * i;
s8_deserial_data_ex(arena, par, mem_p, base);
parser_expect(par, lex_kind_comma);
}
parser_expect(par, lex_kind_close_brace);
}
}
#define s8_deserial_data(ARENA, DATA, TYPE) (TYPE *)s8__deserial_data(ARENA, DATA, &type__##TYPE)
void *s8__deserial_data(ma_arena_t *arena, s8_t data, type_t *type) {
void *p = ma_push_size(arena, type->size);
ma_temp_t scratch = ma_begin_scratch();
lex_array_t tokens = lex_tokens(scratch.arena, "data serializing", data.str);
parser_t *par = parser_make(scratch.arena, tokens.data);
s8_deserial_data_ex(arena, par, p, type);
ma_end_scratch(scratch);
return p;
}

314
src/core/type_info.h Normal file
View File

@@ -0,0 +1,314 @@
typedef int type_kind_t;
enum {
type_kind_invalid,
type_kind_i8,
type_kind_i16,
type_kind_i32,
type_kind_i64,
type_kind_b8,
type_kind_b16,
type_kind_b32,
type_kind_b64,
type_kind_u8,
type_kind_u16,
type_kind_u32,
type_kind_u64,
type_kind_f32,
type_kind_f64,
type_kind_isize,
type_kind_usize,
type_kind_int,
type_kind_char,
type_kind_count,
type_kind_pointer,
type_kind_array,
type_kind_struct,
type_kind_union,
type_kind_enum,
};
typedef struct type_member_t type_member_t;
typedef struct type_t type_t;
struct type_t {
type_kind_t kind;
s8_t name;
i32 size;
i32 count;
type_member_t *members;
type_t *base;
};
struct type_member_t {
s8_t name;
type_t *type;
i64 value;
u64 offset;
};
#define type(X) &type__##X
#define DEFINE_ENUM(x) type_t type__##x = {type_kind_enum, s8_const_lit(#x), sizeof(x), .members = members__##x, .count = lengthof(members__##x)}
#define DEFINE_STRUCT(x) type_t type__##x = {type_kind_struct, s8_const_lit(#x), sizeof(x), .members = members__##x, .count = lengthof(members__##x)}
#define POINTER(x) (type_t){type_kind_pointer, s8_const_lit(#x "*"), sizeof(void *), .base = &type__##x}
s8_t ti_enum_value_to_name(type_t *type, i64 value);
i64 ti_enum_name_to_value(type_t *type, s8_t name);
type_member_t *ti_get_member(type_t *type, s8_t name);
type_t type__i8 = {type_kind_i8, s8_const_lit("i8"), sizeof(i8)};
type_t type__i16 = {type_kind_i16, s8_const_lit("i16"), sizeof(i16)};
type_t type__i32 = {type_kind_i32, s8_const_lit("i32"), sizeof(i32)};
type_t type__i64 = {type_kind_i64, s8_const_lit("i64"), sizeof(i64)};
type_t type__u8 = {type_kind_u8, s8_const_lit("u8"), sizeof(u8)};
type_t type__u16 = {type_kind_u16, s8_const_lit("u16"), sizeof(u16)};
type_t type__u32 = {type_kind_u32, s8_const_lit("u32"), sizeof(u32)};
type_t type__u64 = {type_kind_u64, s8_const_lit("u64"), sizeof(u64)};
type_t type__b8 = {type_kind_b8, s8_const_lit("b8"), sizeof(b8)};
type_t type__b16 = {type_kind_b16, s8_const_lit("b16"), sizeof(b16)};
type_t type__b32 = {type_kind_b32, s8_const_lit("b32"), sizeof(b32)};
type_t type__b64 = {type_kind_b64, s8_const_lit("b64"), sizeof(b64)};
type_t type__f32 = {type_kind_f32, s8_const_lit("f32"), sizeof(f32)};
type_t type__f64 = {type_kind_f64, s8_const_lit("f64"), sizeof(f64)};
type_t type__isize = {type_kind_isize, s8_const_lit("isize"), sizeof(isize)};
type_t type__usize = {type_kind_usize, s8_const_lit("usize"), sizeof(usize)};
type_t type__int = {type_kind_int, s8_const_lit("int"), sizeof(int)};
type_t type__char = {type_kind_char, s8_const_lit("char"), sizeof(char)};
type_t type__s8_t = { type_kind_struct, s8_const_lit("s8_t"), sizeof(s8_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("str"), &POINTER(char), .offset = offsetof(s8_t, str)},
{s8_const_lit("len"), &type__i64, .offset = offsetof(s8_t, len)},
}
};
type_t type__s16_t = { type_kind_struct, s8_const_lit("s16_t"), sizeof(s16_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("str"), &POINTER(u16), .offset = offsetof(s16_t, str)},
{s8_const_lit("len"), &type__i64, .offset = offsetof(s16_t, len)},
}
};
type_t type__s32_t = { type_kind_struct, s8_const_lit("s32_t"), sizeof(s32_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("str"), &POINTER(u32), .offset = offsetof(s32_t, str)},
{s8_const_lit("len"), &type__i64, .offset = offsetof(s32_t, len)},
}
};
type_t type__ma_arena_t = { type_kind_struct, s8_const_lit("ma_arena_t"), sizeof(ma_arena_t), .count = 6,
.members = (type_member_t[]){
{s8_const_lit("data"), &POINTER(u8), .offset = offsetof(ma_arena_t, data)},
{s8_const_lit("len"), &type__usize, .offset = offsetof(ma_arena_t, len)},
{s8_const_lit("base_len"), &type__usize, .offset = offsetof(ma_arena_t, base_len)},
{s8_const_lit("reserve"), &type__usize, .offset = offsetof(ma_arena_t, reserve)},
{s8_const_lit("commit"), &type__usize, .offset = offsetof(ma_arena_t, commit)},
{s8_const_lit("align"), &type__usize, .offset = offsetof(ma_arena_t, align)},
}
};
type_t type__ma_temp_t = { type_kind_struct, s8_const_lit("ma_temp_t"), sizeof(ma_temp_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("arena"), &POINTER(ma_arena_t), .offset = offsetof(ma_temp_t, arena)},
{s8_const_lit("len"), &type__usize, .offset = offsetof(ma_temp_t, len)},
}
};
type_t type__v2f32_t = { type_kind_struct, s8_const_lit("v2f32_t"), sizeof(v2f32_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__f32, .offset = offsetof(v2f32_t, x)},
{s8_const_lit("y"), &type__f32, .offset = offsetof(v2f32_t, y)},
}
};
type_t type__v3f32_t = { type_kind_struct, s8_const_lit("v3f32_t"), sizeof(v3f32_t), .count = 3,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__f32, .offset = offsetof(v3f32_t, x)},
{s8_const_lit("y"), &type__f32, .offset = offsetof(v3f32_t, y)},
{s8_const_lit("z"), &type__f32, .offset = offsetof(v3f32_t, z)},
}
};
type_t type__v4f32_t = { type_kind_struct, s8_const_lit("v4f32_t"), sizeof(v4f32_t), .count = 4,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__f32, .offset = offsetof(v4f32_t, x)},
{s8_const_lit("y"), &type__f32, .offset = offsetof(v4f32_t, y)},
{s8_const_lit("z"), &type__f32, .offset = offsetof(v4f32_t, z)},
{s8_const_lit("w"), &type__f32, .offset = offsetof(v4f32_t, w)},
}
};
type_t type__r3f32_t = { type_kind_struct, s8_const_lit("r3f32_t"), sizeof(r3f32_t), .count = 6,
.members = (type_member_t[]){
{s8_const_lit("x0"), &type__f32, .offset = offsetof(r3f32_t, x0)},
{s8_const_lit("y0"), &type__f32, .offset = offsetof(r3f32_t, y0)},
{s8_const_lit("x0"), &type__f32, .offset = offsetof(r3f32_t, z0)},
{s8_const_lit("x1"), &type__f32, .offset = offsetof(r3f32_t, x1)},
{s8_const_lit("y1"), &type__f32, .offset = offsetof(r3f32_t, y1)},
{s8_const_lit("x1"), &type__f32, .offset = offsetof(r3f32_t, z1)},
}
};
type_member_t members__r2f32_t[] = {
{s8_const_lit("x0"), &type__f32, .offset = offsetof(r2f32_t, x0)},
{s8_const_lit("y0"), &type__f32, .offset = offsetof(r2f32_t, y0)},
{s8_const_lit("x1"), &type__f32, .offset = offsetof(r2f32_t, x1)},
{s8_const_lit("y1"), &type__f32, .offset = offsetof(r2f32_t, y1)},
};
DEFINE_STRUCT(r2f32_t);
type_member_t members__r1f32_t[] = {
{s8_const_lit("x0"), &type__f32, .offset = offsetof(r1f32_t, x0)},
{s8_const_lit("x1"), &type__f32, .offset = offsetof(r1f32_t, x1)},
};
DEFINE_STRUCT(r1f32_t);
type_t type__v2f64_t = { type_kind_struct, s8_const_lit("v2f64_t"), sizeof(v2f64_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__f64, .offset = offsetof(v2f64_t, x)},
{s8_const_lit("y"), &type__f64, .offset = offsetof(v2f64_t, y)},
}
};
type_t type__v3f64_t = { type_kind_struct, s8_const_lit("v3f64_t"), sizeof(v3f64_t), .count = 3,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__f64, .offset = offsetof(v3f64_t, x)},
{s8_const_lit("y"), &type__f64, .offset = offsetof(v3f64_t, y)},
{s8_const_lit("z"), &type__f64, .offset = offsetof(v3f64_t, z)},
}
};
type_t type__v4f64_t = { type_kind_struct, s8_const_lit("v4f64_t"), sizeof(v4f64_t), .count = 4,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__f64, .offset = offsetof(v4f64_t, x)},
{s8_const_lit("y"), &type__f64, .offset = offsetof(v4f64_t, y)},
{s8_const_lit("z"), &type__f64, .offset = offsetof(v4f64_t, z)},
{s8_const_lit("w"), &type__f64, .offset = offsetof(v4f64_t, w)},
}
};
type_t type__r3f64_t = { type_kind_struct, s8_const_lit("r3f64_t"), sizeof(r3f64_t), .count = 6,
.members = (type_member_t[]){
{s8_const_lit("x0"), &type__f64, .offset = offsetof(r3f64_t, x0)},
{s8_const_lit("y0"), &type__f64, .offset = offsetof(r3f64_t, y0)},
{s8_const_lit("x0"), &type__f64, .offset = offsetof(r3f64_t, z0)},
{s8_const_lit("x1"), &type__f64, .offset = offsetof(r3f64_t, x1)},
{s8_const_lit("y1"), &type__f64, .offset = offsetof(r3f64_t, y1)},
{s8_const_lit("x1"), &type__f64, .offset = offsetof(r3f64_t, z1)},
}
};
type_member_t members__r2f64_t[] = {
{s8_const_lit("x0"), &type__f64, .offset = offsetof(r2f64_t, x0)},
{s8_const_lit("y0"), &type__f64, .offset = offsetof(r2f64_t, y0)},
{s8_const_lit("x1"), &type__f64, .offset = offsetof(r2f64_t, x1)},
{s8_const_lit("y1"), &type__f64, .offset = offsetof(r2f64_t, y1)},
};
DEFINE_STRUCT(r2f64_t);
type_member_t members__r1f64_t[] = {
{s8_const_lit("x0"), &type__f64, .offset = offsetof(r1f64_t, x0)},
{s8_const_lit("x1"), &type__f64, .offset = offsetof(r1f64_t, x1)},
};
DEFINE_STRUCT(r1f64_t);
type_t type__v2i32_t = { type_kind_struct, s8_const_lit("v2i32_t"), sizeof(v2i32_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__i32, .offset = offsetof(v2i32_t, x)},
{s8_const_lit("y"), &type__i32, .offset = offsetof(v2i32_t, y)},
}
};
type_t type__v3i32_t = { type_kind_struct, s8_const_lit("v3i32_t"), sizeof(v3i32_t), .count = 3,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__i32, .offset = offsetof(v3i32_t, x)},
{s8_const_lit("y"), &type__i32, .offset = offsetof(v3i32_t, y)},
{s8_const_lit("z"), &type__i32, .offset = offsetof(v3i32_t, z)},
}
};
type_t type__v4i32_t = { type_kind_struct, s8_const_lit("v4i32_t"), sizeof(v4i32_t), .count = 4,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__i32, .offset = offsetof(v4i32_t, x)},
{s8_const_lit("y"), &type__i32, .offset = offsetof(v4i32_t, y)},
{s8_const_lit("z"), &type__i32, .offset = offsetof(v4i32_t, z)},
{s8_const_lit("w"), &type__i32, .offset = offsetof(v4i32_t, w)},
}
};
type_t type__r3i32_t = { type_kind_struct, s8_const_lit("r3i32_t"), sizeof(r3i32_t), .count = 6,
.members = (type_member_t[]){
{s8_const_lit("x0"), &type__i32, .offset = offsetof(r3i32_t, x0)},
{s8_const_lit("y0"), &type__i32, .offset = offsetof(r3i32_t, y0)},
{s8_const_lit("x0"), &type__i32, .offset = offsetof(r3i32_t, z0)},
{s8_const_lit("x1"), &type__i32, .offset = offsetof(r3i32_t, x1)},
{s8_const_lit("y1"), &type__i32, .offset = offsetof(r3i32_t, y1)},
{s8_const_lit("x1"), &type__i32, .offset = offsetof(r3i32_t, z1)},
}
};
type_member_t members__r2i32_t[] = {
{s8_const_lit("x0"), &type__i32, .offset = offsetof(r2i32_t, x0)},
{s8_const_lit("y0"), &type__i32, .offset = offsetof(r2i32_t, y0)},
{s8_const_lit("x1"), &type__i32, .offset = offsetof(r2i32_t, x1)},
{s8_const_lit("y1"), &type__i32, .offset = offsetof(r2i32_t, y1)},
};
DEFINE_STRUCT(r2i32_t);
type_member_t members__r1i32_t[] = {
{s8_const_lit("x0"), &type__i32, .offset = offsetof(r1i32_t, x0)},
{s8_const_lit("x1"), &type__i32, .offset = offsetof(r1i32_t, x1)},
};
DEFINE_STRUCT(r1i32_t);
type_t type__v2i64_t = { type_kind_struct, s8_const_lit("v2i64_t"), sizeof(v2i64_t), .count = 2,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__i64, .offset = offsetof(v2i64_t, x)},
{s8_const_lit("y"), &type__i64, .offset = offsetof(v2i64_t, y)},
}
};
type_t type__v3i64_t = { type_kind_struct, s8_const_lit("v3i64_t"), sizeof(v3i64_t), .count = 3,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__i64, .offset = offsetof(v3i64_t, x)},
{s8_const_lit("y"), &type__i64, .offset = offsetof(v3i64_t, y)},
{s8_const_lit("z"), &type__i64, .offset = offsetof(v3i64_t, z)},
}
};
type_t type__v4i64_t = { type_kind_struct, s8_const_lit("v4i64_t"), sizeof(v4i64_t), .count = 4,
.members = (type_member_t[]){
{s8_const_lit("x"), &type__i64, .offset = offsetof(v4i64_t, x)},
{s8_const_lit("y"), &type__i64, .offset = offsetof(v4i64_t, y)},
{s8_const_lit("z"), &type__i64, .offset = offsetof(v4i64_t, z)},
{s8_const_lit("w"), &type__i64, .offset = offsetof(v4i64_t, w)},
}
};
type_t type__r3i64_t = { type_kind_struct, s8_const_lit("r3i64_t"), sizeof(r3i64_t), .count = 6,
.members = (type_member_t[]){
{s8_const_lit("x0"), &type__i64, .offset = offsetof(r3i64_t, x0)},
{s8_const_lit("y0"), &type__i64, .offset = offsetof(r3i64_t, y0)},
{s8_const_lit("x0"), &type__i64, .offset = offsetof(r3i64_t, z0)},
{s8_const_lit("x1"), &type__i64, .offset = offsetof(r3i64_t, x1)},
{s8_const_lit("y1"), &type__i64, .offset = offsetof(r3i64_t, y1)},
{s8_const_lit("x1"), &type__i64, .offset = offsetof(r3i64_t, z1)},
}
};
type_member_t members__r2i64_t[] = {
{s8_const_lit("x0"), &type__i64, .offset = offsetof(r2i64_t, x0)},
{s8_const_lit("y0"), &type__i64, .offset = offsetof(r2i64_t, y0)},
{s8_const_lit("x1"), &type__i64, .offset = offsetof(r2i64_t, x1)},
{s8_const_lit("y1"), &type__i64, .offset = offsetof(r2i64_t, y1)},
};
DEFINE_STRUCT(r2i64_t);
type_member_t members__r1i64_t[] = {
{s8_const_lit("x0"), &type__i64, .offset = offsetof(r1i64_t, x0)},
{s8_const_lit("x1"), &type__i64, .offset = offsetof(r1i64_t, x1)},
};
DEFINE_STRUCT(r1i64_t);

538
src/core/types.h Normal file
View File

@@ -0,0 +1,538 @@
typedef uintptr_t usize;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef intptr_t isize;
typedef int64_t i64;
typedef int32_t i32;
typedef int16_t i16;
typedef int8_t i8;
typedef int64_t b64;
typedef int32_t b32;
typedef int16_t b16;
typedef int8_t b8;
typedef float f32;
typedef double f64;
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define CLAMP_TOP(A,X) MIN(A,X)
#define CLAMP_BOT(X,B) MAX(X,B)
#define CLAMP(x,a,b) (((x)<(a))?(a):((x)>(b))?(b):(x))
#define set_bit(x) (1ULL << (x))
#define lengthof(x) (sizeof((x))/sizeof((x)[0]))
#ifndef offsetof
#define offsetof(st, m) ((usize)&(((st *)0)->m))
#endif
#define kib(x) (1024ULL * (x##ULL))
#define mib(x) (1024ULL * kib(x))
#define gib(x) (1024ULL * mib(x))
#define DEFER_LOOP(begin, end) for (int PASTE(_i_, __LINE__) = (begin, 0); !PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) += (end, 1))
#define STACK(type, size) struct { type data[size]; i32 len; }
#define STACK_PUSH(stack, ...) (assert((stack).len < lengthof((stack).data)), (stack).data[(stack).len++] = __VA_ARGS__)
#define STACK_POP(stack) (assert((stack).len > 0), (stack).data[--(stack).len])
#define STACK_LAST(stack) (assert((stack).len > 0), (stack).data + ((stack).len-1))
#define STRINGIFY_(S) #S
#define STRINGIFY(S) STRINGIFY_(S)
#define PASTE_(a, b) a##b
#define PASTE(a, b) PASTE_(a, b)
#define SWAP(t, a, b) do { t PASTE(temp__, __LINE__) = a; a = b; b = PASTE(temp__, __LINE__); } while(0)
#define CODE(...) #__VA_ARGS__
#define S8_CODE(...) s8_lit(#__VA_ARGS__)
#if PLATFORM_CL
#define FILE_AND_LINE __FILE__"("STRINGIFY(__LINE__)")"
#else
#define FILE_AND_LINE __FILE__":"STRINGIFY(__LINE__)
#endif
#if PLATFORM_CL
#define debug__break() __debugbreak()
#else
#define debug__break() __builtin_trap()
#endif
#define debug_break() (debug__break(), 0)
#if PLATFORM_ASSERT
#define assert(x) (!(x) && debug_break())
#define assertf(x, ...) do {\
debugf(__VA_ARGS__);\
assert(x);\
} while(0)
#else
#define assert(x) ((void)(x))
#define assertf(x,...) ((void)(x))
#endif
#if PLATFORM_WASM
#define THREAD_LOCAL
#elif PLATFORM_GCC | PLATFORM_CLANG
#define THREAD_LOCAL __thread
#elif PLATFORM_CL
#define THREAD_LOCAL __declspec(thread)
#else
#define THREAD_LOCAL _Thread_local
#endif
// Single linked list Queue
#define SLLQ_APPEND_MOD(f, l, n, next) \
do { \
assert((n)->next == NULL); \
if ((f) == 0) { \
(f) = (l) = (n); \
} else { \
(l) = (l)->next = (n); \
} \
} while (0)
#define SLLQ_APPEND(f, l, n) SLLQ_APPEND_MOD(f, l, n, next)
#define SLLQ_PREPEND_MOD(f, l, n, next) \
do { \
assert((n)->next == NULL); \
if ((f) == 0) { \
(f) = (l) = (n); \
} else { \
(n)->next = (f); \
(f) = (n); \
} \
} while (0)
#define SLLQ_PREPEND(f, l, n) SLLQ_PREPEND_MOD(f, l, n, next)
#define SLLQ_REMOVE_FIRST_MOD(f, l, next) \
do { \
if ((f) == (l)) { \
(f) = (l) = 0; \
} else { \
(f) = (f)->next; \
} \
} while (0)
#define SLLQ_REMOVE_FIRST(f, l) SLLQ_REMOVE_FIRST_MOD(f, l, next)
// Singly linked list stack
#define SLLS_PUSH_MOD(stack_base, new_stack_base, next) \
do { \
(new_stack_base)->next = (stack_base); \
(stack_base) = (new_stack_base); \
} while (0)
#define SLLS_PUSH(stack_base, new_stack_base) \
SLLS_PUSH_MOD(stack_base, new_stack_base, next)
#define SLLS_POP_AND_STORE(stack_base, out_node) \
do { \
if (stack_base) { \
(out_node) = (stack_base); \
(stack_base) = (stack_base)->next; \
(out_node)->next = 0; \
} \
} while (0)
// Doubly linked list Queue
#define DLLQ_APPEND_MOD(f, l, node, next, prev) \
do { \
assert((node)->next == NULL); \
assert((node)->prev == NULL); \
if ((f) == 0) { \
(f) = (l) = (node); \
} else { \
(l)->next = (node); \
(node)->prev = (l); \
(l) = (node); \
} \
} while (0)
#define DLLQ_APPEND(f, l, node) DLLQ_APPEND_MOD(f, l, node, next, prev)
#define DLLQ_PREPEND_MOD(f, l, node, next, prev) \
do { \
assert((node)->next == NULL); \
assert((node)->prev == NULL); \
if ((f) == 0) { \
(f) = (l) = (node); \
} else { \
(node)->next = (f); \
(f)->prev = (node); \
(f) = (node); \
} \
} while (0)
#define DLLQ_PREPEND(f, l, node) DLLQ_PREPEND_MOD(f, l, node, next, prev)
#define DLLQ_CONTAINS(f, l, n, next, prev) for (
#define DLLQ_REMOVE_MOD(first, last, node, next, prev) \
do { \
if ((first) == (last)) { \
assert((node) == (first)); \
(first) = (last) = 0; \
} else if ((last) == (node)) { \
(last) = (last)->prev; \
(last)->next = 0; \
} else if ((first) == (node)) { \
(first) = (first)->next; \
(first)->prev = 0; \
} else { \
(node)->prev->next = (node)->next; \
(node)->next->prev = (node)->prev; \
} \
if (node) { \
(node)->prev = 0; \
(node)->next = 0; \
} \
} while (0)
#define DLLQ_REMOVE(first, last, node) DLLQ_REMOVE_MOD(first, last, node, next, prev)
// Doubly linked list Stack
#define DLLS_ADD_MOD(first, node, next, prev) \
do { \
assert((node)->next == NULL); \
assert((node)->prev == NULL); \
(node)->next = (first); \
if ((first)) \
(first)->prev = (node); \
(first) = (node); \
} while (0)
#define DLLS_ADD(first, node) DLLS_ADD_MOD(first, node, next, prev)
#define DLLS_REMOVE_MOD(first, node, next, prev) \
do { \
if ((node) == (first)) { \
(first) = (first)->next; \
if ((first)) \
(first)->prev = 0; \
} else { \
(node)->prev->next = (node)->next; \
if ((node)->next) \
(node)->next->prev = (node)->prev; \
} \
if (node) { \
(node)->prev = 0; \
(node)->next = 0; \
} \
} while (0)
#define DLLS_REMOVE(first, node) DLLS_REMOVE_MOD(first, node, next, prev)
const usize ma_page_size = 4096;
const usize ma_default_alignment = sizeof(void *);
const usize ma_default_reserve_size = mib(256);
typedef struct ma_arena_t ma_arena_t;
struct ma_arena_t {
u8 *data;
usize len;
usize base_len; // to prevent self deleting the arena
usize reserve;
usize commit;
usize align;
};
typedef struct ma_temp_t ma_temp_t;
struct ma_temp_t {
ma_arena_t *arena;
usize len;
};
void ma_init(ma_arena_t *arena, usize reserve);
ma_arena_t *ma_create(usize reserve);
void ma_destroy(ma_arena_t *arena);
void *ma_push_size_ex(ma_arena_t *arena, usize size);
void *ma_push_size(ma_arena_t *arena, usize size);
ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size);
#define ma_push_type(arena, Type) (Type *)ma_push_size((arena), sizeof(Type))
#define ma_push_array(arena, Type, count) (Type *)ma_push_size((arena), sizeof(Type) * (count))
void ma_set_len(ma_arena_t *arena, usize pos);
void ma_pop(ma_arena_t *arena, usize size);
void ma_set0(ma_arena_t *arena);
ma_temp_t ma_begin_temp(ma_arena_t *arena);
void ma_end_temp(ma_temp_t temp);
typedef struct s8_t s8_t;
struct s8_t {
char *str;
int64_t len;
};
typedef struct s16_t s16_t;
struct s16_t {
u16 *str;
i64 len;
};
typedef struct s32_t s32_t;
struct s32_t {
u32 *str;
i64 len;
};
typedef struct sb8_node_t sb8_node_t;
struct sb8_node_t {
sb8_node_t *next;
union {
struct { char *str; int64_t len; };
s8_t s;
};
};
typedef struct sb8_t sb8_t;
struct sb8_t {
ma_arena_t *arena;
sb8_node_t *first;
sb8_node_t *last;
int indent;
};
i64 wstr_len(wchar_t *string);
int str_len(char *str);
char char_to_lower_case(char a);
char char_to_upper_case(char a);
b32 char_is_whitespace(char w);
b32 char_is_alphabetic(char a);
b32 char_is_ident(char a);
b32 char_is_digit(char a);
b32 char_is_alphanumeric(char a);
b32 s8_equal(s8_t a, s8_t b);
enum { s8_ignore_case = 1 };
#define s8(str,len) (s8_t){str, len}
#define s8_nil() (s8_t){0}
#define s8_lit(string) (s8_t){(char *)string, sizeof(string) - 1}
#define s8_const_lit(string) { string, sizeof(string) - 1 }
#define s8_fmtspec(string) (int)(string).len, (string).str
#define sb8_serial_begin(arena) &(sb8_t){.arena = arena}
#define sb8_serial_end(sb) sb8_merge(sb)
typedef struct core_desc_t core_desc_t;
struct core_desc_t {
void (*print)(char *string);
void (*panic)(void);
void (*on_exit)(void);
ma_arena_t scratch[3];
b32 break_on_panic;
};
extern THREAD_LOCAL core_desc_t core_desc;
void debugf(const char *string, ...);
void panicf(const char *string, ...);
typedef union v2f32_t v2f32_t;
union v2f32_t {
struct { f32 x, y; };
f32 e[2];
};
typedef union v3f32_t v3f32_t;
union v3f32_t {
struct { f32 x, y, z; };
struct { v2f32_t xy; };
struct { f32 _x0; v2f32_t zw; };
struct { f32 r, g, b; };
struct { f32 h, s, l; };
f32 e[3];
};
typedef union v4f32_t v4f32_t;
union v4f32_t {
struct { f32 x, y, z, w; };
struct { v2f32_t xy; v2f32_t zw; };
struct { v3f32_t xyz; };
struct { f32 _x0; f32 yzw; };
struct { f32 r, g, b, a; };
struct { f32 h, s, l, _a; };
f32 e[4];
};
typedef union r1f32_t r1f32_t;
union r1f32_t {
struct { f32 min, max; };
struct { f32 x0, x1; };
f32 e[2];
};
typedef union r2f32_t r2f32_t;
union r2f32_t {
struct { v2f32_t min, max; };
struct { f32 x0, y0, x1, y1; };
v4f32_t e4;
f32 e[4];
};
typedef union r3f32_t r3f32_t;
union r3f32_t {
struct { v3f32_t min, max; };
struct { f32 x0, y0, z0, x1, y1, z1; };
f32 e[6];
};
typedef union v2f64_t v2f64_t;
union v2f64_t {
struct { f64 x, y; };
f64 e[2];
};
typedef union v3f64_t v3f64_t;
union v3f64_t {
struct { f64 x, y, z; };
struct { v2f64_t xy; };
struct { f64 _x0; v2f64_t zw; };
struct { f64 r, g, b; };
struct { f64 h, s, l; };
f64 e[3];
};
typedef union v4f64_t v4f64_t;
union v4f64_t {
struct { f64 x, y, z, w; };
struct { v2f64_t xy; v2f64_t zw; };
struct { v3f64_t xyz; };
struct { f64 _x0; f64 yzw; };
struct { f64 r, g, b, a; };
struct { f64 h, s, l, _a; };
f64 e[4];
};
typedef union r1f64_t r1f64_t;
union r1f64_t {
struct { f64 min, max; };
struct { f64 x0, x1; };
f64 e[2];
};
typedef union r2f64_t r2f64_t;
union r2f64_t {
struct { v2f64_t min, max; };
struct { f64 x0, y0, x1, y1; };
v4f64_t e4;
f64 e[4];
};
typedef union r3f64_t r3f64_t;
union r3f64_t {
struct { v3f64_t min, max; };
struct { f64 x0, y0, z0, x1, y1, z1; };
f64 e[6];
};
typedef union v2i32_t v2i32_t;
union v2i32_t {
struct { i32 x, y; };
i32 e[2];
};
typedef union v3i32_t v3i32_t;
union v3i32_t {
struct { i32 x, y, z; };
struct { v2i32_t xy; };
struct { i32 _x0; v2i32_t zw; };
struct { i32 r, g, b; };
struct { i32 h, s, l; };
i32 e[3];
};
typedef union v4i32_t v4i32_t;
union v4i32_t {
struct { i32 x, y, z, w; };
struct { v2i32_t xy; v2i32_t zw; };
struct { v3i32_t xyz; };
struct { i32 _x0; i32 yzw; };
struct { i32 r, g, b, a; };
struct { i32 h, s, l, _a; };
i32 e[4];
};
typedef union r1i32_t r1i32_t;
union r1i32_t {
struct { i32 min, max; };
struct { i32 x0, x1; };
i32 e[2];
};
typedef union r2i32_t r2i32_t;
union r2i32_t {
struct { v2i32_t min, max; };
struct { i32 x0, y0, x1, y1; };
v4i32_t e4;
i32 e[4];
};
typedef union r3i32_t r3i32_t;
union r3i32_t {
struct { v3i32_t min, max; };
struct { i32 x0, y0, z0, x1, y1, z1; };
i32 e[6];
};
typedef union v2i64_t v2i64_t;
union v2i64_t {
struct { i64 x, y; };
i64 e[2];
};
typedef union v3i64_t v3i64_t;
union v3i64_t {
struct { i64 x, y, z; };
struct { v2i64_t xy; };
struct { i64 _x0; v2i64_t zw; };
struct { i64 r, g, b; };
struct { i64 h, s, l; };
i64 e[3];
};
typedef union v4i64_t v4i64_t;
union v4i64_t {
struct { i64 x, y, z, w; };
struct { v2i64_t xy; v2i64_t zw; };
struct { v3i64_t xyz; };
struct { i64 _x0; i64 yzw; };
struct { i64 r, g, b, a; };
struct { i64 h, s, l, _a; };
i64 e[4];
};
typedef union r1i64_t r1i64_t;
union r1i64_t {
struct { i64 min, max; };
struct { i64 x0, x1; };
i64 e[2];
};
typedef union r2i64_t r2i64_t;
union r2i64_t {
struct { v2i64_t min, max; };
struct { i64 x0, y0, x1, y1; };
v4i64_t e4;
i64 e[4];
};
typedef union r3i64_t r3i64_t;
union r3i64_t {
struct { v3i64_t min, max; };
struct { i64 x0, y0, z0, x1, y1, z1; };
i64 e[6];
};

226
src/core/unicode.c Normal file
View File

@@ -0,0 +1,226 @@
typedef struct utf32_result_t utf32_result_t;
struct utf32_result_t {
uint32_t out_str;
int advance;
int error;
};
typedef struct utf16_result_t utf16_result_t;
struct utf16_result_t {
uint16_t out_str[2];
int len;
int error;
};
typedef struct utf8_result_t utf8_result_t;
struct utf8_result_t {
uint8_t out_str[4];
int len;
int error;
};
typedef struct utf8_iter_t utf8_iter_t;
struct utf8_iter_t {
char *str;
int len;
int utf8_codepoint_byte_size;
int i;
uint32_t item;
};
utf32_result_t utf16_to_utf32(uint16_t *c, int max_advance) {
utf32_result_t result = {0};
if (max_advance >= 1) {
result.advance = 1;
result.out_str = c[0];
if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) {
if (max_advance >= 2) {
result.out_str = 0x10000;
result.out_str += (uint32_t)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF);
result.advance = 2;
}
else
result.error = 2;
}
}
else {
result.error = 1;
}
return result;
}
utf8_result_t utf32_to_utf8(uint32_t codepoint) {
utf8_result_t result = {0};
if (codepoint <= 0x7F) {
result.len = 1;
result.out_str[0] = (char)codepoint;
}
else if (codepoint <= 0x7FF) {
result.len = 2;
result.out_str[0] = 0xc0 | (0x1f & (codepoint >> 6));
result.out_str[1] = 0x80 | (0x3f & codepoint);
}
else if (codepoint <= 0xFFFF) { // 16 bit word
result.len = 3;
result.out_str[0] = 0xe0 | (0xf & (codepoint >> 12)); // 4 bits
result.out_str[1] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits
result.out_str[2] = 0x80 | (0x3f & codepoint); // 6 bits
}
else if (codepoint <= 0x10FFFF) { // 21 bit word
result.len = 4;
result.out_str[0] = 0xf0 | (0x7 & (codepoint >> 18)); // 3 bits
result.out_str[1] = 0x80 | (0x3f & (codepoint >> 12)); // 6 bits
result.out_str[2] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits
result.out_str[3] = 0x80 | (0x3f & codepoint); // 6 bits
}
else {
result.error = 1;
}
return result;
}
utf32_result_t utf8_to_utf32(char *c, int max_advance) {
utf32_result_t result = {0};
if ((c[0] & 0x80) == 0) { // Check if leftmost zero of first byte is unset
if (max_advance >= 1) {
result.out_str = c[0];
result.advance = 1;
}
else result.error = 1;
}
else if ((c[0] & 0xe0) == 0xc0) {
if ((c[1] & 0xc0) == 0x80) { // Continuation byte required
if (max_advance >= 2) {
result.out_str = (uint32_t)(c[0] & 0x1f) << 6u | (c[1] & 0x3f);
result.advance = 2;
}
else result.error = 2;
}
else result.error = 2;
}
else if ((c[0] & 0xf0) == 0xe0) {
if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80) { // Two continuation bytes required
if (max_advance >= 3) {
result.out_str = (uint32_t)(c[0] & 0xf) << 12u | (uint32_t)(c[1] & 0x3f) << 6u | (c[2] & 0x3f);
result.advance = 3;
}
else result.error = 3;
}
else result.error = 3;
}
else if ((c[0] & 0xf8) == 0xf0) {
if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80 && (c[3] & 0xc0) == 0x80) { // Three continuation bytes required
if (max_advance >= 4) {
result.out_str = (uint32_t)(c[0] & 0xf) << 18u | (uint32_t)(c[1] & 0x3f) << 12u | (uint32_t)(c[2] & 0x3f) << 6u | (uint32_t)(c[3] & 0x3f);
result.advance = 4;
}
else result.error = 4;
}
else result.error = 4;
}
else result.error = 4;
return result;
}
utf16_result_t utf32_to_utf16(uint32_t codepoint) {
utf16_result_t result = {0};
if (codepoint < 0x10000) {
result.out_str[0] = (uint16_t)codepoint;
result.out_str[1] = 0;
result.len = 1;
}
else if (codepoint <= 0x10FFFF) {
uint32_t code = (codepoint - 0x10000);
result.out_str[0] = (uint16_t)(0xD800 | (code >> 10));
result.out_str[1] = (uint16_t)(0xDC00 | (code & 0x3FF));
result.len = 2;
}
else {
result.error = 1;
}
return result;
}
#define UTF__HANDLE_DECODE_ERROR(question_mark) \
{ \
if (outlen < buffer_size - 1) buffer[outlen++] = (question_mark); \
break; \
}
int64_t str_from_wstr(char *buffer, int64_t buffer_size, uint16_t *in, int64_t inlen) {
int64_t outlen = 0;
for (int64_t i = 0; i < inlen && in[i];) {
utf32_result_t decode = utf16_to_utf32((uint16_t *)(in + i), (int)(inlen - i));
if (!decode.error) {
i += decode.advance;
utf8_result_t encode = utf32_to_utf8(decode.out_str);
if (!encode.error) {
for (int64_t j = 0; j < encode.len; j++) {
if (outlen < buffer_size - 1) {
buffer[outlen++] = encode.out_str[j];
}
}
}
else UTF__HANDLE_DECODE_ERROR('?');
}
else UTF__HANDLE_DECODE_ERROR('?');
}
buffer[outlen] = 0;
return outlen;
}
int64_t wstr_from_str(uint16_t *buffer, int64_t buffer_size, char *in, int64_t inlen) {
int64_t outlen = 0;
for (int64_t i = 0; i < inlen;) {
utf32_result_t decode = utf8_to_utf32(in + i, (int)(inlen - i));
if (!decode.error) {
i += decode.advance;
utf16_result_t encode = utf32_to_utf16(decode.out_str);
if (!encode.error) {
for (int64_t j = 0; j < encode.len; j++) {
if (outlen < buffer_size - 1) {
buffer[outlen++] = encode.out_str[j];
}
}
}
else UTF__HANDLE_DECODE_ERROR(0x003f);
}
else UTF__HANDLE_DECODE_ERROR(0x003f);
}
buffer[outlen] = 0;
return outlen;
}
void utf8_advance(utf8_iter_t *iter) {
iter->i += iter->utf8_codepoint_byte_size;
utf32_result_t r = utf8_to_utf32(iter->str + iter->i, iter->len - iter->i);
if (r.error) {
iter->item = 0;
return;
}
iter->utf8_codepoint_byte_size = r.advance;
iter->item = r.out_str;
}
utf8_iter_t utf8_iterate_ex(char *str, int len) {
utf8_iter_t result = {str, len};
if (len) utf8_advance(&result);
return result;
}
utf8_iter_t utf8_iterate(char *str) {
int length = 0;
while (str[length]) length += 1;
return utf8_iterate_ex(str, length);
}