1 /*************************************************************************/
2 /* packed_data_container.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
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 #include "packed_data_container.h"
31 #include "core_string_names.h"
32 #include "io/marshalls.h"
33
getvar(const Variant & p_key,bool * r_valid) const34 Variant PackedDataContainer::getvar(const Variant &p_key, bool *r_valid) const {
35
36 bool err = false;
37 Variant ret = _key_at_ofs(0, p_key, err);
38 if (r_valid)
39 *r_valid = !err;
40 return ret;
41 }
42
size() const43 int PackedDataContainer::size() const {
44
45 return _size(0);
46 };
47
_iter_init_ofs(const Array & p_iter,uint32_t p_offset)48 Variant PackedDataContainer::_iter_init_ofs(const Array &p_iter, uint32_t p_offset) {
49
50 Array ref = p_iter;
51 uint32_t size = _size(p_offset);
52 if (size == 0 || ref.size() != 1)
53 return false;
54 else {
55 ref[0] = 0;
56 return true;
57 }
58 }
59
_iter_next_ofs(const Array & p_iter,uint32_t p_offset)60 Variant PackedDataContainer::_iter_next_ofs(const Array &p_iter, uint32_t p_offset) {
61
62 Array ref = p_iter;
63 uint32_t size = _size(p_offset);
64 if (ref.size() != 1)
65 return false;
66 int pos = ref[0];
67 if (pos < 0 || pos >= size)
68 return false;
69 pos += 1;
70 ref[0] = pos;
71 return pos != size;
72 }
73
_iter_get_ofs(const Variant & p_iter,uint32_t p_offset)74 Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_offset) {
75
76 uint32_t size = _size(p_offset);
77 int pos = p_iter;
78 if (pos < 0 || pos >= size)
79 return Variant();
80
81 DVector<uint8_t>::Read rd = data.read();
82 const uint8_t *r = &rd[p_offset];
83 uint32_t type = decode_uint32(r);
84
85 bool err = false;
86 if (type == TYPE_ARRAY) {
87
88 uint32_t vpos = decode_uint32(rd.ptr() + p_offset + 8 + pos * 4);
89 return _get_at_ofs(vpos, rd.ptr(), err);
90
91 } else if (type == TYPE_DICT) {
92
93 uint32_t vpos = decode_uint32(rd.ptr() + p_offset + 8 + pos * 12 + 4);
94 return _get_at_ofs(vpos, rd.ptr(), err);
95 } else {
96 ERR_FAIL_V(Variant());
97 }
98 }
99
_get_at_ofs(uint32_t p_ofs,const uint8_t * p_buf,bool & err) const100 Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, bool &err) const {
101
102 uint32_t type = decode_uint32(p_buf + p_ofs);
103
104 if (type == TYPE_ARRAY || type == TYPE_DICT) {
105
106 Ref<PackedDataContainerRef> pdcr = memnew(PackedDataContainerRef);
107 Ref<PackedDataContainer> pdc = Ref<PackedDataContainer>((PackedDataContainer *)this);
108
109 pdcr->from = pdc;
110 pdcr->offset = p_ofs;
111 return pdcr;
112 } else {
113
114 Variant v;
115 Error rerr = decode_variant(v, p_buf + p_ofs, datalen - p_ofs, NULL);
116
117 if (rerr != OK) {
118
119 err = true;
120 ERR_FAIL_COND_V(err != OK, Variant());
121 }
122 return v;
123 }
124 }
125
_type_at_ofs(uint32_t p_ofs) const126 uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const {
127
128 DVector<uint8_t>::Read rd = data.read();
129 const uint8_t *r = &rd[p_ofs];
130 uint32_t type = decode_uint32(r);
131
132 return type;
133 };
134
_size(uint32_t p_ofs) const135 int PackedDataContainer::_size(uint32_t p_ofs) const {
136
137 DVector<uint8_t>::Read rd = data.read();
138 const uint8_t *r = &rd[p_ofs];
139 uint32_t type = decode_uint32(r);
140
141 if (type == TYPE_ARRAY) {
142
143 uint32_t len = decode_uint32(r + 4);
144 return len;
145
146 } else if (type == TYPE_DICT) {
147
148 uint32_t len = decode_uint32(r + 4);
149 return len;
150 };
151
152 return -1;
153 };
154
_key_at_ofs(uint32_t p_ofs,const Variant & p_key,bool & err) const155 Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, bool &err) const {
156
157 DVector<uint8_t>::Read rd = data.read();
158 const uint8_t *r = &rd[p_ofs];
159 uint32_t type = decode_uint32(r);
160
161 if (type == TYPE_ARRAY) {
162
163 if (p_key.is_num()) {
164
165 int idx = p_key;
166 uint32_t len = decode_uint32(r + 4);
167 if (idx < 0 || idx >= len) {
168 err = true;
169 return Variant();
170 }
171 uint32_t ofs = decode_uint32(r + 8 + 4 * idx);
172 return _get_at_ofs(ofs, rd.ptr(), err);
173
174 } else {
175 err = true;
176 return Variant();
177 }
178
179 } else if (type == TYPE_DICT) {
180
181 uint32_t hash = p_key.hash();
182 uint32_t len = decode_uint32(r + 4);
183
184 bool found = false;
185 for (int i = 0; i < len; i++) {
186 uint32_t khash = decode_uint32(r + 8 + i * 12 + 0);
187 if (khash == hash) {
188 Variant key = _get_at_ofs(decode_uint32(r + 8 + i * 12 + 4), rd.ptr(), err);
189 if (err)
190 return Variant();
191 if (key == p_key) {
192 //key matches, return value
193 return _get_at_ofs(decode_uint32(r + 8 + i * 12 + 8), rd.ptr(), err);
194 }
195 found = true;
196 } else {
197 if (found)
198 break;
199 }
200 }
201
202 err = true;
203 return Variant();
204
205 } else {
206
207 err = true;
208 return Variant();
209 }
210 }
211
_pack(const Variant & p_data,Vector<uint8_t> & tmpdata,Map<String,uint32_t> & string_cache)212 uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpdata, Map<String, uint32_t> &string_cache) {
213
214 switch (p_data.get_type()) {
215
216 case Variant::STRING: {
217
218 String s = p_data;
219 if (string_cache.has(s)) {
220 return string_cache[s];
221 }
222
223 string_cache[s] = tmpdata.size();
224
225 }; //fallthrough
226 case Variant::NIL:
227 case Variant::BOOL:
228 case Variant::INT:
229 case Variant::REAL:
230 case Variant::VECTOR2:
231 case Variant::RECT2:
232 case Variant::VECTOR3:
233 case Variant::MATRIX32:
234 case Variant::PLANE:
235 case Variant::QUAT:
236 case Variant::_AABB:
237 case Variant::MATRIX3:
238 case Variant::TRANSFORM:
239 case Variant::IMAGE:
240 case Variant::INPUT_EVENT:
241 case Variant::RAW_ARRAY:
242 case Variant::INT_ARRAY:
243 case Variant::REAL_ARRAY:
244 case Variant::STRING_ARRAY:
245 case Variant::VECTOR2_ARRAY:
246 case Variant::VECTOR3_ARRAY:
247 case Variant::COLOR_ARRAY:
248 case Variant::NODE_PATH: {
249
250 uint32_t pos = tmpdata.size();
251 int len;
252 encode_variant(p_data, NULL, len);
253 tmpdata.resize(tmpdata.size() + len);
254 encode_variant(p_data, &tmpdata[pos], len);
255 return pos;
256
257 } break;
258 // misc types
259 case Variant::_RID:
260 case Variant::OBJECT: {
261
262 return _pack(Variant(), tmpdata, string_cache);
263 } break;
264 case Variant::DICTIONARY: {
265
266 Dictionary d = p_data;
267 //size is known, use sort
268 uint32_t pos = tmpdata.size();
269 int len = d.size();
270 tmpdata.resize(tmpdata.size() + len * 12 + 8);
271 encode_uint32(TYPE_DICT, &tmpdata[pos + 0]);
272 encode_uint32(len, &tmpdata[pos + 4]);
273
274 List<Variant> keys;
275 d.get_key_list(&keys);
276 List<DictKey> sortk;
277
278 for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
279
280 DictKey dk;
281 dk.hash = E->get().hash();
282 dk.key = E->get();
283 sortk.push_back(dk);
284 }
285
286 sortk.sort();
287
288 int idx = 0;
289 for (List<DictKey>::Element *E = sortk.front(); E; E = E->next()) {
290
291 encode_uint32(E->get().hash, &tmpdata[pos + 8 + idx * 12 + 0]);
292 uint32_t ofs = _pack(E->get().key, tmpdata, string_cache);
293 encode_uint32(ofs, &tmpdata[pos + 8 + idx * 12 + 4]);
294 ofs = _pack(d[E->get().key], tmpdata, string_cache);
295 encode_uint32(ofs, &tmpdata[pos + 8 + idx * 12 + 8]);
296 idx++;
297 }
298
299 return pos;
300
301 } break;
302 case Variant::ARRAY: {
303
304 Array a = p_data;
305 //size is known, use sort
306 uint32_t pos = tmpdata.size();
307 int len = a.size();
308 tmpdata.resize(tmpdata.size() + len * 4 + 8);
309 encode_uint32(TYPE_ARRAY, &tmpdata[pos + 0]);
310 encode_uint32(len, &tmpdata[pos + 4]);
311
312 for (int i = 0; i < len; i++) {
313
314 uint32_t ofs = _pack(a[i], tmpdata, string_cache);
315 encode_uint32(ofs, &tmpdata[pos + 8 + i * 4]);
316 }
317
318 return pos;
319
320 } break;
321
322 default: {}
323 }
324
325 return OK;
326 }
327
pack(const Variant & p_data)328 Error PackedDataContainer::pack(const Variant &p_data) {
329
330 Vector<uint8_t> tmpdata;
331 Map<String, uint32_t> string_cache;
332 _pack(p_data, tmpdata, string_cache);
333 datalen = tmpdata.size();
334 data.resize(tmpdata.size());
335 DVector<uint8_t>::Write w = data.write();
336 copymem(w.ptr(), tmpdata.ptr(), tmpdata.size());
337
338 return OK;
339 }
340
_set_data(const DVector<uint8_t> & p_data)341 void PackedDataContainer::_set_data(const DVector<uint8_t> &p_data) {
342
343 data = p_data;
344 datalen = data.size();
345 }
346
_get_data() const347 DVector<uint8_t> PackedDataContainer::_get_data() const {
348 return data;
349 }
350
_iter_init(const Array & p_iter)351 Variant PackedDataContainer::_iter_init(const Array &p_iter) {
352
353 return _iter_init_ofs(p_iter, 0);
354 }
355
_iter_next(const Array & p_iter)356 Variant PackedDataContainer::_iter_next(const Array &p_iter) {
357
358 return _iter_next_ofs(p_iter, 0);
359 }
_iter_get(const Variant & p_iter)360 Variant PackedDataContainer::_iter_get(const Variant &p_iter) {
361
362 return _iter_get_ofs(p_iter, 0);
363 }
364
_bind_methods()365 void PackedDataContainer::_bind_methods() {
366
367 ObjectTypeDB::bind_method(_MD("_set_data"), &PackedDataContainer::_set_data);
368 ObjectTypeDB::bind_method(_MD("_get_data"), &PackedDataContainer::_get_data);
369 ObjectTypeDB::bind_method(_MD("_iter_init"), &PackedDataContainer::_iter_init);
370 ObjectTypeDB::bind_method(_MD("_iter_get"), &PackedDataContainer::_iter_get);
371 ObjectTypeDB::bind_method(_MD("_iter_next"), &PackedDataContainer::_iter_next);
372 ObjectTypeDB::bind_method(_MD("pack:Error", "value"), &PackedDataContainer::pack);
373 ObjectTypeDB::bind_method(_MD("size"), &PackedDataContainer::size);
374
375 ADD_PROPERTY(PropertyInfo(Variant::RAW_ARRAY, "__data__"), _SCS("_set_data"), _SCS("_get_data"));
376 }
377
PackedDataContainer()378 PackedDataContainer::PackedDataContainer() {
379
380 datalen = 0;
381 }
382
383 //////////////////
384
_iter_init(const Array & p_iter)385 Variant PackedDataContainerRef::_iter_init(const Array &p_iter) {
386
387 return from->_iter_init_ofs(p_iter, offset);
388 }
389
_iter_next(const Array & p_iter)390 Variant PackedDataContainerRef::_iter_next(const Array &p_iter) {
391
392 return from->_iter_next_ofs(p_iter, offset);
393 }
_iter_get(const Variant & p_iter)394 Variant PackedDataContainerRef::_iter_get(const Variant &p_iter) {
395
396 return from->_iter_get_ofs(p_iter, offset);
397 }
398
_is_dictionary() const399 bool PackedDataContainerRef::_is_dictionary() const {
400
401 return from->_type_at_ofs(offset) == PackedDataContainer::TYPE_DICT;
402 };
403
_bind_methods()404 void PackedDataContainerRef::_bind_methods() {
405
406 ObjectTypeDB::bind_method(_MD("size"), &PackedDataContainerRef::size);
407 ObjectTypeDB::bind_method(_MD("_iter_init"), &PackedDataContainerRef::_iter_init);
408 ObjectTypeDB::bind_method(_MD("_iter_get"), &PackedDataContainerRef::_iter_get);
409 ObjectTypeDB::bind_method(_MD("_iter_next"), &PackedDataContainerRef::_iter_next);
410 ObjectTypeDB::bind_method(_MD("_is_dictionary"), &PackedDataContainerRef::_is_dictionary);
411 }
412
getvar(const Variant & p_key,bool * r_valid) const413 Variant PackedDataContainerRef::getvar(const Variant &p_key, bool *r_valid) const {
414
415 bool err = false;
416 Variant ret = from->_key_at_ofs(offset, p_key, err);
417 if (r_valid)
418 *r_valid = !err;
419 return ret;
420 }
421
size() const422 int PackedDataContainerRef::size() const {
423
424 return from->_size(offset);
425 };
426
PackedDataContainerRef()427 PackedDataContainerRef::PackedDataContainerRef() {
428 }
429