diff options
author | Hugo Locurcio <hugo.locurcio@hugo.pro> | 2021-07-10 20:19:47 +0200 |
---|---|---|
committer | Hugo Locurcio <hugo.locurcio@hugo.pro> | 2022-05-25 16:09:10 +0200 |
commit | a98e31aa3a78e9b9521407f04971eb9e066177ad (patch) | |
tree | ebff4e2bf1e2d7ea0d3c296a569b56c8fa5a10d4 /core/variant | |
parent | 2ec379e1f96345af5daf46cd31a1efb2a698d5d3 (diff) |
Add `any()` and `all()` methods to Array
These can be used as faster, more convenient shorthands to
using `filter()` + `size()`.
Diffstat (limited to 'core/variant')
-rw-r--r-- | core/variant/array.cpp | 44 | ||||
-rw-r--r-- | core/variant/array.h | 2 | ||||
-rw-r--r-- | core/variant/variant_call.cpp | 2 |
3 files changed, 48 insertions, 0 deletions
diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 7551350c95..b1e142d239 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -501,6 +501,50 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const return ret; } +bool Array::any(const Callable &p_callable) const { + const Variant *argptrs[1]; + for (int i = 0; i < size(); i++) { + argptrs[0] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 1, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + } + + if (result.operator bool()) { + // Return as early as possible when one of the conditions is `true`. + // This improves performance compared to relying on `filter(...).size() >= 1`. + return true; + } + } + + return false; +} + +bool Array::all(const Callable &p_callable) const { + const Variant *argptrs[1]; + for (int i = 0; i < size(); i++) { + argptrs[0] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 1, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + } + + if (!(result.operator bool())) { + // Return as early as possible when one of the inverted conditions is `false`. + // This improves performance compared to relying on `filter(...).size() >= array_size().`. + return false; + } + } + + return true; +} + struct _ArrayVariantSort { _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { bool valid = false; diff --git a/core/variant/array.h b/core/variant/array.h index f537700f99..c007376734 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -108,6 +108,8 @@ public: 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; + bool any(const Callable &p_callable) const; + bool all(const Callable &p_callable) const; bool operator<(const Array &p_array) const; bool operator<=(const Array &p_array) const; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index a3568a8d6a..d86bc70d21 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1853,6 +1853,8 @@ static void _register_variant_builtin_methods() { bind_method(Array, filter, sarray("method"), varray()); bind_method(Array, map, sarray("method"), varray()); bind_method(Array, reduce, sarray("method", "accum"), varray(Variant())); + bind_method(Array, any, sarray("method"), varray()); + bind_method(Array, all, sarray("method"), varray()); bind_method(Array, max, sarray(), varray()); bind_method(Array, min, sarray(), varray()); |