summaryrefslogtreecommitdiff
path: root/core/variant
diff options
context:
space:
mode:
authorHugo Locurcio <hugo.locurcio@hugo.pro>2021-07-10 20:19:47 +0200
committerHugo Locurcio <hugo.locurcio@hugo.pro>2022-05-25 16:09:10 +0200
commita98e31aa3a78e9b9521407f04971eb9e066177ad (patch)
treeebff4e2bf1e2d7ea0d3c296a569b56c8fa5a10d4 /core/variant
parent2ec379e1f96345af5daf46cd31a1efb2a698d5d3 (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.cpp44
-rw-r--r--core/variant/array.h2
-rw-r--r--core/variant/variant_call.cpp2
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());