mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -124,13 +124,13 @@ jobs:
|
|||||||
build_macos:
|
build_macos:
|
||||||
name: MacOS Build
|
name: MacOS Build
|
||||||
if: github.repository == 'odin-lang/Odin'
|
if: github.repository == 'odin-lang/Odin'
|
||||||
runs-on: macos-13
|
runs-on: macos-14 # Intel machine
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Download LLVM and setup PATH
|
- name: Download LLVM and setup PATH
|
||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
brew install llvm@20 dylibbundler lld
|
brew install llvm@20 dylibbundler lld@20
|
||||||
|
|
||||||
- name: build odin
|
- name: build odin
|
||||||
# These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
|
# These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
|
||||||
@@ -169,7 +169,7 @@ jobs:
|
|||||||
- name: Download LLVM and setup PATH
|
- name: Download LLVM and setup PATH
|
||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
brew install llvm@20 dylibbundler lld
|
brew install llvm@20 dylibbundler lld@20
|
||||||
|
|
||||||
- name: build odin
|
- name: build odin
|
||||||
# These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
|
# These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
|
||||||
|
|||||||
@@ -303,3 +303,9 @@ codegen/build/gen_src.map
|
|||||||
.cache/
|
.cache/
|
||||||
.clangd
|
.clangd
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
||||||
|
# Dev cmake helpers
|
||||||
|
build/
|
||||||
|
cmake-build*/
|
||||||
|
CMakeLists.txt
|
||||||
|
sandbox/
|
||||||
|
|||||||
@@ -138,10 +138,13 @@ type_is_rune :: proc($T: typeid) -> bool ---
|
|||||||
type_is_float :: proc($T: typeid) -> bool ---
|
type_is_float :: proc($T: typeid) -> bool ---
|
||||||
type_is_complex :: proc($T: typeid) -> bool ---
|
type_is_complex :: proc($T: typeid) -> bool ---
|
||||||
type_is_quaternion :: proc($T: typeid) -> bool ---
|
type_is_quaternion :: proc($T: typeid) -> bool ---
|
||||||
type_is_string :: proc($T: typeid) -> bool ---
|
|
||||||
type_is_typeid :: proc($T: typeid) -> bool ---
|
type_is_typeid :: proc($T: typeid) -> bool ---
|
||||||
type_is_any :: proc($T: typeid) -> bool ---
|
type_is_any :: proc($T: typeid) -> bool ---
|
||||||
|
type_is_string :: proc($T: typeid) -> bool ---
|
||||||
type_is_string16 :: proc($T: typeid) -> bool ---
|
type_is_string16 :: proc($T: typeid) -> bool ---
|
||||||
|
type_is_cstring :: proc($T: typeid) -> bool ---
|
||||||
|
type_is_cstring16 :: proc($T: typeid) -> bool ---
|
||||||
|
|
||||||
|
|
||||||
type_is_endian_platform :: proc($T: typeid) -> bool ---
|
type_is_endian_platform :: proc($T: typeid) -> bool ---
|
||||||
type_is_endian_little :: proc($T: typeid) -> bool ---
|
type_is_endian_little :: proc($T: typeid) -> bool ---
|
||||||
@@ -154,6 +157,7 @@ type_is_indexable :: proc($T: typeid) -> bool ---
|
|||||||
type_is_sliceable :: proc($T: typeid) -> bool ---
|
type_is_sliceable :: proc($T: typeid) -> bool ---
|
||||||
type_is_comparable :: proc($T: typeid) -> bool ---
|
type_is_comparable :: proc($T: typeid) -> bool ---
|
||||||
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
|
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
|
||||||
|
type_is_nearly_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (including floats)
|
||||||
type_is_dereferenceable :: proc($T: typeid) -> bool ---
|
type_is_dereferenceable :: proc($T: typeid) -> bool ---
|
||||||
type_is_valid_map_key :: proc($T: typeid) -> bool ---
|
type_is_valid_map_key :: proc($T: typeid) -> bool ---
|
||||||
type_is_valid_matrix_elements :: proc($T: typeid) -> bool ---
|
type_is_valid_matrix_elements :: proc($T: typeid) -> bool ---
|
||||||
@@ -344,6 +348,9 @@ simd_lanes_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
|
|||||||
has_target_feature :: proc($test: $T) -> bool where type_is_string(T) || type_is_proc(T) ---
|
has_target_feature :: proc($test: $T) -> bool where type_is_string(T) || type_is_proc(T) ---
|
||||||
|
|
||||||
|
|
||||||
|
// Utility Calls
|
||||||
|
concatentate :: proc(x, y: $T, z: ..T) -> T where type_is_array(T) || type_is_slice(T) ---
|
||||||
|
|
||||||
// Returns the value of the procedure where `x` must be a call expression
|
// Returns the value of the procedure where `x` must be a call expression
|
||||||
procedure_of :: proc(x: $T) -> T where type_is_proc(T) ---
|
procedure_of :: proc(x: $T) -> T where type_is_proc(T) ---
|
||||||
|
|
||||||
@@ -374,10 +381,11 @@ objc_selector :: struct{}
|
|||||||
objc_class :: struct{}
|
objc_class :: struct{}
|
||||||
objc_ivar :: struct{}
|
objc_ivar :: struct{}
|
||||||
|
|
||||||
objc_id :: ^objc_object
|
objc_id :: ^objc_object
|
||||||
objc_SEL :: ^objc_selector
|
objc_SEL :: ^objc_selector
|
||||||
objc_Class :: ^objc_class
|
objc_Class :: ^objc_class
|
||||||
objc_Ivar :: ^objc_ivar
|
objc_Ivar :: ^objc_ivar
|
||||||
|
objc_instancetype :: distinct objc_id
|
||||||
|
|
||||||
objc_find_selector :: proc($name: string) -> objc_SEL ---
|
objc_find_selector :: proc($name: string) -> objc_SEL ---
|
||||||
objc_register_selector :: proc($name: string) -> objc_SEL ---
|
objc_register_selector :: proc($name: string) -> objc_SEL ---
|
||||||
@@ -385,6 +393,7 @@ objc_find_class :: proc($name: string) -> objc_Class ---
|
|||||||
objc_register_class :: proc($name: string) -> objc_Class ---
|
objc_register_class :: proc($name: string) -> objc_Class ---
|
||||||
objc_ivar_get :: proc(self: ^$T) -> ^$U ---
|
objc_ivar_get :: proc(self: ^$T) -> ^$U ---
|
||||||
objc_block :: proc(invoke: $T, ..any) -> ^Objc_Block(T) where type_is_proc(T) ---
|
objc_block :: proc(invoke: $T, ..any) -> ^Objc_Block(T) where type_is_proc(T) ---
|
||||||
|
objc_super :: proc(obj: ^$T) -> ^$U where type_is_subtype_of(T, objc_object) && type_is_subtype_of(U, objc_object) ---
|
||||||
|
|
||||||
valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
|
valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
|
||||||
|
|
||||||
|
|||||||
@@ -636,6 +636,8 @@ _cleanup_runtime_contextless :: proc "contextless" () {
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// type_info_base returns the base-type of a `^Type_Info` stripping the `distinct`ness from the first level
|
||||||
|
@(require_results)
|
||||||
type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -652,6 +654,10 @@ type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// type_info_core returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
|
||||||
|
// returns the backing integer type of an enum or bit_set `^Type_Info`.
|
||||||
|
// This is also aliased as `type_info_base_without_enum`
|
||||||
|
@(require_results)
|
||||||
type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -668,6 +674,10 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
|||||||
}
|
}
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type_info_base_without_enum returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
|
||||||
|
// returns the backing integer type of an enum or bit_set `^Type_Info`.
|
||||||
|
// This is also aliased as `type_info_core`
|
||||||
type_info_base_without_enum :: type_info_core
|
type_info_base_without_enum :: type_info_core
|
||||||
|
|
||||||
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
|
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
|
||||||
@@ -684,15 +694,23 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
|
|||||||
}
|
}
|
||||||
|
|
||||||
when !ODIN_NO_RTTI {
|
when !ODIN_NO_RTTI {
|
||||||
|
// typeid_base returns the base-type of a `typeid` stripping the `distinct`ness from the first level
|
||||||
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
||||||
ti := type_info_of(id)
|
ti := type_info_of(id)
|
||||||
ti = type_info_base(ti)
|
ti = type_info_base(ti)
|
||||||
return ti.id
|
return ti.id
|
||||||
}
|
}
|
||||||
|
// typeid_core returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR
|
||||||
|
// returns the backing integer type of an enum or bit_set `typeid`.
|
||||||
|
// This is also aliased as `typeid_base_without_enum`
|
||||||
typeid_core :: proc "contextless" (id: typeid) -> typeid {
|
typeid_core :: proc "contextless" (id: typeid) -> typeid {
|
||||||
ti := type_info_core(type_info_of(id))
|
ti := type_info_core(type_info_of(id))
|
||||||
return ti.id
|
return ti.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// typeid_base_without_enum returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR
|
||||||
|
// returns the backing integer type of an enum or bit_set `typeid`.
|
||||||
|
// This is also aliased as `typeid_core`
|
||||||
typeid_base_without_enum :: typeid_core
|
typeid_base_without_enum :: typeid_core
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,11 +726,15 @@ default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, opt
|
|||||||
// Nothing
|
// Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the default logger used by `context.logger`
|
||||||
|
@(require_results)
|
||||||
default_logger :: proc() -> Logger {
|
default_logger :: proc() -> Logger {
|
||||||
return Logger{default_logger_proc, nil, Logger_Level.Debug, nil}
|
return Logger{default_logger_proc, nil, Logger_Level.Debug, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the default `context`
|
||||||
|
@(require_results)
|
||||||
default_context :: proc "contextless" () -> Context {
|
default_context :: proc "contextless" () -> Context {
|
||||||
c: Context
|
c: Context
|
||||||
__init_context(&c)
|
__init_context(&c)
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ when !NO_DEFAULT_TEMP_ALLOCATOR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initializes the global temporary allocator used as the default `context.temp_allocator`.
|
||||||
|
// This is ignored when `NO_DEFAULT_TEMP_ALLOCATOR` is true.
|
||||||
@(builtin, disabled=NO_DEFAULT_TEMP_ALLOCATOR)
|
@(builtin, disabled=NO_DEFAULT_TEMP_ALLOCATOR)
|
||||||
init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) {
|
init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) {
|
||||||
when !NO_DEFAULT_TEMP_ALLOCATOR {
|
when !NO_DEFAULT_TEMP_ALLOCATOR {
|
||||||
@@ -565,6 +567,7 @@ _append_elem :: #force_no_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, a
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `append_elem` appends an element to the end of a dynamic array.
|
||||||
@builtin
|
@builtin
|
||||||
append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
when size_of(E) == 0 {
|
when size_of(E) == 0 {
|
||||||
@@ -576,6 +579,9 @@ append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `non_zero_append_elem` appends an element to the end of a dynamic array, without zeroing any reserved memory
|
||||||
|
//
|
||||||
|
// Note: Prefer using the procedure group `non_zero_append
|
||||||
@builtin
|
@builtin
|
||||||
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
when size_of(E) == 0 {
|
when size_of(E) == 0 {
|
||||||
@@ -614,6 +620,9 @@ _append_elems :: #force_no_inline proc(array: ^Raw_Dynamic_Array, size_of_elem,
|
|||||||
return arg_len, err
|
return arg_len, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `append_elems` appends `args` to the end of a dynamic array.
|
||||||
|
//
|
||||||
|
// Note: Prefer using the procedure group `append`.
|
||||||
@builtin
|
@builtin
|
||||||
append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
when size_of(E) == 0 {
|
when size_of(E) == 0 {
|
||||||
@@ -625,6 +634,9 @@ append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #ca
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `non_zero_append_elems` appends `args` to the end of a dynamic array, without zeroing any reserved memory
|
||||||
|
//
|
||||||
|
// Note: Prefer using the procedure group `non_zero_append
|
||||||
@builtin
|
@builtin
|
||||||
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
when size_of(E) == 0 {
|
when size_of(E) == 0 {
|
||||||
@@ -641,10 +653,16 @@ _append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_ze
|
|||||||
return _append_elems((^Raw_Dynamic_Array)(array), 1, 1, should_zero, loc, raw_data(arg), len(arg))
|
return _append_elems((^Raw_Dynamic_Array)(array), 1, 1, should_zero, loc, raw_data(arg), len(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `append_elem_string` appends a string to the end of a dynamic array of bytes
|
||||||
|
//
|
||||||
|
// Note: Prefer using the procedure group `append`.
|
||||||
@builtin
|
@builtin
|
||||||
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
return _append_elem_string(array, arg, true, loc)
|
return _append_elem_string(array, arg, true, loc)
|
||||||
}
|
}
|
||||||
|
// `non_zero_append_elem_string` appends a string to the end of a dynamic array of bytes, without zeroing any reserved memory
|
||||||
|
//
|
||||||
|
// Note: Prefer using the procedure group `non_zero_append`.
|
||||||
@builtin
|
@builtin
|
||||||
non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
return _append_elem_string(array, arg, false, loc)
|
return _append_elem_string(array, arg, false, loc)
|
||||||
@@ -652,6 +670,8 @@ non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, l
|
|||||||
|
|
||||||
|
|
||||||
// The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type
|
// The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type
|
||||||
|
//
|
||||||
|
// Note: Prefer using the procedure group `append`.
|
||||||
@builtin
|
@builtin
|
||||||
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
n_arg: int
|
n_arg: int
|
||||||
@@ -666,7 +686,8 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The append built-in procedure appends elements to the end of a dynamic array
|
// The append built-in procedure appends elements to the end of a dynamic array
|
||||||
@builtin append :: proc{
|
@builtin
|
||||||
|
append :: proc{
|
||||||
append_elem,
|
append_elem,
|
||||||
append_elems,
|
append_elems,
|
||||||
append_elem_string,
|
append_elem_string,
|
||||||
@@ -675,7 +696,8 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
|||||||
append_soa_elems,
|
append_soa_elems,
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin non_zero_append :: proc{
|
@builtin
|
||||||
|
non_zero_append :: proc{
|
||||||
non_zero_append_elem,
|
non_zero_append_elem,
|
||||||
non_zero_append_elems,
|
non_zero_append_elems,
|
||||||
non_zero_append_elem_string,
|
non_zero_append_elem_string,
|
||||||
@@ -685,6 +707,8 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// `append_nothing` appends an empty value to a dynamic array. It returns `1, nil` if successful, and `0, err` when it was not possible,
|
||||||
|
// whatever `err` happens to be.
|
||||||
@builtin
|
@builtin
|
||||||
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
if array == nil {
|
if array == nil {
|
||||||
@@ -696,6 +720,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// `inject_at_elem` injects an element in a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||||
@builtin
|
@builtin
|
||||||
inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||||
when !ODIN_NO_BOUNDS_CHECK {
|
when !ODIN_NO_BOUNDS_CHECK {
|
||||||
@@ -717,6 +742,7 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcas
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `inject_at_elems` injects multiple elements in a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||||
@builtin
|
@builtin
|
||||||
inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||||
when !ODIN_NO_BOUNDS_CHECK {
|
when !ODIN_NO_BOUNDS_CHECK {
|
||||||
@@ -743,6 +769,7 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadca
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `inject_at_elem_string` injects a string into a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||||
@builtin
|
@builtin
|
||||||
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||||
when !ODIN_NO_BOUNDS_CHECK {
|
when !ODIN_NO_BOUNDS_CHECK {
|
||||||
@@ -767,10 +794,13 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `inject_at` injects something into a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||||
@builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string}
|
@builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// `assign_at_elem` assigns a value at a given index. If the requested index is smaller than the current
|
||||||
|
// size of the dynamic array, it will attempt to `resize` the a new length of `index+1` and then assign as `index`.
|
||||||
@builtin
|
@builtin
|
||||||
assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||||
if index < len(array) {
|
if index < len(array) {
|
||||||
@@ -785,6 +815,8 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// `assign_at_elems` assigns a values at a given index. If the requested index is smaller than the current
|
||||||
|
// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(args)` and then assign as `index`.
|
||||||
@builtin
|
@builtin
|
||||||
assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||||
new_size := index + len(args)
|
new_size := index + len(args)
|
||||||
@@ -801,7 +833,8 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadca
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `assign_at_elem_string` assigns a string at a given index. If the requested index is smaller than the current
|
||||||
|
// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(arg)` and then assign as `index`.
|
||||||
@builtin
|
@builtin
|
||||||
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||||
new_size := index + len(arg)
|
new_size := index + len(arg)
|
||||||
@@ -818,7 +851,14 @@ assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin assign_at :: proc{assign_at_elem, assign_at_elems, assign_at_elem_string}
|
// `assign_at` assigns a value at a given index. If the requested index is smaller than the current
|
||||||
|
// size of the dynamic array, it will attempt to `resize` the a new length of `index+size_needed` and then assign as `index`.
|
||||||
|
@builtin
|
||||||
|
assign_at :: proc{
|
||||||
|
assign_at_elem,
|
||||||
|
assign_at_elems,
|
||||||
|
assign_at_elem_string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -835,6 +875,8 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {
|
|||||||
|
|
||||||
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
||||||
//
|
//
|
||||||
|
// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`).
|
||||||
|
//
|
||||||
// Note: Prefer the procedure group `reserve`.
|
// Note: Prefer the procedure group `reserve`.
|
||||||
_reserve_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
|
_reserve_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
@@ -870,11 +912,21 @@ _reserve_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
||||||
|
//
|
||||||
|
// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`).
|
||||||
|
//
|
||||||
|
// Note: Prefer the procedure group `reserve`.
|
||||||
@builtin
|
@builtin
|
||||||
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||||
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, true, loc)
|
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, true, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `non_zero_reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
||||||
|
//
|
||||||
|
// When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls `non_zero_mem_resize`).
|
||||||
|
//
|
||||||
|
// Note: Prefer the procedure group `non_zero_reserve`.
|
||||||
@builtin
|
@builtin
|
||||||
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||||
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, false, loc)
|
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, false, loc)
|
||||||
@@ -924,28 +976,33 @@ _resize_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_el
|
|||||||
|
|
||||||
// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
||||||
//
|
//
|
||||||
|
// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`).
|
||||||
|
//
|
||||||
// Note: Prefer the procedure group `resize`
|
// Note: Prefer the procedure group `resize`
|
||||||
@builtin
|
@builtin
|
||||||
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
||||||
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, true, loc=loc)
|
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, true, loc=loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `non_zero_resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
||||||
|
//
|
||||||
|
// When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls `non_zero_mem_resize`).
|
||||||
|
//
|
||||||
|
// Note: Prefer the procedure group `non_zero_resize`
|
||||||
@builtin
|
@builtin
|
||||||
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
||||||
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, false, loc=loc)
|
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, false, loc=loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
|
||||||
Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
|
//
|
||||||
|
// If `new_cap` is negative, then `len(array)` is used.
|
||||||
If `new_cap` is negative, then `len(array)` is used.
|
//
|
||||||
|
// Returns false if `cap(array) < new_cap`, or the allocator report failure.
|
||||||
Returns false if `cap(array) < new_cap`, or the allocator report failure.
|
//
|
||||||
|
// If `len(array) < new_cap`, then `len(array)` will be left unchanged.
|
||||||
If `len(array) < new_cap`, then `len(array)` will be left unchanged.
|
//
|
||||||
|
// Note: Prefer the procedure group `shrink`
|
||||||
Note: Prefer the procedure group `shrink`
|
|
||||||
*/
|
|
||||||
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
||||||
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
|
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
|
||||||
}
|
}
|
||||||
@@ -1027,6 +1084,7 @@ map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// `card` returns the number of bits that are set in a bit_set—its cardinality
|
||||||
@builtin
|
@builtin
|
||||||
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||||
return int(intrinsics.count_ones(transmute(intrinsics.type_bit_set_underlying_type(S))s))
|
return int(intrinsics.count_ones(transmute(intrinsics.type_bit_set_underlying_type(S))s))
|
||||||
@@ -1034,6 +1092,10 @@ card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Evaluates the condition and panics the program iff the condition is false.
|
||||||
|
// This uses the `context.assertion_failure_procedure` to assert.
|
||||||
|
//
|
||||||
|
// This routine will be ignored when `ODIN_DISABLE_ASSERT` is true.
|
||||||
@builtin
|
@builtin
|
||||||
@(disabled=ODIN_DISABLE_ASSERT)
|
@(disabled=ODIN_DISABLE_ASSERT)
|
||||||
assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||||
@@ -1054,9 +1116,9 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc :=
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluates the condition and aborts the program iff the condition is
|
// Evaluates the condition and panics the program iff the condition is false.
|
||||||
// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always
|
// This uses the `context.assertion_failure_procedure` to assert.
|
||||||
// execute.
|
// This routine ignores `ODIN_DISABLE_ASSERT`, and will always execute.
|
||||||
@builtin
|
@builtin
|
||||||
ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||||
if !condition {
|
if !condition {
|
||||||
@@ -1072,6 +1134,8 @@ ensure :: proc(condition: bool, message := #caller_expression(condition), loc :=
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panics the program with a message.
|
||||||
|
// This uses the `context.assertion_failure_procedure` to panic.
|
||||||
@builtin
|
@builtin
|
||||||
panic :: proc(message: string, loc := #caller_location) -> ! {
|
panic :: proc(message: string, loc := #caller_location) -> ! {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
@@ -1081,6 +1145,8 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
|
|||||||
p("panic", message, loc)
|
p("panic", message, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panics the program with a message to indicate something has yet to be implemented.
|
||||||
|
// This uses the `context.assertion_failure_procedure` to assert.
|
||||||
@builtin
|
@builtin
|
||||||
unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
@@ -1090,7 +1156,10 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
|||||||
p("not yet implemented", message, loc)
|
p("not yet implemented", message, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Evaluates the condition and panics the program iff the condition is false.
|
||||||
|
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||||
|
//
|
||||||
|
// This routine will be ignored when `ODIN_DISABLE_ASSERT` is true.
|
||||||
@builtin
|
@builtin
|
||||||
@(disabled=ODIN_DISABLE_ASSERT)
|
@(disabled=ODIN_DISABLE_ASSERT)
|
||||||
assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||||
@@ -1107,6 +1176,8 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Evaluates the condition and panics the program iff the condition is false.
|
||||||
|
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||||
@builtin
|
@builtin
|
||||||
ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||||
if !condition {
|
if !condition {
|
||||||
@@ -1118,11 +1189,15 @@ ensure_contextless :: proc "contextless" (condition: bool, message := #caller_ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panics the program with a message to indicate something has yet to be implemented.
|
||||||
|
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||||
@builtin
|
@builtin
|
||||||
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
|
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
|
||||||
default_assertion_contextless_failure_proc("panic", message, loc)
|
default_assertion_contextless_failure_proc("panic", message, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panics the program with a message.
|
||||||
|
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||||
@builtin
|
@builtin
|
||||||
unimplemented_contextless :: proc "contextless" (message := "", loc := #caller_location) -> ! {
|
unimplemented_contextless :: proc "contextless" (message := "", loc := #caller_location) -> ! {
|
||||||
default_assertion_contextless_failure_proc("not yet implemented", message, loc)
|
default_assertion_contextless_failure_proc("not yet implemented", message, loc)
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return nil, .None
|
return nil, .None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nil_allocator returns an allocator which will return `nil` for any result.
|
||||||
|
// * `.Alloc`, `.Alloc_Non_Zero`, `.Resize`, `.Resize_Non_Zeroed` will return `nil, .Out_Of_Memory`
|
||||||
|
// * `.Free` will return `nil, .None`
|
||||||
|
// * `.Free_All` will return `nil, .Mode_Not_Implemented`
|
||||||
|
// * `.Query_Features`, `.Query_Info` will return `nil, .Mode_Not_Implemented`
|
||||||
|
//
|
||||||
|
// This is extremely useful for creating a dynamic array from a buffer which does not nothing
|
||||||
|
// on a resize/reserve beyond the originally allocated memory.
|
||||||
@(require_results)
|
@(require_results)
|
||||||
nil_allocator :: proc "contextless" () -> Allocator {
|
nil_allocator :: proc "contextless" () -> Allocator {
|
||||||
return Allocator{
|
return Allocator{
|
||||||
@@ -73,6 +81,9 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// panic_allocator returns an allocator which will panic for any non-zero-sized allocation or `query_info`
|
||||||
|
//
|
||||||
|
// This is extremely useful for to check when something does a memory operation when it should not, and thus panic.
|
||||||
@(require_results)
|
@(require_results)
|
||||||
panic_allocator :: proc() -> Allocator {
|
panic_allocator :: proc() -> Allocator {
|
||||||
return Allocator{
|
return Allocator{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKIN
|
|||||||
NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_DEFAULT_TO_NIL_ALLOCATOR
|
NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_DEFAULT_TO_NIL_ALLOCATOR
|
||||||
|
|
||||||
when NO_DEFAULT_TEMP_ALLOCATOR {
|
when NO_DEFAULT_TEMP_ALLOCATOR {
|
||||||
|
// `Default_Temp_Allocator` is a `nil_allocator` when `NO_DEFAULT_TEMP_ALLOCATOR` is `true`.
|
||||||
Default_Temp_Allocator :: struct {}
|
Default_Temp_Allocator :: struct {}
|
||||||
|
|
||||||
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) {}
|
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) {}
|
||||||
@@ -20,6 +21,11 @@ when NO_DEFAULT_TEMP_ALLOCATOR {
|
|||||||
default_temp_allocator_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {
|
default_temp_allocator_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// `Default_Temp_Allocator` is an `Arena` based type of allocator. See `runtime.Arena` for its implementation.
|
||||||
|
// The default `context.temp_allocator` is typically called with `free_all(context.temp_allocator)` once per "frame-loop"
|
||||||
|
// to prevent it from "leaking" memory.
|
||||||
|
//
|
||||||
|
// Note: `Default_Temp_Allocator` is a `nil_allocator` when `NO_DEFAULT_TEMP_ALLOCATOR` is `true`.
|
||||||
Default_Temp_Allocator :: struct {
|
Default_Temp_Allocator :: struct {
|
||||||
arena: Arena,
|
arena: Arena,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,25 @@ objc_SEL :: ^intrinsics.objc_selector
|
|||||||
objc_Ivar :: ^intrinsics.objc_ivar
|
objc_Ivar :: ^intrinsics.objc_ivar
|
||||||
objc_BOOL :: bool
|
objc_BOOL :: bool
|
||||||
|
|
||||||
|
objc_super :: struct {
|
||||||
|
receiver: objc_id,
|
||||||
|
super_class: objc_Class,
|
||||||
|
}
|
||||||
|
|
||||||
objc_IMP :: proc "c" (object: objc_id, sel: objc_SEL, #c_vararg args: ..any) -> objc_id
|
objc_IMP :: proc "c" (object: objc_id, sel: objc_SEL, #c_vararg args: ..any) -> objc_id
|
||||||
|
|
||||||
foreign ObjC {
|
foreign ObjC {
|
||||||
sel_registerName :: proc "c" (name: cstring) -> objc_SEL ---
|
sel_registerName :: proc "c" (name: cstring) -> objc_SEL ---
|
||||||
|
|
||||||
objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
||||||
objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 ---
|
objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 ---
|
||||||
objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 ---
|
objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 ---
|
||||||
objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
||||||
|
|
||||||
|
// See: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-abi.h#L111
|
||||||
|
objc_msgSendSuper2 :: proc "c" (super: rawptr, op: objc_SEL, #c_vararg args: ..any) -> objc_id ---
|
||||||
|
objc_msgSendSuper2_stret :: proc "c" (super: ^objc_super, op: objc_SEL, #c_vararg args: ..any) ---
|
||||||
|
|
||||||
|
|
||||||
objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class ---
|
objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class ---
|
||||||
objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) -> objc_Class ---
|
objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) -> objc_Class ---
|
||||||
@@ -33,6 +42,7 @@ foreign ObjC {
|
|||||||
class_addIvar :: proc "c" (cls: objc_Class, name: cstring, size: uint, alignment: u8, types: cstring) -> objc_BOOL ---
|
class_addIvar :: proc "c" (cls: objc_Class, name: cstring, size: uint, alignment: u8, types: cstring) -> objc_BOOL ---
|
||||||
class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar ---
|
class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar ---
|
||||||
class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint ---
|
class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint ---
|
||||||
|
class_getSuperclass :: proc "c" (cls : objc_Class) -> objc_Class ---
|
||||||
ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr ---
|
ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr ---
|
||||||
object_getClass :: proc "c" (obj: objc_id) -> objc_Class ---
|
object_getClass :: proc "c" (obj: objc_id) -> objc_Class ---
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Wraps an `io.Stream` interface to provide buffered I/O.
|
||||||
|
package bufio
|
||||||
@@ -29,6 +29,7 @@ MIN_READ_BUFFER_SIZE :: 16
|
|||||||
@(private)
|
@(private)
|
||||||
DEFAULT_MAX_CONSECUTIVE_EMPTY_READS :: 128
|
DEFAULT_MAX_CONSECUTIVE_EMPTY_READS :: 128
|
||||||
|
|
||||||
|
// reader_init initializes using an `allocator`
|
||||||
reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator, loc := #caller_location) {
|
reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator, loc := #caller_location) {
|
||||||
size := size
|
size := size
|
||||||
size = max(size, MIN_READ_BUFFER_SIZE)
|
size = max(size, MIN_READ_BUFFER_SIZE)
|
||||||
@@ -37,6 +38,7 @@ reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, all
|
|||||||
b.buf = make([]byte, size, allocator, loc)
|
b.buf = make([]byte, size, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reader_init initializes using a user provided bytes buffer `buf`
|
||||||
reader_init_with_buf :: proc(b: ^Reader, rd: io.Reader, buf: []byte) {
|
reader_init_with_buf :: proc(b: ^Reader, rd: io.Reader, buf: []byte) {
|
||||||
reader_reset(b, rd)
|
reader_reset(b, rd)
|
||||||
b.buf_allocator = {}
|
b.buf_allocator = {}
|
||||||
@@ -49,10 +51,12 @@ reader_destroy :: proc(b: ^Reader) {
|
|||||||
b^ = {}
|
b^ = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reader_size returns the number of bytes in the backing buffer
|
||||||
reader_size :: proc(b: ^Reader) -> int {
|
reader_size :: proc(b: ^Reader) -> int {
|
||||||
return len(b.buf)
|
return len(b.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reader_reset resets the read and write positions, and the error values
|
||||||
reader_reset :: proc(b: ^Reader, r: io.Reader) {
|
reader_reset :: proc(b: ^Reader, r: io.Reader) {
|
||||||
b.rd = r
|
b.rd = r
|
||||||
b.r, b.w = 0, 0
|
b.r, b.w = 0, 0
|
||||||
|
|||||||
+21
-7
@@ -46,6 +46,7 @@ DEFAULT_MAX_SCAN_TOKEN_SIZE :: 1<<16
|
|||||||
@(private)
|
@(private)
|
||||||
_INIT_BUF_SIZE :: 4096
|
_INIT_BUF_SIZE :: 4096
|
||||||
|
|
||||||
|
// Initializes a Scanner buffer an allocator `buf_allocator`
|
||||||
scanner_init :: proc(s: ^Scanner, r: io.Reader, buf_allocator := context.allocator) -> ^Scanner {
|
scanner_init :: proc(s: ^Scanner, r: io.Reader, buf_allocator := context.allocator) -> ^Scanner {
|
||||||
s.r = r
|
s.r = r
|
||||||
s.split = scan_lines
|
s.split = scan_lines
|
||||||
@@ -53,6 +54,8 @@ scanner_init :: proc(s: ^Scanner, r: io.Reader, buf_allocator := context.allocat
|
|||||||
s.buf.allocator = buf_allocator
|
s.buf.allocator = buf_allocator
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initializes a Scanner buffer a user provided bytes buffer `buf`
|
||||||
scanner_init_with_buffer :: proc(s: ^Scanner, r: io.Reader, buf: []byte) -> ^Scanner {
|
scanner_init_with_buffer :: proc(s: ^Scanner, r: io.Reader, buf: []byte) -> ^Scanner {
|
||||||
s.r = r
|
s.r = r
|
||||||
s.split = scan_lines
|
s.split = scan_lines
|
||||||
@@ -75,24 +78,27 @@ scanner_error :: proc(s: ^Scanner) -> Scanner_Error {
|
|||||||
return s._err
|
return s._err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the most recent token created by scanner_scan.
|
// Returns the most recent token created by 'scan'.
|
||||||
// The underlying array may point to data that may be overwritten
|
// The underlying array may point to data that may be overwritten
|
||||||
// by another call to scanner_scan.
|
// by another call to 'scan'.
|
||||||
// Treat the returned value as if it is immutable.
|
// Treat the returned value as if it is immutable.
|
||||||
scanner_bytes :: proc(s: ^Scanner) -> []byte {
|
scanner_bytes :: proc(s: ^Scanner) -> []byte {
|
||||||
return s.token
|
return s.token
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the most recent token created by scanner_scan.
|
// Returns the most recent token created by 'scan'.
|
||||||
// The underlying array may point to data that may be overwritten
|
// The underlying array may point to data that may be overwritten
|
||||||
// by another call to scanner_scan.
|
// by another call to 'scan'.
|
||||||
// Treat the returned value as if it is immutable.
|
// Treat the returned value as if it is immutable.
|
||||||
scanner_text :: proc(s: ^Scanner) -> string {
|
scanner_text :: proc(s: ^Scanner) -> string {
|
||||||
return string(s.token)
|
return string(s.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// scanner_scan advances the scanner
|
// scanner_scan is an alias of scan
|
||||||
scanner_scan :: proc(s: ^Scanner) -> bool {
|
scanner_scan :: scan
|
||||||
|
|
||||||
|
// scan advances the Scanner
|
||||||
|
scan :: proc(s: ^Scanner) -> bool {
|
||||||
set_err :: proc(s: ^Scanner, err: Scanner_Error) {
|
set_err :: proc(s: ^Scanner, err: Scanner_Error) {
|
||||||
switch s._err {
|
switch s._err {
|
||||||
case nil, .EOF:
|
case nil, .EOF:
|
||||||
@@ -229,6 +235,7 @@ scanner_scan :: proc(s: ^Scanner) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scan_bytes is a splitting procedure that returns each byte as a token
|
||||||
scan_bytes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
scan_bytes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
||||||
if at_eof && len(data) == 0 {
|
if at_eof && len(data) == 0 {
|
||||||
return
|
return
|
||||||
@@ -236,6 +243,10 @@ scan_bytes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte,
|
|||||||
return 1, data[0:1], nil, false
|
return 1, data[0:1], nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scan_runes is a splitting procedure that returns each UTF-8 encoded rune as a token.
|
||||||
|
// The lsit of runes return is equivalent to that of iterating over a string in a 'for in' loop, meaning any
|
||||||
|
// erroneous UTF-8 encodings will be returned as U+FFFD. Unfortunately this means it is impossible for the "client"
|
||||||
|
// to know whether a U+FFFD is an expected replacement rune or an encoding of an error.
|
||||||
scan_runes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
scan_runes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
||||||
if at_eof && len(data) == 0 {
|
if at_eof && len(data) == 0 {
|
||||||
return
|
return
|
||||||
@@ -264,7 +275,8 @@ scan_runes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte,
|
|||||||
token = ERROR_RUNE
|
token = ERROR_RUNE
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// scan_words is a splitting procedure that returns each Unicode-space-separated word of text, excluding the surrounded spaces.
|
||||||
|
// It will never return return an empty string.
|
||||||
scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
||||||
is_space :: proc "contextless" (r: rune) -> bool {
|
is_space :: proc "contextless" (r: rune) -> bool {
|
||||||
switch r {
|
switch r {
|
||||||
@@ -312,6 +324,8 @@ scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scan_lines is a splitting procedure that returns each line of text stripping of any trailing newline and an optional preceding carriage return (\r?\n).
|
||||||
|
// A new line is allowed to be empty.
|
||||||
scan_lines :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
scan_lines :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) {
|
||||||
trim_carriage_return :: proc "contextless" (data: []byte) -> []byte {
|
trim_carriage_return :: proc "contextless" (data: []byte) -> []byte {
|
||||||
if len(data) > 0 && data[len(data)-1] == '\r' {
|
if len(data) > 0 && data[len(data)-1] == '\r' {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Writer :: struct {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialized a Writer with an `allocator`
|
||||||
writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) {
|
writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) {
|
||||||
size := size
|
size := size
|
||||||
size = max(size, MIN_READ_BUFFER_SIZE)
|
size = max(size, MIN_READ_BUFFER_SIZE)
|
||||||
@@ -27,6 +28,7 @@ writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, all
|
|||||||
b.buf = make([]byte, size, allocator)
|
b.buf = make([]byte, size, allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialized a Writer with a user provided buffer `buf`
|
||||||
writer_init_with_buf :: proc(b: ^Writer, wr: io.Writer, buf: []byte) {
|
writer_init_with_buf :: proc(b: ^Writer, wr: io.Writer, buf: []byte) {
|
||||||
writer_reset(b, wr)
|
writer_reset(b, wr)
|
||||||
b.buf_allocator = {}
|
b.buf_allocator = {}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Procedures for manipulation of `[]byte` slices.
|
||||||
package bytes
|
package bytes
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
@@ -134,8 +135,13 @@ equal_fold :: proc(u, v: []byte) -> bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bill): Unicode folding
|
r := unicode.simple_fold(sr)
|
||||||
|
for r != sr && r < tr {
|
||||||
|
r = unicode.simple_fold(sr)
|
||||||
|
}
|
||||||
|
if r == tr {
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Defines the basic types used by `C` programs for foreign function and data structure interop.
|
||||||
package c
|
package c
|
||||||
|
|
||||||
import builtin "base:builtin"
|
import builtin "base:builtin"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Declares the commonly used things in `libc` (`C` standard library).
|
||||||
|
package libc
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// A collection of utilities to aid with other `compress`ion packages.
|
||||||
|
package compress
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -6,10 +9,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation, optimization.
|
Jeroen van Rijn: Initial implementation, optimization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// package compress is a collection of utilities to aid with other compression packages
|
|
||||||
package compress
|
|
||||||
|
|
||||||
import "core:io"
|
import "core:io"
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
+12
-10
@@ -1,15 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
A small `GZIP` unpacker.
|
||||||
Made available under Odin's BSD-3 license.
|
|
||||||
|
|
||||||
List of contributors:
|
|
||||||
Jeroen van Rijn: Initial implementation.
|
|
||||||
Ginger Bill: Cosmetic changes.
|
|
||||||
|
|
||||||
A small GZIP implementation as an example.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Example:
|
Example:
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
@@ -88,3 +79,14 @@ Example:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
package compress_gzip
|
package compress_gzip
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
|
List of contributors:
|
||||||
|
Jeroen van Rijn: Initial implementation.
|
||||||
|
Ginger Bill: Cosmetic changes.
|
||||||
|
|
||||||
|
A small GZIP implementation as an example.
|
||||||
|
*/
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
|
package compress_shoco
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file was generated, so don't edit this by hand.
|
This file was generated, so don't edit this by hand.
|
||||||
Transliterated from https://github.com/Ed-von-Schleck/shoco/blob/master/shoco_model.h,
|
Transliterated from https://github.com/Ed-von-Schleck/shoco/blob/master/shoco_model.h,
|
||||||
which is an English word model.
|
which is an English word model.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package compress_shoco
|
|
||||||
|
|
||||||
DEFAULT_MODEL :: Shoco_Model {
|
DEFAULT_MODEL :: Shoco_Model {
|
||||||
min_char = 39,
|
min_char = 39,
|
||||||
max_char = 122,
|
max_char = 122,
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// `Shoco` short string compression and decompression.
|
||||||
|
package compress_shoco
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -8,9 +11,6 @@
|
|||||||
An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm.
|
An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// package shoco is an implementation of the shoco short string compressor.
|
|
||||||
package compress_shoco
|
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
import "core:compress"
|
import "core:compress"
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
`Deflate` decompression of raw and `ZLIB`-type streams.
|
||||||
Made available under Odin's BSD-3 license.
|
|
||||||
|
|
||||||
List of contributors:
|
|
||||||
Jeroen van Rijn: Initial implementation.
|
|
||||||
|
|
||||||
An example of how to use `zlib.inflate`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Example:
|
Example:
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -49,3 +41,13 @@ Example:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
package compress_zlib
|
package compress_zlib
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
|
List of contributors:
|
||||||
|
Jeroen van Rijn: Initial implementation.
|
||||||
|
|
||||||
|
An example of how to use `zlib.inflate`.
|
||||||
|
*/
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
/*
|
// A non-intrusive and non-recursive implementation of `AVL` trees.
|
||||||
package avl implements an AVL tree.
|
|
||||||
|
|
||||||
The implementation is non-intrusive, and non-recursive.
|
|
||||||
*/
|
|
||||||
package container_avl
|
package container_avl
|
||||||
|
|
||||||
@(require) import "base:intrinsics"
|
@(require) import "base:intrinsics"
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
|
A dynamically-sized array of bits.
|
||||||
|
|
||||||
The Bit Array can be used in several ways:
|
The Bit Array can be used in several ways:
|
||||||
|
|
||||||
By default you don't need to instantiate a Bit Array.
|
By default you don't need to instantiate a `Bit_Array`.
|
||||||
Example:
|
Example:
|
||||||
package test
|
package test
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ Example:
|
|||||||
destroy(&bits)
|
destroy(&bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
A Bit Array can optionally allow for negative indices, if the minimum value was given during creation.
|
A `Bit_Array` can optionally allow for negative indices, if the minimum value was given during creation.
|
||||||
Example:
|
Example:
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Package list implements an intrusive doubly-linked list.
|
An intrusive doubly-linked list.
|
||||||
|
|
||||||
An intrusive container requires a `Node` to be embedded in your own structure, like this.
|
The intrusive container requires a `Node` to be embedded in your own structure, like this.
|
||||||
Example:
|
Example:
|
||||||
My_String :: struct {
|
My_String :: struct {
|
||||||
node: list.Node,
|
node: list.Node,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// A least-recently-used (`LRU`) cache. It automatically removes older entries if its capacity is reached.
|
||||||
package container_lru
|
package container_lru
|
||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// A priority queue data structure.
|
||||||
package container_priority_queue
|
package container_priority_queue
|
||||||
|
|
||||||
import "base:builtin"
|
import "base:builtin"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// A dynamically resizable double-ended queue/ring-buffer.
|
||||||
package container_queue
|
package container_queue
|
||||||
|
|
||||||
import "base:builtin"
|
import "base:builtin"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// This package implements a red-black tree
|
// A red-black tree with the same API as our AVL tree.
|
||||||
package container_rbtree
|
package container_rbtree
|
||||||
|
|
||||||
@(require) import "base:intrinsics"
|
@(require) import "base:intrinsics"
|
||||||
@@ -128,9 +128,9 @@ find_value :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (value: Value, ok: bo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// find_or_insert attempts to insert the value into the tree, and returns
|
// find_or_insert attempts to insert the key-value pair into the tree, and returns
|
||||||
// the node, a boolean indicating if the value was inserted, and the
|
// the node, a boolean indicating if a new node was inserted, and the
|
||||||
// node allocator error if relevant. If the value is already present, the existing node is updated.
|
// node allocator error if relevant. If the key is already present, the existing node is updated and returned.
|
||||||
find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: ^Node(Key, Value), inserted: bool, err: runtime.Allocator_Error) {
|
find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: ^Node(Key, Value), inserted: bool, err: runtime.Allocator_Error) {
|
||||||
n_ptr := &t._root
|
n_ptr := &t._root
|
||||||
for n_ptr^ != nil {
|
for n_ptr^ != nil {
|
||||||
@@ -141,6 +141,7 @@ find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n:
|
|||||||
case .Greater:
|
case .Greater:
|
||||||
n_ptr = &n._right
|
n_ptr = &n._right
|
||||||
case .Equal:
|
case .Equal:
|
||||||
|
n.value = value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Package small_array implements a dynamic array like
|
A dynamic array-like interface on a stack-allocated, fixed-size array.
|
||||||
interface on a stack-allocated, fixed-size array.
|
|
||||||
|
|
||||||
The Small_Array type is optimal for scenarios where you need
|
The `Small_Array` type is optimal for scenarios where you need
|
||||||
a container for a fixed number of elements of a specific type,
|
a container for a fixed number of elements of a specific type,
|
||||||
with the total number known at compile time but the exact
|
with the total number known at compile time but the exact
|
||||||
number to be used determined at runtime.
|
number to be used determined at runtime.
|
||||||
@@ -33,7 +32,7 @@ Example:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// the Small_Array can be an ordinary parameter 'generic' over
|
// the `Small_Array` can be an ordinary parameter 'generic' over
|
||||||
// the actual length to be usable with different sizes
|
// the actual length to be usable with different sizes
|
||||||
print_elements :: proc(arr: ^small_array.Small_Array($N, rune)) {
|
print_elements :: proc(arr: ^small_array.Small_Array($N, rune)) {
|
||||||
for r in small_array.slice(arr) {
|
for r in small_array.slice(arr) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// The following is a generic O(V+E) topological sorter implementation.
|
// A generic `O(V+E)` topological sorter implementation. This is the fastest known method for topological sorting.
|
||||||
// This is the fastest known method for topological sorting and Odin's
|
// Odin's map type is being used to accelerate lookups.
|
||||||
// map type is being used to accelerate lookups.
|
|
||||||
package container_topological_sort
|
package container_topological_sort
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package aead provides a generic interface to the supported Authenticated
|
A generic interface to Authenticated Encryption with Associated Data (`AEAD`) algorithms.
|
||||||
Encryption with Associated Data algorithms.
|
|
||||||
|
|
||||||
Both a one-shot and context based interface are provided, with similar
|
Both a one-shot and context based interface are provided, with similar
|
||||||
usage. If multiple messages are to be sealed/opened via the same key,
|
usage. If multiple messages are to be sealed/opened via the same key,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
package aegis implements the AEGIS-128L and AEGIS-256 Authenticated
|
`AEGIS-128L` and `AEGIS-256` AEAD algorithms.
|
||||||
Encryption with Additional Data algorithms.
|
|
||||||
|
Where AEAD stands for Authenticated Encryption with Additional Data.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://www.ietf.org/archive/id/draft-irtf-cfrg-aegis-aead-12.txt ]]
|
- [[ https://www.ietf.org/archive/id/draft-irtf-cfrg-aegis-aead-12.txt ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package aes implements the AES block cipher and some common modes.
|
The `AES` block cipher and some common modes.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]]
|
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package blake2b implements the BLAKE2b hash algorithm.
|
`BLAKE2b` hash algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
|
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package blake2s implements the BLAKE2s hash algorithm.
|
`BLAKE2s` hash algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
|
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers.
|
`ChaCha20` and `XChaCha20` stream ciphers.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
|
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 and
|
`AEAD_CHACHA20_POLY1305` and `AEAD_XChaCha20_Poly1305` algorithms.
|
||||||
AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data
|
|
||||||
algorithms.
|
Where AEAD stands for Authenticated Encryption with Additional Data.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
|
- [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
/*
|
// A selection of cryptography algorithms and useful helper routines.
|
||||||
package crypto implements a selection of cryptography algorithms and useful
|
|
||||||
helper routines.
|
|
||||||
*/
|
|
||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package deoxysii implements the Deoxys-II-256 Authenticated Encryption
|
`Deoxys-II-256` Authenticated Encryption with Additional Data (`AEAD`) algorithm.
|
||||||
with Additional Data algorithm.
|
|
||||||
|
|
||||||
- [[ https://sites.google.com/view/deoxyscipher ]]
|
- [[ https://sites.google.com/view/deoxyscipher ]]
|
||||||
- [[ https://thomaspeyrin.github.io/web/assets/docs/papers/Jean-etal-JoC2021.pdf ]]
|
- [[ https://thomaspeyrin.github.io/web/assets/docs/papers/Jean-etal-JoC2021.pdf ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package ed25519 implements the Ed25519 EdDSA signature algorithm.
|
`Ed25519` EdDSA signature algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://datatracker.ietf.org/doc/html/rfc8032 ]]
|
- [[ https://datatracker.ietf.org/doc/html/rfc8032 ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package hash provides a generic interface to the supported hash algorithms.
|
A generic interface to the supported hash algorithms.
|
||||||
|
|
||||||
A high-level convenience procedure group `hash` is provided to easily
|
A high-level convenience procedure group `hash` is provided to easily
|
||||||
accomplish common tasks.
|
accomplish common tasks.
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package hkdf implements the HKDF HMAC-based Extract-and-Expand Key
|
`HKDF` HMAC-based Extract-and-Expand Key Derivation Function.
|
||||||
Derivation Function.
|
|
||||||
|
|
||||||
See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]]
|
See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]]
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package hmac implements the HMAC MAC algorithm.
|
`HMAC` message authentication code (`MAC`) algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf ]]
|
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package kmac implements the KMAC MAC algorithm.
|
`KMAC` message authentication code (`MAC`) algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package keccak implements the Keccak hash algorithm family.
|
`Keccak` hash algorithm family.
|
||||||
|
|
||||||
During the SHA-3 standardization process, the padding scheme was changed
|
During the SHA-3 standardization process, the padding scheme was changed
|
||||||
thus Keccac and SHA-3 produce different outputs. Most users should use
|
thus Keccac and SHA-3 produce different outputs. Most users should use
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package md5 implements the MD5 hash algorithm.
|
`MD5` hash algorithm.
|
||||||
|
|
||||||
WARNING: The MD5 algorithm is known to be insecure and should only be
|
WARNING: The MD5 algorithm is known to be insecure and should only be
|
||||||
used for interoperating with legacy applications.
|
used for interoperating with legacy applications.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package sha1 implements the SHA1 hash algorithm.
|
`SHA1` hash algorithm.
|
||||||
|
|
||||||
WARNING: The SHA1 algorithm is known to be insecure and should only be
|
WARNING: The SHA1 algorithm is known to be insecure and should only be
|
||||||
used for interoperating with legacy applications.
|
used for interoperating with legacy applications.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package pbkdf2 implements the PBKDF2 password-based key derivation function.
|
`PBKDF2` password-based key derivation function.
|
||||||
|
|
||||||
See: [[ https://www.rfc-editor.org/rfc/rfc2898 ]]
|
See: [[ https://www.rfc-editor.org/rfc/rfc2898 ]]
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package poly1305 implements the Poly1305 one-time MAC algorithm.
|
`Poly1305` one-time MAC algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
|
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package ristretto255 implement the ristretto255 prime-order group.
|
Ristretto255 prime-order group.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://www.rfc-editor.org/rfc/rfc9496 ]]
|
- [[ https://www.rfc-editor.org/rfc/rfc9496 ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package sha2 implements the SHA2 hash algorithm family.
|
`SHA2` hash algorithm family.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
|
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package sha3 implements the SHA3 hash algorithm family.
|
`SHA3` hash algorithm family.
|
||||||
|
|
||||||
The SHAKE XOF can be found in crypto/shake. While discouraged if the
|
The SHAKE XOF can be found in crypto/shake. While discouraged if the
|
||||||
pre-standardization Keccak algorithm is required, it can be found in
|
pre-standardization Keccak algorithm is required, it can be found in
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package shake implements the SHAKE and cSHAKE XOF algorithm families.
|
`SHAKE` and `cSHAKE` XOF algorithm families.
|
||||||
|
|
||||||
The SHA3 hash algorithm can be found in the crypto/sha3.
|
The SHA3 hash algorithm can be found in the crypto/sha3.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package siphash Implements the SipHash hashing algorithm.
|
`SipHash` hashing algorithm.
|
||||||
|
|
||||||
Use the specific procedures for a certain setup. The generic procedures will default to Siphash 2-4.
|
Use the specific procedures for a certain setup. The generic procedures will default to Siphash 2-4.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package sm3 implements the SM3 hash algorithm.
|
`SM3` hash algorithm.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 ]]
|
- [[ https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 ]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package tuplehash implements the TupleHash and TupleHashXOF algorithms.
|
`TupleHash` and `TupleHashXOF` algorithms.
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package x25519 implements the X25519 (aka curve25519) Elliptic-Curve
|
`X25519` (aka `curve25519`) Elliptic-Curve Diffie-Hellman key exchange protocol.
|
||||||
Diffie-Hellman key exchange protocol.
|
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
|
- [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package x448 implements the X448 (aka curve448) Elliptic-Curve
|
`X448` (aka `curve448`) Elliptic-Curve Diffie-Hellman key exchange protocol.
|
||||||
Diffie-Hellman key exchange protocol.
|
|
||||||
|
|
||||||
See:
|
See:
|
||||||
- [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
|
- [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// A reader for the Windows `PE` executable format for debug purposes.
|
||||||
package debug_pe
|
package debug_pe
|
||||||
|
|
||||||
PE_SIGNATURE_OFFSET_INDEX_POS :: 0x3c
|
PE_SIGNATURE_OFFSET_INDEX_POS :: 0x3c
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
A debug stack trace library. Only works when debug symbols are enabled `-debug`.
|
Stack trace library. Only works when debug symbols are enabled using `-debug`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Package `core:dynlib` implements loading of shared libraries/DLLs and their symbols.
|
Cross-platform loading of shared libraries/DLLs and their symbols.
|
||||||
|
|
||||||
The behaviour of dynamically loaded libraries is specific to the target platform of the program.
|
The behaviour of dynamically loaded libraries is specific to the target platform of the program.
|
||||||
For in depth detail on the underlying behaviour please refer to your target platform's documentation.
|
For in depth detail on the underlying behaviour please refer to your target platform's documentation.
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
// Base32 encoding/decoding implementation as specified in RFC 4648.
|
/*
|
||||||
// [[ More; https://www.rfc-editor.org/rfc/rfc4648.html ]]
|
`Base32` encoding and decoding, as specified in [[ RFC 4648; https://www.rfc-editor.org/rfc/rfc4648.html ]].
|
||||||
|
|
||||||
|
A secondary param can be used to supply a custom alphabet to `encode` and a matching decoding table to `decode`.
|
||||||
|
|
||||||
|
If none is supplied it just uses the standard Base32 alphabet.
|
||||||
|
In case your specific version does not use padding, you may
|
||||||
|
truncate it from the encoded output.
|
||||||
|
|
||||||
|
Error represents errors that can occur during base32 decoding operations.
|
||||||
|
As per RFC 4648:
|
||||||
|
- Section 3.3: Invalid character handling
|
||||||
|
- Section 3.2: Padding requirements
|
||||||
|
- Section 6: Base32 encoding specifics (including block size requirements)
|
||||||
|
*/
|
||||||
package encoding_base32
|
package encoding_base32
|
||||||
|
|
||||||
// @note(zh): Encoding utility for Base32
|
|
||||||
// A secondary param can be used to supply a custom alphabet to
|
|
||||||
// @link(encode) and a matching decoding table to @link(decode).
|
|
||||||
// If none is supplied it just uses the standard Base32 alphabet.
|
|
||||||
// In case your specific version does not use padding, you may
|
|
||||||
// truncate it from the encoded output.
|
|
||||||
|
|
||||||
// Error represents errors that can occur during base32 decoding operations.
|
|
||||||
// As per RFC 4648:
|
|
||||||
// - Section 3.3: Invalid character handling
|
|
||||||
// - Section 3.2: Padding requirements
|
|
||||||
// - Section 6: Base32 encoding specifics (including block size requirements)
|
|
||||||
Error :: enum {
|
Error :: enum {
|
||||||
None,
|
None,
|
||||||
Invalid_Character, // Input contains characters outside the specified alphabet
|
Invalid_Character, // Input contains characters outside the specified alphabet
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
|
/*
|
||||||
|
`Base64` encoding and decoding.
|
||||||
|
|
||||||
|
A secondary param can be used to supply a custom alphabet to `encode` and a matching decoding table to `decode`.
|
||||||
|
|
||||||
|
If none is supplied it just uses the standard Base64 alphabet.
|
||||||
|
In case your specific version does not use padding, you may
|
||||||
|
truncate it from the encoded output.
|
||||||
|
*/
|
||||||
package encoding_base64
|
package encoding_base64
|
||||||
|
|
||||||
import "core:io"
|
import "core:io"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
// @note(zh): Encoding utility for Base64
|
|
||||||
// A secondary param can be used to supply a custom alphabet to
|
|
||||||
// @link(encode) and a matching decoding table to @link(decode).
|
|
||||||
// If none is supplied it just uses the standard Base64 alphabet.
|
|
||||||
// Incase your specific version does not use padding, you may
|
|
||||||
// truncate it from the encoded output.
|
|
||||||
|
|
||||||
ENC_TABLE := [64]byte {
|
ENC_TABLE := [64]byte {
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Package cbor encodes, decodes, marshals and unmarshals types from/into RCF 8949 compatible CBOR binary.
|
Encodes and decodes types from/into [[ RCF 8949; https://www.rfc-editor.org/rfc/rfc8949.html ]] compatible `CBOR` binary.
|
||||||
|
|
||||||
Also provided are conversion to and from JSON and the CBOR diagnostic format.
|
Also provided are conversion to and from JSON and the CBOR diagnostic format.
|
||||||
|
|
||||||
**Allocations:**
|
**Allocations:**
|
||||||
@@ -166,4 +167,3 @@ Output:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
package encoding_cbor
|
package encoding_cbor
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package csv reads and writes comma-separated values (CSV) files.
|
Reader and writer for comma-separated values (`CSV`) files, per [[ RFC 4180 ; https://tools.ietf.org/html/rfc4180.html ]].
|
||||||
This package supports the format described in [[ RFC 4180; https://tools.ietf.org/html/rfc4180.html ]]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Package endian implements a simple translation between bytes and numbers with
|
A simple translation between bytes and numbers with specific endian encodings.
|
||||||
specific endian encodings.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
buf: [100]u8
|
buf: [100]u8
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Encode and decode `rune`s to/from a Unicode `&entity;`.
|
||||||
Made available under Odin's BSD-3 license.
|
|
||||||
|
|
||||||
List of contributors:
|
|
||||||
Jeroen van Rijn: Initial implementation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
A unicode entity encoder/decoder.
|
|
||||||
|
|
||||||
This code has several procedures to map unicode runes to/from different textual encodings.
|
This code has several procedures to map unicode runes to/from different textual encodings.
|
||||||
- SGML/XML/HTML entity
|
- SGML/XML/HTML entity
|
||||||
@@ -21,6 +13,14 @@
|
|||||||
*/
|
*/
|
||||||
package encoding_unicode_entity
|
package encoding_unicode_entity
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
|
List of contributors:
|
||||||
|
Jeroen van Rijn: Initial implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
import "core:unicode"
|
import "core:unicode"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Encoding and decoding of hex-encoded binary, e.g. `0x23` -> `#`.
|
||||||
package encoding_hex
|
package encoding_hex
|
||||||
|
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Implementation of the HxA 3D asset format
|
Eskil Steenberg's `HxA` 3D asset interchange format.
|
||||||
|
|
||||||
HxA is a interchangeable graphics asset format.
|
HxA is a interchangeable graphics asset format.
|
||||||
Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com
|
Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Reader and writer for a variant of the `.ini` file format with `key = value` entries in `[sections]`.
|
||||||
package encoding_ini
|
package encoding_ini
|
||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
@@ -176,7 +176,11 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
|||||||
return .Unsupported_Type
|
return .Unsupported_Type
|
||||||
|
|
||||||
case runtime.Type_Info_Pointer:
|
case runtime.Type_Info_Pointer:
|
||||||
return .Unsupported_Type
|
if v.id == typeid_of(Null) {
|
||||||
|
io.write_string(w, "null") or_return
|
||||||
|
} else {
|
||||||
|
return .Unsupported_Type
|
||||||
|
}
|
||||||
|
|
||||||
case runtime.Type_Info_Multi_Pointer:
|
case runtime.Type_Info_Multi_Pointer:
|
||||||
return .Unsupported_Type
|
return .Unsupported_Type
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package encoding_json
|
|
||||||
|
|
||||||
import "core:strings"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Encoding and decoding JSON in strict `JSON`, [[ JSON5 ; https://json5.org/ ]] and [[ BitSquid ; https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html ]] variants.
|
||||||
|
|
||||||
|
Using one of these `Specification`s.
|
||||||
JSON
|
JSON
|
||||||
strict JSON
|
strict JSON
|
||||||
JSON5
|
JSON5
|
||||||
@@ -32,6 +31,10 @@ import "core:strings"
|
|||||||
* Quotes around object keys are optional if the keys are valid identifiers.
|
* Quotes around object keys are optional if the keys are valid identifiers.
|
||||||
* : can be replaced with =
|
* : can be replaced with =
|
||||||
*/
|
*/
|
||||||
|
package encoding_json
|
||||||
|
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
Specification :: enum {
|
Specification :: enum {
|
||||||
JSON,
|
JSON,
|
||||||
JSON5, // https://json5.org/
|
JSON5, // https://json5.org/
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package uuid implements Universally Unique Identifiers according to the
|
Universally Unique Identifiers (`UUID`) according to [[ RFC 4122 ; https://tools.ietf.org/html/rfc4122.html ]], with additions from [[ RFC 9562 ; https://tools.ietf.org/html/rfc9562.html ]].
|
||||||
standard originally outlined in RFC 4122 with additions from RFC 9562.
|
|
||||||
|
|
||||||
The UUIDs are textually represented and read in the following string format:
|
The UUIDs are textually represented and read in the following string format:
|
||||||
`00000000-0000-v000-V000-000000000000`
|
`00000000-0000-v000-V000-000000000000`
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
package uuid/legacy implements versions 3 and 5 of UUID generation, both of
|
Versions 3 and 5 of `UUID` generation, both of which use legacy (`MD5` + `SHA1`) hashes.
|
||||||
which are using hashing algorithms (MD5 and SHA1, respectively) that are known
|
Those are known these days to no longer be secure.
|
||||||
these days to no longer be secure.
|
|
||||||
*/
|
*/
|
||||||
package uuid_legacy
|
package uuid_legacy
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Implementation of the LEB128 variable integer encoding as used by DWARF encoding and DEX files, among others.
|
`LEB128` variable integer encoding and decoding, as used by `DWARF` & `DEX` files.
|
||||||
|
|
||||||
Author of this Odin package: Jeroen van Rijn
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package encoding_varint
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -6,8 +8,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package encoding_varint
|
|
||||||
|
|
||||||
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file.
|
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file.
|
||||||
// Instead we'll set limits on the values we'll encode/decode
|
// Instead we'll set limits on the values we'll encode/decode
|
||||||
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be `0b0000_0011`.
|
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be `0b0000_0011`.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
XML 1.0 / 1.1 parser
|
A parser for a useful subset of the `XML` specification.
|
||||||
|
|
||||||
A from-scratch XML implementation, loosely modelled on the [[ spec; https://www.w3.org/TR/2006/REC-xml11-20060816 ]].
|
A from-scratch `XML` implementation, loosely modelled on the [[ spec; https://www.w3.org/TR/2006/REC-xml11-20060816 ]].
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
- Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage.
|
- Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage.
|
||||||
@@ -11,8 +11,8 @@ Caveats:
|
|||||||
- We do NOT support HTML in this package, as that may or may not be valid XML.
|
- We do NOT support HTML in this package, as that may or may not be valid XML.
|
||||||
If it works, great. If it doesn't, that's not considered a bug.
|
If it works, great. If it doesn't, that's not considered a bug.
|
||||||
|
|
||||||
- We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences.
|
- We do NOT support `UTF-16`. If you have a `UTF-16` XML file, please convert it to `UTF-8` first. Also, our condolences.
|
||||||
- <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options.
|
- `<[!ELEMENT` and `<[!ATTLIST` are not supported, and will be either ignored or return an error depending on the parser options.
|
||||||
|
|
||||||
MAYBE:
|
MAYBE:
|
||||||
- XML writer?
|
- XML writer?
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
package encoding_xml
|
||||||
/*
|
/*
|
||||||
|
An XML 1.0 / 1.1 parser
|
||||||
|
|
||||||
2021-2022 Jeroen van Rijn <nom@duclavier.com>.
|
2021-2022 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
available under Odin's BSD-3 license.
|
available under Odin's BSD-3 license.
|
||||||
|
|
||||||
@@ -6,9 +9,6 @@
|
|||||||
- Jeroen van Rijn: Initial implementation.
|
- Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package encoding_xml
|
|
||||||
// An XML 1.0 / 1.1 parser
|
|
||||||
|
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "core:encoding/entity"
|
import "core:encoding/entity"
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package flags implements a command-line argument parser.
|
Command-line argument parser.
|
||||||
|
|
||||||
It works by using Odin's run-time type information to determine where and how
|
It works by using Odin's run-time type information to determine where and how
|
||||||
to store data on a struct provided by the program. Type conversion is handled
|
to store data on a struct provided by the program. Type conversion is handled
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package fmt implements formatted I/O with procedures similar to C's printf and Python's format.
|
Formatted `I/O` with procedures similar to `C`'s printf and `Python`'s format.
|
||||||
The format 'verbs' are derived from C's but simpler.
|
The format 'verbs' are derived from C's but simpler.
|
||||||
|
|
||||||
Printing
|
Printing
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// `crc32`, `crc64`, `adler32`, `djb`, `fnv`, `jenkins`, `murmur` and other hashes.
|
||||||
|
package hash
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
// Yann Collet's `xxhash`.
|
||||||
|
//
|
||||||
|
// [[ xxhash Fast Hash Algorithm; https://cyan4973.github.io/xxHash/ ]]
|
||||||
|
package xxhash
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
|
|
||||||
@@ -7,9 +12,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// An implementation of Yann Collet's [[ xxhash Fast Hash Algorithm; https://cyan4973.github.io/xxHash/ ]].
|
|
||||||
package xxhash
|
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package xxhash
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
@@ -8,8 +10,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package xxhash
|
|
||||||
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package xxhash
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
@@ -8,8 +10,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package xxhash
|
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package xxhash
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
@@ -8,8 +10,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package xxhash
|
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package xxhash
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
@@ -8,8 +10,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package xxhash
|
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// package bmp implements a Microsoft BMP image reader
|
// Reader and writer for Microsoft `BMP` images.
|
||||||
package core_image_bmp
|
package core_image_bmp
|
||||||
|
|
||||||
import "core:image"
|
import "core:image"
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package image
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -7,9 +9,6 @@
|
|||||||
Ginger Bill: Cosmetic changes.
|
Ginger Bill: Cosmetic changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// package image implements a general 2D image library to be used with other image related packages
|
|
||||||
package image
|
|
||||||
|
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// General 2D image types and procedures to be used with other image related packages.
|
||||||
|
package image
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Reader for baseline `JPEG` images.
|
||||||
package jpeg
|
package jpeg
|
||||||
|
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
Readers and writers for `PBM`, `PGM`, `PPM`, `PAM` and `PFM` images.
|
||||||
|
|
||||||
Formats:
|
Formats:
|
||||||
|
|
||||||
PBM (P1, P4): Portable Bit Map, stores black and white images (1 channel)
|
PBM (P1, P4): Portable Bit Map, stores black and white images (1 channel)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
package png implements a PNG image reader
|
Reader for `PNG` images.
|
||||||
|
|
||||||
The PNG specification is at [[ https://www.w3.org/TR/PNG/ ]].
|
The PNG specification is at [[ https://www.w3.org/TR/PNG/ ]].
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package png
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-2 license.
|
Made available under Odin's BSD-2 license.
|
||||||
@@ -9,8 +11,6 @@
|
|||||||
These are a few useful utility functions to work with PNG images.
|
These are a few useful utility functions to work with PNG images.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package png
|
|
||||||
|
|
||||||
import "core:image"
|
import "core:image"
|
||||||
import "core:compress/zlib"
|
import "core:compress/zlib"
|
||||||
import coretime "core:time"
|
import coretime "core:time"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#+vet !using-stmt
|
||||||
|
package png
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -7,10 +10,6 @@
|
|||||||
Ginger Bill: Cosmetic changes.
|
Ginger Bill: Cosmetic changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#+vet !using-stmt
|
|
||||||
package png
|
|
||||||
|
|
||||||
import "core:compress"
|
import "core:compress"
|
||||||
import "core:compress/zlib"
|
import "core:compress/zlib"
|
||||||
import "core:image"
|
import "core:image"
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
// Reader and writer for `QOI` images.
|
||||||
|
//
|
||||||
|
// The QOI specification is at [[ https://qoiformat.org ]].
|
||||||
|
package qoi
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -6,12 +11,6 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// package qoi implements a QOI image reader
|
|
||||||
//
|
|
||||||
// The QOI specification is at [[ https://qoiformat.org ]].
|
|
||||||
package qoi
|
|
||||||
|
|
||||||
import "core:image"
|
import "core:image"
|
||||||
import "core:compress"
|
import "core:compress"
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// Reader and writer for 8-bit RGB and RGBA `TGA` images.
|
||||||
|
package tga
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -7,10 +10,6 @@
|
|||||||
Benoit Jacquier: tga loader
|
Benoit Jacquier: tga loader
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// package tga implements a TGA image writer for 8-bit RGB and RGBA images.
|
|
||||||
package tga
|
|
||||||
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:image"
|
import "core:image"
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// package io provides basic interfaces for generic data stream primitives.
|
// Basic interfaces for generic data stream primitives.
|
||||||
// The purpose of this package is wrap existing data structures and their
|
// The purpose of this package is wrap existing data structures and their
|
||||||
// operations into an abstracted stream interface.
|
// operations into an abstracted stream interface.
|
||||||
package io
|
package io
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Implementations of the `context.Logger` interface.
|
||||||
package log
|
package log
|
||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
+70
-71
@@ -2,26 +2,30 @@ package log
|
|||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
import "core:sync"
|
||||||
|
|
||||||
Log_Allocator_Format :: enum {
|
Log_Allocator_Format :: enum {
|
||||||
Bytes, // Actual number of bytes.
|
Bytes, // Actual number of bytes.
|
||||||
Human, // Bytes in human units like bytes, kibibytes, etc. as appropriate.
|
Human, // Bytes in human units like bytes, kibibytes, etc. as appropriate.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Log_Allocator is an allocator which calls `context.logger` on each of its allocations operations.
|
||||||
|
// The format can be changed by setting the `size_fmt: Log_Allocator_Format` field to either `Bytes` or `Human`.
|
||||||
Log_Allocator :: struct {
|
Log_Allocator :: struct {
|
||||||
allocator: runtime.Allocator,
|
allocator: runtime.Allocator,
|
||||||
level: Level,
|
level: Level,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
locked: bool,
|
lock: sync.Mutex,
|
||||||
size_fmt: Log_Allocator_Format,
|
size_fmt: Log_Allocator_Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
log_allocator_init :: proc(la: ^Log_Allocator, level: Level, size_fmt := Log_Allocator_Format.Bytes,
|
log_allocator_init :: proc(la: ^Log_Allocator, level: Level, size_fmt := Log_Allocator_Format.Bytes,
|
||||||
allocator := context.allocator, prefix := "") {
|
allocator := context.allocator, prefix := "") {
|
||||||
la.allocator = allocator
|
la.allocator = allocator
|
||||||
la.level = level
|
la.level = level
|
||||||
la.prefix = prefix
|
la.prefix = prefix
|
||||||
la.locked = false
|
la.lock = {}
|
||||||
la.size_fmt = size_fmt
|
la.size_fmt = size_fmt
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,83 +50,78 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
|
|||||||
|
|
||||||
buf: [256]byte = ---
|
buf: [256]byte = ---
|
||||||
|
|
||||||
if !la.locked {
|
sync.lock(&la.lock)
|
||||||
la.locked = true
|
switch mode {
|
||||||
defer la.locked = false
|
case .Alloc:
|
||||||
|
format: string
|
||||||
|
switch la.size_fmt {
|
||||||
|
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)"
|
||||||
|
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%m, alignment=%d)"
|
||||||
|
}
|
||||||
|
str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
|
||||||
switch mode {
|
case .Alloc_Non_Zeroed:
|
||||||
case .Alloc:
|
format: string
|
||||||
|
switch la.size_fmt {
|
||||||
|
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)"
|
||||||
|
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%m, alignment=%d)"
|
||||||
|
}
|
||||||
|
str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
|
||||||
|
case .Free:
|
||||||
|
if old_size != 0 {
|
||||||
format: string
|
format: string
|
||||||
switch la.size_fmt {
|
switch la.size_fmt {
|
||||||
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)"
|
case .Bytes: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)"
|
||||||
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%m, alignment=%d)"
|
case .Human: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%m)"
|
||||||
}
|
}
|
||||||
str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment)
|
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size)
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
} else {
|
||||||
case .Alloc_Non_Zeroed:
|
str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", la.prefix, padding, old_memory)
|
||||||
format: string
|
|
||||||
switch la.size_fmt {
|
|
||||||
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)"
|
|
||||||
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%m, alignment=%d)"
|
|
||||||
}
|
|
||||||
str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
|
|
||||||
case .Free:
|
|
||||||
if old_size != 0 {
|
|
||||||
format: string
|
|
||||||
switch la.size_fmt {
|
|
||||||
case .Bytes: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)"
|
|
||||||
case .Human: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%m)"
|
|
||||||
}
|
|
||||||
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
} else {
|
|
||||||
str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", la.prefix, padding, old_memory)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
}
|
|
||||||
|
|
||||||
case .Free_All:
|
|
||||||
str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free_All)", la.prefix, padding)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
|
|
||||||
case .Resize:
|
|
||||||
format: string
|
|
||||||
switch la.size_fmt {
|
|
||||||
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)"
|
|
||||||
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%m, size=%m, alignment=%d)"
|
|
||||||
}
|
|
||||||
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
|
|
||||||
case .Resize_Non_Zeroed:
|
|
||||||
format: string
|
|
||||||
switch la.size_fmt {
|
|
||||||
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)"
|
|
||||||
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)"
|
|
||||||
}
|
|
||||||
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
|
|
||||||
case .Query_Features:
|
|
||||||
str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
|
|
||||||
case .Query_Info:
|
|
||||||
str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Info)", la.prefix, padding)
|
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case .Free_All:
|
||||||
|
str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free_All)", la.prefix, padding)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
|
||||||
|
case .Resize:
|
||||||
|
format: string
|
||||||
|
switch la.size_fmt {
|
||||||
|
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)"
|
||||||
|
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%m, size=%m, alignment=%d)"
|
||||||
|
}
|
||||||
|
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
|
||||||
|
case .Resize_Non_Zeroed:
|
||||||
|
format: string
|
||||||
|
switch la.size_fmt {
|
||||||
|
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)"
|
||||||
|
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)"
|
||||||
|
}
|
||||||
|
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
|
||||||
|
case .Query_Features:
|
||||||
|
str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
|
|
||||||
|
case .Query_Info:
|
||||||
|
str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Info)", la.prefix, padding)
|
||||||
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
}
|
}
|
||||||
|
sync.unlock(&la.lock)
|
||||||
|
|
||||||
data, err := la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location)
|
data, err := la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location)
|
||||||
if !la.locked {
|
if err != nil {
|
||||||
la.locked = true
|
sync.lock(&la.lock)
|
||||||
defer la.locked = false
|
str := fmt.bprintf(buf[:], "%s%sALLOCATOR ERROR=%v", la.prefix, padding, err)
|
||||||
if err != nil {
|
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
||||||
str := fmt.bprintf(buf[:], "%s%sALLOCATOR ERROR=%v", la.prefix, padding, err)
|
sync.unlock(&la.lock)
|
||||||
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package math_big
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -5,8 +7,6 @@
|
|||||||
This file collects public proc maps and their aliases.
|
This file collects public proc maps and their aliases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
=== === === === === === === === === === === === === === === === === === === === === === === ===
|
=== === === === === === === === === === === === === === === === === === === === === === === ===
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
package math_big
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user