Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/variant/dictionary.cpp
20852 views
1
/**************************************************************************/
2
/* dictionary.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "dictionary.h"
32
33
STATIC_ASSERT_INCOMPLETE_TYPE(class, Array);
34
STATIC_ASSERT_INCOMPLETE_TYPE(class, Object);
35
STATIC_ASSERT_INCOMPLETE_TYPE(class, String);
36
37
#include "core/templates/hash_map.h"
38
#include "core/templates/safe_refcount.h"
39
#include "core/variant/container_type_validate.h"
40
#include "core/variant/variant.h"
41
// required in this order by VariantInternal, do not remove this comment.
42
#include "core/object/class_db.h"
43
#include "core/object/object.h"
44
#include "core/variant/type_info.h"
45
#include "core/variant/variant_internal.h"
46
47
struct DictionaryPrivate {
48
SafeRefCount refcount;
49
Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
50
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator> variant_map;
51
ContainerTypeValidate typed_key;
52
ContainerTypeValidate typed_value;
53
Variant *typed_fallback = nullptr; // Allows a typed dictionary to return dummy values when attempting an invalid access.
54
};
55
56
Dictionary::ConstIterator Dictionary::begin() const {
57
return _p->variant_map.begin();
58
}
59
60
Dictionary::ConstIterator Dictionary::end() const {
61
return _p->variant_map.end();
62
}
63
64
LocalVector<Variant> Dictionary::get_key_list() const {
65
LocalVector<Variant> keys;
66
67
keys.reserve(_p->variant_map.size());
68
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
69
keys.push_back(E.key);
70
}
71
return keys;
72
}
73
74
Variant Dictionary::get_key_at_index(int p_index) const {
75
int index = 0;
76
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
77
if (index == p_index) {
78
return E.key;
79
}
80
index++;
81
}
82
83
return Variant();
84
}
85
86
Variant Dictionary::get_value_at_index(int p_index) const {
87
int index = 0;
88
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
89
if (index == p_index) {
90
return E.value;
91
}
92
index++;
93
}
94
95
return Variant();
96
}
97
98
// WARNING: This operator does not validate the value type. For scripting/extensions this is
99
// done in `variant_setget.cpp`. Consider using `set()` if the data might be invalid.
100
Variant &Dictionary::operator[](const Variant &p_key) {
101
Variant key = p_key;
102
if (unlikely(!_p->typed_key.validate(key, "use `operator[]`"))) {
103
if (unlikely(!_p->typed_fallback)) {
104
_p->typed_fallback = memnew(Variant);
105
}
106
VariantInternal::initialize(_p->typed_fallback, _p->typed_value.type);
107
return *_p->typed_fallback;
108
} else if (unlikely(_p->read_only)) {
109
if (likely(_p->variant_map.has(key))) {
110
*_p->read_only = _p->variant_map[key];
111
} else {
112
VariantInternal::initialize(_p->read_only, _p->typed_value.type);
113
}
114
return *_p->read_only;
115
} else {
116
const uint32_t old_size = _p->variant_map.size();
117
Variant &value = _p->variant_map[key];
118
if (_p->variant_map.size() > old_size) {
119
VariantInternal::initialize(&value, _p->typed_value.type);
120
}
121
return value;
122
}
123
}
124
125
const Variant &Dictionary::operator[](const Variant &p_key) const {
126
Variant key = p_key;
127
if (unlikely(!_p->typed_key.validate(key, "use `operator[]`"))) {
128
if (unlikely(!_p->typed_fallback)) {
129
_p->typed_fallback = memnew(Variant);
130
}
131
VariantInternal::initialize(_p->typed_fallback, _p->typed_value.type);
132
return *_p->typed_fallback;
133
} else {
134
static Variant empty;
135
const Variant *value = _p->variant_map.getptr(key);
136
ERR_FAIL_COND_V_MSG(!value, empty, vformat(R"(Bug: Dictionary::operator[] used when there was no value for the given key "%s". Please report.)", key));
137
return *value;
138
}
139
}
140
141
const Variant *Dictionary::getptr(const Variant &p_key) const {
142
Variant key = p_key;
143
if (unlikely(!_p->typed_key.validate(key, "getptr"))) {
144
return nullptr;
145
}
146
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(key));
147
if (!E) {
148
return nullptr;
149
}
150
return &E->value;
151
}
152
153
// WARNING: This method does not validate the value type.
154
Variant *Dictionary::getptr(const Variant &p_key) {
155
Variant key = p_key;
156
if (unlikely(!_p->typed_key.validate(key, "getptr"))) {
157
return nullptr;
158
}
159
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(key));
160
if (!E) {
161
return nullptr;
162
}
163
if (unlikely(_p->read_only != nullptr)) {
164
*_p->read_only = E->value;
165
return _p->read_only;
166
} else {
167
return &E->value;
168
}
169
}
170
171
Variant Dictionary::get_valid(const Variant &p_key) const {
172
Variant key = p_key;
173
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "get_valid"), Variant());
174
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(key));
175
176
if (!E) {
177
return Variant();
178
}
179
return E->value;
180
}
181
182
Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
183
Variant key = p_key;
184
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "get"), p_default);
185
const Variant *result = getptr(key);
186
if (!result) {
187
return p_default;
188
}
189
190
return *result;
191
}
192
193
Variant Dictionary::get_or_add(const Variant &p_key, const Variant &p_default) {
194
Variant key = p_key;
195
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "get"), p_default);
196
const Variant *result = getptr(key);
197
if (!result) {
198
Variant value = p_default;
199
ERR_FAIL_COND_V(!_p->typed_value.validate(value, "add"), value);
200
operator[](key) = value;
201
return value;
202
}
203
return *result;
204
}
205
206
bool Dictionary::set(const Variant &p_key, const Variant &p_value) {
207
ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
208
Variant key = p_key;
209
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "set"), false);
210
Variant value = p_value;
211
ERR_FAIL_COND_V(!_p->typed_value.validate(value, "set"), false);
212
_p->variant_map[key] = value;
213
return true;
214
}
215
216
int Dictionary::size() const {
217
return _p->variant_map.size();
218
}
219
220
bool Dictionary::is_empty() const {
221
return !_p->variant_map.size();
222
}
223
224
bool Dictionary::has(const Variant &p_key) const {
225
Variant key = p_key;
226
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "use 'has'"), false);
227
return _p->variant_map.has(key);
228
}
229
230
bool Dictionary::has_all(const Array &p_keys) const {
231
for (int i = 0; i < p_keys.size(); i++) {
232
Variant key = p_keys[i];
233
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "use 'has_all'"), false);
234
if (!_p->variant_map.has(key)) {
235
return false;
236
}
237
}
238
return true;
239
}
240
241
Variant Dictionary::find_key(const Variant &p_value) const {
242
Variant value = p_value;
243
ERR_FAIL_COND_V(!_p->typed_value.validate(value, "find_key"), Variant());
244
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
245
if (E.value == value) {
246
return E.key;
247
}
248
}
249
return Variant();
250
}
251
252
bool Dictionary::erase(const Variant &p_key) {
253
Variant key = p_key;
254
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "erase"), false);
255
ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
256
return _p->variant_map.erase(key);
257
}
258
259
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
260
return recursive_equal(p_dictionary, 0);
261
}
262
263
bool Dictionary::operator!=(const Dictionary &p_dictionary) const {
264
return !recursive_equal(p_dictionary, 0);
265
}
266
267
bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_count) const {
268
// Cheap checks
269
if (_p == p_dictionary._p) {
270
return true;
271
}
272
if (_p->variant_map.size() != p_dictionary._p->variant_map.size()) {
273
return false;
274
}
275
276
// Heavy O(n) check
277
if (recursion_count > MAX_RECURSION) {
278
ERR_PRINT("Max recursion reached");
279
return true;
280
}
281
recursion_count++;
282
for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
283
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key));
284
if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count, false)) {
285
return false;
286
}
287
}
288
return true;
289
}
290
291
void Dictionary::_ref(const Dictionary &p_from) const {
292
//make a copy first (thread safe)
293
if (!p_from._p->refcount.ref()) {
294
return; // couldn't copy
295
}
296
297
//if this is the same, unreference the other one
298
if (p_from._p == _p) {
299
_p->refcount.unref();
300
return;
301
}
302
if (_p) {
303
_unref();
304
}
305
_p = p_from._p;
306
}
307
308
void Dictionary::reserve(int p_new_capacity) {
309
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
310
ERR_FAIL_COND_MSG(p_new_capacity < 0, "New capacity must be non-negative.");
311
_p->variant_map.reserve(p_new_capacity);
312
}
313
314
void Dictionary::clear() {
315
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
316
_p->variant_map.clear();
317
}
318
319
struct _DictionaryVariantSort {
320
_FORCE_INLINE_ bool operator()(const KeyValue<Variant, Variant> &p_l, const KeyValue<Variant, Variant> &p_r) const {
321
bool valid = false;
322
Variant res;
323
Variant::evaluate(Variant::OP_LESS, p_l.key, p_r.key, res, valid);
324
if (!valid) {
325
res = false;
326
}
327
return res;
328
}
329
};
330
331
void Dictionary::sort() {
332
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
333
_p->variant_map.sort_custom<_DictionaryVariantSort>();
334
}
335
336
void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) {
337
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
338
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
339
Variant key = E.key;
340
Variant value = E.value;
341
ERR_FAIL_COND(!_p->typed_key.validate(key, "merge"));
342
ERR_FAIL_COND(!_p->typed_value.validate(value, "merge"));
343
if (p_overwrite || !has(key)) {
344
operator[](key) = value;
345
}
346
}
347
}
348
349
Dictionary Dictionary::merged(const Dictionary &p_dictionary, bool p_overwrite) const {
350
Dictionary ret = duplicate();
351
ret.merge(p_dictionary, p_overwrite);
352
return ret;
353
}
354
355
void Dictionary::_unref() const {
356
ERR_FAIL_NULL(_p);
357
if (_p->refcount.unref()) {
358
if (_p->read_only) {
359
memdelete(_p->read_only);
360
}
361
if (_p->typed_fallback) {
362
memdelete(_p->typed_fallback);
363
}
364
memdelete(_p);
365
}
366
_p = nullptr;
367
}
368
369
uint32_t Dictionary::hash() const {
370
return recursive_hash(0);
371
}
372
373
uint32_t Dictionary::recursive_hash(int recursion_count) const {
374
if (recursion_count > MAX_RECURSION) {
375
ERR_PRINT("Max recursion reached");
376
return 0;
377
}
378
379
uint32_t h = hash_murmur3_one_32(Variant::DICTIONARY);
380
381
recursion_count++;
382
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
383
h = hash_murmur3_one_32(E.key.recursive_hash(recursion_count), h);
384
h = hash_murmur3_one_32(E.value.recursive_hash(recursion_count), h);
385
}
386
387
return hash_fmix32(h);
388
}
389
390
Array Dictionary::keys() const {
391
Array varr;
392
if (is_typed_key()) {
393
varr.set_typed(get_typed_key_builtin(), get_typed_key_class_name(), get_typed_key_script());
394
}
395
if (_p->variant_map.is_empty()) {
396
return varr;
397
}
398
399
varr.resize(size());
400
401
int i = 0;
402
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
403
varr[i] = E.key;
404
i++;
405
}
406
407
return varr;
408
}
409
410
Array Dictionary::values() const {
411
Array varr;
412
if (is_typed_value()) {
413
varr.set_typed(get_typed_value_builtin(), get_typed_value_class_name(), get_typed_value_script());
414
}
415
if (_p->variant_map.is_empty()) {
416
return varr;
417
}
418
419
varr.resize(size());
420
421
int i = 0;
422
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
423
varr[i] = E.value;
424
i++;
425
}
426
427
return varr;
428
}
429
430
void Dictionary::assign(const Dictionary &p_dictionary) {
431
const ContainerTypeValidate &typed_key = _p->typed_key;
432
const ContainerTypeValidate &typed_key_source = p_dictionary._p->typed_key;
433
434
const ContainerTypeValidate &typed_value = _p->typed_value;
435
const ContainerTypeValidate &typed_value_source = p_dictionary._p->typed_value;
436
437
if ((typed_key == typed_key_source || typed_key.type == Variant::NIL || (typed_key_source.type == Variant::OBJECT && typed_key.can_reference(typed_key_source))) &&
438
(typed_value == typed_value_source || typed_value.type == Variant::NIL || (typed_value_source.type == Variant::OBJECT && typed_value.can_reference(typed_value_source)))) {
439
// From same to same or,
440
// from anything to variants or,
441
// from subclasses to base classes.
442
_p->variant_map = p_dictionary._p->variant_map;
443
return;
444
}
445
446
int size = p_dictionary._p->variant_map.size();
447
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator> variant_map = HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator>(size);
448
449
Vector<Variant> key_array;
450
key_array.resize(size);
451
Variant *key_data = key_array.ptrw();
452
453
Vector<Variant> value_array;
454
value_array.resize(size);
455
Variant *value_data = value_array.ptrw();
456
457
if (typed_key == typed_key_source || typed_key.type == Variant::NIL || (typed_key_source.type == Variant::OBJECT && typed_key.can_reference(typed_key_source))) {
458
// From same to same or,
459
// from anything to variants or,
460
// from subclasses to base classes.
461
int i = 0;
462
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
463
const Variant *key = &E.key;
464
key_data[i++] = *key;
465
}
466
} else if ((typed_key_source.type == Variant::NIL && typed_key.type == Variant::OBJECT) || (typed_key_source.type == Variant::OBJECT && typed_key_source.can_reference(typed_key))) {
467
// From variants to objects or,
468
// from base classes to subclasses.
469
int i = 0;
470
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
471
const Variant *key = &E.key;
472
if (key->get_type() != Variant::NIL && (key->get_type() != Variant::OBJECT || !typed_key.validate_object(*key, "assign"))) {
473
ERR_FAIL_MSG(vformat(R"(Unable to convert key from "%s" to "%s".)", Variant::get_type_name(key->get_type()), Variant::get_type_name(typed_key.type)));
474
}
475
key_data[i++] = *key;
476
}
477
} else if (typed_key.type == Variant::OBJECT || typed_key_source.type == Variant::OBJECT) {
478
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Dictionary[%s, %s]" to "Dictionary[%s, %s]".)", Variant::get_type_name(typed_key_source.type), Variant::get_type_name(typed_value_source.type),
479
Variant::get_type_name(typed_key.type), Variant::get_type_name(typed_value.type)));
480
} else if (typed_key_source.type == Variant::NIL && typed_key.type != Variant::OBJECT) {
481
// From variants to primitives.
482
int i = 0;
483
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
484
const Variant *key = &E.key;
485
if (key->get_type() == typed_key.type) {
486
key_data[i++] = *key;
487
continue;
488
}
489
if (!Variant::can_convert_strict(key->get_type(), typed_key.type)) {
490
ERR_FAIL_MSG(vformat(R"(Unable to convert key from "%s" to "%s".)", Variant::get_type_name(key->get_type()), Variant::get_type_name(typed_key.type)));
491
}
492
Callable::CallError ce;
493
Variant::construct(typed_key.type, key_data[i++], &key, 1, ce);
494
ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert key from "%s" to "%s".)", Variant::get_type_name(key->get_type()), Variant::get_type_name(typed_key.type)));
495
}
496
} else if (Variant::can_convert_strict(typed_key_source.type, typed_key.type)) {
497
// From primitives to different convertible primitives.
498
int i = 0;
499
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
500
const Variant *key = &E.key;
501
Callable::CallError ce;
502
Variant::construct(typed_key.type, key_data[i++], &key, 1, ce);
503
ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert key from "%s" to "%s".)", Variant::get_type_name(key->get_type()), Variant::get_type_name(typed_key.type)));
504
}
505
} else {
506
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Dictionary[%s, %s]" to "Dictionary[%s, %s].)", Variant::get_type_name(typed_key_source.type), Variant::get_type_name(typed_value_source.type),
507
Variant::get_type_name(typed_key.type), Variant::get_type_name(typed_value.type)));
508
}
509
510
if (typed_value == typed_value_source || typed_value.type == Variant::NIL || (typed_value_source.type == Variant::OBJECT && typed_value.can_reference(typed_value_source))) {
511
// From same to same or,
512
// from anything to variants or,
513
// from subclasses to base classes.
514
int i = 0;
515
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
516
const Variant *value = &E.value;
517
value_data[i++] = *value;
518
}
519
} else if (((typed_value_source.type == Variant::NIL && typed_value.type == Variant::OBJECT) || (typed_value_source.type == Variant::OBJECT && typed_value_source.can_reference(typed_value)))) {
520
// From variants to objects or,
521
// from base classes to subclasses.
522
int i = 0;
523
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
524
const Variant *value = &E.value;
525
if (value->get_type() != Variant::NIL && (value->get_type() != Variant::OBJECT || !typed_value.validate_object(*value, "assign"))) {
526
ERR_FAIL_MSG(vformat(R"(Unable to convert value at key "%s" from "%s" to "%s".)", key_data[i], Variant::get_type_name(value->get_type()), Variant::get_type_name(typed_value.type)));
527
}
528
value_data[i++] = *value;
529
}
530
} else if (typed_value.type == Variant::OBJECT || typed_value_source.type == Variant::OBJECT) {
531
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Dictionary[%s, %s]" to "Dictionary[%s, %s]".)", Variant::get_type_name(typed_key_source.type), Variant::get_type_name(typed_value_source.type),
532
Variant::get_type_name(typed_key.type), Variant::get_type_name(typed_value.type)));
533
} else if (typed_value_source.type == Variant::NIL && typed_value.type != Variant::OBJECT) {
534
// From variants to primitives.
535
int i = 0;
536
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
537
const Variant *value = &E.value;
538
if (value->get_type() == typed_value.type) {
539
value_data[i++] = *value;
540
continue;
541
}
542
if (!Variant::can_convert_strict(value->get_type(), typed_value.type)) {
543
ERR_FAIL_MSG(vformat(R"(Unable to convert value at key "%s" from "%s" to "%s".)", key_data[i], Variant::get_type_name(value->get_type()), Variant::get_type_name(typed_value.type)));
544
}
545
Callable::CallError ce;
546
Variant::construct(typed_value.type, value_data[i++], &value, 1, ce);
547
ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert value at key "%s" from "%s" to "%s".)", key_data[i - 1], Variant::get_type_name(value->get_type()), Variant::get_type_name(typed_value.type)));
548
}
549
} else if (Variant::can_convert_strict(typed_value_source.type, typed_value.type)) {
550
// From primitives to different convertible primitives.
551
int i = 0;
552
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
553
const Variant *value = &E.value;
554
Callable::CallError ce;
555
Variant::construct(typed_value.type, value_data[i++], &value, 1, ce);
556
ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert value at key "%s" from "%s" to "%s".)", key_data[i - 1], Variant::get_type_name(value->get_type()), Variant::get_type_name(typed_value.type)));
557
}
558
} else {
559
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Dictionary[%s, %s]" to "Dictionary[%s, %s].)", Variant::get_type_name(typed_key_source.type), Variant::get_type_name(typed_value_source.type),
560
Variant::get_type_name(typed_key.type), Variant::get_type_name(typed_value.type)));
561
}
562
563
for (int i = 0; i < size; i++) {
564
variant_map.insert(key_data[i], value_data[i]);
565
}
566
567
_p->variant_map = variant_map;
568
}
569
570
const Variant *Dictionary::next(const Variant *p_key) const {
571
if (p_key == nullptr) {
572
// caller wants to get the first element
573
if (_p->variant_map.begin()) {
574
return &_p->variant_map.begin()->key;
575
}
576
return nullptr;
577
}
578
Variant key = *p_key;
579
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "next"), nullptr);
580
HashMap<Variant, Variant, HashMapHasherDefault, StringLikeVariantComparator>::Iterator E = _p->variant_map.find(key);
581
582
if (!E) {
583
return nullptr;
584
}
585
586
++E;
587
588
if (E) {
589
return &E->key;
590
}
591
592
return nullptr;
593
}
594
595
Dictionary Dictionary::duplicate(bool p_deep) const {
596
return recursive_duplicate(p_deep, RESOURCE_DEEP_DUPLICATE_NONE, 0);
597
}
598
599
Dictionary Dictionary::duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode) const {
600
return recursive_duplicate(true, p_deep_subresources_mode, 0);
601
}
602
603
void Dictionary::make_read_only() {
604
if (_p->read_only == nullptr) {
605
_p->read_only = memnew(Variant);
606
}
607
}
608
bool Dictionary::is_read_only() const {
609
return _p->read_only != nullptr;
610
}
611
612
Dictionary Dictionary::recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const {
613
Dictionary n;
614
n._p->typed_key = _p->typed_key;
615
n._p->typed_value = _p->typed_value;
616
617
if (recursion_count > MAX_RECURSION) {
618
ERR_PRINT("Max recursion reached");
619
return n;
620
}
621
622
n.reserve(_p->variant_map.size());
623
if (p_deep) {
624
bool is_call_chain_end = recursion_count == 0;
625
626
recursion_count++;
627
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
628
n[E.key.recursive_duplicate(true, p_deep_subresources_mode, recursion_count)] = E.value.recursive_duplicate(true, p_deep_subresources_mode, recursion_count);
629
}
630
631
// Variant::recursive_duplicate() may have created a remap cache by now.
632
if (is_call_chain_end) {
633
Resource::_teardown_duplicate_from_variant();
634
}
635
} else {
636
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
637
n[E.key] = E.value;
638
}
639
}
640
641
return n;
642
}
643
644
void Dictionary::set_typed(const ContainerType &p_key_type, const ContainerType &p_value_type) {
645
set_typed(p_key_type.builtin_type, p_key_type.class_name, p_key_type.script, p_value_type.builtin_type, p_value_type.class_name, p_key_type.script);
646
}
647
648
void Dictionary::set_typed(uint32_t p_key_type, const StringName &p_key_class_name, const Variant &p_key_script, uint32_t p_value_type, const StringName &p_value_class_name, const Variant &p_value_script) {
649
ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
650
ERR_FAIL_COND_MSG(_p->variant_map.size() > 0, "Type can only be set when dictionary is empty.");
651
ERR_FAIL_COND_MSG(_p->refcount.get() > 1, "Type can only be set when dictionary has no more than one user.");
652
ERR_FAIL_COND_MSG(_p->typed_key.type != Variant::NIL || _p->typed_value.type != Variant::NIL, "Type can only be set once.");
653
ERR_FAIL_COND_MSG((p_key_class_name != StringName() && p_key_type != Variant::OBJECT) || (p_value_class_name != StringName() && p_value_type != Variant::OBJECT), "Class names can only be set for type OBJECT.");
654
Ref<Script> key_script = p_key_script;
655
ERR_FAIL_COND_MSG(key_script.is_valid() && p_key_class_name == StringName(), "Script class can only be set together with base class name.");
656
Ref<Script> value_script = p_value_script;
657
ERR_FAIL_COND_MSG(value_script.is_valid() && p_value_class_name == StringName(), "Script class can only be set together with base class name.");
658
659
_p->typed_key.type = Variant::Type(p_key_type);
660
_p->typed_key.class_name = p_key_class_name;
661
_p->typed_key.script = key_script;
662
_p->typed_key.where = "TypedDictionary.Key";
663
664
_p->typed_value.type = Variant::Type(p_value_type);
665
_p->typed_value.class_name = p_value_class_name;
666
_p->typed_value.script = value_script;
667
_p->typed_value.where = "TypedDictionary.Value";
668
}
669
670
bool Dictionary::is_typed() const {
671
return is_typed_key() || is_typed_value();
672
}
673
674
bool Dictionary::is_typed_key() const {
675
return _p->typed_key.type != Variant::NIL;
676
}
677
678
bool Dictionary::is_typed_value() const {
679
return _p->typed_value.type != Variant::NIL;
680
}
681
682
bool Dictionary::is_same_instance(const Dictionary &p_other) const {
683
return _p == p_other._p;
684
}
685
686
bool Dictionary::is_same_typed(const Dictionary &p_other) const {
687
return is_same_typed_key(p_other) && is_same_typed_value(p_other);
688
}
689
690
bool Dictionary::is_same_typed_key(const Dictionary &p_other) const {
691
return _p->typed_key == p_other._p->typed_key;
692
}
693
694
bool Dictionary::is_same_typed_value(const Dictionary &p_other) const {
695
return _p->typed_value == p_other._p->typed_value;
696
}
697
698
ContainerType Dictionary::get_key_type() const {
699
ContainerType type;
700
type.builtin_type = _p->typed_key.type;
701
type.class_name = _p->typed_key.class_name;
702
type.script = _p->typed_key.script;
703
return type;
704
}
705
706
ContainerType Dictionary::get_value_type() const {
707
ContainerType type;
708
type.builtin_type = _p->typed_value.type;
709
type.class_name = _p->typed_value.class_name;
710
type.script = _p->typed_value.script;
711
return type;
712
}
713
714
uint32_t Dictionary::get_typed_key_builtin() const {
715
return _p->typed_key.type;
716
}
717
718
uint32_t Dictionary::get_typed_value_builtin() const {
719
return _p->typed_value.type;
720
}
721
722
StringName Dictionary::get_typed_key_class_name() const {
723
return _p->typed_key.class_name;
724
}
725
726
StringName Dictionary::get_typed_value_class_name() const {
727
return _p->typed_value.class_name;
728
}
729
730
Variant Dictionary::get_typed_key_script() const {
731
return _p->typed_key.script;
732
}
733
734
Variant Dictionary::get_typed_value_script() const {
735
return _p->typed_value.script;
736
}
737
738
const ContainerTypeValidate &Dictionary::get_key_validator() const {
739
return _p->typed_key;
740
}
741
742
const ContainerTypeValidate &Dictionary::get_value_validator() const {
743
return _p->typed_value;
744
}
745
746
void Dictionary::operator=(const Dictionary &p_dictionary) {
747
if (this == &p_dictionary) {
748
return;
749
}
750
_ref(p_dictionary);
751
}
752
753
const void *Dictionary::id() const {
754
return _p;
755
}
756
757
Dictionary::Dictionary(const Dictionary &p_base, uint32_t p_key_type, const StringName &p_key_class_name, const Variant &p_key_script, uint32_t p_value_type, const StringName &p_value_class_name, const Variant &p_value_script) {
758
_p = memnew(DictionaryPrivate);
759
_p->refcount.init();
760
set_typed(p_key_type, p_key_class_name, p_key_script, p_value_type, p_value_class_name, p_value_script);
761
assign(p_base);
762
}
763
764
Dictionary::Dictionary(const Dictionary &p_from) {
765
_p = nullptr;
766
_ref(p_from);
767
}
768
769
Dictionary::Dictionary() {
770
_p = memnew(DictionaryPrivate);
771
_p->refcount.init();
772
}
773
774
Dictionary::Dictionary(std::initializer_list<KeyValue<Variant, Variant>> p_init) {
775
_p = memnew(DictionaryPrivate);
776
_p->refcount.init();
777
778
for (const KeyValue<Variant, Variant> &E : p_init) {
779
operator[](E.key) = E.value;
780
}
781
}
782
783
Dictionary::~Dictionary() {
784
_unref();
785
}
786
787