| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  array.cpp                                                            */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-01-13 09:45:09 +01:00
										 |  |  | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "array.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-16 08:04:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/hashfuncs.h"
 | 
					
						
							|  |  |  | #include "core/object.h"
 | 
					
						
							|  |  |  | #include "core/variant.h"
 | 
					
						
							|  |  |  | #include "core/vector.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 21:16:08 +02:00
										 |  |  | class ArrayPrivate { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	SafeRefCount refcount; | 
					
						
							|  |  |  | 	Vector<Variant> array; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::_ref(const Array &p_from) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	ArrayPrivate *_fp = p_from._p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!_fp); // should NOT happen.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (_fp == _p) { | 
					
						
							| 
									
										
										
										
											2017-09-21 23:58:29 -04:00
										 |  |  | 		return; // whatever it is, nothing to do here move along
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	bool success = _fp->refcount.ref(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-21 23:58:29 -04:00
										 |  |  | 	ERR_FAIL_COND(!success); // should really not happen either
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_unref(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:53:31 -03:00
										 |  |  | 	_p = p_from._p; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Array::_unref() const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!_p) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (_p->refcount.unref()) { | 
					
						
							|  |  |  | 		memdelete(_p); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	_p = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Variant &Array::operator[](int p_idx) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	return _p->array.write[p_idx]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | const Variant &Array::operator[](int p_idx) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return _p->array[p_idx]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Array::size() const { | 
					
						
							|  |  |  | 	return _p->array.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool Array::empty() const { | 
					
						
							|  |  |  | 	return _p->array.empty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void Array::clear() { | 
					
						
							|  |  |  | 	_p->array.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-07 19:23:06 +02:00
										 |  |  | bool Array::deep_equal(const Array &p_array, int p_recursion_count) const { | 
					
						
							|  |  |  | 	// Cheap checks
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(p_recursion_count > MAX_RECURSION, true, "Max recursion reached"); | 
					
						
							|  |  |  | 	if (_p == p_array._p) { | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	const Vector<Variant> &a1 = _p->array; | 
					
						
							|  |  |  | 	const Vector<Variant> &a2 = p_array._p->array; | 
					
						
							|  |  |  | 	const int size = a1.size(); | 
					
						
							|  |  |  | 	if (size != a2.size()) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Heavy O(n) check
 | 
					
						
							|  |  |  | 	p_recursion_count++; | 
					
						
							|  |  |  | 	for (int i = 0; i < size; i++) { | 
					
						
							|  |  |  | 		if (!a1[i].deep_equal(a2[i], p_recursion_count)) { | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool Array::operator==(const Array &p_array) const { | 
					
						
							|  |  |  | 	return _p == p_array._p; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t Array::hash() const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	uint32_t h = hash_djb2_one_32(0); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < _p->array.size(); i++) { | 
					
						
							|  |  |  | 		h = hash_djb2_one_32(_p->array[i].hash(), h); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return h; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::operator=(const Array &p_array) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_ref(p_array); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::push_back(const Variant &p_value) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_p->array.push_back(p_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-08 21:09:45 +01:00
										 |  |  | void Array::append_array(const Array &p_array) { | 
					
						
							|  |  |  | 	_p->array.append_array(p_array._p->array); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | Error Array::resize(int p_new_size) { | 
					
						
							|  |  |  | 	return _p->array.resize(p_new_size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::insert(int p_pos, const Variant &p_value) { | 
					
						
							|  |  |  | 	_p->array.insert(p_pos, p_value); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-22 18:45:34 +08:00
										 |  |  | void Array::fill(const Variant &p_value) { | 
					
						
							|  |  |  | 	_p->array.fill(p_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::erase(const Variant &p_value) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_p->array.erase(p_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-18 18:30:16 -02:00
										 |  |  | Variant Array::front() const { | 
					
						
							| 
									
										
										
										
											2019-08-14 20:57:49 -06:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array."); | 
					
						
							| 
									
										
										
										
											2016-11-18 18:30:16 -02:00
										 |  |  | 	return operator[](0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant Array::back() const { | 
					
						
							| 
									
										
										
										
											2019-08-14 20:57:49 -06:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array."); | 
					
						
							| 
									
										
										
										
											2016-11-18 18:30:16 -02:00
										 |  |  | 	return operator[](_p->array.size() - 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int Array::find(const Variant &p_value, int p_from) const { | 
					
						
							| 
									
										
										
										
											2016-06-10 14:57:56 -03:00
										 |  |  | 	return _p->array.find(p_value, p_from); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int Array::rfind(const Variant &p_value, int p_from) const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (_p->array.size() == 0) { | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-10 17:28:09 -03:00
										 |  |  | 	if (p_from < 0) { | 
					
						
							|  |  |  | 		// Relative offset from the end
 | 
					
						
							|  |  |  | 		p_from = _p->array.size() + p_from; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (p_from < 0 || p_from >= _p->array.size()) { | 
					
						
							|  |  |  | 		// Limit to array boundaries
 | 
					
						
							|  |  |  | 		p_from = _p->array.size() - 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = p_from; i >= 0; i--) { | 
					
						
							|  |  |  | 		if (_p->array[i] == p_value) { | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 			return i; | 
					
						
							| 
									
										
										
										
											2019-07-01 12:59:42 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int Array::find_last(const Variant &p_value) const { | 
					
						
							| 
									
										
										
										
											2016-06-10 17:28:09 -03:00
										 |  |  | 	return rfind(p_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int Array::count(const Variant &p_value) const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (_p->array.size() == 0) { | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int amount = 0; | 
					
						
							|  |  |  | 	for (int i = 0; i < _p->array.size(); i++) { | 
					
						
							|  |  |  | 		if (_p->array[i] == p_value) { | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 			amount++; | 
					
						
							| 
									
										
										
										
											2019-07-01 12:59:42 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-03 23:10:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return amount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool Array::has(const Variant &p_value) const { | 
					
						
							| 
									
										
										
										
											2016-07-02 19:03:35 +02:00
										 |  |  | 	return _p->array.find(p_value, 0) != -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void Array::remove(int p_pos) { | 
					
						
							|  |  |  | 	_p->array.remove(p_pos); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::set(int p_idx, const Variant &p_value) { | 
					
						
							|  |  |  | 	operator[](p_idx) = p_value; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | const Variant &Array::get(int p_idx) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return operator[](p_idx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 21:16:08 +02:00
										 |  |  | Array Array::duplicate(bool p_deep) const { | 
					
						
							| 
									
										
										
										
											2017-09-06 18:13:05 -03:00
										 |  |  | 	Array new_arr; | 
					
						
							|  |  |  | 	int element_count = size(); | 
					
						
							|  |  |  | 	new_arr.resize(element_count); | 
					
						
							|  |  |  | 	for (int i = 0; i < element_count; i++) { | 
					
						
							| 
									
										
										
										
											2018-03-09 21:16:08 +02:00
										 |  |  | 		new_arr[i] = p_deep ? get(i).duplicate(p_deep) : get(i); | 
					
						
							| 
									
										
										
										
											2017-09-06 18:13:05 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return new_arr; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | int Array::_clamp_slice_index(int p_index) const { | 
					
						
							|  |  |  | 	int arr_size = size(); | 
					
						
							|  |  |  | 	int fixed_index = CLAMP(p_index, -arr_size, arr_size - 1); | 
					
						
							|  |  |  | 	if (fixed_index < 0) { | 
					
						
							|  |  |  | 		fixed_index = arr_size + fixed_index; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fixed_index; | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound
 | 
					
						
							| 
									
										
										
										
											2019-09-24 21:33:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 	Array new_arr; | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(p_step == 0, new_arr, "Array slice step size cannot be zero."); | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (empty()) { // Don't try to slice empty arrays.
 | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 		return new_arr; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 	if (p_step > 0) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (p_begin >= size() || p_end < -size()) { | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 			return new_arr; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 	} else { // p_step < 0
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (p_begin < -size() || p_end >= size()) { | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 			return new_arr; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 	int begin = _clamp_slice_index(p_begin); | 
					
						
							|  |  |  | 	int end = _clamp_slice_index(p_end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int new_arr_size = MAX(((end - begin + p_step) / p_step), 0); | 
					
						
							|  |  |  | 	new_arr.resize(new_arr_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_step > 0) { | 
					
						
							|  |  |  | 		int dest_idx = 0; | 
					
						
							|  |  |  | 		for (int idx = begin; idx <= end; idx += p_step) { | 
					
						
							|  |  |  | 			ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()"); | 
					
						
							|  |  |  | 			new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx); | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-01 17:06:36 +01:00
										 |  |  | 	} else { // p_step < 0
 | 
					
						
							|  |  |  | 		int dest_idx = 0; | 
					
						
							|  |  |  | 		for (int idx = begin; idx >= end; idx += p_step) { | 
					
						
							|  |  |  | 			ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()"); | 
					
						
							|  |  |  | 			new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx); | 
					
						
							| 
									
										
										
										
											2019-07-16 18:31:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return new_arr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | struct _ArrayVariantSort { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { | 
					
						
							|  |  |  | 		bool valid = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		Variant res; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (!valid) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			res = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 17:49:23 +02:00
										 |  |  | Array &Array::sort() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_p->array.sort_custom<_ArrayVariantSort>(); | 
					
						
							| 
									
										
										
										
											2017-10-07 17:49:23 +02:00
										 |  |  | 	return *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _ArrayVariantSortCustom { | 
					
						
							|  |  |  | 	Object *obj; | 
					
						
							|  |  |  | 	StringName func; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { | 
					
						
							|  |  |  | 		const Variant *args[2] = { &p_l, &p_r }; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		Variant::CallError err; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		bool res = obj->call(func, args, 2, err); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (err.error != Variant::CallError::CALL_OK) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			res = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-10-07 17:49:23 +02:00
										 |  |  | Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { | 
					
						
							|  |  |  | 	ERR_FAIL_NULL_V(p_obj, *this); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 19:03:51 +01:00
										 |  |  | 	SortArray<Variant, _ArrayVariantSortCustom, true> avs; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	avs.compare.obj = p_obj; | 
					
						
							|  |  |  | 	avs.compare.func = p_function; | 
					
						
							| 
									
										
										
										
											2017-11-25 00:07:54 -03:00
										 |  |  | 	avs.sort(_p->array.ptrw(), _p->array.size()); | 
					
						
							| 
									
										
										
										
											2017-10-07 17:49:23 +02:00
										 |  |  | 	return *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-10 19:36:53 +01:00
										 |  |  | void Array::shuffle() { | 
					
						
							|  |  |  | 	const int n = _p->array.size(); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (n < 2) { | 
					
						
							| 
									
										
										
										
											2018-01-10 19:36:53 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-10 19:36:53 +01:00
										 |  |  | 	Variant *data = _p->array.ptrw(); | 
					
						
							|  |  |  | 	for (int i = n - 1; i >= 1; i--) { | 
					
						
							|  |  |  | 		const int j = Math::rand() % (i + 1); | 
					
						
							|  |  |  | 		const Variant tmp = data[j]; | 
					
						
							|  |  |  | 		data[j] = data[i]; | 
					
						
							|  |  |  | 		data[i] = tmp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 19:04:38 +01:00
										 |  |  | template <typename Less> | 
					
						
							|  |  |  | _FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) { | 
					
						
							|  |  |  | 	int lo = 0; | 
					
						
							|  |  |  | 	int hi = p_array.size(); | 
					
						
							|  |  |  | 	if (p_before) { | 
					
						
							|  |  |  | 		while (lo < hi) { | 
					
						
							|  |  |  | 			const int mid = (lo + hi) / 2; | 
					
						
							|  |  |  | 			if (p_less(p_array.get(mid), p_value)) { | 
					
						
							|  |  |  | 				lo = mid + 1; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				hi = mid; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		while (lo < hi) { | 
					
						
							|  |  |  | 			const int mid = (lo + hi) / 2; | 
					
						
							|  |  |  | 			if (p_less(p_value, p_array.get(mid))) { | 
					
						
							|  |  |  | 				hi = mid; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				lo = mid + 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return lo; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Array::bsearch(const Variant &p_value, bool p_before) { | 
					
						
							|  |  |  | 	return bisect(_p->array, p_value, p_before, _ArrayVariantSort()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) { | 
					
						
							|  |  |  | 	ERR_FAIL_NULL_V(p_obj, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_ArrayVariantSortCustom less; | 
					
						
							|  |  |  | 	less.obj = p_obj; | 
					
						
							|  |  |  | 	less.func = p_function; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return bisect(_p->array, p_value, p_before, less); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 17:49:23 +02:00
										 |  |  | Array &Array::invert() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_p->array.invert(); | 
					
						
							| 
									
										
										
										
											2017-10-07 17:49:23 +02:00
										 |  |  | 	return *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Array::push_front(const Variant &p_value) { | 
					
						
							|  |  |  | 	_p->array.insert(0, p_value); | 
					
						
							| 
									
										
										
										
											2015-12-12 08:27:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Variant Array::pop_back() { | 
					
						
							| 
									
										
										
										
											2016-08-27 17:33:45 +02:00
										 |  |  | 	if (!_p->array.empty()) { | 
					
						
							| 
									
										
										
										
											2021-08-27 01:27:07 +02:00
										 |  |  | 		const int n = _p->array.size() - 1; | 
					
						
							|  |  |  | 		const Variant ret = _p->array.get(n); | 
					
						
							| 
									
										
										
										
											2016-08-27 17:33:45 +02:00
										 |  |  | 		_p->array.resize(n); | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return Variant(); | 
					
						
							| 
									
										
										
										
											2015-12-12 08:27:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Variant Array::pop_front() { | 
					
						
							| 
									
										
										
										
											2016-08-27 17:33:45 +02:00
										 |  |  | 	if (!_p->array.empty()) { | 
					
						
							| 
									
										
										
										
											2021-08-27 01:27:07 +02:00
										 |  |  | 		const Variant ret = _p->array.get(0); | 
					
						
							| 
									
										
										
										
											2015-12-12 08:27:30 -03:00
										 |  |  | 		_p->array.remove(0); | 
					
						
							| 
									
										
										
										
											2016-08-27 17:33:45 +02:00
										 |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return Variant(); | 
					
						
							| 
									
										
										
										
											2015-12-12 08:27:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 01:27:07 +02:00
										 |  |  | Variant Array::pop_at(int p_pos) { | 
					
						
							|  |  |  | 	if (_p->array.empty()) { | 
					
						
							|  |  |  | 		// Return `null` without printing an error to mimic `pop_back()` and `pop_front()` behavior.
 | 
					
						
							|  |  |  | 		return Variant(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_pos < 0) { | 
					
						
							|  |  |  | 		// Relative offset from the end
 | 
					
						
							|  |  |  | 		p_pos = _p->array.size() + p_pos; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V_MSG( | 
					
						
							|  |  |  | 			p_pos, | 
					
						
							|  |  |  | 			_p->array.size(), | 
					
						
							|  |  |  | 			Variant(), | 
					
						
							|  |  |  | 			vformat( | 
					
						
							|  |  |  | 					"The calculated index %s is out of bounds (the array has %s elements). Leaving the array untouched and returning `null`.", | 
					
						
							|  |  |  | 					p_pos, | 
					
						
							|  |  |  | 					_p->array.size())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const Variant ret = _p->array.get(p_pos); | 
					
						
							|  |  |  | 	_p->array.remove(p_pos); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-23 15:31:02 -03:00
										 |  |  | Variant Array::min() const { | 
					
						
							|  |  |  | 	Variant minval; | 
					
						
							|  |  |  | 	for (int i = 0; i < size(); i++) { | 
					
						
							|  |  |  | 		if (i == 0) { | 
					
						
							|  |  |  | 			minval = get(i); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			bool valid; | 
					
						
							|  |  |  | 			Variant ret; | 
					
						
							|  |  |  | 			Variant test = get(i); | 
					
						
							|  |  |  | 			Variant::evaluate(Variant::OP_LESS, test, minval, ret, valid); | 
					
						
							|  |  |  | 			if (!valid) { | 
					
						
							|  |  |  | 				return Variant(); //not a valid comparison
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (bool(ret)) { | 
					
						
							|  |  |  | 				//is less
 | 
					
						
							|  |  |  | 				minval = test; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return minval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant Array::max() const { | 
					
						
							|  |  |  | 	Variant maxval; | 
					
						
							|  |  |  | 	for (int i = 0; i < size(); i++) { | 
					
						
							|  |  |  | 		if (i == 0) { | 
					
						
							|  |  |  | 			maxval = get(i); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			bool valid; | 
					
						
							|  |  |  | 			Variant ret; | 
					
						
							|  |  |  | 			Variant test = get(i); | 
					
						
							|  |  |  | 			Variant::evaluate(Variant::OP_GREATER, test, maxval, ret, valid); | 
					
						
							|  |  |  | 			if (!valid) { | 
					
						
							|  |  |  | 				return Variant(); //not a valid comparison
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (bool(ret)) { | 
					
						
							|  |  |  | 				//is less
 | 
					
						
							|  |  |  | 				maxval = test; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return maxval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-20 01:57:29 +02:00
										 |  |  | const void *Array::id() const { | 
					
						
							| 
									
										
										
										
											2021-12-30 13:14:09 +08:00
										 |  |  | 	return _p; | 
					
						
							| 
									
										
										
										
											2019-04-20 01:57:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Array::Array(const Array &p_from) { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	_p = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_ref(p_from); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-08-23 15:31:02 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:53:31 -03:00
										 |  |  | Array::Array() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	_p = memnew(ArrayPrivate); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_p->refcount.init(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | Array::~Array() { | 
					
						
							|  |  |  | 	_unref(); | 
					
						
							|  |  |  | } |