mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-16 02:42:22 -07:00
177 lines
4.3 KiB
Odin
177 lines
4.3 KiB
Odin
putchar :: proc(c: i32) -> i32 #foreign
|
|
|
|
mem_compare :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcmp"
|
|
mem_copy :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcpy"
|
|
mem_move :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memmove"
|
|
|
|
debug_trap :: proc() #foreign "llvm.debugtrap"
|
|
|
|
// TODO(bill): make custom heap procedures
|
|
heap_realloc :: proc(ptr: rawptr, sz: int) -> rawptr #foreign "realloc"
|
|
heap_alloc :: proc(sz: int) -> rawptr { return heap_realloc(null, sz); }
|
|
heap_free :: proc(ptr: rawptr) { _ = heap_realloc(ptr, 0); }
|
|
|
|
|
|
__string_eq :: proc(a, b : string) -> bool {
|
|
if len(a) != len(b) {
|
|
return false;
|
|
}
|
|
if ^a[0] == ^b[0] {
|
|
return true;
|
|
}
|
|
return mem_compare(^a[0], ^b[0], len(a)) == 0;
|
|
}
|
|
|
|
__string_ne :: proc(a, b : string) -> bool {
|
|
return !__string_eq(a, b);
|
|
}
|
|
|
|
__string_cmp :: proc(a, b : string) -> int {
|
|
min_len := len(a);
|
|
if len(b) < min_len {
|
|
min_len = len(b);
|
|
}
|
|
for i := 0; i < min_len; i++ {
|
|
x := a[i];
|
|
y := b[i];
|
|
if x < y {
|
|
return -1;
|
|
} else if x > y {
|
|
return +1;
|
|
}
|
|
}
|
|
if len(a) < len(b) {
|
|
return -1;
|
|
} else if len(a) > len(b) {
|
|
return +1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
__string_lt :: proc(a, b : string) -> bool { return __string_cmp(a, b) < 0; }
|
|
__string_gt :: proc(a, b : string) -> bool { return __string_cmp(a, b) > 0; }
|
|
__string_le :: proc(a, b : string) -> bool { return __string_cmp(a, b) <= 0; }
|
|
__string_ge :: proc(a, b : string) -> bool { return __string_cmp(a, b) >= 0; }
|
|
|
|
|
|
type AllocationMode: int;
|
|
ALLOCATION_ALLOC :: 0;
|
|
ALLOCATION_DEALLOC :: 1;
|
|
ALLOCATION_DEALLOC_ALL :: 2;
|
|
ALLOCATION_RESIZE :: 3;
|
|
|
|
|
|
type AllocatorProc: proc(allocator_data: rawptr, mode: AllocationMode,
|
|
size, alignment: int,
|
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
|
|
|
type Allocator: struct {
|
|
procedure: AllocatorProc,
|
|
data: rawptr,
|
|
}
|
|
|
|
|
|
type Context: struct {
|
|
thread_id: i32,
|
|
|
|
user_index: i32,
|
|
user_data: rawptr,
|
|
|
|
allocator: Allocator,
|
|
}
|
|
|
|
#thread_local context: Context;
|
|
|
|
DEFAULT_ALIGNMENT :: 2*size_of(int);
|
|
|
|
|
|
__check_context :: proc() {
|
|
if context.allocator.procedure == null {
|
|
context.allocator = __default_allocator();
|
|
}
|
|
|
|
ptr := __check_context as rawptr;
|
|
}
|
|
|
|
|
|
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
|
|
|
|
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
|
|
__check_context();
|
|
a := context.allocator;
|
|
return a.procedure(a.data, ALLOCATION_ALLOC, size, alignment, null, 0, 0);
|
|
}
|
|
|
|
dealloc :: proc(ptr: rawptr) #inline {
|
|
__check_context();
|
|
a := context.allocator;
|
|
_ = a.procedure(a.data, ALLOCATION_DEALLOC, 0, 0, ptr, 0, 0);
|
|
}
|
|
dealloc_all :: proc(ptr: rawptr) #inline {
|
|
__check_context();
|
|
a := context.allocator;
|
|
_ = a.procedure(a.data, ALLOCATION_DEALLOC_ALL, 0, 0, ptr, 0, 0);
|
|
}
|
|
|
|
|
|
resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
|
|
resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
|
|
__check_context();
|
|
a := context.allocator;
|
|
return a.procedure(a.data, ALLOCATION_RESIZE, new_size, alignment, ptr, old_size, 0);
|
|
}
|
|
|
|
|
|
|
|
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
|
if old_memory == null {
|
|
return alloc_align(new_size, alignment);
|
|
}
|
|
|
|
if new_size == 0 {
|
|
dealloc(old_memory);
|
|
return null;
|
|
}
|
|
|
|
if new_size < old_size {
|
|
new_size = old_size;
|
|
}
|
|
|
|
if old_size == new_size {
|
|
return old_memory;
|
|
}
|
|
|
|
new_memory := alloc_align(new_size, alignment);
|
|
if new_memory == null {
|
|
return null;
|
|
}
|
|
_ = copy((new_memory as ^u8)[:new_size], (old_memory as ^u8)[:old_size]);
|
|
dealloc(old_memory);
|
|
return new_memory;
|
|
}
|
|
|
|
|
|
__default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocationMode,
|
|
size, alignment: int,
|
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
|
if mode == ALLOCATION_ALLOC {
|
|
return heap_alloc(size);
|
|
} else if mode == ALLOCATION_RESIZE {
|
|
return heap_realloc(old_memory, size);
|
|
} else if mode == ALLOCATION_DEALLOC {
|
|
heap_free(old_memory);
|
|
} else if mode == ALLOCATION_DEALLOC_ALL {
|
|
// NOTE(bill): Does nothing
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
__default_allocator :: proc() -> Allocator {
|
|
return Allocator{
|
|
__default_allocator_proc,
|
|
null,
|
|
};
|
|
}
|
|
|