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