reinit repo after broken git
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
backup
|
||||
build/
|
||||
*.wasm
|
||||
*.o
|
||||
MSVC/
|
||||
multimedia.c
|
||||
multimedia.h
|
||||
13
build.bat
Normal file
13
build.bat
Normal file
@@ -0,0 +1,13 @@
|
||||
@echo off
|
||||
|
||||
if not exist build\build_tool.exe (
|
||||
mkdir build
|
||||
pushd build
|
||||
cl ..\src\meta\build_tool.c -Fe:build_tool.exe -Fd:build_tool.pdb /Zi /FC /nologo
|
||||
rem clang ..\src\meta\build_tool.c -o build_tool.exe -g
|
||||
popd
|
||||
)
|
||||
|
||||
build\build_tool.exe
|
||||
|
||||
|
||||
65
build_file.c
Normal file
65
build_file.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "src/core/core.h"
|
||||
#include "src/core/core.c"
|
||||
|
||||
#define BUILD_TOOL_LIB
|
||||
#define S8_String s8_t
|
||||
#include "src/meta/build_tool.c"
|
||||
#include "src/meta/parser.c"
|
||||
#include "src/meta/serialize.c"
|
||||
|
||||
#include "src/app/app.meta.c"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int ok = 0;
|
||||
|
||||
ma_arena_t *arena = ma_create(ma_default_reserve_size);
|
||||
meta_app(arena);
|
||||
|
||||
bool run_server = false;
|
||||
bool core_test_target = false;
|
||||
bool wasm_target = true;
|
||||
bool win32_target = false;
|
||||
|
||||
if (run_server) {
|
||||
os_systemf("start /D ..\\package ..\\package\\run_server.bat");
|
||||
}
|
||||
|
||||
if (win32_target) {
|
||||
os_delete_file(s8_lit("win32_app.pdb"));
|
||||
ok = os_systemf(
|
||||
"cl ../src/app/app_win32.c -Fe:win32_app.exe -Fd:win32_app.pdb"
|
||||
" -I ../src"
|
||||
" /Zi /FC /nologo /Oi"
|
||||
" /WX /W3 /wd4200 /diagnostics:column"
|
||||
" /link /incremental:no"
|
||||
);
|
||||
if (ok != 0) return ok;
|
||||
}
|
||||
|
||||
if (core_test_target) {
|
||||
os_delete_file(s8_lit("core_test.pdb"));
|
||||
ok = os_systemf(
|
||||
"cl ../src/core_test/core_test_entry.c -Fe:core_test.exe -Fd:core_test.pdb"
|
||||
" -I ../src"
|
||||
" /Zi /FC /nologo /Oi"
|
||||
" /WX /W3 /wd4200 /diagnostics:column"
|
||||
" /link /incremental:no"
|
||||
);
|
||||
if (ok != 0) return ok;
|
||||
}
|
||||
|
||||
|
||||
if (wasm_target) {
|
||||
ok = os_systemf(
|
||||
"clang.exe ../src/wasm_app/main.c -o main.wasm"
|
||||
" -Oz -g -I../src"
|
||||
" -Wall -Wno-missing-braces"
|
||||
" -fdiagnostics-absolute-paths -fdiagnostics-format=msvc"
|
||||
" --target=wasm32 -nostdlib -mbulk-memory -msimd128"
|
||||
" -Wl,-export-dynamic,--allow-undefined,--import-memory,--no-entry,--initial-memory=131072000,--max-memory=4294967296"
|
||||
);
|
||||
os_copy("main.wasm", "../package/main.wasm", os_copy_overwrite);
|
||||
if (ok != 0) return ok;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
BIN
package/FiraCode-Regular.ttf
Normal file
BIN
package/FiraCode-Regular.ttf
Normal file
Binary file not shown.
153
package/index.html
Normal file
153
package/index.html
Normal file
@@ -0,0 +1,153 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas class="fill-screen" id="canvas"></canvas>
|
||||
</body>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: fira;
|
||||
src: url(FiraCode-Regular.ttf);
|
||||
}
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.fill-screen {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
</html>
|
||||
<script>
|
||||
|
||||
class memory_t {
|
||||
exports = null; // this is set after wasm module created
|
||||
constructor(wasm_memory) {
|
||||
this.mem = wasm_memory;
|
||||
this.u8 = new Uint8Array(this.mem.buffer);
|
||||
this.data_view = new DataView(this.mem.buffer);
|
||||
this.utf8decoder = new TextDecoder("utf-8");
|
||||
this.utf8encoder = new TextEncoder("utf-8");
|
||||
}
|
||||
|
||||
read_cstr(str, len) {
|
||||
const arr = this.u8.subarray(str, str+len);
|
||||
const text = this.utf8decoder.decode(arr);
|
||||
return text;
|
||||
}
|
||||
|
||||
write_string_into_cmemory(ptr, ptr_len, string) {
|
||||
const bytes = this.utf8encoder.encode(string);
|
||||
let i = 0;
|
||||
for (; i < bytes.length && i < (ptr_len-1); i += 1) {
|
||||
this.u8[ptr + i] = bytes[i];
|
||||
}
|
||||
this.u8[ptr + i] = 0;
|
||||
}
|
||||
|
||||
write_string(temp, string) {
|
||||
const ptr = this.exports[temp].value;
|
||||
const len = this.data_view.getInt32(this.exports[temp + "_len"].value, true);
|
||||
this.write_string_into_cmemory(ptr, len, string);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
const canvas = document.getElementById("canvas");
|
||||
const ctx2d = canvas.getContext('2d');
|
||||
const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 65536 }));
|
||||
|
||||
(async function main() {
|
||||
if (!ctx2d) {
|
||||
alert('Outdated browser, cant draw :(');
|
||||
return;
|
||||
}
|
||||
|
||||
const request = await fetch('main.wasm');
|
||||
const binary = await request.arrayBuffer();
|
||||
const wasm_imports = {
|
||||
memory: mem.mem,
|
||||
wasm_write_to_console: (str, len) => console.log(mem.read_cstr(str, len)),
|
||||
wasm_draw_text: (str, len, x, y, font_str, font_len, font_size, r, g, b, a) => {
|
||||
ctx2d.font = `${font_size}px ${mem.read_cstr(font_str, font_len)}`;
|
||||
ctx2d.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`;
|
||||
ctx2d.textBaseline = "top"
|
||||
ctx2d.fillText(mem.read_cstr(str, len), x, y)
|
||||
},
|
||||
wasm_measure_text: (str, len, font_str, font_len, font_size) => {
|
||||
ctx2d.font = `${font_size}px ${mem.read_cstr(font_str, font_len)}`;
|
||||
ctx2d.textBaseline = "top";
|
||||
const metrics = ctx2d.measureText(mem.read_cstr(str, len));
|
||||
return metrics.width;
|
||||
},
|
||||
wasm_get_font_height: (font_str, font_len, font_size) => {
|
||||
ctx2d.font = `${font_size}px ${mem.read_cstr(font_str, font_len)}`;
|
||||
ctx2d.textBaseline = "top";
|
||||
return ctx2d.measureText('NothinBelowTheBaseline').actualBoundingBoxDescent;
|
||||
},
|
||||
wasm_draw_rect: (x, y, w, h, r, g, b, a) => {
|
||||
ctx2d.beginPath();
|
||||
ctx2d.rect(x, y, w, h);
|
||||
ctx2d.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`;
|
||||
ctx2d.fill();
|
||||
},
|
||||
wasm_set_clip: (x, y, w, h) => {
|
||||
ctx2d.restore();
|
||||
ctx2d.save();
|
||||
ctx2d.beginPath();
|
||||
ctx2d.rect(x, y, w, h);
|
||||
ctx2d.clip();
|
||||
},
|
||||
wasm_parse_float: (str, len) => {
|
||||
return parseFloat(mem.read_cstr(str, len));
|
||||
},
|
||||
wasm_trap: () => { throw new Error() },
|
||||
};
|
||||
|
||||
const program = await WebAssembly['instantiate'](binary, { "env": wasm_imports });
|
||||
const instance = program['instance'];
|
||||
const wasm_exports = instance['exports'];
|
||||
mem.exports = wasm_exports;
|
||||
wasm_exports['wasm_init']();
|
||||
|
||||
addEventListener("keydown", (event) => {
|
||||
wasm_exports["wasm_key_down"](mem.write_string("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
||||
});
|
||||
addEventListener("keyup", (event) => {
|
||||
wasm_exports["wasm_key_up"](mem.write_string("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
||||
});
|
||||
addEventListener("mousemove", (event) => {
|
||||
wasm_exports["wasm_mouse_move"](event.clientX, event.clientY, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
||||
});
|
||||
addEventListener("mousedown", (event) => {
|
||||
wasm_exports["wasm_mouse_down"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
||||
});
|
||||
addEventListener("mouseup", (event) => {
|
||||
wasm_exports["wasm_mouse_up"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
||||
});
|
||||
addEventListener("wheel", (event) => {
|
||||
wasm_exports["wasm_mouse_wheel"](event.deltaX, event.deltaY, event.deltaZ, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
||||
});
|
||||
|
||||
requestAnimationFrame(function update(time) {
|
||||
const dpr = window.devicePixelRatio;
|
||||
canvas.width = canvas.getBoundingClientRect().width * dpr;
|
||||
canvas.height = canvas.getBoundingClientRect().height * dpr;
|
||||
wasm_exports['wasm_update'](time / 1000, canvas.width, canvas.height, dpr);
|
||||
requestAnimationFrame(update);
|
||||
});
|
||||
})()
|
||||
</script>
|
||||
1
package/run_server.bat
Normal file
1
package/run_server.bat
Normal file
@@ -0,0 +1 @@
|
||||
py.exe -m http.server 8080
|
||||
2
src/app/app.c
Normal file
2
src/app/app.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "app.gen.c"
|
||||
#include "app_wasm.c"
|
||||
274
src/app/app.gen.c
Normal file
274
src/app/app.gen.c
Normal file
@@ -0,0 +1,274 @@
|
||||
|
||||
type_t type__app_key_t = { type_kind_enum, s8_const_lit("app_key_t"), sizeof(app_key_t),
|
||||
.members = (type_member_t[]){
|
||||
{.name = s8_const_lit("app_key_invalid"), .value = app_key_invalid},
|
||||
{.name = s8_const_lit("app_key_1"), .value = app_key_1},
|
||||
{.name = s8_const_lit("app_key_2"), .value = app_key_2},
|
||||
{.name = s8_const_lit("app_key_3"), .value = app_key_3},
|
||||
{.name = s8_const_lit("app_key_4"), .value = app_key_4},
|
||||
{.name = s8_const_lit("app_key_5"), .value = app_key_5},
|
||||
{.name = s8_const_lit("app_key_6"), .value = app_key_6},
|
||||
{.name = s8_const_lit("app_key_7"), .value = app_key_7},
|
||||
{.name = s8_const_lit("app_key_8"), .value = app_key_8},
|
||||
{.name = s8_const_lit("app_key_9"), .value = app_key_9},
|
||||
{.name = s8_const_lit("app_key_0"), .value = app_key_0},
|
||||
{.name = s8_const_lit("app_key_f1"), .value = app_key_f1},
|
||||
{.name = s8_const_lit("app_key_f2"), .value = app_key_f2},
|
||||
{.name = s8_const_lit("app_key_f3"), .value = app_key_f3},
|
||||
{.name = s8_const_lit("app_key_f4"), .value = app_key_f4},
|
||||
{.name = s8_const_lit("app_key_f5"), .value = app_key_f5},
|
||||
{.name = s8_const_lit("app_key_f6"), .value = app_key_f6},
|
||||
{.name = s8_const_lit("app_key_f7"), .value = app_key_f7},
|
||||
{.name = s8_const_lit("app_key_f8"), .value = app_key_f8},
|
||||
{.name = s8_const_lit("app_key_f9"), .value = app_key_f9},
|
||||
{.name = s8_const_lit("app_key_f10"), .value = app_key_f10},
|
||||
{.name = s8_const_lit("app_key_f11"), .value = app_key_f11},
|
||||
{.name = s8_const_lit("app_key_f12"), .value = app_key_f12},
|
||||
{.name = s8_const_lit("app_key_a"), .value = app_key_a},
|
||||
{.name = s8_const_lit("app_key_b"), .value = app_key_b},
|
||||
{.name = s8_const_lit("app_key_c"), .value = app_key_c},
|
||||
{.name = s8_const_lit("app_key_d"), .value = app_key_d},
|
||||
{.name = s8_const_lit("app_key_e"), .value = app_key_e},
|
||||
{.name = s8_const_lit("app_key_f"), .value = app_key_f},
|
||||
{.name = s8_const_lit("app_key_g"), .value = app_key_g},
|
||||
{.name = s8_const_lit("app_key_h"), .value = app_key_h},
|
||||
{.name = s8_const_lit("app_key_i"), .value = app_key_i},
|
||||
{.name = s8_const_lit("app_key_j"), .value = app_key_j},
|
||||
{.name = s8_const_lit("app_key_k"), .value = app_key_k},
|
||||
{.name = s8_const_lit("app_key_l"), .value = app_key_l},
|
||||
{.name = s8_const_lit("app_key_m"), .value = app_key_m},
|
||||
{.name = s8_const_lit("app_key_n"), .value = app_key_n},
|
||||
{.name = s8_const_lit("app_key_o"), .value = app_key_o},
|
||||
{.name = s8_const_lit("app_key_p"), .value = app_key_p},
|
||||
{.name = s8_const_lit("app_key_q"), .value = app_key_q},
|
||||
{.name = s8_const_lit("app_key_r"), .value = app_key_r},
|
||||
{.name = s8_const_lit("app_key_s"), .value = app_key_s},
|
||||
{.name = s8_const_lit("app_key__t"), .value = app_key__t},
|
||||
{.name = s8_const_lit("app_key_u"), .value = app_key_u},
|
||||
{.name = s8_const_lit("app_key_v"), .value = app_key_v},
|
||||
{.name = s8_const_lit("app_key_w"), .value = app_key_w},
|
||||
{.name = s8_const_lit("app_key_x"), .value = app_key_x},
|
||||
{.name = s8_const_lit("app_key_y"), .value = app_key_y},
|
||||
{.name = s8_const_lit("app_key_z"), .value = app_key_z},
|
||||
{.name = s8_const_lit("app_key_space"), .value = app_key_space},
|
||||
{.name = s8_const_lit("app_key_enter"), .value = app_key_enter},
|
||||
{.name = s8_const_lit("app_key_escape"), .value = app_key_escape},
|
||||
{.name = s8_const_lit("app_key_left"), .value = app_key_left},
|
||||
{.name = s8_const_lit("app_key_up"), .value = app_key_up},
|
||||
{.name = s8_const_lit("app_key_right"), .value = app_key_right},
|
||||
{.name = s8_const_lit("app_key_down"), .value = app_key_down},
|
||||
{.name = s8_const_lit("app_key_tab"), .value = app_key_tab},
|
||||
{.name = s8_const_lit("app_key_backspace"), .value = app_key_backspace},
|
||||
{.name = s8_const_lit("app_key_control"), .value = app_key_control},
|
||||
{.name = s8_const_lit("app_key_shift"), .value = app_key_shift},
|
||||
{.name = s8_const_lit("app_key_alt"), .value = app_key_alt},
|
||||
{.name = s8_const_lit("app_key_meta"), .value = app_key_meta},
|
||||
{.name = s8_const_lit("app_key_caps_lock"), .value = app_key_caps_lock},
|
||||
{.name = s8_const_lit("app_key_delete"), .value = app_key_delete},
|
||||
{.name = s8_const_lit("app_key_home"), .value = app_key_home},
|
||||
{.name = s8_const_lit("app_key_end"), .value = app_key_end},
|
||||
{.name = s8_const_lit("app_key_insert"), .value = app_key_insert},
|
||||
{.name = s8_const_lit("app_key_page_up"), .value = app_key_page_up},
|
||||
{.name = s8_const_lit("app_key_page_down"), .value = app_key_page_down},
|
||||
},
|
||||
.count = 69,
|
||||
};
|
||||
|
||||
#if PLATFORM_WASM
|
||||
typedef struct { app_key_t key; b32 filter_out; } wasm_key_map_t;
|
||||
wasm_key_map_t wasm_map_key_string_to_app_key(s8_t key) {
|
||||
if (0) {}
|
||||
else if (s8_equal_ex(key, s8_lit("1"), s8_ignore_case)) return (wasm_key_map_t){app_key_1, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("2"), s8_ignore_case)) return (wasm_key_map_t){app_key_2, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("3"), s8_ignore_case)) return (wasm_key_map_t){app_key_3, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("4"), s8_ignore_case)) return (wasm_key_map_t){app_key_4, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("5"), s8_ignore_case)) return (wasm_key_map_t){app_key_5, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("6"), s8_ignore_case)) return (wasm_key_map_t){app_key_6, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("7"), s8_ignore_case)) return (wasm_key_map_t){app_key_7, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("8"), s8_ignore_case)) return (wasm_key_map_t){app_key_8, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("9"), s8_ignore_case)) return (wasm_key_map_t){app_key_9, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("0"), s8_ignore_case)) return (wasm_key_map_t){app_key_0, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("F1"), s8_ignore_case)) return (wasm_key_map_t){app_key_f1, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F2"), s8_ignore_case)) return (wasm_key_map_t){app_key_f2, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F3"), s8_ignore_case)) return (wasm_key_map_t){app_key_f3, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F4"), s8_ignore_case)) return (wasm_key_map_t){app_key_f4, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F5"), s8_ignore_case)) return (wasm_key_map_t){app_key_f5, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F6"), s8_ignore_case)) return (wasm_key_map_t){app_key_f6, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F7"), s8_ignore_case)) return (wasm_key_map_t){app_key_f7, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F8"), s8_ignore_case)) return (wasm_key_map_t){app_key_f8, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F9"), s8_ignore_case)) return (wasm_key_map_t){app_key_f9, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F10"), s8_ignore_case)) return (wasm_key_map_t){app_key_f10, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F11"), s8_ignore_case)) return (wasm_key_map_t){app_key_f11, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("F12"), s8_ignore_case)) return (wasm_key_map_t){app_key_f12, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("a"), s8_ignore_case)) return (wasm_key_map_t){app_key_a, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("b"), s8_ignore_case)) return (wasm_key_map_t){app_key_b, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("c"), s8_ignore_case)) return (wasm_key_map_t){app_key_c, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("d"), s8_ignore_case)) return (wasm_key_map_t){app_key_d, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("e"), s8_ignore_case)) return (wasm_key_map_t){app_key_e, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("f"), s8_ignore_case)) return (wasm_key_map_t){app_key_f, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("g"), s8_ignore_case)) return (wasm_key_map_t){app_key_g, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("h"), s8_ignore_case)) return (wasm_key_map_t){app_key_h, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("i"), s8_ignore_case)) return (wasm_key_map_t){app_key_i, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("j"), s8_ignore_case)) return (wasm_key_map_t){app_key_j, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("k"), s8_ignore_case)) return (wasm_key_map_t){app_key_k, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("l"), s8_ignore_case)) return (wasm_key_map_t){app_key_l, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("m"), s8_ignore_case)) return (wasm_key_map_t){app_key_m, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("n"), s8_ignore_case)) return (wasm_key_map_t){app_key_n, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("o"), s8_ignore_case)) return (wasm_key_map_t){app_key_o, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("p"), s8_ignore_case)) return (wasm_key_map_t){app_key_p, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("q"), s8_ignore_case)) return (wasm_key_map_t){app_key_q, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("r"), s8_ignore_case)) return (wasm_key_map_t){app_key_r, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("s"), s8_ignore_case)) return (wasm_key_map_t){app_key_s, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("t"), s8_ignore_case)) return (wasm_key_map_t){app_key__t, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("u"), s8_ignore_case)) return (wasm_key_map_t){app_key_u, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("v"), s8_ignore_case)) return (wasm_key_map_t){app_key_v, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("w"), s8_ignore_case)) return (wasm_key_map_t){app_key_w, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("x"), s8_ignore_case)) return (wasm_key_map_t){app_key_x, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("y"), s8_ignore_case)) return (wasm_key_map_t){app_key_y, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("z"), s8_ignore_case)) return (wasm_key_map_t){app_key_z, 0};
|
||||
else if (s8_equal_ex(key, s8_lit(" "), s8_ignore_case)) return (wasm_key_map_t){app_key_space, 0};
|
||||
else if (s8_equal_ex(key, s8_lit("Enter"), s8_ignore_case)) return (wasm_key_map_t){app_key_enter, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Escape"), s8_ignore_case)) return (wasm_key_map_t){app_key_escape, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("ArrowLeft"), s8_ignore_case)) return (wasm_key_map_t){app_key_left, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("ArrowUp"), s8_ignore_case)) return (wasm_key_map_t){app_key_up, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("ArrowRight"), s8_ignore_case)) return (wasm_key_map_t){app_key_right, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("ArrowDown"), s8_ignore_case)) return (wasm_key_map_t){app_key_down, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Tab"), s8_ignore_case)) return (wasm_key_map_t){app_key_tab, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Backspace"), s8_ignore_case)) return (wasm_key_map_t){app_key_backspace, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Control"), s8_ignore_case)) return (wasm_key_map_t){app_key_control, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Shift"), s8_ignore_case)) return (wasm_key_map_t){app_key_shift, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Alt"), s8_ignore_case)) return (wasm_key_map_t){app_key_alt, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("AltGraph"), s8_ignore_case)) return (wasm_key_map_t){app_key_alt, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Meta"), s8_ignore_case)) return (wasm_key_map_t){app_key_meta, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("CapsLock"), s8_ignore_case)) return (wasm_key_map_t){app_key_caps_lock, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Delete"), s8_ignore_case)) return (wasm_key_map_t){app_key_delete, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Home"), s8_ignore_case)) return (wasm_key_map_t){app_key_home, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("End"), s8_ignore_case)) return (wasm_key_map_t){app_key_end, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("Insert"), s8_ignore_case)) return (wasm_key_map_t){app_key_insert, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("PageUp"), s8_ignore_case)) return (wasm_key_map_t){app_key_page_up, 1};
|
||||
else if (s8_equal_ex(key, s8_lit("PageDown"), s8_ignore_case)) return (wasm_key_map_t){app_key_page_down, 1};
|
||||
return (wasm_key_map_t){0};
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
void w32_key_dispatch(WPARAM wparam, void (*handle_key)(app_key_t)) {
|
||||
switch(wparam) {
|
||||
case '1': handle_key(app_key_1); break;
|
||||
case '2': handle_key(app_key_2); break;
|
||||
case '3': handle_key(app_key_3); break;
|
||||
case '4': handle_key(app_key_4); break;
|
||||
case '5': handle_key(app_key_5); break;
|
||||
case '6': handle_key(app_key_6); break;
|
||||
case '7': handle_key(app_key_7); break;
|
||||
case '8': handle_key(app_key_8); break;
|
||||
case '9': handle_key(app_key_9); break;
|
||||
case '0': handle_key(app_key_0); break;
|
||||
case VK_F1: handle_key(app_key_f1); break;
|
||||
case VK_F2: handle_key(app_key_f2); break;
|
||||
case VK_F3: handle_key(app_key_f3); break;
|
||||
case VK_F4: handle_key(app_key_f4); break;
|
||||
case VK_F5: handle_key(app_key_f5); break;
|
||||
case VK_F6: handle_key(app_key_f6); break;
|
||||
case VK_F7: handle_key(app_key_f7); break;
|
||||
case VK_F8: handle_key(app_key_f8); break;
|
||||
case VK_F9: handle_key(app_key_f9); break;
|
||||
case VK_F10: handle_key(app_key_f10); break;
|
||||
case VK_F11: handle_key(app_key_f11); break;
|
||||
case VK_F12: handle_key(app_key_f12); break;
|
||||
case 'A': handle_key(app_key_a); break;
|
||||
case 'B': handle_key(app_key_b); break;
|
||||
case 'C': handle_key(app_key_c); break;
|
||||
case 'D': handle_key(app_key_d); break;
|
||||
case 'E': handle_key(app_key_e); break;
|
||||
case 'F': handle_key(app_key_f); break;
|
||||
case 'G': handle_key(app_key_g); break;
|
||||
case 'H': handle_key(app_key_h); break;
|
||||
case 'I': handle_key(app_key_i); break;
|
||||
case 'J': handle_key(app_key_j); break;
|
||||
case 'K': handle_key(app_key_k); break;
|
||||
case 'L': handle_key(app_key_l); break;
|
||||
case 'M': handle_key(app_key_m); break;
|
||||
case 'N': handle_key(app_key_n); break;
|
||||
case 'O': handle_key(app_key_o); break;
|
||||
case 'P': handle_key(app_key_p); break;
|
||||
case 'Q': handle_key(app_key_q); break;
|
||||
case 'R': handle_key(app_key_r); break;
|
||||
case 'S': handle_key(app_key_s); break;
|
||||
case 'T': handle_key(app_key__t); break;
|
||||
case 'U': handle_key(app_key_u); break;
|
||||
case 'V': handle_key(app_key_v); break;
|
||||
case 'W': handle_key(app_key_w); break;
|
||||
case 'X': handle_key(app_key_x); break;
|
||||
case 'Y': handle_key(app_key_y); break;
|
||||
case 'Z': handle_key(app_key_z); break;
|
||||
case VK_SPACE: handle_key(app_key_space); break;
|
||||
case VK_RETURN: handle_key(app_key_enter); break;
|
||||
case VK_ESCAPE: handle_key(app_key_escape); break;
|
||||
case VK_LEFT: handle_key(app_key_left); break;
|
||||
case VK_UP: handle_key(app_key_up); break;
|
||||
case VK_RIGHT: handle_key(app_key_right); break;
|
||||
case VK_DOWN: handle_key(app_key_down); break;
|
||||
case VK_TAB: handle_key(app_key_tab); break;
|
||||
case VK_BACK: handle_key(app_key_backspace); break;
|
||||
case VK_CONTROL: handle_key(app_key_control); break;
|
||||
case VK_SHIFT: handle_key(app_key_shift); break;
|
||||
case VK_LMENU: handle_key(app_key_alt); break;
|
||||
case VK_RMENU: handle_key(app_key_alt); break;
|
||||
case VK_LWIN: handle_key(app_key_meta); break;
|
||||
case VK_RWIN: handle_key(app_key_meta); break;
|
||||
case VK_CAPITAL: handle_key(app_key_caps_lock); break;
|
||||
case VK_DELETE: handle_key(app_key_delete); break;
|
||||
case VK_HOME: handle_key(app_key_home); break;
|
||||
case VK_END: handle_key(app_key_end); break;
|
||||
case VK_NEXT: handle_key(app_key_insert); break;
|
||||
case VK_INSERT: handle_key(app_key_page_up); break;
|
||||
case VK_PRIOR: handle_key(app_key_page_down); break;
|
||||
default: {} break;
|
||||
}
|
||||
}
|
||||
#endif/*D:\dev\wasm\src/app/app.meta.c*/
|
||||
type_t type__app_mouse_button_t = { type_kind_enum, s8_const_lit("app_mouse_button_t"), sizeof(app_mouse_button_t),
|
||||
.members = (type_member_t[]){
|
||||
{.name = s8_const_lit("app_mouse_button_null"), .value = app_mouse_button_null},
|
||||
{.name = s8_const_lit("app_mouse_button_left"), .value = app_mouse_button_left},
|
||||
{.name = s8_const_lit("app_mouse_button_middle"), .value = app_mouse_button_middle},
|
||||
{.name = s8_const_lit("app_mouse_button_right"), .value = app_mouse_button_right},
|
||||
{.name = s8_const_lit("app_mouse_button_count"), .value = app_mouse_button_count},
|
||||
},
|
||||
.count = 5,
|
||||
};
|
||||
type_t type__app_event_kind_t = { type_kind_enum, s8_const_lit("app_event_kind_t"), sizeof(app_event_kind_t),
|
||||
.members = (type_member_t[]){
|
||||
{.name = s8_const_lit("app_event_kind_invalid"), .value = app_event_kind_invalid},
|
||||
{.name = s8_const_lit("app_event_kind_update"), .value = app_event_kind_update},
|
||||
{.name = s8_const_lit("app_event_kind_text"), .value = app_event_kind_text},
|
||||
{.name = s8_const_lit("app_event_kind_key_down"), .value = app_event_kind_key_down},
|
||||
{.name = s8_const_lit("app_event_kind_key_up"), .value = app_event_kind_key_up},
|
||||
{.name = s8_const_lit("app_event_kind_mouse_down"), .value = app_event_kind_mouse_down},
|
||||
{.name = s8_const_lit("app_event_kind_mouse_up"), .value = app_event_kind_mouse_up},
|
||||
{.name = s8_const_lit("app_event_kind_mouse_wheel"), .value = app_event_kind_mouse_wheel},
|
||||
{.name = s8_const_lit("app_event_kind_mouse_move"), .value = app_event_kind_mouse_move},
|
||||
{.name = s8_const_lit("app_event_kind_count"), .value = app_event_kind_count},
|
||||
},
|
||||
.count = 10,
|
||||
};
|
||||
type_t type__app_event_t = { type_kind_struct, s8_const_lit("app_event_t"), sizeof(app_event_t),
|
||||
.members = (type_member_t[]){
|
||||
{.name = s8_const_lit("kind"), .type = &type__app_event_kind_t, .offset = offsetof(app_event_t, kind)},
|
||||
{.name = s8_const_lit("mouse_button"), .type = &type__app_mouse_button_t, .offset = offsetof(app_event_t, mouse_button)},
|
||||
{.name = s8_const_lit("key"), .type = &type__app_key_t, .offset = offsetof(app_event_t, key)},
|
||||
{.name = s8_const_lit("text"), .type = &type__s8_t, .offset = offsetof(app_event_t, text)},
|
||||
{.name = s8_const_lit("ctrl"), .type = &type__b8, .offset = offsetof(app_event_t, ctrl)},
|
||||
{.name = s8_const_lit("shift"), .type = &type__b8, .offset = offsetof(app_event_t, shift)},
|
||||
{.name = s8_const_lit("alt"), .type = &type__b8, .offset = offsetof(app_event_t, alt)},
|
||||
{.name = s8_const_lit("meta"), .type = &type__b8, .offset = offsetof(app_event_t, meta)},
|
||||
{.name = s8_const_lit("time"), .type = &type__f64, .offset = offsetof(app_event_t, time)},
|
||||
{.name = s8_const_lit("delta_time"), .type = &type__f64, .offset = offsetof(app_event_t, delta_time)},
|
||||
{.name = s8_const_lit("dpr"), .type = &type__f64, .offset = offsetof(app_event_t, dpr)},
|
||||
{.name = s8_const_lit("window_size"), .type = &type__v2f32_t, .offset = offsetof(app_event_t, window_size)},
|
||||
{.name = s8_const_lit("mouse_pos"), .type = &type__v2f32_t, .offset = offsetof(app_event_t, mouse_pos)},
|
||||
{.name = s8_const_lit("mouse_wheel_delta"), .type = &type__v3f32_t, .offset = offsetof(app_event_t, mouse_wheel_delta)},
|
||||
},
|
||||
.count = 14,
|
||||
};
|
||||
110
src/app/app.gen.h
Normal file
110
src/app/app.gen.h
Normal file
@@ -0,0 +1,110 @@
|
||||
typedef enum {
|
||||
app_key_invalid,
|
||||
app_key_1,
|
||||
app_key_2,
|
||||
app_key_3,
|
||||
app_key_4,
|
||||
app_key_5,
|
||||
app_key_6,
|
||||
app_key_7,
|
||||
app_key_8,
|
||||
app_key_9,
|
||||
app_key_0,
|
||||
app_key_f1,
|
||||
app_key_f2,
|
||||
app_key_f3,
|
||||
app_key_f4,
|
||||
app_key_f5,
|
||||
app_key_f6,
|
||||
app_key_f7,
|
||||
app_key_f8,
|
||||
app_key_f9,
|
||||
app_key_f10,
|
||||
app_key_f11,
|
||||
app_key_f12,
|
||||
app_key_a,
|
||||
app_key_b,
|
||||
app_key_c,
|
||||
app_key_d,
|
||||
app_key_e,
|
||||
app_key_f,
|
||||
app_key_g,
|
||||
app_key_h,
|
||||
app_key_i,
|
||||
app_key_j,
|
||||
app_key_k,
|
||||
app_key_l,
|
||||
app_key_m,
|
||||
app_key_n,
|
||||
app_key_o,
|
||||
app_key_p,
|
||||
app_key_q,
|
||||
app_key_r,
|
||||
app_key_s,
|
||||
app_key__t,
|
||||
app_key_u,
|
||||
app_key_v,
|
||||
app_key_w,
|
||||
app_key_x,
|
||||
app_key_y,
|
||||
app_key_z,
|
||||
app_key_space,
|
||||
app_key_enter,
|
||||
app_key_escape,
|
||||
app_key_left,
|
||||
app_key_up,
|
||||
app_key_right,
|
||||
app_key_down,
|
||||
app_key_tab,
|
||||
app_key_backspace,
|
||||
app_key_control,
|
||||
app_key_shift,
|
||||
app_key_alt,
|
||||
app_key_meta,
|
||||
app_key_caps_lock,
|
||||
app_key_delete,
|
||||
app_key_home,
|
||||
app_key_end,
|
||||
app_key_insert,
|
||||
app_key_page_up,
|
||||
app_key_page_down,
|
||||
app_key_count,
|
||||
} app_key_t;
|
||||
/*D:\dev\wasm\src/app/app.meta.c*/
|
||||
typedef enum {
|
||||
app_mouse_button_null,
|
||||
app_mouse_button_left,
|
||||
app_mouse_button_middle,
|
||||
app_mouse_button_right,
|
||||
app_mouse_button_count,
|
||||
} app_mouse_button_t;
|
||||
typedef enum {
|
||||
app_event_kind_invalid,
|
||||
app_event_kind_update,
|
||||
app_event_kind_text,
|
||||
app_event_kind_key_down,
|
||||
app_event_kind_key_up,
|
||||
app_event_kind_mouse_down,
|
||||
app_event_kind_mouse_up,
|
||||
app_event_kind_mouse_wheel,
|
||||
app_event_kind_mouse_move,
|
||||
app_event_kind_count,
|
||||
} app_event_kind_t;
|
||||
|
||||
typedef struct app_event_t app_event_t;
|
||||
struct app_event_t {
|
||||
app_event_kind_t kind;
|
||||
app_mouse_button_t mouse_button;
|
||||
app_key_t key;
|
||||
s8_t text;
|
||||
b8 ctrl;
|
||||
b8 shift;
|
||||
b8 alt;
|
||||
b8 meta;
|
||||
f64 time;
|
||||
f64 delta_time;
|
||||
f64 dpr;
|
||||
v2f32_t window_size;
|
||||
v2f32_t mouse_pos;
|
||||
v3f32_t mouse_wheel_delta;
|
||||
};
|
||||
3
src/app/app.h
Normal file
3
src/app/app.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "app.gen.h"
|
||||
|
||||
|
||||
189
src/app/app.meta.c
Normal file
189
src/app/app.meta.c
Normal file
@@ -0,0 +1,189 @@
|
||||
void meta_app(ma_arena_t *arena) {
|
||||
sb8_t *h = sb8_serial_begin(arena);
|
||||
sb8_t *c = sb8_serial_begin(arena);
|
||||
|
||||
|
||||
ast_t *keys = parse_table(arena, __FILE__, CODE(
|
||||
// javascript filter out
|
||||
| name | js1 | js2 | jf | windows1 | windows2 |
|
||||
| invalid | XXX | XXX | 1 | XXX | XXX |
|
||||
| 1 | 1 | XXX | 0 | `'1'` | XXX |
|
||||
| 2 | 2 | XXX | 0 | `'2'` | XXX |
|
||||
| 3 | 3 | XXX | 0 | `'3'` | XXX |
|
||||
| 4 | 4 | XXX | 0 | `'4'` | XXX |
|
||||
| 5 | 5 | XXX | 0 | `'5'` | XXX |
|
||||
| 6 | 6 | XXX | 0 | `'6'` | XXX |
|
||||
| 7 | 7 | XXX | 0 | `'7'` | XXX |
|
||||
| 8 | 8 | XXX | 0 | `'8'` | XXX |
|
||||
| 9 | 9 | XXX | 0 | `'9'` | XXX |
|
||||
| 0 | 0 | XXX | 0 | `'0'` | XXX |
|
||||
| f1 | F1 | XXX | 1 | VK_F1 | XXX |
|
||||
| f2 | F2 | XXX | 1 | VK_F2 | XXX |
|
||||
| f3 | F3 | XXX | 1 | VK_F3 | XXX |
|
||||
| f4 | F4 | XXX | 1 | VK_F4 | XXX |
|
||||
| f5 | F5 | XXX | 1 | VK_F5 | XXX |
|
||||
| f6 | F6 | XXX | 1 | VK_F6 | XXX |
|
||||
| f7 | F7 | XXX | 1 | VK_F7 | XXX |
|
||||
| f8 | F8 | XXX | 1 | VK_F8 | XXX |
|
||||
| f9 | F9 | XXX | 1 | VK_F9 | XXX |
|
||||
| f10 | F10 | XXX | 1 | VK_F10 | XXX |
|
||||
| f11 | F11 | XXX | 1 | VK_F11 | XXX |
|
||||
| f12 | F12 | XXX | 1 | VK_F12 | XXX |
|
||||
| a | a | XXX | 0 | `'A'` | XXX |
|
||||
| b | b | XXX | 0 | `'B'` | XXX |
|
||||
| c | c | XXX | 0 | `'C'` | XXX |
|
||||
| d | d | XXX | 0 | `'D'` | XXX |
|
||||
| e | e | XXX | 0 | `'E'` | XXX |
|
||||
| f | f | XXX | 0 | `'F'` | XXX |
|
||||
| g | g | XXX | 0 | `'G'` | XXX |
|
||||
| h | h | XXX | 0 | `'H'` | XXX |
|
||||
| i | i | XXX | 0 | `'I'` | XXX |
|
||||
| j | j | XXX | 0 | `'J'` | XXX |
|
||||
| k | k | XXX | 0 | `'K'` | XXX |
|
||||
| l | l | XXX | 0 | `'L'` | XXX |
|
||||
| m | m | XXX | 0 | `'M'` | XXX |
|
||||
| n | n | XXX | 0 | `'N'` | XXX |
|
||||
| o | o | XXX | 0 | `'O'` | XXX |
|
||||
| p | p | XXX | 0 | `'P'` | XXX |
|
||||
| q | q | XXX | 0 | `'Q'` | XXX |
|
||||
| r | r | XXX | 0 | `'R'` | XXX |
|
||||
| s | s | XXX | 0 | `'S'` | XXX |
|
||||
| _t | t | XXX | 0 | `'T'` | XXX |
|
||||
| u | u | XXX | 0 | `'U'` | XXX |
|
||||
| v | v | XXX | 0 | `'V'` | XXX |
|
||||
| w | w | XXX | 0 | `'W'` | XXX |
|
||||
| x | x | XXX | 0 | `'X'` | XXX |
|
||||
| y | y | XXX | 0 | `'Y'` | XXX |
|
||||
| z | z | XXX | 0 | `'Z'` | XXX |
|
||||
| space | ` ` | XXX | 0 | VK_SPACE | XXX |
|
||||
| enter | Enter | XXX | 1 | VK_RETURN | XXX |
|
||||
| escape | Escape | XXX | 1 | VK_ESCAPE | XXX |
|
||||
| left | ArrowLeft | XXX | 1 | VK_LEFT | XXX |
|
||||
| up | ArrowUp | XXX | 1 | VK_UP | XXX |
|
||||
| right | ArrowRight | XXX | 1 | VK_RIGHT | XXX |
|
||||
| down | ArrowDown | XXX | 1 | VK_DOWN | XXX |
|
||||
| tab | Tab | XXX | 1 | VK_TAB | XXX |
|
||||
| backspace | Backspace | XXX | 1 | VK_BACK | XXX |
|
||||
| control | Control | XXX | 1 | VK_CONTROL | XXX |
|
||||
| shift | Shift | XXX | 1 | VK_SHIFT | XXX |
|
||||
| alt | Alt | AltGraph | 1 | VK_LMENU | VK_RMENU |
|
||||
| meta | Meta | XXX | 1 | VK_LWIN | VK_RWIN |
|
||||
| caps_lock | CapsLock | XXX | 1 | VK_CAPITAL | XXX |
|
||||
| delete | Delete | XXX | 1 | VK_DELETE | XXX |
|
||||
| home | Home | XXX | 1 | VK_HOME | XXX |
|
||||
| end | End | XXX | 1 | VK_END | XXX |
|
||||
| insert | Insert | XXX | 1 | VK_NEXT | XXX |
|
||||
| page_up | PageUp | XXX | 1 | VK_INSERT | XXX |
|
||||
| page_down | PageDown | XXX | 1 | VK_PRIOR | XXX |
|
||||
));
|
||||
sb8_serial_table_enum(c, h, keys, s8_lit("app_key"));
|
||||
|
||||
// Javascript
|
||||
{
|
||||
int name_idx = row_findi(keys->first, "name");
|
||||
int js1_idx = row_findi(keys->first, "js1");
|
||||
int js2_idx = row_findi(keys->first, "js2");
|
||||
int filter_out_idx = row_findi(keys->first, "jf");
|
||||
|
||||
|
||||
sb8_stmtf(c, "\n#if PLATFORM_WASM");
|
||||
sb8_stmtf(c, "typedef struct { app_key_t key; b32 filter_out; } wasm_key_map_t;");
|
||||
sb8_stmtf(c, "wasm_key_map_t wasm_map_key_string_to_app_key(s8_t key) {");
|
||||
c->indent += 1;
|
||||
sb8_stmtf(c, "if (0) {}");
|
||||
for (ast_t *row = keys->first->next; row; row = row->next) {
|
||||
s8_t name = row_geti(row, name_idx)->string;
|
||||
i64 filter_out = row_geti(row, filter_out_idx)->integer;
|
||||
assert(filter_out == 0 || filter_out == 1);
|
||||
|
||||
s8_t js[] = {row_geti(row, js1_idx)->string, row_geti(row, js2_idx)->string};
|
||||
for (i32 i = 0; i < lengthof(js); i += 1) {
|
||||
if (s8_equal(js[i], s8_lit("XXX"))) continue;
|
||||
sb8_stmtf(c, "else if (s8_equal_ex(key, s8_lit(\"%S\"), s8_ignore_case)) return (wasm_key_map_t){app_key_%S, %d};", js[i], name, (int)filter_out);
|
||||
}
|
||||
}
|
||||
sb8_stmtf(c, "return (wasm_key_map_t){0};");
|
||||
c->indent -= 1;
|
||||
sb8_stmtf(c, "}");
|
||||
sb8_stmtf(c, "#endif");
|
||||
}
|
||||
|
||||
// Windows
|
||||
{
|
||||
int name_idx = row_findi(keys->first, "name");
|
||||
int w1i = row_findi(keys->first, "windows1");
|
||||
int w2i = row_findi(keys->first, "windows2");
|
||||
|
||||
sb8_stmtf(c, "\n#if PLATFORM_WINDOWS");
|
||||
sb8_stmtf(c, "void w32_key_dispatch(WPARAM wparam, void (*handle_key)(app_key_t)) {");
|
||||
c->indent += 1;
|
||||
sb8_stmtf(c, "switch(wparam) {");
|
||||
c->indent += 1;
|
||||
for (ast_t *row = keys->first->next; row; row = row->next) {
|
||||
s8_t name = row_geti(row, name_idx)->string;
|
||||
s8_t w[] = {row_geti(row, w1i)->string, row_geti(row, w2i)->string};
|
||||
for (i32 i = 0; i < lengthof(w); i += 1) {
|
||||
if (s8_equal(w[i], s8_lit("XXX"))) continue;
|
||||
|
||||
sb8_stmtf(c, "case %.*s: handle_key(app_key_%.*s); break;", s8_fmtspec(w[i]), s8_fmtspec(name));
|
||||
}
|
||||
}
|
||||
sb8_stmtf(c, "default: {} break;");
|
||||
c->indent -= 1;
|
||||
sb8_stmtf(c, "}");
|
||||
c->indent -= 1;
|
||||
sb8_stmtf(c, "}");
|
||||
sb8_stmtf(c, "#endif");
|
||||
}
|
||||
|
||||
{
|
||||
ast_t *decls = parse_decls(arena, __FILE__, CODE(
|
||||
typedef enum {
|
||||
app_mouse_button_null,
|
||||
app_mouse_button_left,
|
||||
app_mouse_button_middle,
|
||||
app_mouse_button_right,
|
||||
app_mouse_button_count,
|
||||
} app_mouse_button_t;
|
||||
|
||||
typedef enum {
|
||||
app_event_kind_invalid,
|
||||
app_event_kind_update,
|
||||
app_event_kind_text,
|
||||
app_event_kind_key_down,
|
||||
app_event_kind_key_up,
|
||||
app_event_kind_mouse_down,
|
||||
app_event_kind_mouse_up,
|
||||
app_event_kind_mouse_wheel,
|
||||
app_event_kind_mouse_move,
|
||||
app_event_kind_count,
|
||||
} app_event_kind_t;
|
||||
|
||||
struct app_event_t {
|
||||
app_event_kind_t kind;
|
||||
|
||||
app_mouse_button_t mouse_button;
|
||||
app_key_t key;
|
||||
s8_t text;
|
||||
b8 ctrl;
|
||||
b8 shift;
|
||||
b8 alt;
|
||||
b8 meta;
|
||||
|
||||
f64 time;
|
||||
f64 delta_time;
|
||||
|
||||
f64 dpr;
|
||||
v2f32_t window_size;
|
||||
v2f32_t mouse_pos;
|
||||
v3f32_t mouse_wheel_delta;
|
||||
};
|
||||
));
|
||||
|
||||
sb8_serial_ast_to_code(h, decls);
|
||||
sb8_serial_ast_to_type_info(c, decls);
|
||||
}
|
||||
|
||||
os_write_file(gen_c(arena), sb8_merge(c));
|
||||
os_write_file(gen_h(arena), sb8_merge(h));
|
||||
}
|
||||
212
src/app/app_wasm.c
Normal file
212
src/app/app_wasm.c
Normal file
@@ -0,0 +1,212 @@
|
||||
#define WASM_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
f64 wasm_parse_float(isize str, i32 len);
|
||||
void wasm_write_to_console(isize str, i32 len);
|
||||
void wasm_draw_text(isize str, i32 len, f64 x, f64 y, isize font_str, i32 font_len, i32 font_size, f32 r, f32 g, f32 b, f32 a);
|
||||
void wasm_draw_rect(f64 x, f64 y, f64 w, f64 h, f32 r, f32 g, f32 b, f32 a);
|
||||
f64 wasm_measure_text(isize str, i32 len, isize font_str, i32 font_len, i32 font_size);
|
||||
f64 wasm_get_font_height(isize font_str, i32 font_len, i32 font_size);
|
||||
void wasm_set_clip(f64 x, f64 y, f64 w, f64 h);
|
||||
|
||||
void on_update();
|
||||
void app_update(app_event_t *events);
|
||||
|
||||
extern char __heap_base;
|
||||
ma_arena_t wasm_perm_arena;
|
||||
|
||||
WASM_EXPORT char wasm_temp_buff1[128] = {[127] = 0x13};
|
||||
WASM_EXPORT i32 wasm_temp_buff1_len = 127;
|
||||
WASM_EXPORT char wasm_temp_buff2[128] = {[127] = 0x13};
|
||||
WASM_EXPORT i32 wasm_temp_buff2_len = 127;
|
||||
|
||||
|
||||
char *font_face = "fira";
|
||||
i32 font_face_len = 4;
|
||||
|
||||
f64 wasm_dpr;
|
||||
ma_arena_t *wasm_input_text_arena;
|
||||
STACK(app_event_t, 64) wasm_events;
|
||||
b32 wasm_event_failed_to_queue;
|
||||
f64 wasm_last_time = 0;
|
||||
|
||||
void write_to_console(char *string) {
|
||||
int len = str_len(string);
|
||||
wasm_write_to_console((isize)string, len);
|
||||
}
|
||||
|
||||
f64 s8_deserial_f64(s8_t string) {
|
||||
return wasm_parse_float((isize)string.str, (i32)string.len);
|
||||
}
|
||||
|
||||
void clip(r2f64_t rect) {
|
||||
wasm_set_clip(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y));
|
||||
}
|
||||
|
||||
|
||||
f64 get_font_height(void) {
|
||||
return wasm_get_font_height((isize) font_face, font_face_len, 20*wasm_dpr) / wasm_dpr;
|
||||
}
|
||||
|
||||
f64 measure_text_ex(char *str, int len) {
|
||||
return wasm_measure_text((isize)str, len, (isize) font_face, font_face_len, 20*wasm_dpr) / wasm_dpr;
|
||||
}
|
||||
|
||||
f64 measure_text(char *str) {
|
||||
return measure_text_ex(str, str_len(str));
|
||||
}
|
||||
|
||||
void draw_text(v2f64_t pos, v4f32_t color, char *str, int len) {
|
||||
wasm_draw_text((isize)str, len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face, font_face_len, 20*wasm_dpr, color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a);
|
||||
}
|
||||
|
||||
void draw_textf(v2f64_t pos, char *str, ...) {
|
||||
char buff[1024];
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
int len = stbsp_vsnprintf(buff, sizeof(buff), str, args);
|
||||
va_end(args);
|
||||
|
||||
wasm_draw_text((isize)buff, len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face, font_face_len, 20*wasm_dpr, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
void draw_rect(r2f64_t rect, v4f32_t color) {
|
||||
wasm_draw_rect(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y), color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a);
|
||||
}
|
||||
|
||||
void wasm_add_event(app_event_t event) {
|
||||
if (wasm_events.len < lengthof(wasm_events.data)) {
|
||||
STACK_PUSH(wasm_events, event);
|
||||
} else if (wasm_event_failed_to_queue == false) {
|
||||
wasm_event_failed_to_queue = true;
|
||||
debugf("failed to queue event");
|
||||
}
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_mouse_move(f64 x, f64 y, b32 ctrl, b32 shift, b32 alt, b32 meta) {
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_mouse_move,
|
||||
.mouse_pos = {x, y},
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_mouse_down(f64 x, f64 y, i32 button, b32 ctrl, b32 shift, b32 alt, b32 meta) {
|
||||
button += 1;
|
||||
assert(button >= app_mouse_button_left && button <= app_mouse_button_right);
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_mouse_down,
|
||||
.mouse_pos = {x, y},
|
||||
.mouse_button = button,
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_mouse_up(f64 x, f64 y, i32 button, b32 ctrl, b32 shift, b32 alt, b32 meta) {
|
||||
button += 1;
|
||||
assert(button >= app_mouse_button_left && button <= app_mouse_button_right);
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_mouse_up,
|
||||
.mouse_pos = {x, y},
|
||||
.mouse_button = button,
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_mouse_wheel(f64 delta_x, f64 delta_y, f64 delta_z, b32 ctrl, b32 shift, b32 alt, b32 meta) {
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_mouse_wheel,
|
||||
.mouse_wheel_delta = {delta_x, delta_y, delta_z},
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_key_down(char *key, b32 ctrl, b32 shift, b32 alt, b32 meta) {
|
||||
assert(wasm_temp_buff1[127] == 0x13); // make sure we didn't overwrite memory in JS
|
||||
assert(wasm_temp_buff2[127] == 0x13);
|
||||
s8_t key8 = s8_from_char(key);
|
||||
|
||||
wasm_key_map_t map = wasm_map_key_string_to_app_key(key8);
|
||||
if (map.key != app_key_invalid) {
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_key_down,
|
||||
.key = map.key,
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (map.filter_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
s8_t text = s8_copy(wasm_input_text_arena, key8);
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_text,
|
||||
.text = text,
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_key_up(char *key, b32 ctrl, b32 shift, b32 alt, b32 meta) {
|
||||
assert(wasm_temp_buff1[127] == 0x13); // make sure we didn't overwrite memory in JS
|
||||
assert(wasm_temp_buff2[127] == 0x13);
|
||||
s8_t key8 = s8_from_char(key);
|
||||
|
||||
wasm_key_map_t map = wasm_map_key_string_to_app_key(key8);
|
||||
if (map.key != app_key_invalid) {
|
||||
wasm_add_event((app_event_t){
|
||||
.kind = app_event_kind_key_down,
|
||||
.key = map.key,
|
||||
.ctrl = ctrl,
|
||||
.shift = shift,
|
||||
.alt = alt,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_update(f64 time, f64 width, f64 height, f64 dpr) {
|
||||
f64 delta_time = (time - wasm_last_time);
|
||||
for (i32 i = 0; i < wasm_events.len; i += 1) {
|
||||
wasm_events.data[i].dpr = dpr;
|
||||
wasm_events.data[i].window_size = (v2f32_t){width / dpr, height / dpr};
|
||||
wasm_events.data[i].time = time;
|
||||
wasm_events.data[i].delta_time = delta_time;
|
||||
}
|
||||
wasm_dpr = dpr;
|
||||
|
||||
on_update();
|
||||
|
||||
wasm_events.len = 0;
|
||||
wasm_last_time = time;
|
||||
ma_set0(wasm_input_text_arena);
|
||||
}
|
||||
|
||||
WASM_EXPORT void wasm_init(void) {
|
||||
isize page_size = kib(64);
|
||||
isize page_count = __builtin_wasm_memory_size(0);
|
||||
u8 *memory = (u8 *)&__heap_base;
|
||||
usize memory_size = page_count * (page_size) - (isize)memory;
|
||||
wasm_perm_arena.data = memory;
|
||||
wasm_perm_arena.commit = wasm_perm_arena.reserve = memory_size;
|
||||
wasm_input_text_arena = ma_push_arena(&wasm_perm_arena, kib(1));
|
||||
debugf("on_init, __builtin_wasm_memory_size(0) = %d(%d)", page_count, memory_size);
|
||||
}
|
||||
132
src/app/app_win32.c
Normal file
132
src/app/app_win32.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "core/core.h"
|
||||
#include "app.gen.h"
|
||||
|
||||
#include "core/core.c"
|
||||
#include "app.gen.c"
|
||||
|
||||
#pragma comment(linker, "/subsystem:windows")
|
||||
#pragma comment(lib, "gdi32.lib")
|
||||
#pragma comment(lib, "user32.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
|
||||
|
||||
b32 w32_good_scheduling = false;
|
||||
WNDCLASSW w32_wc;
|
||||
HWND w32_window_handle;
|
||||
HDC w32_dc;
|
||||
|
||||
void w32_on_key_down(app_key_t key) {
|
||||
}
|
||||
|
||||
void w32_on_key_up(app_key_t key) {
|
||||
}
|
||||
|
||||
LRESULT CALLBACK w32_window_proc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
switch (msg) {
|
||||
case WM_CLOSE: PostQuitMessage(0); break;
|
||||
case WM_KEYUP: w32_key_dispatch(wparam, w32_on_key_up); break;
|
||||
case WM_KEYDOWN: w32_key_dispatch(wparam, w32_on_key_down); break;
|
||||
default: return DefWindowProcW(wnd, msg, wparam, lparam);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
|
||||
typedef enum W32_PROCESS_DPI_AWARENESS {
|
||||
W32_PROCESS_DPI_UNAWARE = 0,
|
||||
W32_PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||
W32_PROCESS_PER_MONITOR_DPI_AWARE = 2
|
||||
} W32_PROCESS_DPI_AWARENESS;
|
||||
|
||||
typedef unsigned MU_TimeBeginPeriod(unsigned);
|
||||
typedef HRESULT MU_SetProcessDpiAwareness(W32_PROCESS_DPI_AWARENESS);
|
||||
|
||||
HMODULE shcore = LoadLibraryA("Shcore.dll");
|
||||
if (shcore) {
|
||||
MU_SetProcessDpiAwareness *set_dpi_awr = (MU_SetProcessDpiAwareness *)GetProcAddress(shcore, "SetProcessDpiAwareness");
|
||||
if (set_dpi_awr) {
|
||||
HRESULT hr = set_dpi_awr(W32_PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
assert(SUCCEEDED(hr) && "Failed to set dpi awareness");
|
||||
}
|
||||
}
|
||||
|
||||
HMODULE winmm = LoadLibraryA("winmm.dll");
|
||||
if (winmm) {
|
||||
MU_TimeBeginPeriod *timeBeginPeriod = (MU_TimeBeginPeriod *)GetProcAddress(winmm, "timeBeginPeriod");
|
||||
if (timeBeginPeriod) {
|
||||
if (timeBeginPeriod(1) == 0) {
|
||||
w32_good_scheduling = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WNDCLASSW wc = {0};
|
||||
{
|
||||
wc.lpfnWndProc = w32_window_proc;
|
||||
wc.hInstance = GetModuleHandleW(NULL);
|
||||
wc.lpszClassName = L"HelloClassName";
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = NULL; // LoadIcon(wc.hInstance, IDI_APPLICATION);
|
||||
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
|
||||
ATOM result = RegisterClassW(&wc);
|
||||
assert(result != 0);
|
||||
w32_wc = wc;
|
||||
}
|
||||
|
||||
RECT window_rect = {0};
|
||||
{
|
||||
window_rect.left = 0;
|
||||
window_rect.right = 1280;
|
||||
window_rect.bottom = 732;
|
||||
window_rect.top = 12;
|
||||
AdjustWindowRectEx(&window_rect, WS_OVERLAPPEDWINDOW, false, 0);
|
||||
}
|
||||
w32_window_handle = CreateWindowW(w32_wc.lpszClassName, L"Zzz... Window, hello!", WS_OVERLAPPEDWINDOW, window_rect.left, window_rect.top, window_rect.right - window_rect.left, window_rect.bottom - window_rect.top, NULL, NULL, hInstance, NULL);
|
||||
assert(w32_window_handle);
|
||||
|
||||
w32_dc = GetDC(w32_window_handle);
|
||||
assert(w32_dc);
|
||||
ShowWindow(w32_window_handle, SW_SHOW);
|
||||
|
||||
// @todo: rebuild on resize
|
||||
// Create a writable backbuffer bitmap
|
||||
uint32_t *mem = 0;
|
||||
BITMAPINFO bminfo = {0};
|
||||
{
|
||||
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
|
||||
bminfo.bmiHeader.biWidth = (LONG)1280;
|
||||
bminfo.bmiHeader.biHeight = (LONG)720;
|
||||
bminfo.bmiHeader.biPlanes = 1;
|
||||
bminfo.bmiHeader.biBitCount = 32;
|
||||
bminfo.bmiHeader.biCompression = BI_RGB; // AA RR GG BB
|
||||
bminfo.bmiHeader.biXPelsPerMeter = 1;
|
||||
bminfo.bmiHeader.biYPelsPerMeter = 1;
|
||||
}
|
||||
HBITMAP dib = CreateDIBSection(w32_dc, &bminfo, DIB_RGB_COLORS, (void **)&mem, 0, 0);
|
||||
HDC dib_dc = CreateCompatibleDC(w32_dc);
|
||||
|
||||
for (;;) {
|
||||
MSG msg;
|
||||
if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int y = 0; y < 720; y++) {
|
||||
for (int x = 0; x < 1280; x++) {
|
||||
mem[x + y * 1280] = 0xFFFF0000;
|
||||
}
|
||||
}
|
||||
|
||||
SelectObject(dib_dc, dib);
|
||||
BitBlt(w32_dc, 0, 0, 1280, 720, dib_dc, 0, 0, SRCCOPY);
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
132
src/core/arena.c
Normal file
132
src/core/arena.c
Normal 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
41
src/core/core.c
Normal 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
5
src/core/core.h
Normal 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
126
src/core/intrinsics.c
Normal 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
493
src/core/lexer.c
Normal 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
27
src/core/log.c
Normal 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
291
src/core/math_gen.py
Normal 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
520
src/core/mathx.c
Normal 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
519
src/core/mathx.gen.c
Normal 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 }; }
|
||||
69
src/core/platform_defines.h
Normal file
69
src/core/platform_defines.h
Normal 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
36
src/core/scratch.c
Normal 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
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
59
src/core/string.c
Normal 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
454
src/core/string8.c
Normal 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
403
src/core/type_info.c
Normal 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
314
src/core/type_info.h
Normal 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
538
src/core/types.h
Normal 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
226
src/core/unicode.c
Normal 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);
|
||||
}
|
||||
110
src/core_test/core_test_entry.c
Normal file
110
src/core_test/core_test_entry.c
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core.c"
|
||||
|
||||
void test_s8(void) {
|
||||
ma_arena_t *arena = ma_create(ma_default_reserve_size);
|
||||
|
||||
{
|
||||
ma_temp_t temp = ma_begin_temp(arena);
|
||||
sb8_t *sb = &(sb8_t){arena};
|
||||
|
||||
s8_t memes = s8_lit("memes");
|
||||
sb8_printf(sb, "%S", memes);
|
||||
assert(sb->first == sb->last);
|
||||
assert(sb->first->len == 5);
|
||||
assert(s8_equal(sb->first->s, memes));
|
||||
|
||||
sb8_printf(sb, "%S", s8_lit("things are going fine"));
|
||||
s8_t string = sb8_merge(sb);
|
||||
assert(s8_equal(string, s8_lit("memesthings are going fine")));
|
||||
|
||||
ma_end_temp(temp);
|
||||
}
|
||||
|
||||
{
|
||||
s8_t str = s8_lit("thing|another|");
|
||||
sb8_t sb = s8_split(arena, str, s8_lit("|"), s8_split_none);
|
||||
|
||||
assert(s8_equal(sb.first->s, s8_lit("thing")));
|
||||
assert(s8_equal(sb.first->next->s, s8_lit("another")));
|
||||
assert(sb.first->next->next == NULL);
|
||||
}
|
||||
|
||||
{
|
||||
s8_t str = s8_lit("thing|another|");
|
||||
sb8_t sb = s8_split(arena, str, s8_lit("|"), s8_split_inclusive);
|
||||
|
||||
assert(s8_equal(sb.first->s, s8_lit("thing")));
|
||||
assert(s8_equal(sb.first->next->s, s8_lit("|")));
|
||||
assert(s8_equal(sb.first->next->next->s, s8_lit("another")));
|
||||
assert(s8_equal(sb.first->next->next->next->s, s8_lit("|")));
|
||||
assert(sb.first->next->next->next->next == NULL);
|
||||
}
|
||||
|
||||
{
|
||||
s8_t str = s8_lit("aabaaBaa");
|
||||
sb8_t sb = s8_split(arena, str, s8_lit("b"), s8_split_inclusive | s8_split_ignore_case);
|
||||
|
||||
assert(s8_equal(sb.first->s, s8_lit("aa")));
|
||||
assert(s8_equal(sb.first->next->s, s8_lit("b")));
|
||||
assert(s8_equal(sb.first->next->next->s, s8_lit("aa")));
|
||||
assert(s8_equal(sb.first->next->next->next->s, s8_lit("B")));
|
||||
assert(s8_equal(sb.first->next->next->next->next->s, s8_lit("aa")));
|
||||
assert(sb.first->next->next->next->next->next == NULL);
|
||||
}
|
||||
|
||||
{
|
||||
s8_t str = s8_lit("aabaaBaa");
|
||||
sb8_t sb = s8_split(arena, str, s8_lit("b"), s8_split_inclusive);
|
||||
|
||||
assert(s8_equal(sb.first->s, s8_lit("aa")));
|
||||
assert(s8_equal(sb.first->next->s, s8_lit("b")));
|
||||
assert(s8_equal(sb.first->next->next->s, s8_lit("aaBaa")));
|
||||
}
|
||||
|
||||
{
|
||||
s8_t s = s8_lit("0123456789");
|
||||
assert(s8_equal(s8_slice(s, 0, 4), s8_lit("0123")));
|
||||
assert(s8_equal(s8_slice(s, -2, -1), s8_lit("89")));
|
||||
assert(s8_equal(s8_slice(s, -2, 10), s8_lit("89")));
|
||||
assert(s8_equal(s8_slice(s, 8, 10), s8_lit("89")));
|
||||
}
|
||||
|
||||
{
|
||||
s8_t s = s8_lit(" a \n");
|
||||
s = s8_trim(s);
|
||||
assert(s8_equal(s, s8_lit("a")));
|
||||
}
|
||||
|
||||
{
|
||||
s8_t s = s8_lit("C:/memes/the_thing.c");
|
||||
s8_t ss = s8_get_name_no_ext(s);
|
||||
assert(s8_equal(ss, s8_lit("the_thing")));
|
||||
}
|
||||
|
||||
{
|
||||
s8_t s = s8_fmt(arena, "%d%Sv%s", 32, s8_lit("|"), ">");
|
||||
assert(s8_equal(s, s8_lit("32|v>")));
|
||||
}
|
||||
|
||||
ma_destroy(arena);
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
printf("PLATFORM_WASM = %d\n", PLATFORM_WASM);
|
||||
printf("PLATFORM_WINDOWS = %d\n", PLATFORM_WINDOWS);
|
||||
printf("PLATFORM_LINUX = %d\n", PLATFORM_LINUX);
|
||||
printf("PLATFORM_POSIX = %d\n", PLATFORM_POSIX);
|
||||
printf("PLATFORM_MAC_OS = %d\n", PLATFORM_MAC_OS);
|
||||
printf("PLATFORM_CLANG = %d\n", PLATFORM_CLANG);
|
||||
printf("PLATFORM_GCC = %d\n", PLATFORM_GCC);
|
||||
printf("PLATFORM_CL = %d\n", PLATFORM_CL);
|
||||
printf("PLATFORM_TCC = %d\n", PLATFORM_TCC);
|
||||
printf("PLATFORM_ASSERT = %d\n", PLATFORM_ASSERT);
|
||||
|
||||
test_s8();
|
||||
|
||||
printf("all done!\n");
|
||||
}
|
||||
5187
src/meta/build_tool.c
Normal file
5187
src/meta/build_tool.c
Normal file
File diff suppressed because it is too large
Load Diff
307
src/meta/parser.c
Normal file
307
src/meta/parser.c
Normal file
@@ -0,0 +1,307 @@
|
||||
typedef enum {
|
||||
|
||||
#define AST_FLAG_XLIST\
|
||||
X(null)\
|
||||
X(string)\
|
||||
X(integer)\
|
||||
X(real)\
|
||||
X(binary)\
|
||||
X(enum)\
|
||||
X(enum_member)\
|
||||
X(struct)\
|
||||
X(struct_member)\
|
||||
X(var)\
|
||||
X(type_name)\
|
||||
X(type_pointer)\
|
||||
X(type_array)\
|
||||
|
||||
#define X(NAME) ast_flag_##NAME,
|
||||
AST_FLAG_XLIST
|
||||
#undef X
|
||||
} ast_flag_t;
|
||||
|
||||
typedef struct ast_t ast_t;
|
||||
struct ast_t {
|
||||
ast_flag_t flags;
|
||||
|
||||
lex_t *pos;
|
||||
ast_t *next;
|
||||
ast_t *first;
|
||||
ast_t *last;
|
||||
i32 len;
|
||||
|
||||
s8_t string;
|
||||
f64 real;
|
||||
i64 integer;
|
||||
};
|
||||
|
||||
s8_t s8_serial_ast_flag_t(ma_arena_t *arena, ast_flag_t flag) {
|
||||
sb8_t *sb = sb8_serial_begin(arena);
|
||||
#define X(NAME) if (flag & set_bit(ast_flag_##NAME)) sb8_printf(sb, #NAME);
|
||||
AST_FLAG_XLIST
|
||||
#undef X
|
||||
s8_t result = sb8_serial_end(sb);
|
||||
return result;
|
||||
}
|
||||
|
||||
ast_t *create_ast(parser_t *par, lex_t *pos, ast_flag_t flags) {
|
||||
ast_t *result = ma_push_type(par->arena, ast_t);
|
||||
memset(result, 0, sizeof(ast_t));
|
||||
result->flags = flags;
|
||||
result->pos = pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ast_append(ast_t *parent, ast_t *node) {
|
||||
SLLQ_APPEND(parent->first, parent->last, node);
|
||||
parent->len += 1;
|
||||
}
|
||||
|
||||
ast_t *create_ast_binary(parser_t *par, lex_t *pos, ast_t *left, lex_kind_t op, ast_t *right) {
|
||||
ast_t *result = create_ast(par, pos, set_bit(ast_flag_string) | set_bit(ast_flag_binary) | set_bit(ast_flag_integer));
|
||||
ast_append(result, left);
|
||||
ast_append(result, right);
|
||||
result->integer = op;
|
||||
result->string = s8_serial_simple_lex_kind_t(op);
|
||||
return result;
|
||||
}
|
||||
|
||||
ast_t *parse_expr(parser_t *par);
|
||||
ast_t *parse_lit_expr(parser_t *par) {
|
||||
lex_t *token = parser_next(par);
|
||||
if (token->kind == lex_kind_int) {
|
||||
ast_t *result = create_ast(par, token, set_bit(ast_flag_integer) | set_bit(ast_flag_string));
|
||||
result->integer = token->integer;
|
||||
result->string = token->s8;
|
||||
return result;
|
||||
} else if (token->kind == lex_kind_real) {
|
||||
ast_t *result = create_ast(par, token, set_bit(ast_flag_real) | set_bit(ast_flag_string));
|
||||
result->real = (double)token->real;
|
||||
result->string = token->s8;
|
||||
return result;
|
||||
} else if (token->kind == lex_kind_open_paren) {
|
||||
ast_t *result = parse_expr(par);
|
||||
parser_expect(par, lex_kind_close_paren);
|
||||
return result;
|
||||
} else {
|
||||
lex_panicf(token, "got invalid token of kind: %S while parsing expression", s8_serial_lex_kind_t(token->kind));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ast_t *parse_mul_expr(parser_t *par) {
|
||||
ast_t *left = parse_lit_expr(par);
|
||||
while (par->at->kind == lex_kind_multiply || par->at->kind == lex_kind_divide || par->at->kind == lex_kind_modulo) {
|
||||
lex_t *op = parser_next(par);
|
||||
left = create_ast_binary(par, op, left, op->kind, parse_lit_expr(par));
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
ast_t *parse_add_expr(parser_t *par) {
|
||||
ast_t *left = parse_mul_expr(par);
|
||||
while (par->at->kind == lex_kind_plus || par->at->kind == lex_kind_minus) {
|
||||
lex_t *op = parser_next(par);
|
||||
left = create_ast_binary(par, op, left, op->kind, parse_lit_expr(par));
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
ast_t *parse_logical_and_expr(parser_t *par) {
|
||||
ast_t *left = parse_add_expr(par);
|
||||
while (par->at->kind == lex_kind_or) {
|
||||
lex_t *op = parser_next(par);
|
||||
left = create_ast_binary(par, op, left, op->kind, parse_lit_expr(par));
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
ast_t *parse_logical_or_expr(parser_t *par) {
|
||||
ast_t *left = parse_logical_and_expr(par);
|
||||
while (par->at->kind == lex_kind_or) {
|
||||
lex_t *op = parser_next(par);
|
||||
left = create_ast_binary(par, op, left, op->kind, parse_lit_expr(par));
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
ast_t *parse_expr(parser_t *par) {
|
||||
ast_t *expr = parse_logical_or_expr(par);
|
||||
return expr;
|
||||
}
|
||||
|
||||
ast_t *parse_expr_str(ma_arena_t *arena, char *file_name, char *stream) {
|
||||
lex_array_t tokens = lex_tokens(arena, file_name, stream);
|
||||
parser_t *par = parser_make(arena, tokens.data);
|
||||
ast_t *result = parse_expr(par);
|
||||
return result;
|
||||
}
|
||||
|
||||
i64 eval_const_expr(ast_t *expr) {
|
||||
if (expr->flags & set_bit(ast_flag_integer)) {
|
||||
return expr->integer;
|
||||
} else if (expr->flags & set_bit(ast_flag_binary)) {
|
||||
assert(expr->first != expr->last);
|
||||
i64 left = eval_const_expr(expr->first);
|
||||
i64 right = eval_const_expr(expr->last);
|
||||
|
||||
switch(expr->integer) {
|
||||
case lex_kind_plus: return left + right;
|
||||
case lex_kind_minus: return left - right;
|
||||
case lex_kind_multiply: return left * right;
|
||||
case lex_kind_divide: return left / right;
|
||||
case lex_kind_modulo: return left % right;
|
||||
case lex_kind_and: return left && right;
|
||||
case lex_kind_or: return left || right;
|
||||
default: lex_panicf(expr->pos, "unhandled binary operator: %S", s8_serial_lex_kind_t(expr->integer));
|
||||
}
|
||||
} else {
|
||||
ma_temp_t scratch = ma_begin_scratch();
|
||||
lex_panicf(expr->pos, "unhandled ast in const expression evaluation: %S", s8_serial_ast_flag_t(scratch.arena, expr->flags));
|
||||
ma_end_scratch(scratch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define test_expr(x) do {\
|
||||
lex_array_t tokens = lex_tokens(scratch.arena, "parser_test", #x);\
|
||||
parser_t *par = parser_make(scratch.arena, tokens.data);\
|
||||
ast_t *expr = parse_expr(par);\
|
||||
assert(expr != NULL);\
|
||||
i64 value = eval_const_expr(expr);\
|
||||
assert(value == x);\
|
||||
} while (0)
|
||||
|
||||
void run_parser_test() {
|
||||
ma_temp_t scratch = ma_begin_scratch();
|
||||
test_expr(32 + 2 + 5 + 5);
|
||||
test_expr(32 - 2 + 5 - 5);
|
||||
test_expr(2 * 2 / 4 * 5 + 2 + 3);
|
||||
test_expr(2 * 5 * 5 / 2 + 2 - 1 - 1);
|
||||
test_expr(2 * (5 * 5) / 2 + (2 - 1 - 1));
|
||||
test_expr((2 * (5 * 5) / (2)) + (2 - 1 - 1));
|
||||
test_expr(10 % 3);
|
||||
test_expr(10 % 3 + 4 || 2);
|
||||
test_expr(10 % 3 + 4 || 2 && (4 && 2) || 3 && 1 || 0);
|
||||
ma_end_scratch(scratch);
|
||||
}
|
||||
|
||||
ast_t *parse_struct_mem(parser_t *par, s8_t *name) {
|
||||
lex_t *type_name = parser_expect(par, lex_kind_ident);
|
||||
ast_t *type = create_ast(par, type_name, set_bit(ast_flag_type_name) | set_bit(ast_flag_string));
|
||||
type->string = type_name->s8;
|
||||
|
||||
while (parser_match(par, lex_kind_multiply)) {
|
||||
ast_t *pointer = create_ast(par, par->at, set_bit(ast_flag_type_pointer) | set_bit(ast_flag_string));
|
||||
ast_append(pointer, type);
|
||||
pointer->string = s8_fmt(par->arena, "%S*", type->string);
|
||||
type = pointer;
|
||||
}
|
||||
|
||||
*name = parser_expect(par, lex_kind_ident)->s8;
|
||||
|
||||
while (parser_match(par, lex_kind_open_bracket)) {
|
||||
ast_t *array = create_ast(par, par->at, set_bit(ast_flag_type_array) | set_bit(ast_flag_string));
|
||||
ast_append(array, type);
|
||||
lex_t *num = parser_match(par, lex_kind_int);
|
||||
if (num) {
|
||||
array->flags |= set_bit(ast_flag_integer);
|
||||
array->integer = (int)num->integer;
|
||||
array->string = s8_fmt(par->arena, "%S[%d]", type->string, (int)array->integer);
|
||||
} else {
|
||||
array->string = s8_fmt(par->arena, "%S[]", type->string);
|
||||
}
|
||||
parser_expect(par, lex_kind_close_bracket);
|
||||
type = array;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
ast_t *parse_decls(ma_arena_t *arena, char *file, char *code) {
|
||||
lex_array_t tokens = lex_tokens(arena, file, code);
|
||||
parser_t *par = parser_make(arena, tokens.data);
|
||||
ast_t *result = create_ast(par, par->at, set_bit(ast_flag_string));
|
||||
result->string = s8_copy_char(arena, file);
|
||||
for (;par->at->kind != lex_kind_eof;) {
|
||||
lex_t *pos = par->at;
|
||||
if (parser_matchi(par, s8_lit("enum"))) {
|
||||
ast_t *n = create_ast(par, pos, set_bit(ast_flag_string) | set_bit(ast_flag_enum));
|
||||
ast_append(result, n);
|
||||
|
||||
parser_expect(par, lex_kind_open_brace);
|
||||
while (par->at->kind == lex_kind_ident) {
|
||||
lex_t *val = parser_expect(par, lex_kind_ident);
|
||||
ast_t *mem = create_ast(par, val, set_bit(ast_flag_enum_member) | set_bit(ast_flag_string));
|
||||
mem->string = val->s8;
|
||||
ast_append(n, mem);
|
||||
|
||||
// if (parser_match(par, lex_kind_assign)) {
|
||||
// parse_expr();
|
||||
// }
|
||||
|
||||
if (!parser_match(par, lex_kind_comma)) break;
|
||||
}
|
||||
parser_expect(par, lex_kind_close_brace);
|
||||
n->string = parser_expect(par, lex_kind_ident)->s8;
|
||||
parser_expect(par, lex_kind_semicolon);
|
||||
} else if (parser_matchi(par, s8_lit("struct"))) {
|
||||
ast_t *n = create_ast(par, pos, set_bit(ast_flag_string) | set_bit(ast_flag_struct));
|
||||
ast_append(result, n);
|
||||
n->string = parser_expect(par, lex_kind_ident)->s8;
|
||||
|
||||
parser_expect(par, lex_kind_open_brace);
|
||||
while (par->at->kind != lex_kind_close_brace) {
|
||||
ast_t *mem = create_ast(par, par->at, set_bit(ast_flag_struct_member) | set_bit(ast_flag_var) | set_bit(ast_flag_string));
|
||||
ast_append(n, mem);
|
||||
|
||||
ast_t *type = parse_struct_mem(par, &mem->string);
|
||||
ast_append(mem, type);
|
||||
|
||||
parser_expect(par, lex_kind_semicolon);
|
||||
}
|
||||
parser_expect(par, lex_kind_close_brace);
|
||||
parser_expect(par, lex_kind_semicolon);
|
||||
|
||||
} else {
|
||||
parser_next(par);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ast_t *parse_table(ma_arena_t *arena, char *file, char *code) {
|
||||
lex_array_t tokens = lex_tokens(arena, file, code);
|
||||
parser_t *par = parser_make(arena, tokens.data);
|
||||
ast_t *table = create_ast(par, par->at, 0);
|
||||
while (par->at->kind != lex_kind_eof) {
|
||||
ast_t *row = create_ast(par, par->at, 0);
|
||||
ast_append(table, row);
|
||||
while (par->at->kind != lex_kind_eof) {
|
||||
parser_match(par, lex_kind_bit_or);
|
||||
|
||||
lex_t *token = par->at;
|
||||
if (parser_match(par, lex_kind_ident) || parser_match(par, lex_kind_string)) {
|
||||
ast_t *col = create_ast(par, par->at, set_bit(ast_flag_string));
|
||||
ast_append(row, col);
|
||||
col->string = token->s8;
|
||||
} else if (parser_match(par, lex_kind_int)) {
|
||||
ast_t *col = create_ast(par, par->at, set_bit(ast_flag_string) | set_bit(ast_flag_integer));
|
||||
ast_append(row, col);
|
||||
col->string = token->s8;
|
||||
col->integer = token->integer;
|
||||
} else if (parser_match(par, lex_kind_real)) {
|
||||
ast_t *col = create_ast(par, par->at, set_bit(ast_flag_string) | set_bit(ast_flag_real));
|
||||
ast_append(row, col);
|
||||
col->string = token->s8;
|
||||
col->real = token->real;
|
||||
} else if (parser_match(par, lex_kind_bit_or) || parser_match(par, lex_kind_eof)) {
|
||||
break;
|
||||
} else {
|
||||
lex_panicf(par->at, "invalid token: %S", s8_serial_lex_kind_t(par->at->kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
224
src/meta/serialize.c
Normal file
224
src/meta/serialize.c
Normal file
@@ -0,0 +1,224 @@
|
||||
s8_t s8_ast_to_cvar(ma_arena_t *arena, ast_t *ast, s8_t *name) {
|
||||
if (ast->flags & set_bit(ast_flag_type_name)) {
|
||||
return ast->string;
|
||||
} else if (ast->flags & set_bit(ast_flag_type_pointer)) {
|
||||
s8_t base = s8_ast_to_cvar(arena, ast->first, name);
|
||||
return s8_fmt(arena, "%S*", base);
|
||||
} else if (ast->flags & set_bit(ast_flag_type_array)) {
|
||||
if (ast->flags & set_bit(ast_flag_integer)) {
|
||||
*name = s8_fmt(arena, "%S[%d]", *name, ast->integer);
|
||||
} else {
|
||||
*name = s8_fmt(arena, "%S[%d]", *name, ast->integer);
|
||||
}
|
||||
|
||||
s8_t base = s8_ast_to_cvar(arena, ast->first, name);
|
||||
return base;
|
||||
} else {
|
||||
assert(!"invalid ast_str case");
|
||||
return (s8_t){0};
|
||||
}
|
||||
}
|
||||
|
||||
void sb8_serial_ast(sb8_t *sb, ast_t *n) {
|
||||
if (n->flags & set_bit(ast_flag_string)) {
|
||||
sb8_stmtf(sb, "%S", n->string);
|
||||
}
|
||||
|
||||
if (n->first) {
|
||||
sb8_printf(sb, "{");
|
||||
sb->indent += 1;
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
sb8_serial_ast(sb, it);
|
||||
}
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "}");
|
||||
}
|
||||
}
|
||||
|
||||
s8_t s8_serial_ast(ma_arena_t *arena, ast_t *n) {
|
||||
sb8_t *sb = sb8_serial_begin(arena);
|
||||
sb8_serial_ast(sb, n);
|
||||
return sb8_serial_end(sb);
|
||||
}
|
||||
|
||||
s8_t s8_serial_ast_to_code(ma_arena_t *arena, ast_t *n);
|
||||
void sb8_serial_ast_to_code(sb8_t *sb, ast_t *n) {
|
||||
if (n->flags & set_bit(ast_flag_enum)) {
|
||||
sb8_printf(sb, "typedef enum {");
|
||||
sb->indent += 1;
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
sb8_stmtf(sb, "%S,", it->string);
|
||||
}
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "} %S;", n->string);
|
||||
} else if (n->flags & set_bit(ast_flag_struct)) {
|
||||
sb8_stmtf(sb, "typedef struct %S %S;", n->string, n->string);
|
||||
sb8_stmtf(sb, "struct %S {", n->string);
|
||||
sb->indent += 1;
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
s8_t name = it->string;
|
||||
s8_t type = s8_ast_to_cvar(sb->arena, it->first, &name);
|
||||
sb8_stmtf(sb, "%S %S;", type, name);
|
||||
}
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "};");
|
||||
|
||||
} else {
|
||||
if (n->flags & set_bit(ast_flag_string)) {
|
||||
sb8_printf(sb, "/*%S*/", n->string);
|
||||
} else {
|
||||
sb8_printf(sb, "/*null*/");
|
||||
}
|
||||
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
sb8_indent(sb);
|
||||
sb8_serial_ast_to_code(sb, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s8_t s8_serial_ast_to_code(ma_arena_t *arena, ast_t *n) {
|
||||
sb8_t *sb = sb8_serial_begin(arena);
|
||||
sb8_serial_ast_to_code(sb, n);
|
||||
s8_t result = sb8_serial_end(sb);
|
||||
return result;
|
||||
}
|
||||
|
||||
s8_t s8_serial_ast_type_to_type_info(ma_arena_t *arena, ast_t *n) {
|
||||
if (n->flags & set_bit(ast_flag_type_name)) {
|
||||
return s8_fmt(arena, "type__%S", n->string);
|
||||
} else if (n->flags & set_bit(ast_flag_type_pointer)) {
|
||||
s8_t base = s8_serial_ast_type_to_type_info(arena, n->first);
|
||||
return s8_fmt(arena, "(type_t){type_kind_pointer, s8_const_lit(\"%S\"), sizeof(void *), .base = &%S}", n->string, base);
|
||||
} else if (n->flags & set_bit(ast_flag_type_array)) {
|
||||
s8_t base = s8_serial_ast_type_to_type_info(arena, n->first);
|
||||
return s8_fmt(arena, "(type_t){type_kind_array, s8_const_lit(\"%S\"), sizeof(%S), %d, .base = &%S}", n->string, n->string, (int)n->integer, base);
|
||||
} else {
|
||||
lex_panicf(n->pos, "expected type");
|
||||
}
|
||||
return (s8_t){0};
|
||||
}
|
||||
|
||||
void sb8_serial_ast_to_type_info(sb8_t *sb, ast_t *n) {
|
||||
if (n->flags & set_bit(ast_flag_enum)) {
|
||||
sb8_printf(sb, "type_t type__%S = { type_kind_enum, s8_const_lit(\"%S\"), sizeof(%S),", n->string, n->string, n->string);
|
||||
sb->indent += 1;
|
||||
|
||||
sb8_stmtf(sb, ".members = (type_member_t[]){");
|
||||
sb->indent += 1;
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
sb8_stmtf(sb, "{.name = s8_const_lit(\"%S\"), .value = %S},", it->string, it->string);
|
||||
}
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "},");
|
||||
|
||||
sb8_stmtf(sb, ".count = %d,", n->len);
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "};");
|
||||
} else if (n->flags & set_bit(ast_flag_struct)) {
|
||||
sb8_printf(sb, "type_t type__%S = { type_kind_struct, s8_const_lit(\"%S\"), sizeof(%S),", n->string, n->string, n->string);
|
||||
sb->indent += 1;
|
||||
|
||||
sb8_stmtf(sb, ".members = (type_member_t[]){");
|
||||
sb->indent += 1;
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
s8_t name = it->string;
|
||||
s8_t type_info = s8_serial_ast_type_to_type_info(sb->arena, it->first);
|
||||
sb8_stmtf(sb, "{.name = s8_const_lit(\"%S\"), .type = &%S, .offset = offsetof(%S, %S)},", name, type_info, n->string, name);
|
||||
}
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "},");
|
||||
|
||||
sb8_stmtf(sb, ".count = %d,", n->len);
|
||||
sb->indent -= 1;
|
||||
sb8_stmtf(sb, "};");
|
||||
} else {
|
||||
if (n->flags & set_bit(ast_flag_string)) {
|
||||
sb8_printf(sb, "/*%S*/", n->string);
|
||||
} else {
|
||||
sb8_printf(sb, "/*null*/");
|
||||
}
|
||||
|
||||
for (ast_t *it = n->first; it; it = it->next) {
|
||||
sb8_indent(sb);
|
||||
sb8_serial_ast_to_type_info(sb, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s8_t s8_serial_ast_to_type_info(ma_arena_t *arena, ast_t *n) {
|
||||
sb8_t *sb = sb8_serial_begin(arena);
|
||||
sb8_serial_ast_to_type_info(sb, n);
|
||||
s8_t result = sb8_serial_end(sb);
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
int row_findi(ast_t *row, char *name) {
|
||||
s8_t s = s8_from_char(name);
|
||||
int i = 0;
|
||||
for (ast_t *col = row->first; col; col = col->next) {
|
||||
if (s8_equal(col->string, s)) {
|
||||
return i;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_t *row_geti(ast_t *row, int idx) {
|
||||
if (idx == -1) return NULL;
|
||||
|
||||
int i = 0;
|
||||
for (ast_t *col = row->first; col; col = col->next, i+=1) {
|
||||
if (i == idx) return col;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void sb8_serial_table_enum(sb8_t *c, sb8_t *h, ast_t *table, s8_t decl) {
|
||||
int name_idx = row_findi(table->first, "name");
|
||||
int value_idx = row_findi(table->first, "value");
|
||||
|
||||
s8_t name_t = s8_fmt(c->arena, "%S_t", decl);
|
||||
|
||||
sb8_printf(h, "typedef enum {\n");
|
||||
for (ast_t *row = table->first->next; row; row = row->next) {
|
||||
s8_t name = row_geti(row, name_idx)->string;
|
||||
ast_t *value = row_geti(row, value_idx);
|
||||
sb8_printf(h, "%S_%S", decl, name);
|
||||
if (value) sb8_printf(h, " = %S", value->string);
|
||||
sb8_printf(h, ",\n");
|
||||
}
|
||||
sb8_printf(h, "%S_count,\n", decl);
|
||||
sb8_printf(h, "} %S;\n", name_t);
|
||||
|
||||
sb8_stmtf(c, "type_t type__%S = { type_kind_enum, s8_const_lit(\"%S\"), sizeof(%S),", name_t, name_t, name_t);
|
||||
c->indent += 1;
|
||||
|
||||
sb8_stmtf(c, ".members = (type_member_t[]){");
|
||||
c->indent += 1;
|
||||
int item_count = 0;
|
||||
for (ast_t *row = table->first->next; row; row = row->next) {
|
||||
s8_t name = row_geti(row, name_idx)->string;
|
||||
ast_t *value = row_geti(row, value_idx);
|
||||
sb8_stmtf(c, "{.name = s8_const_lit(\"%S_%S\"), .value = %S_%S},", decl, name, decl, name);
|
||||
item_count += 1;
|
||||
}
|
||||
c->indent -= 1;
|
||||
sb8_stmtf(c, "},");
|
||||
|
||||
sb8_stmtf(c, ".count = %d,", item_count);
|
||||
c->indent -= 1;
|
||||
sb8_stmtf(c, "};");
|
||||
}
|
||||
|
||||
#define gen_c(arena) _gen_filename(arena, s8_lit(__FILE__), s8_lit("c"))
|
||||
#define gen_h(arena) _gen_filename(arena, s8_lit(__FILE__), s8_lit("h"))
|
||||
s8_t _gen_filename(ma_arena_t *arena, s8_t lit_file, s8_t ext) {
|
||||
s8_t file_noext = s8_chop_last_period(s8_chop_last_period(lit_file));
|
||||
s8_t file = s8_fmt(arena, "%S.gen.%S", file_noext, ext);
|
||||
return file;
|
||||
}
|
||||
3
src/wasm_app/debug.c
Normal file
3
src/wasm_app/debug.c
Normal file
@@ -0,0 +1,3 @@
|
||||
void dr2f64(r2f64_t r) {
|
||||
debugf("[%f %f %f %f]", r.x0, r.y0, r.x1, r.y1);
|
||||
}
|
||||
19
src/wasm_app/main.c
Normal file
19
src/wasm_app/main.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core.c"
|
||||
#include "app/app.h"
|
||||
#include "app/app.c"
|
||||
// #include "debug.c"
|
||||
// #include "ui2.c"
|
||||
|
||||
void on_update() {
|
||||
// r2f64_t rect = {0, 0, 200, 200};
|
||||
// draw_rect(rect, (v4f32_t){0, 0, 0, 1});
|
||||
// draw_textf((v2f64_t){10 + i, 100}, "time = %f, dt = %f", time_g / 1000, dt_g);
|
||||
|
||||
// f64_mod(4, 2);
|
||||
|
||||
// i += 1;
|
||||
// if (i > 200) i = 0;
|
||||
|
||||
// ui_demo();
|
||||
}
|
||||
280
src/wasm_app/ui.c
Normal file
280
src/wasm_app/ui.c
Normal file
@@ -0,0 +1,280 @@
|
||||
#if 0
|
||||
typedef struct ui_id_t ui_id_t;
|
||||
struct ui_id_t {
|
||||
u64 value;
|
||||
};
|
||||
ui_id_t ui_string_to_id(const char *string) { // FNV HASH (1a?)
|
||||
u8 *data8 = (u8 *)string;
|
||||
u64 hash = (u64)14695981039346656037ULL;
|
||||
for (u64 i = 0; data8[i]; i++) {
|
||||
hash = hash ^ (u64)(data8[i]);
|
||||
hash = hash * (u64)1099511628211ULL;
|
||||
}
|
||||
return (ui_id_t){ .value = hash };
|
||||
}
|
||||
#define ui_location_id() ui_string_to_id(FILE_AND_LINE)
|
||||
ui_id_t ui_element_pressed;
|
||||
|
||||
typedef enum {
|
||||
cut_left,
|
||||
cut_right,
|
||||
cut_bottom,
|
||||
cut_top,
|
||||
} cut_t;
|
||||
|
||||
typedef struct rcut_t rcut_t;
|
||||
struct rcut_t {
|
||||
r2f64_t *rect;
|
||||
cut_t cut;
|
||||
};
|
||||
|
||||
rcut_t rcut(r2f64_t *rect, cut_t cut) {
|
||||
return (rcut_t){rect, cut};
|
||||
}
|
||||
|
||||
r2f64_t ui_cut(r2f64_t *rect, f64 value, cut_t cut) {
|
||||
if (cut == cut_left) return r2f64_cut_left(rect, value);
|
||||
else if (cut == cut_right) return r2f64_cut_right(rect, value);
|
||||
else if (cut == cut_bottom) return r2f64_cut_bottom(rect, value);
|
||||
else if (cut == cut_top) return r2f64_cut_top(rect, value);
|
||||
else assert(!"invalid codepath");
|
||||
return (r2f64_t){0};
|
||||
}
|
||||
|
||||
r2f64_t ui_cut2(rcut_t rc, f64 x, f64 y) {
|
||||
f64 cut_value = 0;
|
||||
if (rc.cut == cut_left || rc.cut == cut_right) cut_value = x;
|
||||
else cut_value = y;
|
||||
r2f64_t result = ui_cut(rc.rect, cut_value, rc.cut);
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct ui_flags_t ui_flags_t;
|
||||
struct ui_flags_t {
|
||||
b32 draw_text : 1;
|
||||
b32 text_centered : 1;
|
||||
b32 text_y_centered;
|
||||
|
||||
b32 draw_rect : 1;
|
||||
|
||||
b32 checkable : 1;
|
||||
b32 draw_checkbox : 1;
|
||||
b32 draw_checked;
|
||||
|
||||
b32 clickable : 1;
|
||||
b32 slider : 1;
|
||||
};
|
||||
|
||||
typedef struct ui_signal_t ui_signal_t;
|
||||
struct ui_signal_t {
|
||||
b32 pressed : 1;
|
||||
b32 overlapping : 1;
|
||||
b32 interacting : 1;
|
||||
};
|
||||
|
||||
// TODO(Karol): Don't use inputs as flags! Use only flags.
|
||||
typedef struct ui_input_t ui_input_t;
|
||||
struct ui_input_t {
|
||||
char *title;
|
||||
b32 *value_b32;
|
||||
f64 *value_f64;
|
||||
ui_id_t id;
|
||||
};
|
||||
|
||||
v2f64_t style_padding = {50, 10};
|
||||
ui_signal_t ui_widget(rcut_t rc, ui_input_t input, ui_flags_t flags) {
|
||||
// Calculate rectangles
|
||||
r2f64_t total_rect = {0};
|
||||
r2f64_t rect = {0};
|
||||
r2f64_t checkbox_rect = {0};
|
||||
{
|
||||
v2f64_t size = style_padding;
|
||||
f64 font_height = get_font_height();
|
||||
|
||||
size.y += font_height;
|
||||
if (flags.draw_text) {
|
||||
size.x += measure_text(input.title);
|
||||
}
|
||||
|
||||
total_rect = ui_cut2(rc, size.x, size.y);
|
||||
rect = total_rect;
|
||||
if (flags.draw_checkbox) {
|
||||
checkbox_rect = r2f64_cut_left(&rect, size.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Solve interactions
|
||||
ui_signal_t result = {0};
|
||||
{
|
||||
if (r2f64_contains(total_rect, mouse_pos_g)) {
|
||||
result.overlapping = true;
|
||||
if (mouse_button_press_g[app_mouse_button_left]) {
|
||||
ui_element_pressed = input.id;
|
||||
result.pressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ui_element_pressed.value == input.id.value && mouse_button_down_g[app_mouse_button_left]) {
|
||||
result.interacting = true;
|
||||
}
|
||||
|
||||
if (flags.checkable && result.pressed) {
|
||||
*input.value_b32 = !*input.value_b32;
|
||||
}
|
||||
|
||||
if (flags.slider && result.interacting) {
|
||||
f64 mouse_pos = mouse_pos_g.x;
|
||||
v2f64_t rect_size = r2f64_get_size(rect);
|
||||
*input.value_f64 = (mouse_pos - rect.min.x) / rect_size.x;
|
||||
*input.value_f64 = CLAMP(*input.value_f64, 0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
clip(total_rect);
|
||||
|
||||
// Draw
|
||||
if (flags.draw_rect) {
|
||||
v4f32_t color = primary_color_global;
|
||||
if (flags.clickable) {
|
||||
if (result.overlapping) color = secondary_color_global;
|
||||
if (flags.draw_checked && input.value_b32[0]) color = accent1_color_global;
|
||||
}
|
||||
draw_rect(rect, color);
|
||||
}
|
||||
|
||||
if (flags.slider) {
|
||||
v2f64_t rect_size = r2f64_get_size(rect);
|
||||
r2f64_t rect_split = r2f64_get_left(&rect, rect_size.x * input.value_f64[0]);
|
||||
draw_rect(rect_split, accent1_color_global);
|
||||
}
|
||||
|
||||
if (flags.draw_text) {
|
||||
v2f64_t text_pos = rect.min;
|
||||
f64 text_width = measure_text(input.title);
|
||||
f64 font_height = get_font_height();
|
||||
|
||||
v2f64_t rect_size = r2f64_get_size(rect);
|
||||
v2f64_t offset_to_center = {(rect_size.x - text_width) / 2, (rect_size.y - font_height) / 2};
|
||||
if (flags.text_y_centered) {
|
||||
text_pos.y += offset_to_center.y;
|
||||
}
|
||||
if (flags.text_centered) {
|
||||
text_pos = v2f64_add(text_pos, offset_to_center);
|
||||
}
|
||||
draw_text(text_pos, input.title);
|
||||
}
|
||||
|
||||
if (flags.draw_checkbox) {
|
||||
v4f32_t color = accent1_color_global;
|
||||
if (flags.checkable) {
|
||||
if (input.value_b32[0]) {
|
||||
color = accent2_color_global;
|
||||
}
|
||||
}
|
||||
if ((flags.checkable || flags.clickable) && result.overlapping) {
|
||||
color = v4f32_lerp(color, v4f32(1,1,1,1), 0.25);
|
||||
}
|
||||
draw_rect(checkbox_rect, color);
|
||||
}
|
||||
|
||||
clip(r2f64(-1000, -1000, 1000000, 1000000));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
b32 ui_button(rcut_t rc, char *title) {
|
||||
ui_signal_t sig = ui_widget(rc, (ui_input_t){.title = title}, (ui_flags_t){.draw_text = true, .text_centered = true, .draw_rect = true, .clickable = true});
|
||||
return sig.pressed;
|
||||
}
|
||||
|
||||
b32 ui_checked_button(b32 *value, rcut_t rc, char *title) {
|
||||
ui_widget(rc, (ui_input_t){.title = title, .value_b32 = value}, (ui_flags_t){.draw_rect = true, .draw_text = true, .text_centered = true, .clickable = true, .checkable = true, .draw_checked = true});
|
||||
return *value;
|
||||
}
|
||||
|
||||
b32 ui_checkbox(rcut_t rc, b32 *value, char *title) {
|
||||
ui_widget(rc, (ui_input_t){.value_b32 = value, .title = title}, (ui_flags_t){.draw_checkbox = true, .draw_text = true, .text_y_centered = true, .draw_rect = true, .checkable = true});
|
||||
return *value;
|
||||
}
|
||||
|
||||
void ui_label(rcut_t rc, char *title) {
|
||||
ui_widget(rc, (ui_input_t){.title = title}, (ui_flags_t){.draw_text = true, .text_centered = true, .draw_rect = true});
|
||||
}
|
||||
|
||||
void ui_slider(rcut_t rc, ui_id_t id, f64 *value, char *title) {
|
||||
ui_widget(rc, (ui_input_t){.title = title, .value_f64 = value, .id = id}, (ui_flags_t){.draw_text = true, .text_centered = true, .slider = true, .draw_rect = true, .clickable = true});
|
||||
}
|
||||
|
||||
void ui_begin_frame(void) {
|
||||
if (mouse_button_release_g[app_mouse_button_left]) {
|
||||
ui_element_pressed = (ui_id_t){0};
|
||||
}
|
||||
}
|
||||
|
||||
void ui_demo(void) {
|
||||
ui_begin_frame();
|
||||
f64 font_height = get_font_height();
|
||||
r2f64_t window_rect = r2f64(0, 0, window_size_g.x, window_size_g.y);
|
||||
{
|
||||
draw_rect(window_rect, while_color_global);
|
||||
}
|
||||
|
||||
|
||||
static b32 panel_open = true;
|
||||
static b32 cool_rect = false;
|
||||
{
|
||||
r2f64_t top_rect = r2f64_cut_top(&window_rect, font_height*2);
|
||||
draw_rect(top_rect, primary_color_global);
|
||||
|
||||
if (ui_checked_button(&cool_rect, rcut(&top_rect, cut_left), "file")) {
|
||||
draw_rect(window_rect, v4f32(0.5, 0.1, 0.1, 1.0));
|
||||
}
|
||||
if (ui_button(rcut(&top_rect, cut_left), "edit")) {}
|
||||
if (ui_button(rcut(&top_rect, cut_left), "view")) {}
|
||||
if (ui_checked_button(&panel_open, rcut(&top_rect, cut_left), "open panel")) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (panel_open) {
|
||||
r2f64_t panel_rect = r2f64_cut_left(&window_rect, measure_text("1234567890")*2);
|
||||
{
|
||||
v4f32_t color = primary_color_global; color.a = 0.3f;
|
||||
draw_rect(panel_rect, color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static f64 value = 0.2f;
|
||||
ui_slider(rcut(&panel_rect, cut_top), ui_location_id(), &value, "value");
|
||||
|
||||
ui_widget(rcut(&panel_rect, cut_top), (ui_input_t){.title = "non centered label"}, (ui_flags_t){.draw_rect = true, .draw_text = true});
|
||||
|
||||
static b32 checkbox_memes;
|
||||
ui_checkbox(rcut(&panel_rect, cut_top), &checkbox_memes, "checkbox");
|
||||
|
||||
|
||||
// TODO(Krzosa): Draw arrows / triangles
|
||||
{
|
||||
f64 font_height = get_font_height();
|
||||
f64 cut_size = font_height + style_padding.y;
|
||||
r2f64_t rect = r2f64_cut_top(&panel_rect, cut_size);
|
||||
|
||||
static int counter;
|
||||
|
||||
if (ui_widget(rcut(&rect, cut_left), (ui_input_t){0}, (ui_flags_t){.draw_checkbox = true, .clickable = true}).pressed) {
|
||||
counter -= 1;
|
||||
}
|
||||
char buff[256];
|
||||
stbsp_snprintf(buff, sizeof(buff), "counter: %d", counter);
|
||||
ui_label(rcut(&rect, cut_left), buff);
|
||||
if (ui_widget(rcut(&rect, cut_left), (ui_input_t){0}, (ui_flags_t){.draw_checkbox = true, .clickable = true}).pressed) {
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
241
src/wasm_app/ui2.c
Normal file
241
src/wasm_app/ui2.c
Normal file
@@ -0,0 +1,241 @@
|
||||
v2f64_t ui_calc_text_pos(r2f64_t rect, char *title) {
|
||||
f64 font_height = get_font_height();
|
||||
f64 text_width = measure_text(title);
|
||||
|
||||
v2f64_t text_pos = rect.min;
|
||||
{
|
||||
v2f64_t rect_size = r2f64_get_size(rect);
|
||||
v2f64_t offset_to_center = {(rect_size.x - text_width) / 2, (rect_size.y - font_height) / 2};
|
||||
text_pos = v2f64_add(text_pos, offset_to_center);
|
||||
}
|
||||
|
||||
return text_pos;
|
||||
}
|
||||
|
||||
typedef struct ui_signal_t ui_signal_t;
|
||||
struct ui_signal_t {
|
||||
b8 pressed;
|
||||
b8 overlapping;
|
||||
};
|
||||
|
||||
ui_signal_t ui_interact(r2f64_t rect) {
|
||||
ui_signal_t sig = {0};
|
||||
if (r2f64_contains(rect, mouse_pos_g)) {
|
||||
sig.overlapping = true;
|
||||
if (mouse_button_press_g[app_mouse_button_left]) {
|
||||
sig.pressed = true;
|
||||
}
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
b32 ui_button(r2f64_t rect, char *title) {
|
||||
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
||||
ui_signal_t sig = ui_interact(rect);
|
||||
|
||||
v4f32_t rect_color = secondary_color_global;
|
||||
v4f32_t text_color = black_color_global;
|
||||
if (sig.overlapping) {
|
||||
rect_color = primary_color_global;
|
||||
}
|
||||
|
||||
clip(rect);
|
||||
draw_rect(rect, rect_color);
|
||||
draw_text(text_pos, text_color, title, str_len(title));
|
||||
clip(r2f64(-1000, -1000, 1000000, 1000000));
|
||||
|
||||
return sig.pressed;
|
||||
}
|
||||
|
||||
b32 ui_checkbox(r2f64_t rect, b32 *value, char *title) {
|
||||
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
||||
ui_signal_t sig = ui_interact(rect);
|
||||
if (sig.pressed) *value = !*value;
|
||||
|
||||
v4f32_t rect_color = secondary_color_global;
|
||||
v4f32_t text_color = black_color_global;
|
||||
if (sig.overlapping) {
|
||||
rect_color = primary_color_global;
|
||||
}
|
||||
if (*value) {
|
||||
rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.5);
|
||||
}
|
||||
|
||||
clip(rect);
|
||||
draw_rect(rect, rect_color);
|
||||
draw_text(text_pos, text_color, title, str_len(title));
|
||||
clip(r2f64(-1000, -1000, 1000000, 1000000));
|
||||
|
||||
return *value;
|
||||
}
|
||||
|
||||
typedef struct ui_id_t ui_id_t;
|
||||
struct ui_id_t { u64 value; };
|
||||
|
||||
ui_id_t ui_string_to_id(const char *string, i32 len) { // FNV HASH (1a?)
|
||||
u8 *data8 = (u8 *)string;
|
||||
u64 hash = (u64)14695981039346656037ULL;
|
||||
for (u64 i = 0; i < len; i++) {
|
||||
hash = hash ^ (u64)(data8[i]);
|
||||
hash = hash * (u64)1099511628211ULL;
|
||||
}
|
||||
return (ui_id_t){ .value = hash };
|
||||
}
|
||||
#define ui_location_id() ui_string_to_id(FILE_AND_LINE, sizeof(FILE_AND_LINE) - 1)
|
||||
ui_id_t ui_active_element = {0};
|
||||
|
||||
void ui_slider(r2f64_t rect, ui_id_t id, f64 *value, char *title) {
|
||||
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
||||
ui_signal_t sig = ui_interact(rect);
|
||||
b32 interacting = false;
|
||||
{
|
||||
if (sig.pressed) {
|
||||
ui_active_element = id;
|
||||
}
|
||||
if (id.value == ui_active_element.value && mouse_button_down_g[app_mouse_button_left]) {
|
||||
interacting = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (interacting) {
|
||||
f64 mouse_pos = mouse_pos_g.x;
|
||||
v2f64_t rect_size = r2f64_get_size(rect);
|
||||
*value = (mouse_pos - rect.min.x) / rect_size.x;
|
||||
*value = CLAMP(*value, 0, 1.0);
|
||||
}
|
||||
|
||||
v2f64_t rect_size = r2f64_get_size(rect);
|
||||
r2f64_t slider_rect = r2f64_get_left(&rect, rect_size.x * value[0]);
|
||||
|
||||
v4f32_t rect_color = secondary_color_global;
|
||||
if (sig.overlapping) rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.2);
|
||||
v4f32_t slider_color = accent2_color_global;
|
||||
if (sig.overlapping) slider_color = v4f32_lerp(slider_color, accent2_color_global, 0.2);
|
||||
v4f32_t text_color = black_color_global;
|
||||
|
||||
clip(rect);
|
||||
draw_rect(rect, rect_color);
|
||||
draw_rect(slider_rect, slider_color);
|
||||
draw_text(text_pos, text_color, title, str_len(title));
|
||||
clip(r2f64(-1000, -1000, 1000000, 1000000));
|
||||
}
|
||||
|
||||
typedef struct ui_input_state ui_input_state;
|
||||
struct ui_input_state {
|
||||
char *buff;
|
||||
int len;
|
||||
int cap;
|
||||
|
||||
int cursor;
|
||||
};
|
||||
|
||||
|
||||
void ui_input_text(r2f64_t rect, ui_input_state *in) {
|
||||
v2f64_t tp = ui_calc_text_pos(rect, "a");
|
||||
v2f64_t text_pos = {rect.min.x, tp.y};
|
||||
ui_signal_t sig = ui_interact(rect);
|
||||
|
||||
v4f32_t rect_color = secondary_color_global;
|
||||
if (r2f64_contains(rect, mouse_pos_g)) {
|
||||
if (key_press_g == app_key_right) in->cursor += 1;
|
||||
if (key_press_g == app_key_left) in->cursor -= 1;
|
||||
if (key_press_g == app_key_backspace) {
|
||||
|
||||
debugf("a");
|
||||
}
|
||||
in->cursor = CLAMP(in->cursor, 0, in->len);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (sig.overlapping) rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.2);
|
||||
}
|
||||
|
||||
|
||||
clip(rect);
|
||||
draw_rect(rect, rect_color);
|
||||
draw_text(text_pos, black_color_global, in->buff, in->len);
|
||||
clip(r2f64(-1000, -1000, 1000000, 1000000));
|
||||
|
||||
f64 cx = measure_text_ex(in->buff, in->cursor);
|
||||
v2f64_t cursor_pos = {text_pos.x + cx, text_pos.y};
|
||||
draw_rect(r2f64_center_halfdim(cursor_pos, v2f64(1, 6)), black_color_global);
|
||||
}
|
||||
|
||||
void ui_demo(void) {
|
||||
if (mouse_button_release_g[app_mouse_button_left]) {
|
||||
ui_active_element = (ui_id_t){0};
|
||||
}
|
||||
|
||||
r2f64_t window_rect = (r2f64_t){(v2f64_t){0}, window_size_g};
|
||||
r2f64_t top_bar_rect = r2f64_cut_top(&window_rect, get_font_height() + 20);
|
||||
draw_rect(window_rect, primary_color_global);
|
||||
|
||||
f64 padding = 50;
|
||||
draw_rect(top_bar_rect, secondary_color_global);
|
||||
|
||||
static b32 open_file_panel;
|
||||
f64 open_file_panel_xsize = 0;
|
||||
{
|
||||
// ▼▲▶◀
|
||||
char *title = "▶ file";
|
||||
if (open_file_panel) title = "▼ file";
|
||||
open_file_panel_xsize = measure_text(title) + padding*2;
|
||||
r2f64_t rect = r2f64_cut_left(&top_bar_rect, open_file_panel_xsize);
|
||||
if (ui_checkbox(rect, &open_file_panel, title)) {
|
||||
}
|
||||
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
||||
draw_rect(gap_rect, black_color_global);
|
||||
}
|
||||
|
||||
if (open_file_panel) {
|
||||
f64 item_count = 20;
|
||||
f64 item_size = get_font_height() + 20;
|
||||
r2f64_t panel_rect = r2f64_get_top(&window_rect, item_count * item_size);
|
||||
panel_rect = r2f64_get_left(&panel_rect, open_file_panel_xsize);
|
||||
|
||||
{
|
||||
static f64 slider_value;
|
||||
char buff[64];
|
||||
stbsp_snprintf(buff, sizeof(buff), "%f", slider_value);
|
||||
r2f64_t rect = r2f64_cut_top(&panel_rect, item_size);
|
||||
ui_slider(rect, ui_location_id(), &slider_value, buff);
|
||||
}
|
||||
|
||||
{
|
||||
static char buff[64];
|
||||
static ui_input_state input;
|
||||
if (input.buff == NULL) {
|
||||
input.buff = buff;
|
||||
input.cap = sizeof(buff);
|
||||
}
|
||||
|
||||
r2f64_t rect = r2f64_cut_top(&panel_rect, item_size);
|
||||
ui_input_text(rect, &input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
char *title = "edit";
|
||||
r2f64_t rect = r2f64_cut_left(&top_bar_rect, measure_text(title) + padding*2);
|
||||
if (ui_button(rect, title)) {
|
||||
}
|
||||
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
||||
draw_rect(gap_rect, black_color_global);
|
||||
}
|
||||
|
||||
{
|
||||
char *title = "view";
|
||||
r2f64_t rect = r2f64_cut_left(&top_bar_rect, measure_text(title) + padding*2);
|
||||
if (ui_button(rect, title)) {
|
||||
}
|
||||
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
||||
draw_rect(gap_rect, black_color_global);
|
||||
}
|
||||
|
||||
if (input_text_len_g) {
|
||||
debugf("%.*s", input_text_len_g, input_text_g);
|
||||
}
|
||||
}
|
||||
23
todo.txt
Normal file
23
todo.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
platform
|
||||
more then 2 platform abstraction
|
||||
app platform game
|
||||
in the future event based?
|
||||
or maybe hybrid?
|
||||
os functionality
|
||||
gfx
|
||||
w32
|
||||
canvas
|
||||
dll hot reload
|
||||
wasm:
|
||||
input and key down (use KeyA KeyB etc.)
|
||||
|
||||
type_info:
|
||||
serialize
|
||||
deserialize
|
||||
|
||||
|
||||
app
|
||||
loop styles:
|
||||
infinite loop update -> gather all events -> loop event and update -> render (vsync wait) + block when no events
|
||||
update (render) + other events (don't render) + block when no events
|
||||
|
||||
Reference in New Issue
Block a user