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 | #include "core/templates/hash_map.h" |
34 | #include "core/templates/safe_refcount.h" |
35 | #include "core/variant/variant.h" |
36 | // required in this order by VariantInternal, do not remove this comment. |
37 | #include "core/object/class_db.h" |
38 | #include "core/object/object.h" |
39 | #include "core/variant/type_info.h" |
40 | #include "core/variant/variant_internal.h" |
41 | |
42 | struct DictionaryPrivate { |
43 | SafeRefCount refcount; |
44 | Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values. |
45 | HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator> variant_map; |
46 | }; |
47 | |
48 | void Dictionary::get_key_list(List<Variant> *p_keys) const { |
49 | if (_p->variant_map.is_empty()) { |
50 | return; |
51 | } |
52 | |
53 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
54 | p_keys->push_back(E.key); |
55 | } |
56 | } |
57 | |
58 | Variant Dictionary::get_key_at_index(int p_index) const { |
59 | int index = 0; |
60 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
61 | if (index == p_index) { |
62 | return E.key; |
63 | } |
64 | index++; |
65 | } |
66 | |
67 | return Variant(); |
68 | } |
69 | |
70 | Variant Dictionary::get_value_at_index(int p_index) const { |
71 | int index = 0; |
72 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
73 | if (index == p_index) { |
74 | return E.value; |
75 | } |
76 | index++; |
77 | } |
78 | |
79 | return Variant(); |
80 | } |
81 | |
82 | Variant &Dictionary::operator[](const Variant &p_key) { |
83 | if (unlikely(_p->read_only)) { |
84 | if (p_key.get_type() == Variant::STRING_NAME) { |
85 | const StringName *sn = VariantInternal::get_string_name(&p_key); |
86 | const String &key = sn->operator String(); |
87 | if (likely(_p->variant_map.has(key))) { |
88 | *_p->read_only = _p->variant_map[key]; |
89 | } else { |
90 | *_p->read_only = Variant(); |
91 | } |
92 | } else if (likely(_p->variant_map.has(p_key))) { |
93 | *_p->read_only = _p->variant_map[p_key]; |
94 | } else { |
95 | *_p->read_only = Variant(); |
96 | } |
97 | |
98 | return *_p->read_only; |
99 | } else { |
100 | if (p_key.get_type() == Variant::STRING_NAME) { |
101 | const StringName *sn = VariantInternal::get_string_name(&p_key); |
102 | return _p->variant_map[sn->operator String()]; |
103 | } else { |
104 | return _p->variant_map[p_key]; |
105 | } |
106 | } |
107 | } |
108 | |
109 | const Variant &Dictionary::operator[](const Variant &p_key) const { |
110 | // Will not insert key, so no conversion is necessary. |
111 | return _p->variant_map[p_key]; |
112 | } |
113 | |
114 | const Variant *Dictionary::getptr(const Variant &p_key) const { |
115 | HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key)); |
116 | if (!E) { |
117 | return nullptr; |
118 | } |
119 | return &E->value; |
120 | } |
121 | |
122 | Variant *Dictionary::getptr(const Variant &p_key) { |
123 | HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(p_key)); |
124 | if (!E) { |
125 | return nullptr; |
126 | } |
127 | if (unlikely(_p->read_only != nullptr)) { |
128 | *_p->read_only = E->value; |
129 | return _p->read_only; |
130 | } else { |
131 | return &E->value; |
132 | } |
133 | } |
134 | |
135 | Variant Dictionary::get_valid(const Variant &p_key) const { |
136 | HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key)); |
137 | |
138 | if (!E) { |
139 | return Variant(); |
140 | } |
141 | return E->value; |
142 | } |
143 | |
144 | Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const { |
145 | const Variant *result = getptr(p_key); |
146 | if (!result) { |
147 | return p_default; |
148 | } |
149 | |
150 | return *result; |
151 | } |
152 | |
153 | int Dictionary::size() const { |
154 | return _p->variant_map.size(); |
155 | } |
156 | |
157 | bool Dictionary::is_empty() const { |
158 | return !_p->variant_map.size(); |
159 | } |
160 | |
161 | bool Dictionary::has(const Variant &p_key) const { |
162 | return _p->variant_map.has(p_key); |
163 | } |
164 | |
165 | bool Dictionary::has_all(const Array &p_keys) const { |
166 | for (int i = 0; i < p_keys.size(); i++) { |
167 | if (!has(p_keys[i])) { |
168 | return false; |
169 | } |
170 | } |
171 | return true; |
172 | } |
173 | |
174 | Variant Dictionary::find_key(const Variant &p_value) const { |
175 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
176 | if (E.value == p_value) { |
177 | return E.key; |
178 | } |
179 | } |
180 | return Variant(); |
181 | } |
182 | |
183 | bool Dictionary::erase(const Variant &p_key) { |
184 | ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state." ); |
185 | return _p->variant_map.erase(p_key); |
186 | } |
187 | |
188 | bool Dictionary::operator==(const Dictionary &p_dictionary) const { |
189 | return recursive_equal(p_dictionary, 0); |
190 | } |
191 | |
192 | bool Dictionary::operator!=(const Dictionary &p_dictionary) const { |
193 | return !recursive_equal(p_dictionary, 0); |
194 | } |
195 | |
196 | bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_count) const { |
197 | // Cheap checks |
198 | if (_p == p_dictionary._p) { |
199 | return true; |
200 | } |
201 | if (_p->variant_map.size() != p_dictionary._p->variant_map.size()) { |
202 | return false; |
203 | } |
204 | |
205 | // Heavy O(n) check |
206 | if (recursion_count > MAX_RECURSION) { |
207 | ERR_PRINT("Max recursion reached" ); |
208 | return true; |
209 | } |
210 | recursion_count++; |
211 | for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) { |
212 | HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key)); |
213 | if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) { |
214 | return false; |
215 | } |
216 | } |
217 | return true; |
218 | } |
219 | |
220 | void Dictionary::_ref(const Dictionary &p_from) const { |
221 | //make a copy first (thread safe) |
222 | if (!p_from._p->refcount.ref()) { |
223 | return; // couldn't copy |
224 | } |
225 | |
226 | //if this is the same, unreference the other one |
227 | if (p_from._p == _p) { |
228 | _p->refcount.unref(); |
229 | return; |
230 | } |
231 | if (_p) { |
232 | _unref(); |
233 | } |
234 | _p = p_from._p; |
235 | } |
236 | |
237 | void Dictionary::clear() { |
238 | ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state." ); |
239 | _p->variant_map.clear(); |
240 | } |
241 | |
242 | void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) { |
243 | for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) { |
244 | if (p_overwrite || !has(E.key)) { |
245 | this->operator[](E.key) = E.value; |
246 | } |
247 | } |
248 | } |
249 | |
250 | void Dictionary::_unref() const { |
251 | ERR_FAIL_NULL(_p); |
252 | if (_p->refcount.unref()) { |
253 | if (_p->read_only) { |
254 | memdelete(_p->read_only); |
255 | } |
256 | memdelete(_p); |
257 | } |
258 | _p = nullptr; |
259 | } |
260 | |
261 | uint32_t Dictionary::hash() const { |
262 | return recursive_hash(0); |
263 | } |
264 | |
265 | uint32_t Dictionary::recursive_hash(int recursion_count) const { |
266 | if (recursion_count > MAX_RECURSION) { |
267 | ERR_PRINT("Max recursion reached" ); |
268 | return 0; |
269 | } |
270 | |
271 | uint32_t h = hash_murmur3_one_32(Variant::DICTIONARY); |
272 | |
273 | recursion_count++; |
274 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
275 | h = hash_murmur3_one_32(E.key.recursive_hash(recursion_count), h); |
276 | h = hash_murmur3_one_32(E.value.recursive_hash(recursion_count), h); |
277 | } |
278 | |
279 | return hash_fmix32(h); |
280 | } |
281 | |
282 | Array Dictionary::keys() const { |
283 | Array varr; |
284 | if (_p->variant_map.is_empty()) { |
285 | return varr; |
286 | } |
287 | |
288 | varr.resize(size()); |
289 | |
290 | int i = 0; |
291 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
292 | varr[i] = E.key; |
293 | i++; |
294 | } |
295 | |
296 | return varr; |
297 | } |
298 | |
299 | Array Dictionary::values() const { |
300 | Array varr; |
301 | if (_p->variant_map.is_empty()) { |
302 | return varr; |
303 | } |
304 | |
305 | varr.resize(size()); |
306 | |
307 | int i = 0; |
308 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
309 | varr[i] = E.value; |
310 | i++; |
311 | } |
312 | |
313 | return varr; |
314 | } |
315 | |
316 | const Variant *Dictionary::next(const Variant *p_key) const { |
317 | if (p_key == nullptr) { |
318 | // caller wants to get the first element |
319 | if (_p->variant_map.begin()) { |
320 | return &_p->variant_map.begin()->key; |
321 | } |
322 | return nullptr; |
323 | } |
324 | HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E = _p->variant_map.find(*p_key); |
325 | |
326 | if (!E) { |
327 | return nullptr; |
328 | } |
329 | |
330 | ++E; |
331 | |
332 | if (E) { |
333 | return &E->key; |
334 | } |
335 | |
336 | return nullptr; |
337 | } |
338 | |
339 | Dictionary Dictionary::duplicate(bool p_deep) const { |
340 | return recursive_duplicate(p_deep, 0); |
341 | } |
342 | |
343 | void Dictionary::make_read_only() { |
344 | if (_p->read_only == nullptr) { |
345 | _p->read_only = memnew(Variant); |
346 | } |
347 | } |
348 | bool Dictionary::is_read_only() const { |
349 | return _p->read_only != nullptr; |
350 | } |
351 | |
352 | Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const { |
353 | Dictionary n; |
354 | |
355 | if (recursion_count > MAX_RECURSION) { |
356 | ERR_PRINT("Max recursion reached" ); |
357 | return n; |
358 | } |
359 | |
360 | if (p_deep) { |
361 | recursion_count++; |
362 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
363 | n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count); |
364 | } |
365 | } else { |
366 | for (const KeyValue<Variant, Variant> &E : _p->variant_map) { |
367 | n[E.key] = E.value; |
368 | } |
369 | } |
370 | |
371 | return n; |
372 | } |
373 | |
374 | void Dictionary::operator=(const Dictionary &p_dictionary) { |
375 | if (this == &p_dictionary) { |
376 | return; |
377 | } |
378 | _ref(p_dictionary); |
379 | } |
380 | |
381 | const void *Dictionary::id() const { |
382 | return _p; |
383 | } |
384 | |
385 | Dictionary::Dictionary(const Dictionary &p_from) { |
386 | _p = nullptr; |
387 | _ref(p_from); |
388 | } |
389 | |
390 | Dictionary::Dictionary() { |
391 | _p = memnew(DictionaryPrivate); |
392 | _p->refcount.init(); |
393 | } |
394 | |
395 | Dictionary::~Dictionary() { |
396 | _unref(); |
397 | } |
398 | |