|
|
@ -5,7 +5,7 @@ module builtin
|
|
|
|
|
|
|
|
|
|
|
|
import strings
|
|
|
|
import strings
|
|
|
|
|
|
|
|
|
|
|
|
// `array` is a struct, used for denoting all array types in V.
|
|
|
|
// array is a struct, used for denoting all array types in V.
|
|
|
|
// `.data` is a void pointer to the backing heap memory block,
|
|
|
|
// `.data` is a void pointer to the backing heap memory block,
|
|
|
|
// which avoids using generics and thus without generating extra
|
|
|
|
// which avoids using generics and thus without generating extra
|
|
|
|
// code for every type.
|
|
|
|
// code for every type.
|
|
|
@ -112,7 +112,9 @@ fn new_array_from_c_array_no_alloc(len int, cap int, elm_size int, c_array voidp
|
|
|
|
return arr
|
|
|
|
return arr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Private function. Doubles array capacity if needed.
|
|
|
|
// Private function. Increases the `cap` of an array to the
|
|
|
|
|
|
|
|
// required value by copying the data to a new memory location
|
|
|
|
|
|
|
|
// (creating a clone) unless `a.cap` is already large enough.
|
|
|
|
fn (mut a array) ensure_cap(required int) {
|
|
|
|
fn (mut a array) ensure_cap(required int) {
|
|
|
|
if required <= a.cap {
|
|
|
|
if required <= a.cap {
|
|
|
|
return
|
|
|
|
return
|
|
|
@ -139,15 +141,17 @@ fn (mut a array) ensure_cap(required int) {
|
|
|
|
|
|
|
|
|
|
|
|
// repeat returns a new array with the given array elements repeated given times.
|
|
|
|
// repeat returns a new array with the given array elements repeated given times.
|
|
|
|
// `cgen` will replace this with an apropriate call to `repeat_to_depth()`
|
|
|
|
// `cgen` will replace this with an apropriate call to `repeat_to_depth()`
|
|
|
|
|
|
|
|
//
|
|
|
|
// This is a dummy placeholder that will be overridden by `cgen` with an appropriate
|
|
|
|
// This is a dummy placeholder that will be overridden by `cgen` with an appropriate
|
|
|
|
// call to `repeat_to_depth()`. However the `checker` needs it here.
|
|
|
|
// call to `repeat_to_depth()`. However the `checker` needs it here.
|
|
|
|
pub fn (a array) repeat(count int) array {
|
|
|
|
pub fn (a array) repeat(count int) array {
|
|
|
|
return unsafe { a.repeat_to_depth(count, 0) }
|
|
|
|
return unsafe { a.repeat_to_depth(count, 0) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// version of `repeat()` that handles multi dimensional arrays
|
|
|
|
// repeat_to_depth is an unsafe version of `repeat()` that handles
|
|
|
|
// `unsafe` to call directly because `depth` is not checked
|
|
|
|
// multi-dimensional arrays.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// It is `unsafe` to call directly because `depth` is not checked
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
|
|
|
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
|
|
|
if count < 0 {
|
|
|
|
if count < 0 {
|
|
|
@ -176,16 +180,24 @@ pub fn (a array) repeat_to_depth(count int, depth int) array {
|
|
|
|
return arr
|
|
|
|
return arr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// sort_with_compare sorts array in-place using given `compare` function as comparator.
|
|
|
|
// insert inserts a value in the array at index `i` and increases
|
|
|
|
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
|
|
|
|
// the index of subsequent elements by 1.
|
|
|
|
$if freestanding {
|
|
|
|
//
|
|
|
|
panic('sort does not work with -freestanding')
|
|
|
|
// This function is type-aware and can insert items of the same
|
|
|
|
} $else {
|
|
|
|
// or lower dimensionality as the original array. That is, if
|
|
|
|
unsafe { vqsort(a.data, usize(a.len), usize(a.element_size), callback) }
|
|
|
|
// the original array is `[]int`, then the insert `val` may be
|
|
|
|
}
|
|
|
|
// `int` or `[]int`. If the original array is `[][]int`, then `val`
|
|
|
|
}
|
|
|
|
// may be `[]int` or `[][]int`. Consider the examples.
|
|
|
|
|
|
|
|
//
|
|
|
|
// insert inserts a value in the array at index `i`
|
|
|
|
// Example:
|
|
|
|
|
|
|
|
// ```v
|
|
|
|
|
|
|
|
// mut a := [1, 2, 4]
|
|
|
|
|
|
|
|
// a.insert(2, 3) // a now is [1, 2, 3, 4]
|
|
|
|
|
|
|
|
// mut b := [3, 4]
|
|
|
|
|
|
|
|
// b.insert(0, [1, 2]) // b now is [1, 2, 3, 4]
|
|
|
|
|
|
|
|
// mut c := [[3, 4]]
|
|
|
|
|
|
|
|
// c.insert(0, [1, 2]) // c now is [[1, 2], [3, 4]]
|
|
|
|
|
|
|
|
// ```
|
|
|
|
pub fn (mut a array) insert(i int, val voidptr) {
|
|
|
|
pub fn (mut a array) insert(i int, val voidptr) {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
if i < 0 || i > a.len {
|
|
|
|
if i < 0 || i > a.len {
|
|
|
@ -200,7 +212,9 @@ pub fn (mut a array) insert(i int, val voidptr) {
|
|
|
|
a.len++
|
|
|
|
a.len++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// insert_many inserts many values into the array from index `i`.
|
|
|
|
// insert_many inserts many values into the array beginning at `i`.
|
|
|
|
|
|
|
|
// NOTE: `array.insert()` already handles inserting multiple values
|
|
|
|
|
|
|
|
// use that unless you know you need to use this.
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
|
|
|
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
@ -218,23 +232,58 @@ pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
|
|
|
a.len += size
|
|
|
|
a.len += size
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// prepend prepends one value to the array.
|
|
|
|
// prepend prepends one or more elements to an array.
|
|
|
|
|
|
|
|
// Just like `.insert`, `.prepend` can take a single element
|
|
|
|
|
|
|
|
// or an array of elements of the same type as the original list.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example:
|
|
|
|
|
|
|
|
// ```v
|
|
|
|
|
|
|
|
// mut a := []int{}
|
|
|
|
|
|
|
|
// a.prepend(1) // a == [1]
|
|
|
|
|
|
|
|
// mut b := [3, 4]
|
|
|
|
|
|
|
|
// b.prepend([1, 2]) // b == [1, 2, 3, 4]
|
|
|
|
|
|
|
|
//
|
|
|
|
pub fn (mut a array) prepend(val voidptr) {
|
|
|
|
pub fn (mut a array) prepend(val voidptr) {
|
|
|
|
a.insert(0, val)
|
|
|
|
a.insert(0, val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// prepend_many prepends another array to this array.
|
|
|
|
// prepend_many prepends another array to this array.
|
|
|
|
|
|
|
|
// NOTE: `.prepend` is probably all you need.
|
|
|
|
|
|
|
|
// NOTE: This code is never called in all of vlib
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (mut a array) prepend_many(val voidptr, size int) {
|
|
|
|
pub fn (mut a array) prepend_many(val voidptr, size int) {
|
|
|
|
unsafe { a.insert_many(0, val, size) }
|
|
|
|
unsafe { a.insert_many(0, val, size) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// delete deletes array element at index `i`.
|
|
|
|
// delete deletes array element at index `i`.
|
|
|
|
|
|
|
|
// This is exactly the same as calling `.delete_many(i, 1)`.
|
|
|
|
|
|
|
|
// NOTE: This function does NOT operate in-place. Internally, it
|
|
|
|
|
|
|
|
// creates a copy of the array, skipping over the element at `i`,
|
|
|
|
|
|
|
|
// and then points the original variable to the new memory location.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example:
|
|
|
|
|
|
|
|
// ```v
|
|
|
|
|
|
|
|
// mut a := ['0', '1', '2', '3', '4', '5']
|
|
|
|
|
|
|
|
// a.delete(1) // a is now ['0', '2', '3', '4', '5']
|
|
|
|
|
|
|
|
// ```
|
|
|
|
pub fn (mut a array) delete(i int) {
|
|
|
|
pub fn (mut a array) delete(i int) {
|
|
|
|
a.delete_many(i, 1)
|
|
|
|
a.delete_many(i, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// delete_many deletes `size` elements beginning with index `i`
|
|
|
|
// delete_many deletes `size` elements beginning with index `i`
|
|
|
|
|
|
|
|
// NOTE: This function does NOT operate in-place. Internally, it
|
|
|
|
|
|
|
|
// creates a copy of the array, skipping over `size` elements
|
|
|
|
|
|
|
|
// starting at `i`, and then points the original variable
|
|
|
|
|
|
|
|
// to the new memory location.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example:
|
|
|
|
|
|
|
|
// ```v
|
|
|
|
|
|
|
|
// mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
|
|
|
|
// b := a[..9] // creates a `slice` of `a`, not a clone
|
|
|
|
|
|
|
|
// a.delete_many(4, 3) // replaces `a` with a modified clone
|
|
|
|
|
|
|
|
// dump(a) // a: [1, 2, 3, 4, 8, 9] // `a` is now different
|
|
|
|
|
|
|
|
// dump(b) // b: [1, 2, 3, 4, 5, 6, 7, 8, 9] // `b` is still the same
|
|
|
|
|
|
|
|
// ```
|
|
|
|
pub fn (mut a array) delete_many(i int, size int) {
|
|
|
|
pub fn (mut a array) delete_many(i int, size int) {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
if i < 0 || i + size > a.len {
|
|
|
|
if i < 0 || i + size > a.len {
|
|
|
@ -263,12 +312,15 @@ pub fn (mut a array) delete_many(i int, size int) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// clear clears the array without deallocating the allocated data.
|
|
|
|
// clear clears the array without deallocating the allocated data.
|
|
|
|
|
|
|
|
// It does it by setting the array length to `0`
|
|
|
|
|
|
|
|
// Example: a.clear() // `a.len` is now 0
|
|
|
|
pub fn (mut a array) clear() {
|
|
|
|
pub fn (mut a array) clear() {
|
|
|
|
a.len = 0
|
|
|
|
a.len = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// trim trims the array length to "index" without modifying the allocated data. If "index" is greater
|
|
|
|
// trim trims the array length to `index` without modifying the allocated data.
|
|
|
|
// than len nothing will be changed.
|
|
|
|
// If `index` is greater than `len` nothing will be changed.
|
|
|
|
|
|
|
|
// Example: a.trim(3) // `a.len` is now <= 3
|
|
|
|
pub fn (mut a array) trim(index int) {
|
|
|
|
pub fn (mut a array) trim(index int) {
|
|
|
|
if index < a.len {
|
|
|
|
if index < a.len {
|
|
|
|
a.len = index
|
|
|
|
a.len = index
|
|
|
@ -305,7 +357,10 @@ fn (a array) get_with_check(i int) voidptr {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// first returns the first element of the array.
|
|
|
|
// first returns the first element of the `array`.
|
|
|
|
|
|
|
|
// If the `array` is empty, this will panic.
|
|
|
|
|
|
|
|
// However, `a[0]` returns an error object
|
|
|
|
|
|
|
|
// so it can be handled with an `or` block.
|
|
|
|
pub fn (a array) first() voidptr {
|
|
|
|
pub fn (a array) first() voidptr {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
if a.len == 0 {
|
|
|
|
if a.len == 0 {
|
|
|
@ -315,7 +370,8 @@ pub fn (a array) first() voidptr {
|
|
|
|
return a.data
|
|
|
|
return a.data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// last returns the last element of the array.
|
|
|
|
// last returns the last element of the `array`.
|
|
|
|
|
|
|
|
// If the `array` is empty, this will panic.
|
|
|
|
pub fn (a array) last() voidptr {
|
|
|
|
pub fn (a array) last() voidptr {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
if a.len == 0 {
|
|
|
|
if a.len == 0 {
|
|
|
@ -328,6 +384,20 @@ pub fn (a array) last() voidptr {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// pop returns the last element of the array, and removes it.
|
|
|
|
// pop returns the last element of the array, and removes it.
|
|
|
|
|
|
|
|
// If the `array` is empty, this will panic.
|
|
|
|
|
|
|
|
// NOTE: this function reduces the length of the given array,
|
|
|
|
|
|
|
|
// but arrays sliced from this one will not change. They still
|
|
|
|
|
|
|
|
// retain their "view" of the underlying memory.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example:
|
|
|
|
|
|
|
|
// ```v
|
|
|
|
|
|
|
|
// mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
|
|
|
|
// b := a[..9] // creates a "view" into the same memory
|
|
|
|
|
|
|
|
// c := a.pop() // c == 9
|
|
|
|
|
|
|
|
// a[1] = 5
|
|
|
|
|
|
|
|
// dump(a) // a: [1, 5, 3, 4, 5, 6, 7, 8]
|
|
|
|
|
|
|
|
// dump(b) // b: [1, 5, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
|
|
|
|
// ```
|
|
|
|
pub fn (mut a array) pop() voidptr {
|
|
|
|
pub fn (mut a array) pop() voidptr {
|
|
|
|
// in a sense, this is the opposite of `a << x`
|
|
|
|
// in a sense, this is the opposite of `a << x`
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
@ -344,6 +414,8 @@ pub fn (mut a array) pop() voidptr {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// delete_last efficiently deletes the last element of the array.
|
|
|
|
// delete_last efficiently deletes the last element of the array.
|
|
|
|
|
|
|
|
// It does it simply by reducing the length of the array by 1.
|
|
|
|
|
|
|
|
// If the array is empty, this will panic.
|
|
|
|
pub fn (mut a array) delete_last() {
|
|
|
|
pub fn (mut a array) delete_last() {
|
|
|
|
// copy pasting code for performance
|
|
|
|
// copy pasting code for performance
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
@ -358,6 +430,11 @@ pub fn (mut a array) delete_last() {
|
|
|
|
// but starting from the `start` element and ending with the element before
|
|
|
|
// but starting from the `start` element and ending with the element before
|
|
|
|
// the `end` element of the original array with the length and capacity
|
|
|
|
// the `end` element of the original array with the length and capacity
|
|
|
|
// set to the number of the elements in the slice.
|
|
|
|
// set to the number of the elements in the slice.
|
|
|
|
|
|
|
|
// It will remain tied to the same memory location until the length increases
|
|
|
|
|
|
|
|
// (copy on grow) or `.clone()` is called on it.
|
|
|
|
|
|
|
|
// If `start` and `end` are invalid this function will panic.
|
|
|
|
|
|
|
|
// Alternative: Slices can also be made with [start..end] notation
|
|
|
|
|
|
|
|
// Alternative: `.slice_ni()` will always return an array.
|
|
|
|
fn (a array) slice(start int, _end int) array {
|
|
|
|
fn (a array) slice(start int, _end int) array {
|
|
|
|
mut end := _end
|
|
|
|
mut end := _end
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
|
$if !no_bounds_checking ? {
|
|
|
@ -441,7 +518,7 @@ fn (a array) slice2(start int, _end int, end_max bool) array {
|
|
|
|
return a.slice(start, end)
|
|
|
|
return a.slice(start, end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// `clone_static_to_depth()` returns an independent copy of a given array.
|
|
|
|
// clone_static_to_depth() returns an independent copy of a given array.
|
|
|
|
// Unlike `clone_to_depth()` it has a value receiver and is used internally
|
|
|
|
// Unlike `clone_to_depth()` it has a value receiver and is used internally
|
|
|
|
// for slice-clone expressions like `a[2..4].clone()` and in -autofree generated code.
|
|
|
|
// for slice-clone expressions like `a[2..4].clone()` and in -autofree generated code.
|
|
|
|
fn (a array) clone_static_to_depth(depth int) array {
|
|
|
|
fn (a array) clone_static_to_depth(depth int) array {
|
|
|
@ -562,7 +639,6 @@ pub fn (a array) reverse() array {
|
|
|
|
return arr
|
|
|
|
return arr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// pub fn (a []int) free() {
|
|
|
|
|
|
|
|
// free frees all memory occupied by the array.
|
|
|
|
// free frees all memory occupied by the array.
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (a &array) free() {
|
|
|
|
pub fn (a &array) free() {
|
|
|
@ -576,29 +652,105 @@ pub fn (a &array) free() {
|
|
|
|
unsafe { free(mblock_ptr) }
|
|
|
|
unsafe { free(mblock_ptr) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// filter creates a new array with all elements that pass the test implemented by the provided function
|
|
|
|
// Some of the following functions have no implementation in V and exist here
|
|
|
|
|
|
|
|
// to expose them to the array namespace. Their implementation is compiler
|
|
|
|
|
|
|
|
// specific because of their use of `it` and `a < b` expressions.
|
|
|
|
|
|
|
|
// Therefore, the implementation is left to the backend.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// filter creates a new array with all elements that pass the test.
|
|
|
|
|
|
|
|
// Ignore the function signature. `filter` does not take an actual callback. Rather, it
|
|
|
|
|
|
|
|
// takes an `it` expression.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example: array.filter(it % 2 == 1) // will yield a new array of only odd elements
|
|
|
|
pub fn (a array) filter(predicate fn (voidptr) bool) array
|
|
|
|
pub fn (a array) filter(predicate fn (voidptr) bool) array
|
|
|
|
|
|
|
|
|
|
|
|
// any tests whether at least one element in the array passes the test implemented by the
|
|
|
|
// any tests whether at least one element in the array passes the test.
|
|
|
|
// provided function. It returns true if, in the array, it finds an element for which the provided
|
|
|
|
// Ignore the function signature. `any` does not take an actual callback. Rather, it
|
|
|
|
// function returns true; otherwise it returns false. It doesn't modify the array
|
|
|
|
// takes an `it` expression.
|
|
|
|
|
|
|
|
// It returns `true` if it finds an element passing the test. Otherwise,
|
|
|
|
|
|
|
|
// it returns `false`. It doesn't modify the array.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example: array.any(it % 2 == 1) // will return true if any element is odd
|
|
|
|
pub fn (a array) any(predicate fn (voidptr) bool) bool
|
|
|
|
pub fn (a array) any(predicate fn (voidptr) bool) bool
|
|
|
|
|
|
|
|
|
|
|
|
// all tests whether all elements in the array pass the test implemented by the provided function
|
|
|
|
// all tests whether all elements in the array pass the test
|
|
|
|
|
|
|
|
// Ignore the function signature. `all` does not take an actual callback. Rather, it
|
|
|
|
|
|
|
|
// takes an `it` expression.
|
|
|
|
|
|
|
|
// It returns `false` if any element fails the test. Otherwise,
|
|
|
|
|
|
|
|
// it returns `true`. It doesn't modify the array.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example: array.all(it % 2 == 1) // will return true if every element is odd
|
|
|
|
pub fn (a array) all(predicate fn (voidptr) bool) bool
|
|
|
|
pub fn (a array) all(predicate fn (voidptr) bool) bool
|
|
|
|
|
|
|
|
|
|
|
|
// map creates a new array populated with the results of calling a provided function
|
|
|
|
// map creates a new array populated with the results of calling a provided function
|
|
|
|
// on every element in the calling array
|
|
|
|
// on every element in the calling array
|
|
|
|
pub fn (a array) map(callback fn (voidptr) voidptr) array
|
|
|
|
pub fn (a array) map(callback fn (voidptr) voidptr) array
|
|
|
|
|
|
|
|
|
|
|
|
// sort sorts an array in place in ascending order.
|
|
|
|
// sort sorts an array in place.
|
|
|
|
|
|
|
|
// Ignore the function signature. Passing a callback to `.sort` is not supported
|
|
|
|
|
|
|
|
// for now. Consider using the `.sort_with_compare` method if you need it.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Instead, a very simple syntax is available to you for custom sorting and more.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Certain array functions (`filter` `any` `all` and `sort`) support a simplified
|
|
|
|
|
|
|
|
// domain-specific-language by the backend compiler to make these operations
|
|
|
|
|
|
|
|
// more idiomatic to V. These functions are described here, but their implementation
|
|
|
|
|
|
|
|
// is compiler specific.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Each function takes a boolean test expression as its single argument.
|
|
|
|
|
|
|
|
// These test expressions may use certain 'magic' variables depending on their context:
|
|
|
|
|
|
|
|
// - `sort` may use `a` and `b` as pointers to two elements
|
|
|
|
|
|
|
|
// giving you direct access to those objects
|
|
|
|
|
|
|
|
// - `filter`, `any`, and `all` may use `it` as a pointer to a single element at a time.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example: array.sort() // will sort the array in ascending order
|
|
|
|
|
|
|
|
// Example: array.sort(b < a) // will sort the array in decending order
|
|
|
|
|
|
|
|
// Example: array.sort(b.name < a.name) // will sort descending by the .name field
|
|
|
|
|
|
|
|
// Example: array.filter(it % 2 == 1) // will yield a new array of only odd elements
|
|
|
|
|
|
|
|
// Example: array.any(it.name == 'Bob') // will yield `true` if any element has `.name == 'Bob'`
|
|
|
|
pub fn (mut a array) sort(callback fn (voidptr, voidptr) int)
|
|
|
|
pub fn (mut a array) sort(callback fn (voidptr, voidptr) int)
|
|
|
|
|
|
|
|
|
|
|
|
// contains determines whether an array includes a certain value among its entries
|
|
|
|
// sort_with_compare sorts array in-place using the results of the
|
|
|
|
pub fn (a array) contains(val voidptr) bool
|
|
|
|
// given function to determine sort order.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// The function should return one of three values:
|
|
|
|
|
|
|
|
// - `-1` when `a` should come before `b` ( `a < b` )
|
|
|
|
|
|
|
|
// - `1` when `b` should come before `a` ( `b < a` )
|
|
|
|
|
|
|
|
// - `0` when the order cannot be determined ( `a == b` )
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// ### Example:
|
|
|
|
|
|
|
|
// ```v
|
|
|
|
|
|
|
|
// fn main() {
|
|
|
|
|
|
|
|
// mut a := ['hi', '1', '5', '3']
|
|
|
|
|
|
|
|
// a.sort_with_compare(fn (a &string, b &string) int {
|
|
|
|
|
|
|
|
// if a < b {
|
|
|
|
|
|
|
|
// return -1
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if a > b {
|
|
|
|
|
|
|
|
// return 1
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return 0
|
|
|
|
|
|
|
|
// })
|
|
|
|
|
|
|
|
// assert a == ['1', '3', '5', 'hi']
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// ```
|
|
|
|
|
|
|
|
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
|
|
|
|
|
|
|
|
$if freestanding {
|
|
|
|
|
|
|
|
panic('sort does not work with -freestanding')
|
|
|
|
|
|
|
|
} $else {
|
|
|
|
|
|
|
|
unsafe { vqsort(a.data, usize(a.len), usize(a.element_size), callback) }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// contains determines whether an array includes a certain value among its elements
|
|
|
|
|
|
|
|
// It will return `true` if the array contains an element with this value.
|
|
|
|
|
|
|
|
// It is similar to `.any` but does not take an `it` expression.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Example: [1, 2, 3].contains(4) == false
|
|
|
|
|
|
|
|
pub fn (a array) contains(value voidptr) bool
|
|
|
|
|
|
|
|
|
|
|
|
// index returns the first index at which a given element can be found in the array
|
|
|
|
// index returns the first index at which a given element can be found in the array
|
|
|
|
// or -1 if the value is not found.
|
|
|
|
// or `-1` if the value is not found.
|
|
|
|
pub fn (a array) index(value voidptr) int
|
|
|
|
pub fn (a array) index(value voidptr) int
|
|
|
|
|
|
|
|
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
@ -612,8 +764,11 @@ pub fn (mut a []string) free() {
|
|
|
|
unsafe { (&array(&a)).free() }
|
|
|
|
unsafe { (&array(&a)).free() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// str returns a string representation of the array of strings
|
|
|
|
// The following functions are type-specific functions that apply
|
|
|
|
// => '["a", "b", "c"]'.
|
|
|
|
// to arrays of different types in different ways.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// str returns a string representation of an array of strings
|
|
|
|
|
|
|
|
// Example: ['a', 'b', 'c'].str() // => "['a', 'b', 'c']".
|
|
|
|
[manualfree]
|
|
|
|
[manualfree]
|
|
|
|
pub fn (a []string) str() string {
|
|
|
|
pub fn (a []string) str() string {
|
|
|
|
mut sb_len := 4 // 2x" + 1x, + 1xspace
|
|
|
|
mut sb_len := 4 // 2x" + 1x, + 1xspace
|
|
|
@ -666,6 +821,7 @@ pub fn (b []byte) hex() string {
|
|
|
|
// copy copies the `src` byte array elements to the `dst` byte array.
|
|
|
|
// copy copies the `src` byte array elements to the `dst` byte array.
|
|
|
|
// The number of the elements copied is the minimum of the length of both arrays.
|
|
|
|
// The number of the elements copied is the minimum of the length of both arrays.
|
|
|
|
// Returns the number of elements copied.
|
|
|
|
// Returns the number of elements copied.
|
|
|
|
|
|
|
|
// NOTE: This is not an `array` method. It is a function that takes two arrays of bytes.
|
|
|
|
// TODO: implement for all types
|
|
|
|
// TODO: implement for all types
|
|
|
|
pub fn copy(dst []byte, src []byte) int {
|
|
|
|
pub fn copy(dst []byte, src []byte) int {
|
|
|
|
min := if dst.len < src.len { dst.len } else { src.len }
|
|
|
|
min := if dst.len < src.len { dst.len } else { src.len }
|
|
|
@ -677,6 +833,7 @@ pub fn copy(dst []byte, src []byte) int {
|
|
|
|
|
|
|
|
|
|
|
|
// reduce executes a given reducer function on each element of the array,
|
|
|
|
// reduce executes a given reducer function on each element of the array,
|
|
|
|
// resulting in a single output value.
|
|
|
|
// resulting in a single output value.
|
|
|
|
|
|
|
|
// NOTE: It exists as a method on `[]int` types only
|
|
|
|
pub fn (a []int) reduce(iter fn (int, int) int, accum_start int) int {
|
|
|
|
pub fn (a []int) reduce(iter fn (int, int) int, accum_start int) int {
|
|
|
|
mut accum_ := accum_start
|
|
|
|
mut accum_ := accum_start
|
|
|
|
for i in a {
|
|
|
|
for i in a {
|
|
|
@ -686,11 +843,16 @@ pub fn (a []int) reduce(iter fn (int, int) int, accum_start int) int {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// grow_cap grows the array's capacity by `amount` elements.
|
|
|
|
// grow_cap grows the array's capacity by `amount` elements.
|
|
|
|
|
|
|
|
// Internally, it does this by copying the entire array to
|
|
|
|
|
|
|
|
// a new memory location (creating a clone).
|
|
|
|
pub fn (mut a array) grow_cap(amount int) {
|
|
|
|
pub fn (mut a array) grow_cap(amount int) {
|
|
|
|
a.ensure_cap(a.cap + amount)
|
|
|
|
a.ensure_cap(a.cap + amount)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// grow_len ensures that an array has a.len + amount of length
|
|
|
|
// grow_len ensures that an array has a.len + amount of length
|
|
|
|
|
|
|
|
// Internally, it does this by copying the entire array to
|
|
|
|
|
|
|
|
// a new memory location (creating a clone) unless the array.cap
|
|
|
|
|
|
|
|
// is already large enough.
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (mut a array) grow_len(amount int) {
|
|
|
|
pub fn (mut a array) grow_len(amount int) {
|
|
|
|
a.ensure_cap(a.len + amount)
|
|
|
|
a.ensure_cap(a.len + amount)
|
|
|
@ -708,7 +870,8 @@ pub fn (a array) pointers() []voidptr {
|
|
|
|
return res
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// voidptr.vbytes() - makes a V []byte structure from a C style memory buffer. NB: the data is reused, NOT copied!
|
|
|
|
// vbytes on`voidptr` makes a V []byte structure from a C style memory buffer.
|
|
|
|
|
|
|
|
// NOTE: the data is reused, NOT copied!
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (data voidptr) vbytes(len int) []byte {
|
|
|
|
pub fn (data voidptr) vbytes(len int) []byte {
|
|
|
|
res := array{
|
|
|
|
res := array{
|
|
|
@ -720,7 +883,8 @@ pub fn (data voidptr) vbytes(len int) []byte {
|
|
|
|
return res
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// byteptr.vbytes() - makes a V []byte structure from a C style memory buffer. NB: the data is reused, NOT copied!
|
|
|
|
// vbytes on `&byte` makes a V []byte structure from a C style memory buffer.
|
|
|
|
|
|
|
|
// NOTE: the data is reused, NOT copied!
|
|
|
|
[unsafe]
|
|
|
|
[unsafe]
|
|
|
|
pub fn (data &byte) vbytes(len int) []byte {
|
|
|
|
pub fn (data &byte) vbytes(len int) []byte {
|
|
|
|
return unsafe { voidptr(data).vbytes(len) }
|
|
|
|
return unsafe { voidptr(data).vbytes(len) }
|
|
|
|