@@ -56,6 +56,42 @@ class CowData {
56
56
private:
57
57
mutable T *_ptr;
58
58
59
+ class ElementBackup {
60
+ const T &original;
61
+ bool empty;
62
+ uint8_t backup[sizeof (T)];
63
+
64
+ public:
65
+ _FORCE_INLINE_ void make_backup () {
66
+ if (__has_trivial_copy (T)) {
67
+ memcpy (&backup, &original, sizeof (T));
68
+ } else {
69
+ memnew_placement (&backup, T (original));
70
+ }
71
+ empty = false ;
72
+ }
73
+
74
+ _FORCE_INLINE_ const T *get_original_ptr () {
75
+ return reinterpret_cast <const T *>(&original);
76
+ }
77
+
78
+ _FORCE_INLINE_ const T &get_value () {
79
+ CRASH_COND (empty);
80
+ return *reinterpret_cast <T *>(backup);
81
+ }
82
+
83
+ _FORCE_INLINE_ const bool is_empty () { return empty; }
84
+
85
+ _FORCE_INLINE_ ElementBackup (const T &p_original) :
86
+ original(p_original),
87
+ empty(true ) {}
88
+ _FORCE_INLINE_ ~ElementBackup () {
89
+ if (!empty && !__has_trivial_destructor (T)) {
90
+ reinterpret_cast <T *>(backup)->~T ();
91
+ }
92
+ }
93
+ };
94
+
59
95
// internal helpers
60
96
61
97
_FORCE_INLINE_ uint32_t *_get_refcount () const {
@@ -154,7 +190,7 @@ class CowData {
154
190
return _get_data ()[p_index];
155
191
}
156
192
157
- Error resize (int p_size);
193
+ Error resize (int p_size, ElementBackup *r_elem_backup = NULL );
158
194
159
195
_FORCE_INLINE_ void remove (int p_index) {
160
196
@@ -172,10 +208,17 @@ class CowData {
172
208
Error insert (int p_pos, const T &p_val) {
173
209
174
210
ERR_FAIL_INDEX_V (p_pos, size () + 1 , ERR_INVALID_PARAMETER);
175
- resize (size () + 1 );
211
+
212
+ ElementBackup eb (p_val);
213
+ resize (size () + 1 , &eb);
214
+
176
215
for (int i = (size () - 1 ); i > p_pos; i--)
177
216
set (i, get (i - 1 ));
178
- set (p_pos, p_val);
217
+ if (unlikely (!eb.is_empty ())) {
218
+ set (p_pos, eb.get_value ());
219
+ } else {
220
+ set (p_pos, p_val);
221
+ }
179
222
180
223
return OK;
181
224
};
@@ -248,7 +291,7 @@ void CowData<T>::_copy_on_write() {
248
291
}
249
292
250
293
template <class T >
251
- Error CowData<T>::resize(int p_size) {
294
+ Error CowData<T>::resize(int p_size, ElementBackup *r_elem_backup ) {
252
295
253
296
ERR_FAIL_COND_V (p_size < 0 , ERR_INVALID_PARAMETER);
254
297
@@ -280,6 +323,13 @@ Error CowData<T>::resize(int p_size) {
280
323
_ptr = (T *)ptr;
281
324
282
325
} else {
326
+ if (unlikely (r_elem_backup)) {
327
+ const T *original = r_elem_backup->get_original_ptr ();
328
+ if (unlikely (original >= _ptr && original < _ptr + size ())) {
329
+ r_elem_backup->make_backup ();
330
+ }
331
+ }
332
+
283
333
void *_ptrnew = (T *)Memory::realloc_static (_ptr, alloc_size, true );
284
334
ERR_FAIL_COND_V (!_ptrnew, ERR_OUT_OF_MEMORY);
285
335
_ptr = (T *)(_ptrnew);
0 commit comments