aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-09-05 18:00:35 +0200
committerLaytan Laats <laytanlaats@hotmail.com>2024-09-09 18:49:13 +0200
commit5ae27c6ebce707aa6a153cf01ab658c6b1cbdabf (patch)
treee0794aad3550de7a4ca57e453cd55ec4730a47ac /core
parentd783bca2979db5955885ee6b2a06f20f8a847582 (diff)
wasm: support more vendor libraries
Adds support for: - box2d - cgltf - stb image - stb rect pack
Diffstat (limited to 'core')
-rw-r--r--core/bytes/bytes.odin4
-rw-r--r--core/mem/allocators.odin78
-rw-r--r--core/os/os_js.odin89
-rw-r--r--core/strings/strings.odin14
4 files changed, 106 insertions, 79 deletions
diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin
index 45eb44307..c0d25bcce 100644
--- a/core/bytes/bytes.odin
+++ b/core/bytes/bytes.odin
@@ -334,7 +334,7 @@ Inputs:
Returns:
- index: The index of the byte `c`, or -1 if it was not found.
*/
-index_byte :: proc(s: []byte, c: byte) -> (index: int) #no_bounds_check {
+index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds_check {
i, l := 0, len(s)
// Guard against small strings. On modern systems, it is ALWAYS
@@ -469,7 +469,7 @@ Inputs:
Returns:
- index: The index of the byte `c`, or -1 if it was not found.
*/
-last_index_byte :: proc(s: []byte, c: byte) -> int #no_bounds_check {
+last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_check {
i := len(s)
// Guard against small strings. On modern systems, it is ALWAYS
diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin
index a5b93ad05..cbed5fbe3 100644
--- a/core/mem/allocators.odin
+++ b/core/mem/allocators.odin
@@ -1137,3 +1137,81 @@ buddy_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
return nil, nil
}
+
+// An allocator that keeps track of allocation sizes and passes it along to resizes.
+// This is useful if you are using a library that needs an equivalent of `realloc` but want to use
+// the Odin allocator interface.
+//
+// You want to wrap your allocator into this one if you are trying to use any allocator that relies
+// on the old size to work.
+//
+// The overhead of this allocator is an extra max(alignment, size_of(Header)) bytes allocated for each allocation, these bytes are
+// used to store the size and original pointer.
+Compat_Allocator :: struct {
+ parent: Allocator,
+}
+
+compat_allocator_init :: proc(rra: ^Compat_Allocator, allocator := context.allocator) {
+ rra.parent = allocator
+}
+
+compat_allocator :: proc(rra: ^Compat_Allocator) -> Allocator {
+ return Allocator{
+ data = rra,
+ procedure = compat_allocator_proc,
+ }
+}
+
+compat_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
+ size, alignment: int,
+ old_memory: rawptr, old_size: int,
+ location := #caller_location) -> (data: []byte, err: Allocator_Error) {
+ size, old_size := size, old_size
+
+ Header :: struct {
+ size: int,
+ ptr: rawptr,
+ }
+
+ rra := (^Compat_Allocator)(allocator_data)
+ switch mode {
+ case .Alloc, .Alloc_Non_Zeroed:
+ a := max(alignment, size_of(Header))
+ size += a
+ assert(size >= 0, "overflow")
+
+ allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) or_return
+ #no_bounds_check data = allocation[a:]
+
+ ([^]Header)(raw_data(data))[-1] = {
+ size = size,
+ ptr = raw_data(allocation),
+ }
+ return
+
+ case .Free:
+ header := ([^]Header)(old_memory)[-1]
+ return rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location)
+
+ case .Resize, .Resize_Non_Zeroed:
+ header := ([^]Header)(old_memory)[-1]
+
+ a := max(alignment, size_of(header))
+ size += a
+ assert(size >= 0, "overflow")
+
+ allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location) or_return
+ #no_bounds_check data = allocation[a:]
+
+ ([^]Header)(raw_data(data))[-1] = {
+ size = size,
+ ptr = raw_data(allocation),
+ }
+ return
+
+ case .Free_All, .Query_Info, .Query_Features:
+ return rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location)
+
+ case: unreachable()
+ }
+}
diff --git a/core/os/os_js.odin b/core/os/os_js.odin
index eb434c727..02821c3e3 100644
--- a/core/os/os_js.odin
+++ b/core/os/os_js.odin
@@ -3,33 +3,38 @@ package os
import "base:runtime"
+foreign import "odin_env"
+
@(require_results)
is_path_separator :: proc(c: byte) -> bool {
return c == '/' || c == '\\'
}
+Handle :: distinct u32
+
+stdout: Handle = 1
+stderr: Handle = 2
+
@(require_results)
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) {
unimplemented("core:os procedure not supported on JS target")
}
close :: proc(fd: Handle) -> Error {
- unimplemented("core:os procedure not supported on JS target")
+ return nil
}
flush :: proc(fd: Handle) -> (err: Error) {
- unimplemented("core:os procedure not supported on JS target")
+ return nil
}
-
-
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
- unimplemented("core:os procedure not supported on JS target")
-}
-
-@(private="file")
-read_console :: proc(handle: Handle, b: []byte) -> (n: int, err: Error) {
- unimplemented("core:os procedure not supported on JS target")
+ foreign odin_env {
+ @(link_name="write")
+ _write :: proc "contextless" (fd: Handle, p: []byte) ---
+ }
+ _write(fd, data)
+ return len(data), nil
}
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
@@ -45,19 +50,6 @@ file_size :: proc(fd: Handle) -> (i64, Error) {
unimplemented("core:os procedure not supported on JS target")
}
-
-@(private)
-MAX_RW :: 1<<30
-
-@(private)
-pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
- unimplemented("core:os procedure not supported on JS target")
-}
-@(private)
-pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Error) {
- unimplemented("core:os procedure not supported on JS target")
-}
-
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
@@ -65,16 +57,6 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error)
unimplemented("core:os procedure not supported on JS target")
}
-stdout: Handle = 1
-stderr: Handle = 2
-
-@(require_results)
-get_std_handle :: proc "contextless" (h: uint) -> Handle {
- context = runtime.default_context()
- unimplemented("core:os procedure not supported on JS target")
-}
-
-
@(require_results)
exists :: proc(path: string) -> bool {
unimplemented("core:os procedure not supported on JS target")
@@ -90,9 +72,6 @@ is_dir :: proc(path: string) -> bool {
unimplemented("core:os procedure not supported on JS target")
}
-// NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName
-//@private cwd_lock := win32.SRWLOCK{} // zero is initialized
-
@(require_results)
get_current_directory :: proc(allocator := context.allocator) -> string {
unimplemented("core:os procedure not supported on JS target")
@@ -118,18 +97,6 @@ remove_directory :: proc(path: string) -> (err: Error) {
}
-
-@(private, require_results)
-is_abs :: proc(path: string) -> bool {
- unimplemented("core:os procedure not supported on JS target")
-}
-
-@(private, require_results)
-fix_long_path :: proc(path: string) -> string {
- unimplemented("core:os procedure not supported on JS target")
-}
-
-
link :: proc(old_name, new_name: string) -> (err: Error) {
unimplemented("core:os procedure not supported on JS target")
}
@@ -169,7 +136,6 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
unimplemented("core:os procedure not supported on JS target")
}
-Handle :: distinct uintptr
File_Time :: distinct u64
_Platform_Error :: enum i32 {
@@ -254,12 +220,7 @@ WSAECONNRESET :: Platform_Error.WSAECONNRESET
ERROR_FILE_IS_PIPE :: General_Error.File_Is_Pipe
ERROR_FILE_IS_NOT_DIR :: General_Error.Not_Dir
-// "Argv" arguments converted to Odin strings
-args := _alloc_command_line_arguments()
-
-
-
-
+args: []string
@(require_results)
last_write_time :: proc(fd: Handle) -> (File_Time, Error) {
@@ -279,26 +240,14 @@ get_page_size :: proc() -> int {
@(private, require_results)
_processor_core_count :: proc() -> int {
- unimplemented("core:os procedure not supported on JS target")
+ return 1
}
exit :: proc "contextless" (code: int) -> ! {
- context = runtime.default_context()
- unimplemented("core:os procedure not supported on JS target")
+ unimplemented_contextless("core:os procedure not supported on JS target")
}
-
-
@(require_results)
current_thread_id :: proc "contextless" () -> int {
- context = runtime.default_context()
- unimplemented("core:os procedure not supported on JS target")
+ return 0
}
-
-
-
-@(require_results)
-_alloc_command_line_arguments :: proc() -> []string {
- return nil
-}
-
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index b69c4a0e0..dbc84f8b7 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -93,7 +93,7 @@ Inputs:
Returns:
- res: A string created from the null-terminated byte pointer and length
*/
-string_from_null_terminated_ptr :: proc(ptr: [^]byte, len: int) -> (res: string) {
+string_from_null_terminated_ptr :: proc "contextless" (ptr: [^]byte, len: int) -> (res: string) {
s := string(ptr[:len])
s = truncate_to_byte(s, 0)
return s
@@ -139,7 +139,7 @@ NOTE: Failure to find the byte results in returning the entire string.
Returns:
- res: The truncated string
*/
-truncate_to_byte :: proc(str: string, b: byte) -> (res: string) {
+truncate_to_byte :: proc "contextless" (str: string, b: byte) -> (res: string) {
n := index_byte(str, b)
if n < 0 {
n = len(str)
@@ -261,7 +261,7 @@ Inputs:
Returns:
- result: `-1` if `lhs` comes first, `1` if `rhs` comes first, or `0` if they are equal
*/
-compare :: proc(lhs, rhs: string) -> (result: int) {
+compare :: proc "contextless" (lhs, rhs: string) -> (result: int) {
return mem.compare(transmute([]byte)lhs, transmute([]byte)rhs)
}
/*
@@ -1447,7 +1447,7 @@ Output:
-1
*/
-index_byte :: proc(s: string, c: byte) -> (res: int) {
+index_byte :: proc "contextless" (s: string, c: byte) -> (res: int) {
return #force_inline bytes.index_byte(transmute([]u8)s, c)
}
/*
@@ -1482,7 +1482,7 @@ Output:
-1
*/
-last_index_byte :: proc(s: string, c: byte) -> (res: int) {
+last_index_byte :: proc "contextless" (s: string, c: byte) -> (res: int) {
return #force_inline bytes.last_index_byte(transmute([]u8)s, c)
}
/*
@@ -1576,8 +1576,8 @@ Output:
-1
*/
-index :: proc(s, substr: string) -> (res: int) {
- hash_str_rabin_karp :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) {
+index :: proc "contextless" (s, substr: string) -> (res: int) {
+ hash_str_rabin_karp :: proc "contextless" (s: string) -> (hash: u32 = 0, pow: u32 = 1) {
for i := 0; i < len(s); i += 1 {
hash = hash*PRIME_RABIN_KARP + u32(s[i])
}