You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
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.
This commit is contained in:
@@ -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();
|
||||
|
||||
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_INDEX_V(p_begin, size(), result);
|
||||
ERR_FAIL_INDEX_V(p_end, size() + 1, result);
|
||||
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.");
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user