diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2022-01-10 13:56:55 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2022-01-10 22:42:03 +0100 |
commit | c6cefb1b79d207af1bc78ce20c01b5788e806252 (patch) | |
tree | ca713ba3bf904b57a7408ec50029c9fbcc275d40 | |
parent | 4acc819f9bafacf5f912caf5ba2ebc15f70e3dbb (diff) |
`Array`: Relax `slice` bound checks to properly handle negative indices
The same is done for `Vector` (and thus `Packed*Array`).
`begin` and `end` can now take any value and will be clamped to
`[-size(), size()]`. Negative values are a shorthand for indexing the array
from the last element upward.
`end` is given a default `INT_MAX` value (which will be clamped to `size()`)
so that the `end` parameter can be omitted to go from `begin` to the max size
of the array.
This makes `slice` works similarly to numpy's and JavaScript's.
-rw-r--r-- | core/templates/vector.h | 23 | ||||
-rw-r--r-- | core/variant/array.cpp | 22 | ||||
-rw-r--r-- | core/variant/array.h | 4 | ||||
-rw-r--r-- | core/variant/variant_call.cpp | 20 | ||||
-rw-r--r-- | doc/classes/Array.xml | 7 | ||||
-rw-r--r-- | doc/classes/PackedByteArray.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedColorArray.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedFloat32Array.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedFloat64Array.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedInt32Array.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedInt64Array.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedStringArray.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedVector2Array.xml | 5 | ||||
-rw-r--r-- | doc/classes/PackedVector3Array.xml | 5 | ||||
-rw-r--r-- | tests/core/templates/test_vector.h | 25 | ||||
-rw-r--r-- | tests/core/variant/test_array.h | 35 |
16 files changed, 129 insertions, 52 deletions
diff --git a/core/templates/vector.h b/core/templates/vector.h index 4ada3b597a..d1408125c8 100644 --- a/core/templates/vector.h +++ b/core/templates/vector.h @@ -43,6 +43,7 @@ #include "core/templates/search_array.h" #include "core/templates/sort_array.h" +#include <climits> #include <initializer_list> template <class T> @@ -145,25 +146,29 @@ public: return ret; } - Vector<T> slice(int p_begin, int p_end) const { + Vector<T> slice(int p_begin, int p_end = INT_MAX) const { Vector<T> result; - if (p_end < 0) { - p_end += size() + 1; - } + const int s = size(); - ERR_FAIL_INDEX_V(p_begin, size(), result); - ERR_FAIL_INDEX_V(p_end, size() + 1, result); + int begin = CLAMP(p_begin, -s, s); + if (begin < 0) { + begin += s; + } + int end = CLAMP(p_end, -s, s); + if (end < 0) { + end += s; + } - ERR_FAIL_COND_V(p_begin > p_end, result); + ERR_FAIL_COND_V(begin > end, result); - int result_size = p_end - p_begin; + int result_size = end - begin; result.resize(result_size); const T *const r = ptr(); T *const w = result.ptrw(); for (int i = 0; i < result_size; ++i) { - w[i] = r[p_begin + i]; + w[i] = r[begin + i]; } return result; diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 8d20b1bc79..3d2f337442 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -370,20 +370,24 @@ Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { ERR_FAIL_COND_V_MSG(p_step == 0, result, "Slice step cannot be zero."); - if (p_end < 0) { - p_end += size() + 1; - } + const int s = size(); - ERR_FAIL_INDEX_V(p_begin, size(), result); - ERR_FAIL_INDEX_V(p_end, size() + 1, result); + int begin = CLAMP(p_begin, -s, s); + if (begin < 0) { + begin += s; + } + int end = CLAMP(p_end, -s, s); + if (end < 0) { + end += s; + } - ERR_FAIL_COND_V_MSG(p_step > 0 && p_begin > p_end, result, "Slice is positive, but bounds is decreasing"); - ERR_FAIL_COND_V_MSG(p_step < 0 && p_begin < p_end, result, "Slice is negative, but bounds is increasing"); + ERR_FAIL_COND_V_MSG(p_step > 0 && begin > end, result, "Slice is positive, but bounds is decreasing."); + ERR_FAIL_COND_V_MSG(p_step < 0 && begin < end, result, "Slice is negative, but bounds is increasing."); - int result_size = (p_end - p_begin) / p_step; + int result_size = (end - begin) / p_step; result.resize(result_size); - for (int src_idx = p_begin, dest_idx = 0; dest_idx < result_size; ++dest_idx) { + for (int src_idx = begin, dest_idx = 0; dest_idx < result_size; ++dest_idx) { result[dest_idx] = p_deep ? get(src_idx).duplicate(true) : get(src_idx); src_idx += p_step; } diff --git a/core/variant/array.h b/core/variant/array.h index f48444bb39..72bed5932c 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -33,6 +33,8 @@ #include "core/typedefs.h" +#include <climits> + class Variant; class ArrayPrivate; class Object; @@ -102,7 +104,7 @@ public: Array duplicate(bool p_deep = false) const; Array recursive_duplicate(bool p_deep, int recursion_count) const; - Array slice(int p_begin, int p_end, int p_step = 1, bool p_deep = false) const; + Array slice(int p_begin, int p_end = INT_MAX, int p_step = 1, bool p_deep = false) const; Array filter(const Callable &p_callable) const; Array map(const Callable &p_callable) const; Variant reduce(const Callable &p_callable, const Variant &p_accum) const; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index ecf5009fb6..8dd48a4c28 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1838,7 +1838,7 @@ static void _register_variant_builtin_methods() { bind_method(Array, bsearch_custom, sarray("value", "func", "before"), varray(true)); bind_method(Array, reverse, sarray(), varray()); bind_method(Array, duplicate, sarray("deep"), varray(false)); - bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(1, false)); + bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(INT_MAX, 1, false)); bind_method(Array, filter, sarray("method"), varray()); bind_method(Array, map, sarray("method"), varray()); bind_method(Array, reduce, sarray("method", "accum"), varray(Variant())); @@ -1858,7 +1858,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedByteArray, resize, sarray("new_size"), varray()); bind_method(PackedByteArray, has, sarray("value"), varray()); bind_method(PackedByteArray, reverse, sarray(), varray()); - bind_method(PackedByteArray, slice, sarray("begin", "end"), varray()); + bind_method(PackedByteArray, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedByteArray, sort, sarray(), varray()); bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true)); bind_method(PackedByteArray, duplicate, sarray(), varray()); @@ -1919,7 +1919,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt32Array, resize, sarray("new_size"), varray()); bind_method(PackedInt32Array, has, sarray("value"), varray()); bind_method(PackedInt32Array, reverse, sarray(), varray()); - bind_method(PackedInt32Array, slice, sarray("begin", "end"), varray()); + bind_method(PackedInt32Array, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedInt32Array, to_byte_array, sarray(), varray()); bind_method(PackedInt32Array, sort, sarray(), varray()); bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true)); @@ -1939,7 +1939,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt64Array, resize, sarray("new_size"), varray()); bind_method(PackedInt64Array, has, sarray("value"), varray()); bind_method(PackedInt64Array, reverse, sarray(), varray()); - bind_method(PackedInt64Array, slice, sarray("begin", "end"), varray()); + bind_method(PackedInt64Array, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedInt64Array, to_byte_array, sarray(), varray()); bind_method(PackedInt64Array, sort, sarray(), varray()); bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true)); @@ -1959,7 +1959,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat32Array, resize, sarray("new_size"), varray()); bind_method(PackedFloat32Array, has, sarray("value"), varray()); bind_method(PackedFloat32Array, reverse, sarray(), varray()); - bind_method(PackedFloat32Array, slice, sarray("begin", "end"), varray()); + bind_method(PackedFloat32Array, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedFloat32Array, to_byte_array, sarray(), varray()); bind_method(PackedFloat32Array, sort, sarray(), varray()); bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true)); @@ -1979,7 +1979,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat64Array, resize, sarray("new_size"), varray()); bind_method(PackedFloat64Array, has, sarray("value"), varray()); bind_method(PackedFloat64Array, reverse, sarray(), varray()); - bind_method(PackedFloat64Array, slice, sarray("begin", "end"), varray()); + bind_method(PackedFloat64Array, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedFloat64Array, to_byte_array, sarray(), varray()); bind_method(PackedFloat64Array, sort, sarray(), varray()); bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true)); @@ -1999,7 +1999,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedStringArray, resize, sarray("new_size"), varray()); bind_method(PackedStringArray, has, sarray("value"), varray()); bind_method(PackedStringArray, reverse, sarray(), varray()); - bind_method(PackedStringArray, slice, sarray("begin", "end"), varray()); + bind_method(PackedStringArray, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedStringArray, to_byte_array, sarray(), varray()); bind_method(PackedStringArray, sort, sarray(), varray()); bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true)); @@ -2019,7 +2019,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector2Array, resize, sarray("new_size"), varray()); bind_method(PackedVector2Array, has, sarray("value"), varray()); bind_method(PackedVector2Array, reverse, sarray(), varray()); - bind_method(PackedVector2Array, slice, sarray("begin", "end"), varray()); + bind_method(PackedVector2Array, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedVector2Array, to_byte_array, sarray(), varray()); bind_method(PackedVector2Array, sort, sarray(), varray()); bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true)); @@ -2039,7 +2039,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector3Array, resize, sarray("new_size"), varray()); bind_method(PackedVector3Array, has, sarray("value"), varray()); bind_method(PackedVector3Array, reverse, sarray(), varray()); - bind_method(PackedVector3Array, slice, sarray("begin", "end"), varray()); + bind_method(PackedVector3Array, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedVector3Array, to_byte_array, sarray(), varray()); bind_method(PackedVector3Array, sort, sarray(), varray()); bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true)); @@ -2059,7 +2059,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedColorArray, resize, sarray("new_size"), varray()); bind_method(PackedColorArray, has, sarray("value"), varray()); bind_method(PackedColorArray, reverse, sarray(), varray()); - bind_method(PackedColorArray, slice, sarray("begin", "end"), varray()); + bind_method(PackedColorArray, slice, sarray("begin", "end"), varray(INT_MAX)); bind_method(PackedColorArray, to_byte_array, sarray(), varray()); bind_method(PackedColorArray, sort, sarray(), varray()); bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true)); diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 5b1861bc9a..badd8a4966 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -445,13 +445,14 @@ <method name="slice" qualifiers="const"> <return type="Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <argument index="2" name="step" type="int" default="1" /> <argument index="3" name="deep" type="bool" default="false" /> <description> Returns the slice of the [Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [Array]. - If [code]end[/code] is negative, it will be relative to the end of the array. - If specified, [code]step[/code] is the relative index between source elements. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). + If specified, [code]step[/code] is the relative index between source elements. It can be negative, then [code]begin[/code] must be higher than [code]end[/code]. For example, [code][0, 1, 2, 3, 4, 5].slice(5, 1, -2)[/code] returns [code][5, 3][/code]). If [code]deep[/code] is true, each element will be copied by value rather than by reference. </description> </method> diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 686854ffe8..3dc8307d44 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -369,10 +369,11 @@ <method name="slice" qualifiers="const"> <return type="PackedByteArray" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> Returns the slice of the [PackedByteArray], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedByteArray]. - If [code]end[/code]is negative, it will be relative to the end of the array. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml index d875549319..8aac7d1bf4 100644 --- a/doc/classes/PackedColorArray.xml +++ b/doc/classes/PackedColorArray.xml @@ -132,8 +132,11 @@ <method name="slice" qualifiers="const"> <return type="PackedColorArray" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedColorArray], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedColorArray]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml index 6c77c4bee2..0e66dd7967 100644 --- a/doc/classes/PackedFloat32Array.xml +++ b/doc/classes/PackedFloat32Array.xml @@ -133,8 +133,11 @@ <method name="slice" qualifiers="const"> <return type="PackedFloat32Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedFloat32Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedFloat32Array]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml index a8282c099a..eaad4fec54 100644 --- a/doc/classes/PackedFloat64Array.xml +++ b/doc/classes/PackedFloat64Array.xml @@ -133,8 +133,11 @@ <method name="slice" qualifiers="const"> <return type="PackedFloat64Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedFloat64Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedFloat64Array]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml index da26e93b96..ec698ed8e5 100644 --- a/doc/classes/PackedInt32Array.xml +++ b/doc/classes/PackedInt32Array.xml @@ -133,8 +133,11 @@ <method name="slice" qualifiers="const"> <return type="PackedInt32Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedInt32Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedInt32Array]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index 9ddf43a837..ec4b3c1209 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -133,8 +133,11 @@ <method name="slice" qualifiers="const"> <return type="PackedInt64Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedInt64Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedInt64Array]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml index 439d59dde7..ebe9c591b8 100644 --- a/doc/classes/PackedStringArray.xml +++ b/doc/classes/PackedStringArray.xml @@ -133,8 +133,11 @@ <method name="slice" qualifiers="const"> <return type="PackedStringArray" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedStringArray], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedStringArray]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml index 8c4f052016..d72ca4b4bb 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -133,8 +133,11 @@ <method name="slice" qualifiers="const"> <return type="PackedVector2Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedVector2Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedVector2Array]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml index 8229af984d..cbae0c40e7 100644 --- a/doc/classes/PackedVector3Array.xml +++ b/doc/classes/PackedVector3Array.xml @@ -132,8 +132,11 @@ <method name="slice" qualifiers="const"> <return type="PackedVector3Array" /> <argument index="0" name="begin" type="int" /> - <argument index="1" name="end" type="int" /> + <argument index="1" name="end" type="int" default="2147483647" /> <description> + Returns the slice of the [PackedVector3Array], from [code]begin[/code] (inclusive) to [code]end[/code] (exclusive), as a new [PackedVector3Array]. + The absolute value of [code]begin[/code] and [code]end[/code] will be clamped to the array size, so the default value for [code]end[/code] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). + If either [code]begin[/code] or [code]end[/code] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). </description> </method> <method name="sort"> diff --git a/tests/core/templates/test_vector.h b/tests/core/templates/test_vector.h index 24b3547256..f27d6a332e 100644 --- a/tests/core/templates/test_vector.h +++ b/tests/core/templates/test_vector.h @@ -257,27 +257,42 @@ TEST_CASE("[Vector] Slice") { vector.push_back(3); vector.push_back(4); + Vector<int> slice0 = vector.slice(0, 0); + CHECK(slice0.size() == 0); + Vector<int> slice1 = vector.slice(1, 3); CHECK(slice1.size() == 2); CHECK(slice1[0] == 1); CHECK(slice1[1] == 2); Vector<int> slice2 = vector.slice(1, -1); - CHECK(slice2.size() == 4); + CHECK(slice2.size() == 3); CHECK(slice2[0] == 1); CHECK(slice2[1] == 2); CHECK(slice2[2] == 3); - CHECK(slice2[3] == 4); - Vector<int> slice3 = vector.slice(3, -1); + Vector<int> slice3 = vector.slice(3); CHECK(slice3.size() == 2); CHECK(slice3[0] == 3); CHECK(slice3[1] == 4); Vector<int> slice4 = vector.slice(2, -2); - CHECK(slice4.size() == 2); + CHECK(slice4.size() == 1); CHECK(slice4[0] == 2); - CHECK(slice4[1] == 3); + + Vector<int> slice5 = vector.slice(-2); + CHECK(slice5.size() == 2); + CHECK(slice5[0] == 3); + CHECK(slice5[1] == 4); + + Vector<int> slice6 = vector.slice(2, 42); + CHECK(slice6.size() == 3); + CHECK(slice6[0] == 2); + CHECK(slice6[1] == 3); + CHECK(slice6[2] == 4); + + Vector<int> slice7 = vector.slice(5, 1); + CHECK(slice7.size() == 0); } TEST_CASE("[Vector] Find, has") { diff --git a/tests/core/variant/test_array.h b/tests/core/variant/test_array.h index 205e34daea..6093048307 100644 --- a/tests/core/variant/test_array.h +++ b/tests/core/variant/test_array.h @@ -254,27 +254,52 @@ TEST_CASE("[Array] slice()") { array.push_back(3); array.push_back(4); + Array slice0 = array.slice(0, 0); + CHECK(slice0.size() == 0); + Array slice1 = array.slice(1, 3); CHECK(slice1.size() == 2); CHECK(slice1[0] == Variant(1)); CHECK(slice1[1] == Variant(2)); Array slice2 = array.slice(1, -1); - CHECK(slice2.size() == 4); + CHECK(slice2.size() == 3); CHECK(slice2[0] == Variant(1)); CHECK(slice2[1] == Variant(2)); CHECK(slice2[2] == Variant(3)); - CHECK(slice2[3] == Variant(4)); - Array slice3 = array.slice(3, -1); + Array slice3 = array.slice(3); CHECK(slice3.size() == 2); CHECK(slice3[0] == Variant(3)); CHECK(slice3[1] == Variant(4)); Array slice4 = array.slice(2, -2); - CHECK(slice4.size() == 2); + CHECK(slice4.size() == 1); CHECK(slice4[0] == Variant(2)); - CHECK(slice4[1] == Variant(3)); + + Array slice5 = array.slice(-2); + CHECK(slice5.size() == 2); + CHECK(slice5[0] == Variant(3)); + CHECK(slice5[1] == Variant(4)); + + Array slice6 = array.slice(2, 42); + CHECK(slice6.size() == 3); + CHECK(slice6[0] == Variant(2)); + CHECK(slice6[1] == Variant(3)); + CHECK(slice6[2] == Variant(4)); + + Array slice7 = array.slice(4, 0, -2); + CHECK(slice7.size() == 2); + CHECK(slice7[0] == Variant(4)); + CHECK(slice7[1] == Variant(2)); + + ERR_PRINT_OFF; + Array slice8 = array.slice(4, 1); + CHECK(slice8.size() == 0); + + Array slice9 = array.slice(3, -4); + CHECK(slice9.size() == 0); + ERR_PRINT_ON; } TEST_CASE("[Array] Duplicate array") { |