| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  cowdata.h                                                             */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* 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-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 11:10:34 +01:00
										 |  |  | #ifndef COWDATA_H
 | 
					
						
							|  |  |  | #define COWDATA_H
 | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/error/error_macros.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/os/memory.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/templates/safe_refcount.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 11:10:34 +01:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2024-08-21 13:32:25 -05:00
										 |  |  | #include <initializer_list>
 | 
					
						
							| 
									
										
										
										
											2022-08-04 13:53:03 +02:00
										 |  |  | #include <type_traits>
 | 
					
						
							| 
									
										
										
										
											2024-12-16 17:28:47 +01:00
										 |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2020-03-25 11:10:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | class Vector; | 
					
						
							|  |  |  | class String; | 
					
						
							| 
									
										
										
										
											2020-07-27 13:43:20 +03:00
										 |  |  | class Char16String; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | class CharString; | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T, typename V> | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | class VMap; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>); | 
					
						
							| 
									
										
										
										
											2021-02-10 19:22:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 02:32:19 +03:00
										 |  |  | // Silence a false positive warning (see GH-52119).
 | 
					
						
							|  |  |  | #if defined(__GNUC__) && !defined(__clang__)
 | 
					
						
							|  |  |  | #pragma GCC diagnostic push
 | 
					
						
							|  |  |  | #pragma GCC diagnostic ignored "-Wplacement-new"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | class CowData { | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | 	template <typename TV> | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	friend class Vector; | 
					
						
							|  |  |  | 	friend class String; | 
					
						
							| 
									
										
										
										
											2020-07-27 13:43:20 +03:00
										 |  |  | 	friend class Char16String; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	friend class CharString; | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | 	template <typename TV, typename VV> | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	friend class VMap; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | public: | 
					
						
							|  |  |  | 	typedef int64_t Size; | 
					
						
							|  |  |  | 	typedef uint64_t USize; | 
					
						
							|  |  |  | 	static constexpr USize MAX_INT = INT64_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	// Function to find the next power of 2 to an integer.
 | 
					
						
							|  |  |  | 	static _FORCE_INLINE_ USize next_po2(USize x) { | 
					
						
							|  |  |  | 		if (x == 0) { | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		--x; | 
					
						
							|  |  |  | 		x |= x >> 1; | 
					
						
							|  |  |  | 		x |= x >> 2; | 
					
						
							|  |  |  | 		x |= x >> 4; | 
					
						
							|  |  |  | 		x |= x >> 8; | 
					
						
							|  |  |  | 		x |= x >> 16; | 
					
						
							|  |  |  | 		if (sizeof(USize) == 8) { | 
					
						
							|  |  |  | 			x |= x >> 32; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return ++x; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 	// Alignment:  ↓ max_align_t           ↓ USize          ↓ max_align_t
 | 
					
						
							|  |  |  | 	//             ┌────────────────────┬──┬─────────────┬──┬───────────...
 | 
					
						
							|  |  |  | 	//             │ SafeNumeric<USize> │░░│ USize       │░░│ T[]
 | 
					
						
							|  |  |  | 	//             │ ref. count         │░░│ data size   │░░│ data
 | 
					
						
							|  |  |  | 	//             └────────────────────┴──┴─────────────┴──┴───────────...
 | 
					
						
							|  |  |  | 	// Offset:     ↑ REF_COUNT_OFFSET      ↑ SIZE_OFFSET    ↑ DATA_OFFSET
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static constexpr size_t REF_COUNT_OFFSET = 0; | 
					
						
							|  |  |  | 	static constexpr size_t SIZE_OFFSET = ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize) == 0) ? (REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) : ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) + alignof(USize) - ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize))); | 
					
						
							|  |  |  | 	static constexpr size_t DATA_OFFSET = ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t) == 0) ? (SIZE_OFFSET + sizeof(USize)) : ((SIZE_OFFSET + sizeof(USize)) + alignof(max_align_t) - ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t))); | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 	mutable T *_ptr = nullptr; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// internal helpers
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 	static _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount_ptr(uint8_t *p_ptr) { | 
					
						
							|  |  |  | 		return (SafeNumeric<USize> *)(p_ptr + REF_COUNT_OFFSET); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static _FORCE_INLINE_ USize *_get_size_ptr(uint8_t *p_ptr) { | 
					
						
							|  |  |  | 		return (USize *)(p_ptr + SIZE_OFFSET); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static _FORCE_INLINE_ T *_get_data_ptr(uint8_t *p_ptr) { | 
					
						
							|  |  |  | 		return (T *)(p_ptr + DATA_OFFSET); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ SafeNumeric<USize> *_get_refcount() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (!_ptr) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 			return nullptr; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 		return (SafeNumeric<USize> *)((uint8_t *)_ptr - DATA_OFFSET + REF_COUNT_OFFSET); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ USize *_get_size() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (!_ptr) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 			return nullptr; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 		return (USize *)((uint8_t *)_ptr - DATA_OFFSET + SIZE_OFFSET); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ USize _get_alloc_size(USize p_elements) const { | 
					
						
							|  |  |  | 		return next_po2(p_elements * sizeof(T)); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ bool _get_alloc_size_checked(USize p_elements, USize *out) const { | 
					
						
							| 
									
										
										
										
											2023-09-19 13:59:47 +02:00
										 |  |  | 		if (unlikely(p_elements == 0)) { | 
					
						
							|  |  |  | 			*out = 0; | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | #if defined(__GNUC__) && defined(IS_32_BIT)
 | 
					
						
							|  |  |  | 		USize o; | 
					
						
							|  |  |  | 		USize p; | 
					
						
							| 
									
										
										
										
											2020-03-11 21:01:02 +01:00
										 |  |  | 		if (__builtin_mul_overflow(p_elements, sizeof(T), &o)) { | 
					
						
							| 
									
										
										
										
											2018-10-04 18:54:20 +02:00
										 |  |  | 			*out = 0; | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 		*out = next_po2(o); | 
					
						
							|  |  |  | 		if (__builtin_add_overflow(o, static_cast<USize>(32), &p)) { | 
					
						
							| 
									
										
										
										
											2020-03-11 21:01:02 +01:00
										 |  |  | 			return false; // No longer allocated here.
 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 		// Speed is more important than correctness here, do the operations unchecked
 | 
					
						
							| 
									
										
										
										
											2020-03-11 21:01:02 +01:00
										 |  |  | 		// and hope for the best.
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		*out = _get_alloc_size(p_elements); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-09-19 13:59:47 +02:00
										 |  |  | 		return *out; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 	// Decrements the reference count. Deallocates the backing buffer if needed.
 | 
					
						
							|  |  |  | 	// After this function, _ptr is guaranteed to be NULL.
 | 
					
						
							| 
									
										
										
										
											2024-08-13 08:53:22 +03:00
										 |  |  | 	void _unref(); | 
					
						
							| 
									
										
										
										
											2018-07-29 16:57:05 +02:00
										 |  |  | 	void _ref(const CowData *p_from); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	void _ref(const CowData &p_from); | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	USize _copy_on_write(); | 
					
						
							| 
									
										
										
										
											2024-12-16 16:44:32 +01:00
										 |  |  | 	Error _realloc(Size p_alloc_size); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	void operator=(const CowData<T> &p_from) { _ref(p_from); } | 
					
						
							| 
									
										
										
										
											2024-12-10 13:39:42 +01:00
										 |  |  | 	void operator=(CowData<T> &&p_from) { | 
					
						
							|  |  |  | 		if (_ptr == p_from._ptr) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_unref(); | 
					
						
							|  |  |  | 		_ptr = p_from._ptr; | 
					
						
							|  |  |  | 		p_from._ptr = nullptr; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_FORCE_INLINE_ T *ptrw() { | 
					
						
							|  |  |  | 		_copy_on_write(); | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 		return _ptr; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_FORCE_INLINE_ const T *ptr() const { | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 		return _ptr; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ Size size() const { | 
					
						
							|  |  |  | 		USize *size = (USize *)_get_size(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (size) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 			return *size; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_FORCE_INLINE_ void clear() { resize(0); } | 
					
						
							| 
									
										
										
										
											2020-12-15 12:04:21 +00:00
										 |  |  | 	_FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; } | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ void set(Size p_index, const T &p_elem) { | 
					
						
							| 
									
										
										
										
											2021-02-24 21:36:08 +01:00
										 |  |  | 		ERR_FAIL_INDEX(p_index, size()); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		_copy_on_write(); | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 		_ptr[p_index] = p_elem; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ T &get_m(Size p_index) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		CRASH_BAD_INDEX(p_index, size()); | 
					
						
							|  |  |  | 		_copy_on_write(); | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 		return _ptr[p_index]; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ const T &get(Size p_index) const { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		CRASH_BAD_INDEX(p_index, size()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 		return _ptr[p_index]; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-04 16:43:49 +02:00
										 |  |  | 	template <bool p_ensure_zero = false> | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	Error resize(Size p_size); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	_FORCE_INLINE_ void remove_at(Size p_index) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		ERR_FAIL_INDEX(p_index, size()); | 
					
						
							|  |  |  | 		T *p = ptrw(); | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 		Size len = size(); | 
					
						
							|  |  |  | 		for (Size i = p_index; i < len - 1; i++) { | 
					
						
							| 
									
										
										
										
											2024-12-16 17:28:47 +01:00
										 |  |  | 			p[i] = std::move(p[i + 1]); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		resize(len - 1); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	Error insert(Size p_pos, const T &p_val) { | 
					
						
							| 
									
										
										
										
											2024-07-13 21:36:11 -04:00
										 |  |  | 		Size new_size = size() + 1; | 
					
						
							|  |  |  | 		ERR_FAIL_INDEX_V(p_pos, new_size, ERR_INVALID_PARAMETER); | 
					
						
							|  |  |  | 		Error err = resize(new_size); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(err, err); | 
					
						
							|  |  |  | 		T *p = ptrw(); | 
					
						
							|  |  |  | 		for (Size i = new_size - 1; i > p_pos; i--) { | 
					
						
							| 
									
										
										
										
											2024-12-16 17:28:47 +01:00
										 |  |  | 			p[i] = std::move(p[i - 1]); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-13 21:36:11 -04:00
										 |  |  | 		p[p_pos] = p_val; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return OK; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	Size find(const T &p_val, Size p_from = 0) const; | 
					
						
							|  |  |  | 	Size rfind(const T &p_val, Size p_from = -1) const; | 
					
						
							|  |  |  | 	Size count(const T &p_val) const; | 
					
						
							| 
									
										
										
										
											2019-01-07 17:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 	_FORCE_INLINE_ CowData() {} | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 	_FORCE_INLINE_ ~CowData() { _unref(); } | 
					
						
							| 
									
										
										
										
											2024-08-21 13:32:25 -05:00
										 |  |  | 	_FORCE_INLINE_ CowData(std::initializer_list<T> p_init); | 
					
						
							| 
									
										
										
										
											2024-12-10 13:39:42 +01:00
										 |  |  | 	_FORCE_INLINE_ CowData(const CowData<T> &p_from) { _ref(p_from); } | 
					
						
							|  |  |  | 	_FORCE_INLINE_ CowData(CowData<T> &&p_from) { | 
					
						
							|  |  |  | 		_ptr = p_from._ptr; | 
					
						
							|  |  |  | 		p_from._ptr = nullptr; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2024-08-13 08:53:22 +03:00
										 |  |  | void CowData<T>::_unref() { | 
					
						
							|  |  |  | 	if (!_ptr) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	SafeNumeric<USize> *refc = _get_refcount(); | 
					
						
							| 
									
										
										
										
											2021-02-10 19:22:13 +01:00
										 |  |  | 	if (refc->decrement() > 0) { | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 		// Data is still in use elsewhere.
 | 
					
						
							|  |  |  | 		_ptr = nullptr; | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 	// Clean up.
 | 
					
						
							|  |  |  | 	// First, invalidate our own reference.
 | 
					
						
							|  |  |  | 	// NOTE: It is required to do so immediately because it must not be observable outside of this
 | 
					
						
							|  |  |  | 	//       function after refcount has already been reduced to 0.
 | 
					
						
							|  |  |  | 	// WARNING: It must be done before calling the destructors, because one of them may otherwise
 | 
					
						
							|  |  |  | 	//          observe it through a reference to us. In this case, it may try to access the buffer,
 | 
					
						
							|  |  |  | 	//          which is illegal after some of the elements in it have already been destructed, and
 | 
					
						
							|  |  |  | 	//          may lead to a segmentation fault.
 | 
					
						
							|  |  |  | 	USize current_size = *_get_size(); | 
					
						
							|  |  |  | 	T *prev_ptr = _ptr; | 
					
						
							|  |  |  | 	_ptr = nullptr; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 15:43:21 +01:00
										 |  |  | 	if constexpr (!std::is_trivially_destructible_v<T>) { | 
					
						
							| 
									
										
										
										
											2024-08-13 08:53:22 +03:00
										 |  |  | 		for (USize i = 0; i < current_size; ++i) { | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 			prev_ptr[i].~T(); | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// free mem
 | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 	Memory::free_static((uint8_t *)prev_ptr - DATA_OFFSET, false); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | typename CowData<T>::USize CowData<T>::_copy_on_write() { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!_ptr) { | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:30 +01:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	SafeNumeric<USize> *refc = _get_refcount(); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	USize rc = refc->get(); | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:30 +01:00
										 |  |  | 	if (unlikely(rc > 1)) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		/* in use by more than me */ | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 		USize current_size = *_get_size(); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 		uint8_t *mem_new = (uint8_t *)Memory::alloc_static(_get_alloc_size(current_size) + DATA_OFFSET, false); | 
					
						
							|  |  |  | 		ERR_FAIL_NULL_V(mem_new, 0); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 		SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); | 
					
						
							|  |  |  | 		USize *_size_ptr = _get_size_ptr(mem_new); | 
					
						
							|  |  |  | 		T *_data_ptr = _get_data_ptr(mem_new); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 		new (_refc_ptr) SafeNumeric<USize>(1); //refcount
 | 
					
						
							|  |  |  | 		*(_size_ptr) = current_size; //size
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// initialize new elements
 | 
					
						
							| 
									
										
										
										
											2024-02-02 15:43:21 +01:00
										 |  |  | 		if constexpr (std::is_trivially_copyable_v<T>) { | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 			memcpy((uint8_t *)_data_ptr, _ptr, current_size * sizeof(T)); | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 			for (USize i = 0; i < current_size; i++) { | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 				memnew_placement(&_data_ptr[i], T(_ptr[i])); | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-13 08:53:22 +03:00
										 |  |  | 		_unref(); | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 		_ptr = _data_ptr; | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rc = 1; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:30 +01:00
										 |  |  | 	return rc; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2022-07-04 16:43:49 +02:00
										 |  |  | template <bool p_ensure_zero> | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | Error CowData<T>::resize(Size p_size) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	Size current_size = size(); | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (p_size == current_size) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		return OK; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (p_size == 0) { | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 		// Wants to clean up.
 | 
					
						
							|  |  |  | 		_unref(); // Resets _ptr to nullptr.
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		return OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// possibly changing size, copy on write
 | 
					
						
							| 
									
										
										
										
											2024-12-16 16:44:32 +01:00
										 |  |  | 	_copy_on_write(); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	USize current_alloc_size = _get_alloc_size(current_size); | 
					
						
							|  |  |  | 	USize alloc_size; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 	if (p_size > current_size) { | 
					
						
							|  |  |  | 		if (alloc_size != current_alloc_size) { | 
					
						
							|  |  |  | 			if (current_size == 0) { | 
					
						
							|  |  |  | 				// alloc from scratch
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 				uint8_t *mem_new = (uint8_t *)Memory::alloc_static(alloc_size + DATA_OFFSET, false); | 
					
						
							|  |  |  | 				ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); | 
					
						
							|  |  |  | 				USize *_size_ptr = _get_size_ptr(mem_new); | 
					
						
							|  |  |  | 				T *_data_ptr = _get_data_ptr(mem_new); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-01 10:15:08 +02:00
										 |  |  | 				new (_refc_ptr) SafeNumeric<USize>(1); //refcount
 | 
					
						
							|  |  |  | 				*(_size_ptr) = 0; //size, currently none
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				_ptr = _data_ptr; | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2024-12-16 16:44:32 +01:00
										 |  |  | 				const Error error = _realloc(alloc_size); | 
					
						
							|  |  |  | 				if (error) { | 
					
						
							|  |  |  | 					return error; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// construct the newly created elements
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 15:43:21 +01:00
										 |  |  | 		if constexpr (!std::is_trivially_constructible_v<T>) { | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 			for (Size i = *_get_size(); i < p_size; i++) { | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 				memnew_placement(&_ptr[i], T); | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-07-04 16:43:49 +02:00
										 |  |  | 		} else if (p_ensure_zero) { | 
					
						
							|  |  |  | 			memset((void *)(_ptr + current_size), 0, (p_size - current_size) * sizeof(T)); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		*_get_size() = p_size; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 	} else if (p_size < current_size) { | 
					
						
							| 
									
										
										
										
											2024-02-02 15:43:21 +01:00
										 |  |  | 		if constexpr (!std::is_trivially_destructible_v<T>) { | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 			// deinitialize no longer needed elements
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 			for (USize i = p_size; i < *_get_size(); i++) { | 
					
						
							| 
									
										
										
										
											2022-04-09 21:25:31 +02:00
										 |  |  | 				T *t = &_ptr[i]; | 
					
						
							| 
									
										
										
										
											2019-01-03 05:56:41 +01:00
										 |  |  | 				t->~T(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 		if (alloc_size != current_alloc_size) { | 
					
						
							| 
									
										
										
										
											2024-12-16 16:44:32 +01:00
										 |  |  | 			const Error error = _realloc(alloc_size); | 
					
						
							|  |  |  | 			if (error) { | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-03-27 21:52:42 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		*_get_size() = p_size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 16:44:32 +01:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | Error CowData<T>::_realloc(Size p_alloc_size) { | 
					
						
							|  |  |  | 	uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, p_alloc_size + DATA_OFFSET, false); | 
					
						
							|  |  |  | 	ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); | 
					
						
							|  |  |  | 	T *_data_ptr = _get_data_ptr(mem_new); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If we realloc, we're guaranteed to be the only reference.
 | 
					
						
							|  |  |  | 	new (_refc_ptr) SafeNumeric<USize>(1); | 
					
						
							|  |  |  | 	_ptr = _data_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const { | 
					
						
							|  |  |  | 	Size ret = -1; | 
					
						
							| 
									
										
										
										
											2019-01-07 17:02:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (p_from < 0 || size() == 0) { | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	for (Size i = p_from; i < size(); i++) { | 
					
						
							| 
									
										
										
										
											2019-01-07 17:02:55 +00:00
										 |  |  | 		if (get(i) == p_val) { | 
					
						
							|  |  |  | 			ret = i; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const { | 
					
						
							|  |  |  | 	const Size s = size(); | 
					
						
							| 
									
										
										
										
											2022-05-07 20:16:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (p_from < 0) { | 
					
						
							|  |  |  | 		p_from = s + p_from; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (p_from < 0 || p_from >= s) { | 
					
						
							|  |  |  | 		p_from = s - 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | 	for (Size i = p_from; i >= 0; i--) { | 
					
						
							| 
									
										
										
										
											2022-05-07 20:16:11 +08:00
										 |  |  | 		if (get(i) == p_val) { | 
					
						
							|  |  |  | 			return i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2024-01-03 01:14:50 +01:00
										 |  |  | typename CowData<T>::Size CowData<T>::count(const T &p_val) const { | 
					
						
							|  |  |  | 	Size amount = 0; | 
					
						
							|  |  |  | 	for (Size i = 0; i < size(); i++) { | 
					
						
							| 
									
										
										
										
											2022-05-07 20:16:11 +08:00
										 |  |  | 		if (get(i) == p_val) { | 
					
						
							|  |  |  | 			amount++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return amount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2018-07-29 16:57:05 +02:00
										 |  |  | void CowData<T>::_ref(const CowData *p_from) { | 
					
						
							|  |  |  | 	_ref(*p_from); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 20:29:49 -06:00
										 |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | void CowData<T>::_ref(const CowData &p_from) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (_ptr == p_from._ptr) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		return; // self assign, do nothing.
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-21 12:37:50 +01:00
										 |  |  | 	_unref(); // Resets _ptr to nullptr.
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!p_from._ptr) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		return; //nothing to do
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:30 +01:00
										 |  |  | 	if (p_from._get_refcount()->conditional_increment() > 0) { // could reference
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		_ptr = p_from._ptr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-21 13:32:25 -05:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | CowData<T>::CowData(std::initializer_list<T> p_init) { | 
					
						
							|  |  |  | 	Error err = resize(p_init.size()); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Size i = 0; | 
					
						
							|  |  |  | 	for (const T &element : p_init) { | 
					
						
							|  |  |  | 		set(i++, element); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 02:32:19 +03:00
										 |  |  | #if defined(__GNUC__) && !defined(__clang__)
 | 
					
						
							|  |  |  | #pragma GCC diagnostic pop
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 11:10:34 +01:00
										 |  |  | #endif // COWDATA_H
 |