|
@@ -27,6 +27,11 @@ init_global_temporary_allocator :: proc(size: int, backup_allocator := context.a
|
|
|
}
|
|
|
|
|
|
|
|
|
+// `copy_slice` is a built-in procedure that copies elements from a source slice `src` to a destination slice `dst`.
|
|
|
+// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
|
|
|
+// of len(src) and len(dst).
|
|
|
+//
|
|
|
+// Prefer the procedure group `copy`.
|
|
|
@builtin
|
|
|
copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int {
|
|
|
n := max(0, min(len(dst), len(src)))
|
|
@@ -35,6 +40,11 @@ copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int {
|
|
|
}
|
|
|
return n
|
|
|
}
|
|
|
+// `copy_from_string` is a built-in procedure that copies elements from a source slice `src` to a destination string `dst`.
|
|
|
+// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
|
|
|
+// of len(src) and len(dst).
|
|
|
+//
|
|
|
+// Prefer the procedure group `copy`.
|
|
|
@builtin
|
|
|
copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int {
|
|
|
n := max(0, min(len(dst), len(src)))
|
|
@@ -43,11 +53,20 @@ copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int
|
|
|
}
|
|
|
return n
|
|
|
}
|
|
|
+// `copy` is a built-in procedure that copies elements from a source slice `src` to a destination slice/string `dst`.
|
|
|
+// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
|
|
|
+// of len(src) and len(dst).
|
|
|
@builtin
|
|
|
copy :: proc{copy_slice, copy_from_string}
|
|
|
|
|
|
|
|
|
|
|
|
+// `unordered_remove` removed the element at the specified `index`. It does so by replacing the current end value
|
|
|
+// with the old value, and reducing the length of the dynamic array by 1.
|
|
|
+//
|
|
|
+// Note: This is an O(1) operation.
|
|
|
+// Note: If you the elements to remain in their order, use `ordered_remove`.
|
|
|
+// Note: If the index is out of bounds, this procedure will panic.
|
|
|
@builtin
|
|
|
unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
|
|
|
bounds_check_error_loc(loc, index, len(array))
|
|
@@ -57,7 +76,11 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
|
|
|
}
|
|
|
(^Raw_Dynamic_Array)(array).len -= 1
|
|
|
}
|
|
|
-
|
|
|
+// `ordered_remove` removed the element at the specified `index` whilst keeping the order of the other elements.
|
|
|
+//
|
|
|
+// Note: This is an O(N) operation.
|
|
|
+// Note: If you the elements do not have to remain in their order, prefer `unordered_remove`.
|
|
|
+// Note: If the index is out of bounds, this procedure will panic.
|
|
|
@builtin
|
|
|
ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
|
|
|
bounds_check_error_loc(loc, index, len(array))
|
|
@@ -67,6 +90,10 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_locati
|
|
|
(^Raw_Dynamic_Array)(array).len -= 1
|
|
|
}
|
|
|
|
|
|
+// `remove_range` removes a range of elements specified by the range `lo` and `hi`, whilst keeping the order of the other elements.
|
|
|
+//
|
|
|
+// Note: This is an O(N) operation.
|
|
|
+// Note: If the range is out of bounds, this procedure will panic.
|
|
|
@builtin
|
|
|
remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) #no_bounds_check {
|
|
|
slice_expr_error_lo_hi_loc(loc, lo, hi, len(array))
|
|
@@ -80,6 +107,9 @@ remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_locatio
|
|
|
}
|
|
|
|
|
|
|
|
|
+// `pop` will remove and return the end value of dynamic array `array` and reduces the length of `array` by 1.
|
|
|
+//
|
|
|
+// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
|
|
|
@builtin
|
|
|
pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
|
|
|
assert(len(array) > 0, "", loc)
|
|
@@ -89,6 +119,8 @@ pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bou
|
|
|
}
|
|
|
|
|
|
|
|
|
+// `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1.
|
|
|
+// If the operation is not possible, it will return false.
|
|
|
@builtin
|
|
|
pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
|
|
|
if len(array) == 0 {
|
|
@@ -99,6 +131,9 @@ pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+// `pop_front` will remove and return the first value of dynamic array `array` and reduces the length of `array` by 1.
|
|
|
+//
|
|
|
+// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
|
|
|
@builtin
|
|
|
pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
|
|
|
assert(len(array) > 0, "", loc)
|
|
@@ -110,6 +145,8 @@ pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #
|
|
|
return res
|
|
|
}
|
|
|
|
|
|
+// `pop_front_safe` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1.
|
|
|
+// If the operation is not possible, it will return false.
|
|
|
@builtin
|
|
|
pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
|
|
|
if len(array) == 0 {
|
|
@@ -124,12 +161,15 @@ pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_
|
|
|
}
|
|
|
|
|
|
|
|
|
+// `clear` will set the length of a passed dynamic array or map to `0`
|
|
|
@builtin
|
|
|
clear :: proc{clear_dynamic_array, clear_map}
|
|
|
|
|
|
+// `reserve` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
|
|
@builtin
|
|
|
reserve :: proc{reserve_dynamic_array, reserve_map}
|
|
|
|
|
|
+// `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
|
|
@builtin
|
|
|
resize :: proc{resize_dynamic_array}
|
|
|
|
|
@@ -137,36 +177,56 @@ resize :: proc{resize_dynamic_array}
|
|
|
@builtin
|
|
|
shrink :: proc{shrink_dynamic_array, shrink_map}
|
|
|
|
|
|
+// `free` will try to free the passed pointer, with the given `allocator` if the allocator supports this operation.
|
|
|
@builtin
|
|
|
free :: proc{mem_free}
|
|
|
|
|
|
+// `free_all` will try to free/reset all of the memory of the given `allocator` if the allocator supports this operation.
|
|
|
@builtin
|
|
|
free_all :: proc{mem_free_all}
|
|
|
|
|
|
|
|
|
|
|
|
+// `delete_string` will try to free the underlying data of the passed string, with the given `allocator` if the allocator supports this operation.
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `delete`.
|
|
|
@builtin
|
|
|
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
|
|
return mem_free_with_size(raw_data(str), len(str), allocator, loc)
|
|
|
}
|
|
|
+// `delete_cstring` will try to free the underlying data of the passed string, with the given `allocator` if the allocator supports this operation.
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `delete`.
|
|
|
@builtin
|
|
|
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
|
|
return mem_free((^byte)(str), allocator, loc)
|
|
|
}
|
|
|
+// `delete_dynamic_array` will try to free the underlying data of the passed dynamic array, with the given `allocator` if the allocator supports this operation.
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `delete`.
|
|
|
@builtin
|
|
|
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {
|
|
|
return mem_free_with_size(raw_data(array), cap(array)*size_of(E), array.allocator, loc)
|
|
|
}
|
|
|
+// `delete_slice` will try to free the underlying data of the passed sliced, with the given `allocator` if the allocator supports this operation.
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `delete`.
|
|
|
@builtin
|
|
|
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
|
|
return mem_free_with_size(raw_data(array), len(array)*size_of(E), allocator, loc)
|
|
|
}
|
|
|
+// `delete_map` will try to free the underlying data of the passed map, with the given `allocator` if the allocator supports this operation.
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `delete`.
|
|
|
@builtin
|
|
|
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {
|
|
|
return map_free_dynamic(transmute(Raw_Map)m, map_info(T), loc)
|
|
|
}
|
|
|
|
|
|
|
|
|
+// `delete` will try to free the underlying data of the passed built-in data structure (string, cstring, dynamic array, slice, or map), with the given `allocator` if the allocator supports this operation.
|
|
|
+//
|
|
|
+// Note: Prefer `delete` over the specific `delete_*` procedures where possible.
|
|
|
@builtin
|
|
|
delete :: proc{
|
|
|
delete_string,
|
|
@@ -213,18 +273,34 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat
|
|
|
return transmute(T)s, err
|
|
|
}
|
|
|
|
|
|
+// `make_slice` allocates and initializes a slice. Like `new`, the first argument is a type, not a value.
|
|
|
+// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
|
|
+//
|
|
|
+// Note: Prefer using the procedure group `make`.
|
|
|
@(builtin, require_results)
|
|
|
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
|
|
|
return make_aligned(T, len, align_of(E), allocator, loc)
|
|
|
}
|
|
|
+// `make_dynamic_array` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
|
|
|
+// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
|
|
+//
|
|
|
+// Note: Prefer using the procedure group `make`.
|
|
|
@(builtin, require_results)
|
|
|
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
|
|
|
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc)
|
|
|
}
|
|
|
+// `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
|
|
|
+// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
|
|
+//
|
|
|
+// Note: Prefer using the procedure group `make`.
|
|
|
@(builtin, require_results)
|
|
|
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
|
|
|
return make_dynamic_array_len_cap(T, len, len, allocator, loc)
|
|
|
}
|
|
|
+// `make_dynamic_array_len_cap` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
|
|
|
+// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
|
|
+//
|
|
|
+// Note: Prefer using the procedure group `make`.
|
|
|
@(builtin, require_results)
|
|
|
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
|
|
make_dynamic_array_error_loc(loc, len, cap)
|
|
@@ -236,6 +312,10 @@ make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #a
|
|
|
array = transmute(T)s
|
|
|
return
|
|
|
}
|
|
|
+// `make_map` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
|
|
|
+// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
|
|
+//
|
|
|
+// Note: Prefer using the procedure group `make`.
|
|
|
@(builtin, require_results)
|
|
|
make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) #optional_allocator_error {
|
|
|
make_map_expr_error_loc(loc, capacity)
|
|
@@ -244,6 +324,12 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_
|
|
|
err = reserve_map(&m, capacity, loc)
|
|
|
return
|
|
|
}
|
|
|
+// `make_multi_pointer` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
|
|
|
+// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
|
|
+//
|
|
|
+// This is "similar" to doing `raw_data(make([]E, len, allocator))`.
|
|
|
+//
|
|
|
+// Note: Prefer using the procedure group `make`.
|
|
|
@(builtin, require_results)
|
|
|
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) #optional_allocator_error {
|
|
|
make_slice_error_loc(loc, len)
|
|
@@ -256,8 +342,9 @@ make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := con
|
|
|
}
|
|
|
|
|
|
|
|
|
-// The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only)
|
|
|
-// Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the
|
|
|
+// `make` built-in procedure allocates and initializes a value of type slice, dynamic array, map, or multi-pointer (only).
|
|
|
+//
|
|
|
+// Similar to `new`, the first argument is a type, not a value. Unlike new, make's return type is the same as the
|
|
|
// type of its argument, not a pointer to it.
|
|
|
// Make uses the specified allocator, default is context.allocator, default is context.allocator
|
|
|
@builtin
|
|
@@ -272,6 +359,9 @@ make :: proc{
|
|
|
|
|
|
|
|
|
|
|
|
+// `clear_map` will set the length of a passed map to `0`
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `clear`
|
|
|
@builtin
|
|
|
clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
|
|
|
if m == nil {
|
|
@@ -280,14 +370,17 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
|
|
|
map_clear_dynamic((^Raw_Map)(m), map_info(T))
|
|
|
}
|
|
|
|
|
|
+// `reserve_map` will try to reserve memory of a passed map to the requested element count (setting the `cap`).
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `reserve`
|
|
|
@builtin
|
|
|
reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) -> Allocator_Error {
|
|
|
return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) if m != nil else nil
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- Shrinks the capacity of a map down to the current length.
|
|
|
-*/
|
|
|
+// Shrinks the capacity of a map down to the current length.
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `shrink`
|
|
|
@builtin
|
|
|
shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
|
|
if m != nil {
|
|
@@ -526,6 +619,9 @@ assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
|
|
|
|
|
|
|
|
|
|
|
|
+// `clear_dynamic_array` will set the length of a passed dynamic array to `0`
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `clear`.
|
|
|
@builtin
|
|
|
clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {
|
|
|
if array != nil {
|
|
@@ -533,6 +629,9 @@ 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`).
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `reserve`.
|
|
|
@builtin
|
|
|
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
|
|
if array == nil {
|
|
@@ -563,6 +662,9 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// `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`).
|
|
|
+//
|
|
|
+// Note: Prefer the procedure group `resize`
|
|
|
@builtin
|
|
|
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
|
|
if array == nil {
|
|
@@ -603,6 +705,8 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
|
|
|
Returns false if `cap(array) < new_cap`, or the allocator report failure.
|
|
|
|
|
|
If `len(array) < new_cap`, then `len(array)` will be left unchanged.
|
|
|
+
|
|
|
+ Note: Prefer the procedure group `shrink`
|
|
|
*/
|
|
|
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
|
|
if array == nil {
|