mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Merge pull request #4208 from laytan/more-wasm-vendor-support
wasm: support more vendor libraries
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -2277,3 +2277,81 @@ buddy_allocator_proc :: proc(
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
+19
-70
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
|
||||
Vendored
+18
-4
@@ -3,7 +3,11 @@ package vendor_box2d
|
||||
import "base:intrinsics"
|
||||
import "core:c"
|
||||
|
||||
@(private) VECTOR_EXT :: "avx2" when #config(VENDOR_BOX2D_ENABLE_AVX2, intrinsics.has_target_feature("avx2")) else "sse2"
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
@(private) VECTOR_EXT :: "_simd" when #config(VENDOR_BOX2D_ENABLE_SIMD128, intrinsics.has_target_feature("simd128")) else ""
|
||||
} else {
|
||||
@(private) VECTOR_EXT :: "avx2" when #config(VENDOR_BOX2D_ENABLE_AVX2, intrinsics.has_target_feature("avx2")) else "sse2"
|
||||
}
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
@(private) LIB_PATH :: "lib/box2d_windows_amd64_" + VECTOR_EXT + ".lib"
|
||||
@@ -13,6 +17,8 @@ when ODIN_OS == .Windows {
|
||||
@(private) LIB_PATH :: "lib/box2d_darwin_amd64_" + VECTOR_EXT + ".a"
|
||||
} else when ODIN_ARCH == .amd64 {
|
||||
@(private) LIB_PATH :: "lib/box2d_other_amd64_" + VECTOR_EXT + ".a"
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
@(private) LIB_PATH :: "lib/box2d_wasm" + VECTOR_EXT + ".o"
|
||||
} else {
|
||||
@(private) LIB_PATH :: "lib/box2d_other.a"
|
||||
}
|
||||
@@ -21,8 +27,16 @@ when !#exists(LIB_PATH) {
|
||||
#panic("Could not find the compiled box2d libraries at \"" + LIB_PATH + "\", they can be compiled by running the `build.sh` script at `" + ODIN_ROOT + "vendor/box2d/build_box2d.sh\"`")
|
||||
}
|
||||
|
||||
foreign import lib {
|
||||
LIB_PATH,
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
when VECTOR_EXT == "_simd" {
|
||||
foreign import lib "lib/box2d_wasm_simd.o"
|
||||
} else {
|
||||
foreign import lib "lib/box2d_wasm.o"
|
||||
}
|
||||
} else {
|
||||
foreign import lib {
|
||||
LIB_PATH,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1520,4 +1534,4 @@ IsValid :: proc{
|
||||
Joint_IsValid,
|
||||
|
||||
IsValidRay,
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
package vendor_box2d
|
||||
|
||||
@(require) import _ "vendor:libc"
|
||||
Vendored
+2
@@ -68,5 +68,7 @@ esac
|
||||
|
||||
cd ..
|
||||
|
||||
make -f wasm.Makefile
|
||||
|
||||
rm -rf v3.0.0.tar.gz
|
||||
rm -rf box2d-3.0.0
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
# Custom Makefile to build box2d for Odin's WASM targets.
|
||||
# I tried to make a cmake toolchain file for this / use cmake but this is far easier.
|
||||
# NOTE: We are pretending to be emscripten to box2d so it takes WASM code paths, but we don't actually use emscripten.
|
||||
|
||||
# CC = $(shell brew --prefix llvm)/bin/clang
|
||||
# LD = $(shell brew --prefix llvm)/bin/wasm-ld
|
||||
|
||||
VERSION = 3.0.0
|
||||
SRCS = $(wildcard box2d-$(VERSION)/src/*.c)
|
||||
OBJS_SIMD = $(SRCS:.c=_simd.o)
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
SYSROOT = $(shell odin root)/vendor/libc
|
||||
CFLAGS = -Ibox2d-$(VERSION)/include -Ibox2d-$(VERSION)/Extern/simde --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
|
||||
|
||||
all: lib/box2d_wasm.o lib/box2d_wasm_simd.o clean
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
%_simd.o: %.c
|
||||
$(CC) -c $(CFLAGS) -msimd128 $< -o $@
|
||||
|
||||
lib/box2d_wasm.o: $(OBJS)
|
||||
$(LD) -r -o lib/box2d_wasm.o $(OBJS)
|
||||
|
||||
lib/box2d_wasm_simd.o: $(OBJS_SIMD)
|
||||
$(LD) -r -o lib/box2d_wasm_simd.o $(OBJS_SIMD)
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJS) $(OBJS_SIMD)
|
||||
|
||||
.PHONY: clean
|
||||
Vendored
+5
@@ -5,6 +5,7 @@ LIB :: (
|
||||
"lib/cgltf.lib" when ODIN_OS == .Windows
|
||||
else "lib/cgltf.a" when ODIN_OS == .Linux
|
||||
else "lib/darwin/cgltf.a" when ODIN_OS == .Darwin
|
||||
else "lib/cgltf_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
@@ -13,7 +14,11 @@ when LIB != "" {
|
||||
// Windows library is shipped with the compiler, so a Windows specific message should not be needed.
|
||||
#panic("Could not find the compiled cgltf library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/cgltf/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import lib "lib/cgltf_wasm.o"
|
||||
} else when LIB != "" {
|
||||
foreign import lib { LIB }
|
||||
} else {
|
||||
foreign import lib "system:cgltf"
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
package cgltf
|
||||
|
||||
@(require) import _ "vendor:libc"
|
||||
Vendored
BIN
Binary file not shown.
Vendored
+4
@@ -6,6 +6,10 @@ else
|
||||
all: unix
|
||||
endif
|
||||
|
||||
wasm:
|
||||
mkdir -p ../lib
|
||||
$(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc cgltf.c -o ../lib/cgltf_wasm.o
|
||||
|
||||
unix:
|
||||
mkdir -p ../lib
|
||||
$(CC) -c -O2 -Os -fPIC cgltf.c
|
||||
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
# vendor:libc
|
||||
|
||||
A (very small) subset of a libc implementation over Odin libraries.
|
||||
This is mainly intended for use in Odin WASM builds to allow using libraries like box2d, cgltf etc. without emscripten hacks.
|
||||
|
||||
You can use this with clang by doing `clang -c --target=wasm32 --sysroot=$(odin root)/vendor/libc` (+ all other flags and inputs).
|
||||
This will (if all the libc usage of the library is implemented) spit out a `.o` file you can use with the foreign import system.
|
||||
If you then also make sure this package is included in the Odin side of the project (`@(require) import "vendor:libc"`) you will be able
|
||||
compile to WASM like Odin expects.
|
||||
|
||||
This is currently used by `vendor:box2d`, `vendor:stb/image`, `vendor:stb/truetype`, `vendor:stb/rect_pack`, and `vendor:cgltf`.
|
||||
You can see how building works by looking at those.
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
package odin_libc
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
@(require, linkage="strong", link_name="__odin_libc_assert_fail")
|
||||
__odin_libc_assert_fail :: proc "c" (func: cstring, file: cstring, line: i32, expr: cstring) -> ! {
|
||||
context = g_ctx
|
||||
loc := runtime.Source_Code_Location{
|
||||
file_path = string(file),
|
||||
line = line,
|
||||
column = 0,
|
||||
procedure = string(func),
|
||||
}
|
||||
context.assertion_failure_proc("runtime assertion", string(expr), loc)
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
#ifdef NDEBUG
|
||||
#define assert(e) ((void)0)
|
||||
#else
|
||||
|
||||
#ifdef __FILE_NAME__
|
||||
#define __ASSERT_FILE_NAME __FILE_NAME__
|
||||
#else /* __FILE_NAME__ */
|
||||
#define __ASSERT_FILE_NAME __FILE__
|
||||
#endif /* __FILE_NAME__ */
|
||||
|
||||
void __odin_libc_assert_fail(const char *, const char *, int, const char *);
|
||||
|
||||
#define assert(e) \
|
||||
(__builtin_expect(!(e), 0) ? __odin_libc_assert_fail(__func__, __ASSERT_FILE_NAME, __LINE__, #e) : (void)0)
|
||||
|
||||
#endif /* NDEBUG */
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
float sqrtf(float);
|
||||
float cosf(float);
|
||||
float sinf(float);
|
||||
float atan2f(float, float);
|
||||
bool isnan(float);
|
||||
bool isinf(float);
|
||||
double floor(double x);
|
||||
double ceil(double x);
|
||||
double sqrt(double x);
|
||||
double pow(double x, double y);
|
||||
double fmod(double x, double y);
|
||||
double cos(double x);
|
||||
double acos(double x);
|
||||
double fabs(double x);
|
||||
int abs(int);
|
||||
double ldexp(double, int);
|
||||
double exp(double);
|
||||
float log(float);
|
||||
float sin(float);
|
||||
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct {} FILE;
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
#define stdout ((FILE *)2)
|
||||
#define stderr ((FILE *)3)
|
||||
|
||||
FILE *fopen(const char *, char *);
|
||||
int fclose(FILE *);
|
||||
int fseek(FILE *, long, int);
|
||||
long ftell(FILE *);
|
||||
size_t fread(void *, size_t, size_t, FILE *);
|
||||
size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
|
||||
int vfprintf(FILE *, const char *, va_list);
|
||||
int vsnprintf(char *, size_t, const char *, va_list);
|
||||
|
||||
static inline int snprintf(char *buf, size_t size, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int result = vsnprintf(buf, size, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int fprintf(FILE *f, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int result = vfprintf(f, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int result = vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void *malloc(size_t size);
|
||||
|
||||
void *aligned_alloc(size_t alignment, size_t size);
|
||||
|
||||
void free(void *);
|
||||
|
||||
void *realloc(void *, size_t);
|
||||
|
||||
void qsort(void* base, size_t num, size_t size, int (*compare)(const void*, const void*));
|
||||
|
||||
int atoi(const char *);
|
||||
long atol(const char *);
|
||||
long long atoll(const char *);
|
||||
|
||||
double atof(const char *);
|
||||
|
||||
long strtol(const char *, char **, int);
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void *memcpy(void *, const void *, size_t);
|
||||
void *memset(void *, int, size_t);
|
||||
void *memmove(void *, void *, size_t);
|
||||
int memcmp(const void *, const void *, size_t);
|
||||
|
||||
unsigned long strlen(const char *str);
|
||||
|
||||
char *strchr(const char *, int);
|
||||
char *strrchr(const char *, int);
|
||||
|
||||
char *strncpy(char *, const char *, size_t);
|
||||
char *strcpy(char *, const char *);
|
||||
|
||||
size_t strcspn(const char *, const char *);
|
||||
|
||||
int strcmp(const char *, const char *);
|
||||
int strncmp(const char *, const char *, size_t);
|
||||
|
||||
char *strstr(const char *, const char *);
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
package odin_libc
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
import "core:mem"
|
||||
|
||||
@(private)
|
||||
g_ctx: runtime.Context
|
||||
@(private)
|
||||
g_allocator: mem.Compat_Allocator
|
||||
|
||||
@(init)
|
||||
init_context :: proc() {
|
||||
g_ctx = context
|
||||
|
||||
// Wrapping the allocator with the mem.Compat_Allocator so we can
|
||||
// mimic the realloc semantics.
|
||||
mem.compat_allocator_init(&g_allocator, g_ctx.allocator)
|
||||
g_ctx.allocator = mem.compat_allocator(&g_allocator)
|
||||
}
|
||||
|
||||
// NOTE: the allocator must respect an `old_size` of `-1` on resizes!
|
||||
set_context :: proc(ctx := context) {
|
||||
g_ctx = ctx
|
||||
}
|
||||
Vendored
+100
@@ -0,0 +1,100 @@
|
||||
package odin_libc
|
||||
|
||||
import "base:builtin"
|
||||
|
||||
import "core:math"
|
||||
|
||||
@(require, linkage="strong", link_name="sqrtf")
|
||||
sqrtf :: proc "c" (v: f32) -> f32 {
|
||||
return math.sqrt(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="cosf")
|
||||
cosf :: proc "c" (v: f32) -> f32 {
|
||||
return math.cos(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sinf")
|
||||
sinf :: proc "c" (v: f32) -> f32 {
|
||||
return math.sin(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atan2f")
|
||||
atan2f :: proc "c" (v: f32, v2: f32) -> f32 {
|
||||
return math.atan2(v, v2)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="isnan")
|
||||
isnan :: proc "c" (v: f32) -> bool {
|
||||
return math.is_nan(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="isinf")
|
||||
isinf :: proc "c" (v: f32) -> bool {
|
||||
return math.is_inf(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sqrt")
|
||||
sqrt :: proc "c" (x: f64) -> f64 {
|
||||
return math.sqrt(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="floor")
|
||||
floor :: proc "c" (x: f64) -> f64 {
|
||||
return math.floor(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="ceil")
|
||||
ceil :: proc "c" (x: f64) -> f64 {
|
||||
return math.ceil(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="pow")
|
||||
pow :: proc "c" (x, y: f64) -> f64 {
|
||||
return math.pow(x, y)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fmod")
|
||||
fmod :: proc "c" (x, y: f64) -> f64 {
|
||||
return math.mod(x, y)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="cos")
|
||||
cos :: proc "c" (x: f64) -> f64 {
|
||||
return math.cos(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="acos")
|
||||
acos :: proc "c" (x: f64) -> f64 {
|
||||
return math.acos(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fabs")
|
||||
fabs :: proc "c" (x: f64) -> f64 {
|
||||
return math.abs(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="abs")
|
||||
abs :: proc "c" (x: i32) -> i32 {
|
||||
return builtin.abs(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="ldexp")
|
||||
ldexp :: proc "c" (x: f64, y: i32) -> f64{
|
||||
return math.ldexp(x, int(y))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="exp")
|
||||
exp :: proc "c" (x: f64) -> f64 {
|
||||
return math.exp(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="log")
|
||||
log :: proc "c" (x: f32) -> f32 {
|
||||
return math.ln(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sin")
|
||||
sin :: proc "c" (x: f32) -> f32 {
|
||||
return math.sin(x)
|
||||
}
|
||||
Vendored
+106
@@ -0,0 +1,106 @@
|
||||
package odin_libc
|
||||
|
||||
import "core:c"
|
||||
import "core:io"
|
||||
import "core:os"
|
||||
|
||||
import stb "vendor:stb/sprintf"
|
||||
|
||||
FILE :: uintptr
|
||||
|
||||
@(require, linkage="strong", link_name="fopen")
|
||||
fopen :: proc "c" (path: cstring, mode: cstring) -> FILE {
|
||||
context = g_ctx
|
||||
unimplemented("odin_libc.fopen")
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fseek")
|
||||
fseek :: proc "c" (file: FILE, offset: c.long, whence: i32) -> i32 {
|
||||
context = g_ctx
|
||||
handle := os.Handle(file-1)
|
||||
_, err := os.seek(handle, i64(offset), int(whence))
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="ftell")
|
||||
ftell :: proc "c" (file: FILE) -> c.long {
|
||||
context = g_ctx
|
||||
handle := os.Handle(file-1)
|
||||
off, err := os.seek(handle, 0, os.SEEK_CUR)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return c.long(off)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fclose")
|
||||
fclose :: proc "c" (file: FILE) -> i32 {
|
||||
context = g_ctx
|
||||
handle := os.Handle(file-1)
|
||||
if os.close(handle) != nil {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fread")
|
||||
fread :: proc "c" (buffer: [^]byte, size: uint, count: uint, file: FILE) -> uint {
|
||||
context = g_ctx
|
||||
handle := os.Handle(file-1)
|
||||
n, _ := os.read(handle, buffer[:min(size, count)])
|
||||
return uint(max(0, n))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fwrite")
|
||||
fwrite :: proc "c" (buffer: [^]byte, size: uint, count: uint, file: FILE) -> uint {
|
||||
context = g_ctx
|
||||
handle := os.Handle(file-1)
|
||||
n, _ := os.write(handle, buffer[:min(size, count)])
|
||||
return uint(max(0, n))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="vsnprintf")
|
||||
vsnprintf :: proc "c" (buf: [^]byte, count: uint, fmt: cstring, args: ^c.va_list) -> i32 {
|
||||
i32_count := i32(count)
|
||||
assert_contextless(i32_count >= 0)
|
||||
return stb.vsnprintf(buf, i32_count, fmt, args)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="vfprintf")
|
||||
vfprintf :: proc "c" (file: FILE, fmt: cstring, args: ^c.va_list) -> i32 {
|
||||
context = g_ctx
|
||||
|
||||
handle := os.Handle(file-1)
|
||||
|
||||
MAX_STACK :: 4096
|
||||
|
||||
buf: []byte
|
||||
stack_buf: [MAX_STACK]byte = ---
|
||||
{
|
||||
n := stb.vsnprintf(&stack_buf[0], MAX_STACK, fmt, args)
|
||||
if n <= 0 {
|
||||
return n
|
||||
}
|
||||
|
||||
if n >= MAX_STACK {
|
||||
buf = make([]byte, n)
|
||||
n2 := stb.vsnprintf(raw_data(buf), i32(len(buf)), fmt, args)
|
||||
assert(n == n2)
|
||||
} else {
|
||||
buf = stack_buf[:n]
|
||||
}
|
||||
}
|
||||
defer if len(buf) > MAX_STACK {
|
||||
delete(buf)
|
||||
}
|
||||
|
||||
_, err := io.write_full(os.stream_from_handle(handle), buf)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
return i32(len(buf))
|
||||
}
|
||||
Vendored
+119
@@ -0,0 +1,119 @@
|
||||
package odin_libc
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
import "core:c"
|
||||
import "core:slice"
|
||||
import "core:sort"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
@(require, linkage="strong", link_name="malloc")
|
||||
malloc :: proc "c" (size: uint) -> rawptr {
|
||||
context = g_ctx
|
||||
ptr, err := runtime.mem_alloc_non_zeroed(int(size))
|
||||
assert(err == nil, "allocation failure")
|
||||
return raw_data(ptr)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="aligned_alloc")
|
||||
aligned_alloc :: proc "c" (alignment: uint, size: uint) -> rawptr {
|
||||
context = g_ctx
|
||||
ptr, err := runtime.mem_alloc_non_zeroed(int(size), int(alignment))
|
||||
assert(err == nil, "allocation failure")
|
||||
return raw_data(ptr)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="free")
|
||||
free :: proc "c" (ptr: rawptr) {
|
||||
context = g_ctx
|
||||
runtime.mem_free(ptr)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="realloc")
|
||||
realloc :: proc "c" (ptr: rawptr, new_size: uint) -> rawptr {
|
||||
context = g_ctx
|
||||
// -1 for the old_size, assumed to be wrapped with the mem.Compat_Allocator to get the right size.
|
||||
// Note that realloc does not actually care about alignment and is allowed to just align it to something
|
||||
// else than the original allocation.
|
||||
ptr, err := runtime.non_zero_mem_resize(ptr, -1, int(new_size))
|
||||
assert(err != nil, "realloc failure")
|
||||
return raw_data(ptr)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="qsort")
|
||||
qsort :: proc "c" (base: rawptr, num: uint, size: uint, cmp: proc "c" (a, b: rawptr) -> i32) {
|
||||
context = g_ctx
|
||||
|
||||
Inputs :: struct {
|
||||
base: rawptr,
|
||||
num: uint,
|
||||
size: uint,
|
||||
cmp: proc "c" (a, b: rawptr) -> i32,
|
||||
}
|
||||
|
||||
sort.sort({
|
||||
collection = &Inputs{base, num, size, cmp},
|
||||
len = proc(it: sort.Interface) -> int {
|
||||
inputs := (^Inputs)(it.collection)
|
||||
return int(inputs.num)
|
||||
},
|
||||
less = proc(it: sort.Interface, i, j: int) -> bool {
|
||||
inputs := (^Inputs)(it.collection)
|
||||
a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
|
||||
b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
|
||||
return inputs.cmp(a, b) < 0
|
||||
},
|
||||
swap = proc(it: sort.Interface, i, j: int) {
|
||||
inputs := (^Inputs)(it.collection)
|
||||
|
||||
a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
|
||||
b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
|
||||
|
||||
slice.ptr_swap_non_overlapping(a, b, int(inputs.size))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atoi")
|
||||
atoi :: proc "c" (str: cstring) -> i32 {
|
||||
return i32(atoll(str))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atol")
|
||||
atol :: proc "c" (str: cstring) -> c.long {
|
||||
return c.long(atoll(str))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atoll")
|
||||
atoll :: proc "c" (str: cstring) -> c.longlong {
|
||||
context = g_ctx
|
||||
|
||||
sstr := string(str)
|
||||
sstr = strings.trim_left_space(sstr)
|
||||
i, _ := strconv.parse_i64_of_base(sstr, 10)
|
||||
return c.longlong(i)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atof")
|
||||
atof :: proc "c" (str: cstring) -> f64 {
|
||||
context = g_ctx
|
||||
|
||||
sstr := string(str)
|
||||
sstr = strings.trim_left_space(sstr)
|
||||
f, _ := strconv.parse_f64(sstr)
|
||||
return f
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strtol")
|
||||
strtol :: proc "c" (str: cstring, str_end: ^cstring, base: i32) -> c.long {
|
||||
context = g_ctx
|
||||
|
||||
sstr := string(str)
|
||||
sstr = strings.trim_left_space(sstr)
|
||||
|
||||
n: int
|
||||
i, _ := strconv.parse_i64_of_base(sstr, int(base), &n)
|
||||
str_end ^= cstring(raw_data(sstr)[n:])
|
||||
return c.long(clamp(i, i64(min(c.long)), i64(max(c.long))))
|
||||
}
|
||||
Vendored
+111
@@ -0,0 +1,111 @@
|
||||
package odin_libc
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
import "core:c"
|
||||
import "core:strings"
|
||||
import "core:mem"
|
||||
|
||||
// NOTE: already defined by Odin.
|
||||
// void *memcpy(void *, const void *, size_t);
|
||||
// void *memset(void *, int, size_t);
|
||||
|
||||
@(require, linkage="strong", link_name="memcmp")
|
||||
memcmp :: proc "c" (lhs: [^]byte, rhs: [^]byte, count: uint) -> i32 {
|
||||
icount := int(count)
|
||||
assert_contextless(icount >= 0)
|
||||
return i32(mem.compare(lhs[:icount], rhs[:icount]))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strlen")
|
||||
strlen :: proc "c" (str: cstring) -> c.ulong {
|
||||
return c.ulong(len(str))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strchr")
|
||||
strchr :: proc "c" (str: cstring, ch: i32) -> cstring {
|
||||
bch := u8(ch)
|
||||
sstr := string(str)
|
||||
if bch == 0 {
|
||||
return cstring(raw_data(sstr)[len(sstr):])
|
||||
}
|
||||
|
||||
idx := strings.index_byte(sstr, bch)
|
||||
if idx < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cstring(raw_data(sstr)[idx:])
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strrchr")
|
||||
strrchr :: proc "c" (str: cstring, ch: i32) -> cstring {
|
||||
bch := u8(ch)
|
||||
sstr := string(str)
|
||||
if bch == 0 {
|
||||
return cstring(raw_data(sstr)[len(sstr):])
|
||||
}
|
||||
|
||||
idx := strings.last_index_byte(sstr, bch)
|
||||
if idx < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cstring(raw_data(sstr)[idx:])
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strncpy")
|
||||
strncpy :: proc "c" (dst: [^]byte, src: cstring, count: uint) -> cstring {
|
||||
icount := int(count)
|
||||
assert_contextless(icount >= 0)
|
||||
cnt := min(len(src), icount)
|
||||
intrinsics.mem_copy_non_overlapping(dst, rawptr(src), cnt)
|
||||
intrinsics.mem_zero(dst, icount-cnt)
|
||||
return cstring(dst)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strcpy")
|
||||
strcpy :: proc "c" (dst: [^]byte, src: cstring) -> cstring {
|
||||
intrinsics.mem_copy_non_overlapping(dst, rawptr(src), len(src)+1)
|
||||
return cstring(dst)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strcspn")
|
||||
strcspn :: proc "c" (dst: cstring, src: cstring) -> uint {
|
||||
context = g_ctx
|
||||
sdst := string(dst)
|
||||
idx := strings.index_any(sdst, string(src))
|
||||
if idx == -1 {
|
||||
return len(sdst)
|
||||
}
|
||||
return uint(idx)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strncmp")
|
||||
strncmp :: proc "c" (lhs: cstring, rhs: cstring, count: uint) -> i32 {
|
||||
icount := int(count)
|
||||
assert_contextless(icount >= 0)
|
||||
lhss := strings.string_from_null_terminated_ptr(([^]byte)(lhs), icount)
|
||||
rhss := strings.string_from_null_terminated_ptr(([^]byte)(rhs), icount)
|
||||
return i32(strings.compare(lhss, rhss))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strcmp")
|
||||
strcmp :: proc "c" (lhs: cstring, rhs: cstring) -> i32 {
|
||||
return i32(strings.compare(string(lhs), string(rhs)))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strstr")
|
||||
strstr :: proc "c" (str: cstring, substr: cstring) -> cstring {
|
||||
if substr == "" {
|
||||
return str
|
||||
}
|
||||
|
||||
idx := strings.index(string(str), string(substr))
|
||||
if idx < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cstring(([^]byte)(str)[idx:])
|
||||
}
|
||||
|
||||
Vendored
+44
-13
@@ -7,6 +7,7 @@ LIB :: (
|
||||
"../lib/stb_image.lib" when ODIN_OS == .Windows
|
||||
else "../lib/stb_image.a" when ODIN_OS == .Linux
|
||||
else "../lib/darwin/stb_image.a" when ODIN_OS == .Darwin
|
||||
else "../lib/stb_image_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
@@ -15,12 +16,19 @@ when LIB != "" {
|
||||
// The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed.
|
||||
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import stbi "../lib/stb_image_wasm.o"
|
||||
foreign import stbi { LIB }
|
||||
} else when LIB != "" {
|
||||
foreign import stbi { LIB }
|
||||
} else {
|
||||
foreign import stbi "system:stb_image"
|
||||
}
|
||||
|
||||
NO_STDIO :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
|
||||
#assert(size_of(c.int) == size_of(b32))
|
||||
#assert(size_of(b32) == size_of(c.int))
|
||||
|
||||
@@ -33,14 +41,48 @@ Io_Callbacks :: struct {
|
||||
eof: proc "c" (user: rawptr) -> c.int, // returns nonzero if we are at end of file/data
|
||||
}
|
||||
|
||||
when !NO_STDIO {
|
||||
@(default_calling_convention="c", link_prefix="stbi_")
|
||||
foreign stbi {
|
||||
////////////////////////////////////
|
||||
//
|
||||
// 8-bits-per-channel interface
|
||||
//
|
||||
load :: proc(filename: cstring, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]byte ---
|
||||
load_from_file :: proc(f: ^c.FILE, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]byte ---
|
||||
|
||||
////////////////////////////////////
|
||||
//
|
||||
// 16-bits-per-channel interface
|
||||
//
|
||||
load_16 :: proc(filename: cstring, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]u16 ---
|
||||
load_16_from_file :: proc(f: ^c.FILE, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]u16 ---
|
||||
|
||||
////////////////////////////////////
|
||||
//
|
||||
// float-per-channel interface
|
||||
//
|
||||
loadf :: proc(filename: cstring, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]f32 ---
|
||||
loadf_from_file :: proc(f: ^c.FILE, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]f32 ---
|
||||
|
||||
is_hdr :: proc(filename: cstring) -> c.int ---
|
||||
is_hdr_from_file :: proc(f: ^c.FILE) -> c.int ---
|
||||
|
||||
// get image dimensions & components without fully decoding
|
||||
info :: proc(filename: cstring, x, y, comp: ^c.int) -> c.int ---
|
||||
info_from_file :: proc(f: ^c.FILE, x, y, comp: ^c.int) -> c.int ---
|
||||
|
||||
is_16_bit :: proc(filename: cstring) -> b32 ---
|
||||
is_16_bit_from_file :: proc(f: ^c.FILE) -> b32 ---
|
||||
}
|
||||
}
|
||||
|
||||
@(default_calling_convention="c", link_prefix="stbi_")
|
||||
foreign stbi {
|
||||
////////////////////////////////////
|
||||
//
|
||||
// 8-bits-per-channel interface
|
||||
//
|
||||
load :: proc(filename: cstring, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]byte ---
|
||||
load_from_file :: proc(f: ^c.FILE, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]byte ---
|
||||
load_from_memory :: proc(buffer: [^]byte, len: c.int, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]byte ---
|
||||
load_from_callbacks :: proc(clbk: ^Io_Callbacks, user: rawptr, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]byte ---
|
||||
|
||||
@@ -50,8 +92,6 @@ foreign stbi {
|
||||
//
|
||||
// 16-bits-per-channel interface
|
||||
//
|
||||
load_16 :: proc(filename: cstring, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]u16 ---
|
||||
load_16_from_file :: proc(f: ^c.FILE, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]u16 ---
|
||||
load_16_from_memory :: proc(buffer: [^]byte, len: c.int, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]u16 ---
|
||||
load_16_from_callbacks :: proc(clbk: ^Io_Callbacks, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]u16 ---
|
||||
|
||||
@@ -59,8 +99,6 @@ foreign stbi {
|
||||
//
|
||||
// float-per-channel interface
|
||||
//
|
||||
loadf :: proc(filename: cstring, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]f32 ---
|
||||
loadf_from_file :: proc(f: ^c.FILE, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]f32 ---
|
||||
loadf_from_memory :: proc(buffer: [^]byte, len: c.int, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]f32 ---
|
||||
loadf_from_callbacks :: proc(clbk: ^Io_Callbacks, user: rawptr, x, y, channels_in_file: ^c.int, desired_channels: c.int) -> [^]f32 ---
|
||||
|
||||
@@ -73,9 +111,6 @@ foreign stbi {
|
||||
is_hdr_from_callbacks :: proc(clbk: ^Io_Callbacks, user: rawptr) -> c.int ---
|
||||
is_hdr_from_memory :: proc(buffer: [^]byte, len: c.int) -> c.int ---
|
||||
|
||||
is_hdr :: proc(filename: cstring) -> c.int ---
|
||||
is_hdr_from_file :: proc(f: ^c.FILE) -> c.int ---
|
||||
|
||||
// get a VERY brief reason for failure
|
||||
// NOT THREADSAFE
|
||||
failure_reason :: proc() -> cstring ---
|
||||
@@ -84,13 +119,9 @@ foreign stbi {
|
||||
image_free :: proc(retval_from_load: rawptr) ---
|
||||
|
||||
// get image dimensions & components without fully decoding
|
||||
info :: proc(filename: cstring, x, y, comp: ^c.int) -> c.int ---
|
||||
info_from_file :: proc(f: ^c.FILE, x, y, comp: ^c.int) -> c.int ---
|
||||
info_from_memory :: proc(buffer: [^]byte, len: c.int, x, y, comp: ^c.int) -> c.int ---
|
||||
info_from_callbacks :: proc(clbk: ^Io_Callbacks, user: rawptr, x, y, comp: ^c.int) -> c.int ---
|
||||
|
||||
is_16_bit :: proc(filename: cstring) -> b32 ---
|
||||
is_16_bit_from_file :: proc(f: ^c.FILE) -> b32 ---
|
||||
is_16_bit_from_memory :: proc(buffer: [^]byte, len: c.int) -> c.int ---
|
||||
|
||||
// for image formats that explicitly notate that they have premultiplied alpha,
|
||||
|
||||
+5
@@ -7,6 +7,7 @@ RESIZE_LIB :: (
|
||||
"../lib/stb_image_resize.lib" when ODIN_OS == .Windows
|
||||
else "../lib/stb_image_resize.a" when ODIN_OS == .Linux
|
||||
else "../lib/darwin/stb_image_resize.a" when ODIN_OS == .Darwin
|
||||
else "../lib/stb_image_resize_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
@@ -15,7 +16,11 @@ when RESIZE_LIB != "" {
|
||||
// The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed.
|
||||
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import lib "../lib/stb_image_resize_wasm.o"
|
||||
} else when RESIZE_LIB != "" {
|
||||
foreign import lib { RESIZE_LIB }
|
||||
} else {
|
||||
foreign import lib "system:stb_image_resize"
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
package stb_image
|
||||
|
||||
@(require) import _ "vendor:libc"
|
||||
+16
-6
@@ -7,6 +7,7 @@ WRITE_LIB :: (
|
||||
"../lib/stb_image_write.lib" when ODIN_OS == .Windows
|
||||
else "../lib/stb_image_write.a" when ODIN_OS == .Linux
|
||||
else "../lib/darwin/stb_image_write.a" when ODIN_OS == .Darwin
|
||||
else "../lib/stb_image_write_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
@@ -15,7 +16,11 @@ when WRITE_LIB != "" {
|
||||
// The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed.
|
||||
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import stbiw "../lib/stb_image_write_wasm.o"
|
||||
} else when WRITE_LIB != "" {
|
||||
foreign import stbiw { WRITE_LIB }
|
||||
} else {
|
||||
foreign import stbiw "system:stb_image_write"
|
||||
@@ -25,12 +30,6 @@ write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int)
|
||||
|
||||
@(default_calling_convention="c", link_prefix="stbi_")
|
||||
foreign stbiw {
|
||||
write_png :: proc(filename: cstring, w, h, comp: c.int, data: rawptr, stride_in_bytes: c.int) -> c.int ---
|
||||
write_bmp :: proc(filename: cstring, w, h, comp: c.int, data: rawptr) -> c.int ---
|
||||
write_tga :: proc(filename: cstring, w, h, comp: c.int, data: rawptr) -> c.int ---
|
||||
write_hdr :: proc(filename: cstring, w, h, comp: c.int, data: [^]f32) -> c.int ---
|
||||
write_jpg :: proc(filename: cstring, w, h, comp: c.int, data: rawptr, quality: c.int /*0..=100*/) -> c.int ---
|
||||
|
||||
write_png_to_func :: proc(func: write_func, ctx: rawptr, w, h, comp: c.int, data: rawptr, stride_in_bytes: c.int) -> c.int ---
|
||||
write_bmp_to_func :: proc(func: write_func, ctx: rawptr, w, h, comp: c.int, data: rawptr) -> c.int ---
|
||||
write_tga_to_func :: proc(func: write_func, ctx: rawptr, w, h, comp: c.int, data: rawptr) -> c.int ---
|
||||
@@ -39,3 +38,14 @@ foreign stbiw {
|
||||
|
||||
flip_vertically_on_write :: proc(flip_boolean: b32) ---
|
||||
}
|
||||
|
||||
when !NO_STDIO {
|
||||
@(default_calling_convention="c", link_prefix="stbi_")
|
||||
foreign stbiw {
|
||||
write_png :: proc(filename: cstring, w, h, comp: c.int, data: rawptr, stride_in_bytes: c.int) -> c.int ---
|
||||
write_bmp :: proc(filename: cstring, w, h, comp: c.int, data: rawptr) -> c.int ---
|
||||
write_tga :: proc(filename: cstring, w, h, comp: c.int, data: rawptr) -> c.int ---
|
||||
write_hdr :: proc(filename: cstring, w, h, comp: c.int, data: [^]f32) -> c.int ---
|
||||
write_jpg :: proc(filename: cstring, w, h, comp: c.int, data: rawptr, quality: c.int /*0..=100*/) -> c.int ---
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
+5
@@ -9,6 +9,7 @@ LIB :: (
|
||||
"../lib/stb_rect_pack.lib" when ODIN_OS == .Windows
|
||||
else "../lib/stb_rect_pack.a" when ODIN_OS == .Linux
|
||||
else "../lib/darwin/stb_rect_pack.a" when ODIN_OS == .Darwin
|
||||
else "../lib/stb_rect_pack_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
@@ -16,7 +17,11 @@ when LIB != "" {
|
||||
when !#exists(LIB) {
|
||||
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import lib "../lib/stb_rect_pack_wasm.o"
|
||||
} else when LIB != "" {
|
||||
foreign import lib { LIB }
|
||||
} else {
|
||||
foreign import lib "system:stb_rect_pack"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
package stb_rect_pack
|
||||
|
||||
@(require) import _ "vendor:libc"
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
package stb_sprintf
|
||||
|
||||
import "core:c"
|
||||
|
||||
@(private)
|
||||
LIB :: (
|
||||
"../lib/stb_sprintf.lib" when ODIN_OS == .Windows
|
||||
else "../lib/stb_sprintf.a" when ODIN_OS == .Linux
|
||||
else "../lib/darwin/stb_sprintf.a" when ODIN_OS == .Darwin
|
||||
else "../lib/stb_sprintf_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
when LIB != "" {
|
||||
when !#exists(LIB) {
|
||||
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import stbpf "../lib/stb_sprintf_wasm.o"
|
||||
} else when LIB != "" {
|
||||
foreign import stbpf { LIB }
|
||||
} else {
|
||||
foreign import stbpf "system:stb_sprintf"
|
||||
}
|
||||
|
||||
@(link_prefix="stbsp_", default_calling_convention="c")
|
||||
foreign stbpf {
|
||||
sprintf :: proc(buf: [^]byte, fmt: cstring, #c_vararg args: ..any) -> i32 ---
|
||||
snprintf :: proc(buf: [^]byte, count: i32, fmt: cstring, #c_vararg args: ..any) -> i32 ---
|
||||
vsprintf :: proc(buf: [^]byte, fmt: cstring, va: c.va_list) -> i32 ---
|
||||
vsnprintf :: proc(buf: [^]byte, count: i32, fmt: cstring, va: ^c.va_list) -> i32 ---
|
||||
vsprintfcb :: proc(callback: SPRINTFCB, user: rawptr, buf: [^]byte, fmt: cstring, va: ^c.va_list) -> i32 ---
|
||||
}
|
||||
|
||||
SPRINTFCB :: #type proc "c" (buf: [^]byte, user: rawptr, len: i32) -> cstring
|
||||
Vendored
+12
-2
@@ -8,17 +8,24 @@ endif
|
||||
|
||||
wasm:
|
||||
mkdir -p ../lib
|
||||
$(CC) -c -Os --target=wasm32 -nostdlib stb_truetype_wasm.c -o ../lib/stb_truetype_wasm.o
|
||||
$(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_image.c -o ../lib/stb_image_wasm.o -DSTBI_NO_STDIO
|
||||
$(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_image_write.c -o ../lib/stb_image_write_wasm.o -DSTBI_WRITE_NO_STDIO
|
||||
$(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_image_resize.c -o ../lib/stb_image_resize_wasm.o
|
||||
$(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_truetype.c -o ../lib/stb_truetype_wasm.o
|
||||
# $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_vorbis.c -o ../lib/stb_vorbis_wasm.o -DSTB_VORBIS_NO_STDIO
|
||||
$(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_rect_pack.c -o ../lib/stb_rect_pack_wasm.o
|
||||
$(CC) -c -Os --target=wasm32 stb_sprintf.c -o ../lib/stb_sprintf_wasm.o
|
||||
|
||||
unix:
|
||||
mkdir -p ../lib
|
||||
$(CC) -c -O2 -Os -fPIC stb_image.c stb_image_write.c stb_image_resize.c stb_truetype.c stb_rect_pack.c stb_vorbis.c
|
||||
$(CC) -c -O2 -Os -fPIC stb_image.c stb_image_write.c stb_image_resize.c stb_truetype.c stb_rect_pack.c stb_vorbis.c stb_sprintf.c
|
||||
$(AR) rcs ../lib/stb_image.a stb_image.o
|
||||
$(AR) rcs ../lib/stb_image_write.a stb_image_write.o
|
||||
$(AR) rcs ../lib/stb_image_resize.a stb_image_resize.o
|
||||
$(AR) rcs ../lib/stb_truetype.a stb_truetype.o
|
||||
$(AR) rcs ../lib/stb_rect_pack.a stb_rect_pack.o
|
||||
$(AR) rcs ../lib/stb_vorbis.a stb_vorbis.o
|
||||
$(AR) rcs ../lib/stb_sprintf.a stb_sprintf.o
|
||||
#$(CC) -fPIC -shared -Wl,-soname=stb_image.so -o ../lib/stb_image.so stb_image.o
|
||||
#$(CC) -fPIC -shared -Wl,-soname=stb_image_write.so -o ../lib/stb_image_write.so stb_image_write.o
|
||||
#$(CC) -fPIC -shared -Wl,-soname=stb_image_resize.so -o ../lib/stb_image_resize.so stb_image_resize.o
|
||||
@@ -47,4 +54,7 @@ darwin:
|
||||
$(CC) -arch x86_64 -c -O2 -Os -fPIC stb_vorbis.c -o stb_vorbis-x86_64.o -mmacosx-version-min=10.12
|
||||
$(CC) -arch arm64 -c -O2 -Os -fPIC stb_vorbis.c -o stb_vorbis-arm64.o -mmacosx-version-min=10.12
|
||||
lipo -create stb_vorbis-x86_64.o stb_vorbis-arm64.o -output ../lib/darwin/stb_vorbis.a
|
||||
$(CC) -arch x86_64 -c -O2 -Os -fPIC stb_sprintf.c -o stb_sprintf-x86_64.o -mmacosx-version-min=10.12
|
||||
$(CC) -arch arm64 -c -O2 -Os -fPIC stb_sprintf.c -o stb_sprintf-arm64.o -mmacosx-version-min=10.12
|
||||
lipo -create stb_sprintf-x86_64.o stb_sprintf-arm64.o -output ../lib/darwin/stb_sprintf.a
|
||||
rm *.o
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#include "stb_sprintf.h"
|
||||
Vendored
+1906
File diff suppressed because it is too large
Load Diff
Vendored
-46
@@ -1,46 +0,0 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void *stbtt_malloc(size_t size);
|
||||
void stbtt_free(void *ptr);
|
||||
|
||||
void stbtt_qsort(void* base, size_t num, size_t size, int (*compare)(const void*, const void*));
|
||||
|
||||
double stbtt_floor(double x);
|
||||
double stbtt_ceil(double x);
|
||||
double stbtt_sqrt(double x);
|
||||
double stbtt_pow(double x, double y);
|
||||
double stbtt_fmod(double x, double y);
|
||||
double stbtt_cos(double x);
|
||||
double stbtt_acos(double x);
|
||||
double stbtt_fabs(double x);
|
||||
|
||||
unsigned long stbtt_strlen(const char *str);
|
||||
|
||||
void *memcpy(void *dst, const void *src, size_t count);
|
||||
void *memset(void *dst, int x, size_t count);
|
||||
|
||||
#define STBRP_SORT stbtt_qsort
|
||||
#define STBRP_ASSERT(condition) ((void)0)
|
||||
|
||||
#define STBTT_malloc(x,u) ((void)(u),stbtt_malloc(x))
|
||||
#define STBTT_free(x,u) ((void)(u),stbtt_free(x))
|
||||
|
||||
#define STBTT_assert(condition) ((void)0)
|
||||
|
||||
#define STBTT_ifloor(x) ((int) stbtt_floor(x))
|
||||
#define STBTT_iceil(x) ((int) stbtt_ceil(x))
|
||||
#define STBTT_sqrt(x) stbtt_sqrt(x)
|
||||
#define STBTT_pow(x,y) stbtt_pow(x,y)
|
||||
#define STBTT_fmod(x,y) stbtt_fmod(x,y)
|
||||
#define STBTT_cos(x) stbtt_cos(x)
|
||||
#define STBTT_acos(x) stbtt_acos(x)
|
||||
#define STBTT_fabs(x) stbtt_fabs(x)
|
||||
#define STBTT_strlen(x) stbtt_strlen(x)
|
||||
#define STBTT_memcpy memcpy
|
||||
#define STBTT_memset memset
|
||||
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#include "stb_rect_pack.h"
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
+5
-2
@@ -8,6 +8,7 @@ LIB :: (
|
||||
"../lib/stb_truetype.lib" when ODIN_OS == .Windows
|
||||
else "../lib/stb_truetype.a" when ODIN_OS == .Linux
|
||||
else "../lib/darwin/stb_truetype.a" when ODIN_OS == .Darwin
|
||||
else "../lib/stb_truetype_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
else ""
|
||||
)
|
||||
|
||||
@@ -15,10 +16,12 @@ when LIB != "" {
|
||||
when !#exists(LIB) {
|
||||
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
|
||||
}
|
||||
}
|
||||
|
||||
foreign import stbtt { LIB }
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
foreign import stbtt "../lib/stb_truetype_wasm.o"
|
||||
} else when LIB != "" {
|
||||
foreign import stbtt { LIB }
|
||||
} else {
|
||||
foreign import stbtt "system:stb_truetype"
|
||||
}
|
||||
|
||||
+1
-79
@@ -1,82 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
package stb_truetype
|
||||
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
|
||||
import "core:c"
|
||||
import "core:math"
|
||||
import "core:slice"
|
||||
import "core:sort"
|
||||
|
||||
@(require, linkage="strong", link_name="stbtt_malloc")
|
||||
malloc :: proc "c" (size: uint) -> rawptr {
|
||||
context = runtime.default_context()
|
||||
ptr, _ := runtime.mem_alloc_non_zeroed(int(size))
|
||||
return raw_data(ptr)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="stbtt_free")
|
||||
free :: proc "c" (ptr: rawptr) {
|
||||
context = runtime.default_context()
|
||||
builtin.free(ptr)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="stbtt_qsort")
|
||||
qsort :: proc "c" (base: rawptr, num: uint, size: uint, cmp: proc "c" (a, b: rawptr) -> i32) {
|
||||
context = runtime.default_context()
|
||||
|
||||
Inputs :: struct {
|
||||
base: rawptr,
|
||||
num: uint,
|
||||
size: uint,
|
||||
cmp: proc "c" (a, b: rawptr) -> i32,
|
||||
}
|
||||
|
||||
sort.sort({
|
||||
collection = &Inputs{base, num, size, cmp},
|
||||
len = proc(it: sort.Interface) -> int {
|
||||
inputs := (^Inputs)(it.collection)
|
||||
return int(inputs.num)
|
||||
},
|
||||
less = proc(it: sort.Interface, i, j: int) -> bool {
|
||||
inputs := (^Inputs)(it.collection)
|
||||
a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
|
||||
b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
|
||||
return inputs.cmp(a, b) < 0
|
||||
},
|
||||
swap = proc(it: sort.Interface, i, j: int) {
|
||||
inputs := (^Inputs)(it.collection)
|
||||
|
||||
a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
|
||||
b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
|
||||
|
||||
slice.ptr_swap_non_overlapping(a, b, int(inputs.size))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="stbtt_floor")
|
||||
floor :: proc "c" (x: f64) -> f64 { return math.floor(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_ceil")
|
||||
ceil :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_sqrt")
|
||||
sqrt :: proc "c" (x: f64) -> f64 { return math.sqrt(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_pow")
|
||||
pow :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) }
|
||||
@(require, linkage="strong", link_name="stbtt_fmod")
|
||||
fmod :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
|
||||
@(require, linkage="strong", link_name="stbtt_cos")
|
||||
cos :: proc "c" (x: f64) -> f64 { return math.cos(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_acos")
|
||||
acos :: proc "c" (x: f64) -> f64 { return math.acos(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_fabs")
|
||||
fabs :: proc "c" (x: f64) -> f64 { return math.abs(x) }
|
||||
|
||||
@(require, linkage="strong", link_name="stbtt_strlen")
|
||||
strlen :: proc "c" (str: cstring) -> c.ulong { return c.ulong(len(str)) }
|
||||
|
||||
// NOTE: defined in runtime.
|
||||
// void *memcpy(void *dst, const void *src, size_t count);
|
||||
// void *memset(void *dst, int x, size_t count);
|
||||
@(require) import _ "vendor:libc"
|
||||
|
||||
Reference in New Issue
Block a user