1 /*************************************************************************/
2 /*  variant_parser.cpp                                                   */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 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 
31 #include "variant_parser.h"
32 
33 #include "core/io/resource_loader.h"
34 #include "core/os/input_event.h"
35 #include "core/os/keyboard.h"
36 #include "core/string_buffer.h"
37 
get_char()38 CharType VariantParser::StreamFile::get_char() {
39 
40 	return f->get_8();
41 }
42 
is_utf8() const43 bool VariantParser::StreamFile::is_utf8() const {
44 
45 	return true;
46 }
is_eof() const47 bool VariantParser::StreamFile::is_eof() const {
48 
49 	return f->eof_reached();
50 }
51 
get_char()52 CharType VariantParser::StreamString::get_char() {
53 
54 	if (pos > s.length()) {
55 		return 0;
56 	} else if (pos == s.length()) {
57 		// You need to try to read again when you have reached the end for EOF to be reported,
58 		// so this works the same as files (like StreamFile does)
59 		pos++;
60 		return 0;
61 	} else {
62 		return s[pos++];
63 	}
64 }
65 
is_utf8() const66 bool VariantParser::StreamString::is_utf8() const {
67 	return false;
68 }
is_eof() const69 bool VariantParser::StreamString::is_eof() const {
70 	return pos > s.length();
71 }
72 
73 /////////////////////////////////////////////////////////////////////////////////////////////////
74 
75 const char *VariantParser::tk_name[TK_MAX] = {
76 	"'{'",
77 	"'}'",
78 	"'['",
79 	"']'",
80 	"'('",
81 	"')'",
82 	"identifier",
83 	"string",
84 	"number",
85 	"color",
86 	"':'",
87 	"','",
88 	"'.'",
89 	"'='",
90 	"EOF",
91 	"ERROR"
92 };
93 
get_token(Stream * p_stream,Token & r_token,int & line,String & r_err_str)94 Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, String &r_err_str) {
95 
96 	while (true) {
97 
98 		CharType cchar;
99 		if (p_stream->saved) {
100 			cchar = p_stream->saved;
101 			p_stream->saved = 0;
102 		} else {
103 			cchar = p_stream->get_char();
104 			if (p_stream->is_eof()) {
105 				r_token.type = TK_EOF;
106 				return OK;
107 			}
108 		}
109 
110 		switch (cchar) {
111 
112 			case '\n': {
113 
114 				line++;
115 				break;
116 			};
117 			case 0: {
118 				r_token.type = TK_EOF;
119 				return OK;
120 			} break;
121 			case '{': {
122 
123 				r_token.type = TK_CURLY_BRACKET_OPEN;
124 				return OK;
125 			};
126 			case '}': {
127 
128 				r_token.type = TK_CURLY_BRACKET_CLOSE;
129 				return OK;
130 			};
131 			case '[': {
132 
133 				r_token.type = TK_BRACKET_OPEN;
134 				return OK;
135 			};
136 			case ']': {
137 
138 				r_token.type = TK_BRACKET_CLOSE;
139 				return OK;
140 			};
141 			case '(': {
142 
143 				r_token.type = TK_PARENTHESIS_OPEN;
144 				return OK;
145 			};
146 			case ')': {
147 
148 				r_token.type = TK_PARENTHESIS_CLOSE;
149 				return OK;
150 			};
151 			case ':': {
152 
153 				r_token.type = TK_COLON;
154 				return OK;
155 			};
156 			case ';': {
157 
158 				while (true) {
159 					CharType ch = p_stream->get_char();
160 					if (p_stream->is_eof()) {
161 						r_token.type = TK_EOF;
162 						return OK;
163 					}
164 					if (ch == '\n')
165 						break;
166 				}
167 
168 				break;
169 			};
170 			case ',': {
171 
172 				r_token.type = TK_COMMA;
173 				return OK;
174 			};
175 			case '.': {
176 
177 				r_token.type = TK_PERIOD;
178 				return OK;
179 			};
180 			case '=': {
181 
182 				r_token.type = TK_EQUAL;
183 				return OK;
184 			};
185 			case '#': {
186 
187 				StringBuffer<> color_str;
188 				color_str += '#';
189 				while (true) {
190 					CharType ch = p_stream->get_char();
191 					if (p_stream->is_eof()) {
192 						r_token.type = TK_EOF;
193 						return OK;
194 					} else if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
195 						color_str += ch;
196 
197 					} else {
198 						p_stream->saved = ch;
199 						break;
200 					}
201 				}
202 
203 				r_token.value = Color::html(color_str.as_string());
204 				r_token.type = TK_COLOR;
205 				return OK;
206 			};
207 			case '"': {
208 
209 				String str;
210 				while (true) {
211 
212 					CharType ch = p_stream->get_char();
213 
214 					if (ch == 0) {
215 						r_err_str = "Unterminated String";
216 						r_token.type = TK_ERROR;
217 						return ERR_PARSE_ERROR;
218 					} else if (ch == '"') {
219 						break;
220 					} else if (ch == '\\') {
221 						//escaped characters...
222 						CharType next = p_stream->get_char();
223 						if (next == 0) {
224 							r_err_str = "Unterminated String";
225 							r_token.type = TK_ERROR;
226 							return ERR_PARSE_ERROR;
227 						}
228 						CharType res = 0;
229 
230 						switch (next) {
231 
232 							case 'b': res = 8; break;
233 							case 't': res = 9; break;
234 							case 'n': res = 10; break;
235 							case 'f': res = 12; break;
236 							case 'r': res = 13; break;
237 							case 'u': {
238 								//hexnumbarh - oct is deprecated
239 
240 								for (int j = 0; j < 4; j++) {
241 									CharType c = p_stream->get_char();
242 									if (c == 0) {
243 										r_err_str = "Unterminated String";
244 										r_token.type = TK_ERROR;
245 										return ERR_PARSE_ERROR;
246 									}
247 									if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
248 
249 										r_err_str = "Malformed hex constant in string";
250 										r_token.type = TK_ERROR;
251 										return ERR_PARSE_ERROR;
252 									}
253 									CharType v;
254 									if (c >= '0' && c <= '9') {
255 										v = c - '0';
256 									} else if (c >= 'a' && c <= 'f') {
257 										v = c - 'a';
258 										v += 10;
259 									} else if (c >= 'A' && c <= 'F') {
260 										v = c - 'A';
261 										v += 10;
262 									} else {
263 										ERR_PRINT("BUG");
264 										v = 0;
265 									}
266 
267 									res <<= 4;
268 									res |= v;
269 								}
270 
271 							} break;
272 							//case '\"': res='\"'; break;
273 							//case '\\': res='\\'; break;
274 							//case '/': res='/'; break;
275 							default: {
276 								res = next;
277 								//r_err_str="Invalid escape sequence";
278 								//return ERR_PARSE_ERROR;
279 							} break;
280 						}
281 
282 						str += res;
283 
284 					} else {
285 						if (ch == '\n')
286 							line++;
287 						str += ch;
288 					}
289 				}
290 
291 				if (p_stream->is_utf8()) {
292 					str.parse_utf8(str.ascii(true).get_data());
293 				}
294 				r_token.type = TK_STRING;
295 				r_token.value = str;
296 				return OK;
297 
298 			} break;
299 			default: {
300 
301 				if (cchar <= 32) {
302 					break;
303 				}
304 
305 				if (cchar == '-' || (cchar >= '0' && cchar <= '9')) {
306 					//a number
307 
308 					StringBuffer<> num;
309 #define READING_SIGN 0
310 #define READING_INT 1
311 #define READING_DEC 2
312 #define READING_EXP 3
313 #define READING_DONE 4
314 					int reading = READING_INT;
315 
316 					if (cchar == '-') {
317 						num += '-';
318 						cchar = p_stream->get_char();
319 					}
320 
321 					CharType c = cchar;
322 					bool exp_sign = false;
323 					bool exp_beg = false;
324 					bool is_float = false;
325 
326 					while (true) {
327 
328 						switch (reading) {
329 							case READING_INT: {
330 
331 								if (c >= '0' && c <= '9') {
332 									//pass
333 								} else if (c == '.') {
334 									reading = READING_DEC;
335 									is_float = true;
336 								} else if (c == 'e') {
337 									reading = READING_EXP;
338 									is_float = true;
339 								} else {
340 									reading = READING_DONE;
341 								}
342 
343 							} break;
344 							case READING_DEC: {
345 
346 								if (c >= '0' && c <= '9') {
347 
348 								} else if (c == 'e') {
349 									reading = READING_EXP;
350 								} else {
351 									reading = READING_DONE;
352 								}
353 
354 							} break;
355 							case READING_EXP: {
356 
357 								if (c >= '0' && c <= '9') {
358 									exp_beg = true;
359 
360 								} else if ((c == '-' || c == '+') && !exp_sign && !exp_beg) {
361 									exp_sign = true;
362 
363 								} else {
364 									reading = READING_DONE;
365 								}
366 							} break;
367 						}
368 
369 						if (reading == READING_DONE)
370 							break;
371 						num += c;
372 						c = p_stream->get_char();
373 					}
374 
375 					p_stream->saved = c;
376 
377 					r_token.type = TK_NUMBER;
378 
379 					if (is_float)
380 						r_token.value = num.as_double();
381 					else
382 						r_token.value = num.as_int();
383 					return OK;
384 
385 				} else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') {
386 
387 					StringBuffer<> id;
388 					bool first = true;
389 
390 					while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) {
391 
392 						id += cchar;
393 						cchar = p_stream->get_char();
394 						first = false;
395 					}
396 
397 					p_stream->saved = cchar;
398 
399 					r_token.type = TK_IDENTIFIER;
400 					r_token.value = id.as_string();
401 					return OK;
402 				} else {
403 					r_err_str = "Unexpected character.";
404 					r_token.type = TK_ERROR;
405 					return ERR_PARSE_ERROR;
406 				}
407 			}
408 		}
409 	}
410 
411 	r_token.type = TK_ERROR;
412 	return ERR_PARSE_ERROR;
413 }
414 
_parse_enginecfg(Stream * p_stream,Vector<String> & strings,int & line,String & r_err_str)415 Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings, int &line, String &r_err_str) {
416 
417 	Token token;
418 	get_token(p_stream, token, line, r_err_str);
419 	if (token.type != TK_PARENTHESIS_OPEN) {
420 		r_err_str = "Expected '(' in old-style project.godot construct";
421 		return ERR_PARSE_ERROR;
422 	}
423 
424 	String accum;
425 
426 	while (true) {
427 
428 		CharType c = p_stream->get_char();
429 
430 		if (p_stream->is_eof()) {
431 			r_err_str = "Unexpected EOF while parsing old-style project.godot construct";
432 			return ERR_PARSE_ERROR;
433 		}
434 
435 		if (c == ',') {
436 			strings.push_back(accum.strip_edges());
437 			accum = String();
438 		} else if (c == ')') {
439 			strings.push_back(accum.strip_edges());
440 			return OK;
441 		} else if (c == '\n') {
442 			line++;
443 		}
444 	}
445 }
446 
447 template <class T>
_parse_construct(Stream * p_stream,Vector<T> & r_construct,int & line,String & r_err_str)448 Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct, int &line, String &r_err_str) {
449 
450 	Token token;
451 	get_token(p_stream, token, line, r_err_str);
452 	if (token.type != TK_PARENTHESIS_OPEN) {
453 		r_err_str = "Expected '(' in constructor";
454 		return ERR_PARSE_ERROR;
455 	}
456 
457 	bool first = true;
458 	while (true) {
459 
460 		if (!first) {
461 			get_token(p_stream, token, line, r_err_str);
462 			if (token.type == TK_COMMA) {
463 				//do none
464 			} else if (token.type == TK_PARENTHESIS_CLOSE) {
465 				break;
466 			} else {
467 				r_err_str = "Expected ',' or ')' in constructor";
468 				return ERR_PARSE_ERROR;
469 			}
470 		}
471 		get_token(p_stream, token, line, r_err_str);
472 
473 		if (first && token.type == TK_PARENTHESIS_CLOSE) {
474 			break;
475 		} else if (token.type != TK_NUMBER) {
476 			r_err_str = "Expected float in constructor";
477 			return ERR_PARSE_ERROR;
478 		}
479 
480 		r_construct.push_back(token.value);
481 		first = false;
482 	}
483 
484 	return OK;
485 }
486 
parse_value(Token & token,Variant & value,Stream * p_stream,int & line,String & r_err_str,ResourceParser * p_res_parser)487 Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
488 	if (token.type == TK_CURLY_BRACKET_OPEN) {
489 
490 		Dictionary d;
491 		Error err = _parse_dictionary(d, p_stream, line, r_err_str, p_res_parser);
492 		if (err)
493 			return err;
494 		value = d;
495 		return OK;
496 	} else if (token.type == TK_BRACKET_OPEN) {
497 
498 		Array a;
499 		Error err = _parse_array(a, p_stream, line, r_err_str, p_res_parser);
500 		if (err)
501 			return err;
502 		value = a;
503 		return OK;
504 	} else if (token.type == TK_IDENTIFIER) {
505 
506 		String id = token.value;
507 		if (id == "true")
508 			value = true;
509 		else if (id == "false")
510 			value = false;
511 		else if (id == "null" || id == "nil")
512 			value = Variant();
513 		else if (id == "inf")
514 			value = Math_INF;
515 		else if (id == "nan")
516 			value = Math_NAN;
517 		else if (id == "Vector2") {
518 
519 			Vector<float> args;
520 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
521 			if (err)
522 				return err;
523 
524 			if (args.size() != 2) {
525 				r_err_str = "Expected 2 arguments for constructor";
526 				return ERR_PARSE_ERROR;
527 			}
528 
529 			value = Vector2(args[0], args[1]);
530 		} else if (id == "Rect2") {
531 
532 			Vector<float> args;
533 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
534 			if (err)
535 				return err;
536 
537 			if (args.size() != 4) {
538 				r_err_str = "Expected 4 arguments for constructor";
539 				return ERR_PARSE_ERROR;
540 			}
541 
542 			value = Rect2(args[0], args[1], args[2], args[3]);
543 		} else if (id == "Vector3") {
544 
545 			Vector<float> args;
546 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
547 			if (err)
548 				return err;
549 
550 			if (args.size() != 3) {
551 				r_err_str = "Expected 3 arguments for constructor";
552 				return ERR_PARSE_ERROR;
553 			}
554 
555 			value = Vector3(args[0], args[1], args[2]);
556 		} else if (id == "Transform2D" || id == "Matrix32") { //compatibility
557 			Vector<float> args;
558 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
559 			if (err)
560 				return err;
561 
562 			if (args.size() != 6) {
563 				r_err_str = "Expected 6 arguments for constructor";
564 				return ERR_PARSE_ERROR;
565 			}
566 
567 			Transform2D m;
568 			m[0] = Vector2(args[0], args[1]);
569 			m[1] = Vector2(args[2], args[3]);
570 			m[2] = Vector2(args[4], args[5]);
571 			value = m;
572 		} else if (id == "Plane") {
573 
574 			Vector<float> args;
575 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
576 			if (err)
577 				return err;
578 
579 			if (args.size() != 4) {
580 				r_err_str = "Expected 4 arguments for constructor";
581 				return ERR_PARSE_ERROR;
582 			}
583 
584 			value = Plane(args[0], args[1], args[2], args[3]);
585 		} else if (id == "Quat") {
586 
587 			Vector<float> args;
588 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
589 			if (err)
590 				return err;
591 
592 			if (args.size() != 4) {
593 				r_err_str = "Expected 4 arguments for constructor";
594 				return ERR_PARSE_ERROR;
595 			}
596 
597 			value = Quat(args[0], args[1], args[2], args[3]);
598 		} else if (id == "AABB" || id == "Rect3") {
599 
600 			Vector<float> args;
601 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
602 			if (err)
603 				return err;
604 
605 			if (args.size() != 6) {
606 				r_err_str = "Expected 6 arguments for constructor";
607 				return ERR_PARSE_ERROR;
608 			}
609 
610 			value = AABB(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5]));
611 		} else if (id == "Basis" || id == "Matrix3") { //compatibility
612 			Vector<float> args;
613 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
614 			if (err)
615 				return err;
616 
617 			if (args.size() != 9) {
618 				r_err_str = "Expected 9 arguments for constructor";
619 				return ERR_PARSE_ERROR;
620 			}
621 
622 			value = Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
623 		} else if (id == "Transform") {
624 
625 			Vector<float> args;
626 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
627 			if (err)
628 				return err;
629 
630 			if (args.size() != 12) {
631 				r_err_str = "Expected 12 arguments for constructor";
632 				return ERR_PARSE_ERROR;
633 			}
634 
635 			value = Transform(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11]));
636 		} else if (id == "Color") {
637 
638 			Vector<float> args;
639 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
640 			if (err)
641 				return err;
642 
643 			if (args.size() != 4) {
644 				r_err_str = "Expected 4 arguments for constructor";
645 				return ERR_PARSE_ERROR;
646 			}
647 
648 			value = Color(args[0], args[1], args[2], args[3]);
649 		} else if (id == "NodePath") {
650 
651 			get_token(p_stream, token, line, r_err_str);
652 			if (token.type != TK_PARENTHESIS_OPEN) {
653 				r_err_str = "Expected '('";
654 				return ERR_PARSE_ERROR;
655 			}
656 
657 			get_token(p_stream, token, line, r_err_str);
658 			if (token.type != TK_STRING) {
659 				r_err_str = "Expected string as argument for NodePath()";
660 				return ERR_PARSE_ERROR;
661 			}
662 
663 			value = NodePath(String(token.value));
664 
665 			get_token(p_stream, token, line, r_err_str);
666 			if (token.type != TK_PARENTHESIS_CLOSE) {
667 				r_err_str = "Expected ')'";
668 				return ERR_PARSE_ERROR;
669 			}
670 		} else if (id == "RID") {
671 
672 			get_token(p_stream, token, line, r_err_str);
673 			if (token.type != TK_PARENTHESIS_OPEN) {
674 				r_err_str = "Expected '('";
675 				return ERR_PARSE_ERROR;
676 			}
677 
678 			get_token(p_stream, token, line, r_err_str);
679 			if (token.type != TK_NUMBER) {
680 				r_err_str = "Expected number as argument";
681 				return ERR_PARSE_ERROR;
682 			}
683 
684 			value = token.value;
685 
686 			get_token(p_stream, token, line, r_err_str);
687 			if (token.type != TK_PARENTHESIS_CLOSE) {
688 				r_err_str = "Expected ')'";
689 				return ERR_PARSE_ERROR;
690 			}
691 		} else if (id == "Object") {
692 
693 			get_token(p_stream, token, line, r_err_str);
694 			if (token.type != TK_PARENTHESIS_OPEN) {
695 				r_err_str = "Expected '('";
696 				return ERR_PARSE_ERROR;
697 			}
698 
699 			get_token(p_stream, token, line, r_err_str);
700 
701 			if (token.type != TK_IDENTIFIER) {
702 				r_err_str = "Expected identifier with type of object";
703 				return ERR_PARSE_ERROR;
704 			}
705 
706 			String type = token.value;
707 
708 			Object *obj = ClassDB::instance(type);
709 
710 			if (!obj) {
711 				r_err_str = "Can't instance Object() of type: " + type;
712 				return ERR_PARSE_ERROR;
713 			}
714 
715 			get_token(p_stream, token, line, r_err_str);
716 			if (token.type != TK_COMMA) {
717 				r_err_str = "Expected ',' after object type";
718 				return ERR_PARSE_ERROR;
719 			}
720 
721 			bool at_key = true;
722 			String key;
723 			Token token2;
724 			bool need_comma = false;
725 
726 			while (true) {
727 
728 				if (p_stream->is_eof()) {
729 					r_err_str = "Unexpected End of File while parsing Object()";
730 					return ERR_FILE_CORRUPT;
731 				}
732 
733 				if (at_key) {
734 
735 					Error err = get_token(p_stream, token2, line, r_err_str);
736 					if (err != OK)
737 						return err;
738 
739 					if (token2.type == TK_PARENTHESIS_CLOSE) {
740 						Reference *reference = Object::cast_to<Reference>(obj);
741 						if (reference) {
742 							value = REF(reference);
743 						} else {
744 							value = obj;
745 						}
746 						return OK;
747 					}
748 
749 					if (need_comma) {
750 
751 						if (token2.type != TK_COMMA) {
752 
753 							r_err_str = "Expected '}' or ','";
754 							return ERR_PARSE_ERROR;
755 						} else {
756 							need_comma = false;
757 							continue;
758 						}
759 					}
760 
761 					if (token2.type != TK_STRING) {
762 						r_err_str = "Expected property name as string";
763 						return ERR_PARSE_ERROR;
764 					}
765 
766 					key = token2.value;
767 
768 					err = get_token(p_stream, token2, line, r_err_str);
769 
770 					if (err != OK)
771 						return err;
772 					if (token2.type != TK_COLON) {
773 
774 						r_err_str = "Expected ':'";
775 						return ERR_PARSE_ERROR;
776 					}
777 					at_key = false;
778 				} else {
779 
780 					Error err = get_token(p_stream, token2, line, r_err_str);
781 					if (err != OK)
782 						return err;
783 
784 					Variant v;
785 					err = parse_value(token2, v, p_stream, line, r_err_str, p_res_parser);
786 					if (err)
787 						return err;
788 					obj->set(key, v);
789 					need_comma = true;
790 					at_key = true;
791 				}
792 			}
793 		} else if (id == "Resource" || id == "SubResource" || id == "ExtResource") {
794 
795 			get_token(p_stream, token, line, r_err_str);
796 			if (token.type != TK_PARENTHESIS_OPEN) {
797 				r_err_str = "Expected '('";
798 				return ERR_PARSE_ERROR;
799 			}
800 
801 			if (p_res_parser && id == "Resource" && p_res_parser->func) {
802 
803 				RES res;
804 				Error err = p_res_parser->func(p_res_parser->userdata, p_stream, res, line, r_err_str);
805 				if (err)
806 					return err;
807 
808 				value = res;
809 			} else if (p_res_parser && id == "ExtResource" && p_res_parser->ext_func) {
810 
811 				RES res;
812 				Error err = p_res_parser->ext_func(p_res_parser->userdata, p_stream, res, line, r_err_str);
813 				if (err)
814 					return err;
815 
816 				value = res;
817 			} else if (p_res_parser && id == "SubResource" && p_res_parser->sub_func) {
818 
819 				RES res;
820 				Error err = p_res_parser->sub_func(p_res_parser->userdata, p_stream, res, line, r_err_str);
821 				if (err)
822 					return err;
823 
824 				value = res;
825 			} else {
826 
827 				get_token(p_stream, token, line, r_err_str);
828 				if (token.type == TK_STRING) {
829 					String path = token.value;
830 					RES res = ResourceLoader::load(path);
831 					if (res.is_null()) {
832 						r_err_str = "Can't load resource at path: '" + path + "'.";
833 						return ERR_PARSE_ERROR;
834 					}
835 
836 					get_token(p_stream, token, line, r_err_str);
837 					if (token.type != TK_PARENTHESIS_CLOSE) {
838 						r_err_str = "Expected ')'";
839 						return ERR_PARSE_ERROR;
840 					}
841 
842 					value = res;
843 				} else {
844 					r_err_str = "Expected string as argument for Resource().";
845 					return ERR_PARSE_ERROR;
846 				}
847 			}
848 #ifndef DISABLE_DEPRECATED
849 		} else if (id == "InputEvent") {
850 
851 			get_token(p_stream, token, line, r_err_str);
852 			if (token.type != TK_PARENTHESIS_OPEN) {
853 				r_err_str = "Expected '('";
854 				return ERR_PARSE_ERROR;
855 			}
856 
857 			get_token(p_stream, token, line, r_err_str);
858 
859 			if (token.type != TK_IDENTIFIER) {
860 				r_err_str = "Expected identifier";
861 				return ERR_PARSE_ERROR;
862 			}
863 
864 			String id2 = token.value;
865 
866 			Ref<InputEvent> ie;
867 
868 			if (id2 == "NONE") {
869 
870 				get_token(p_stream, token, line, r_err_str);
871 
872 				if (token.type != TK_PARENTHESIS_CLOSE) {
873 					r_err_str = "Expected ')'";
874 					return ERR_PARSE_ERROR;
875 				}
876 
877 			} else if (id2 == "KEY") {
878 
879 				Ref<InputEventKey> key;
880 				key.instance();
881 				ie = key;
882 
883 				get_token(p_stream, token, line, r_err_str);
884 				if (token.type != TK_COMMA) {
885 					r_err_str = "Expected ','";
886 					return ERR_PARSE_ERROR;
887 				}
888 
889 				get_token(p_stream, token, line, r_err_str);
890 				if (token.type == TK_IDENTIFIER) {
891 					String name = token.value;
892 					key->set_scancode(find_keycode(name));
893 				} else if (token.type == TK_NUMBER) {
894 
895 					key->set_scancode(token.value);
896 				} else {
897 
898 					r_err_str = "Expected string or integer for keycode";
899 					return ERR_PARSE_ERROR;
900 				}
901 
902 				get_token(p_stream, token, line, r_err_str);
903 
904 				if (token.type == TK_COMMA) {
905 
906 					get_token(p_stream, token, line, r_err_str);
907 
908 					if (token.type != TK_IDENTIFIER) {
909 						r_err_str = "Expected identifier with modifier flas";
910 						return ERR_PARSE_ERROR;
911 					}
912 
913 					String mods = token.value;
914 
915 					if (mods.findn("C") != -1)
916 						key->set_control(true);
917 					if (mods.findn("A") != -1)
918 						key->set_alt(true);
919 					if (mods.findn("S") != -1)
920 						key->set_shift(true);
921 					if (mods.findn("M") != -1)
922 						key->set_metakey(true);
923 
924 					get_token(p_stream, token, line, r_err_str);
925 					if (token.type != TK_PARENTHESIS_CLOSE) {
926 						r_err_str = "Expected ')'";
927 						return ERR_PARSE_ERROR;
928 					}
929 
930 				} else if (token.type != TK_PARENTHESIS_CLOSE) {
931 
932 					r_err_str = "Expected ')' or modifier flags.";
933 					return ERR_PARSE_ERROR;
934 				}
935 
936 			} else if (id2 == "MBUTTON") {
937 
938 				Ref<InputEventMouseButton> mb;
939 				mb.instance();
940 				ie = mb;
941 
942 				get_token(p_stream, token, line, r_err_str);
943 				if (token.type != TK_COMMA) {
944 					r_err_str = "Expected ','";
945 					return ERR_PARSE_ERROR;
946 				}
947 
948 				get_token(p_stream, token, line, r_err_str);
949 				if (token.type != TK_NUMBER) {
950 					r_err_str = "Expected button index";
951 					return ERR_PARSE_ERROR;
952 				}
953 
954 				mb->set_button_index(token.value);
955 
956 				get_token(p_stream, token, line, r_err_str);
957 				if (token.type != TK_PARENTHESIS_CLOSE) {
958 					r_err_str = "Expected ')'";
959 					return ERR_PARSE_ERROR;
960 				}
961 
962 			} else if (id2 == "JBUTTON") {
963 
964 				Ref<InputEventJoypadButton> jb;
965 				jb.instance();
966 				ie = jb;
967 
968 				get_token(p_stream, token, line, r_err_str);
969 				if (token.type != TK_COMMA) {
970 					r_err_str = "Expected ','";
971 					return ERR_PARSE_ERROR;
972 				}
973 
974 				get_token(p_stream, token, line, r_err_str);
975 				if (token.type != TK_NUMBER) {
976 					r_err_str = "Expected button index";
977 					return ERR_PARSE_ERROR;
978 				}
979 
980 				jb->set_button_index(token.value);
981 
982 				get_token(p_stream, token, line, r_err_str);
983 				if (token.type != TK_PARENTHESIS_CLOSE) {
984 					r_err_str = "Expected ')'";
985 					return ERR_PARSE_ERROR;
986 				}
987 
988 			} else if (id2 == "JAXIS") {
989 
990 				Ref<InputEventJoypadMotion> jm;
991 				jm.instance();
992 				ie = jm;
993 
994 				get_token(p_stream, token, line, r_err_str);
995 				if (token.type != TK_COMMA) {
996 					r_err_str = "Expected ','";
997 					return ERR_PARSE_ERROR;
998 				}
999 
1000 				get_token(p_stream, token, line, r_err_str);
1001 				if (token.type != TK_NUMBER) {
1002 					r_err_str = "Expected axis index";
1003 					return ERR_PARSE_ERROR;
1004 				}
1005 
1006 				jm->set_axis(token.value);
1007 
1008 				get_token(p_stream, token, line, r_err_str);
1009 
1010 				if (token.type != TK_COMMA) {
1011 					r_err_str = "Expected ',' after axis index";
1012 					return ERR_PARSE_ERROR;
1013 				}
1014 
1015 				get_token(p_stream, token, line, r_err_str);
1016 				if (token.type != TK_NUMBER) {
1017 					r_err_str = "Expected axis sign";
1018 					return ERR_PARSE_ERROR;
1019 				}
1020 
1021 				jm->set_axis_value(token.value);
1022 
1023 				get_token(p_stream, token, line, r_err_str);
1024 
1025 				if (token.type != TK_PARENTHESIS_CLOSE) {
1026 					r_err_str = "Expected ')' for jaxis";
1027 					return ERR_PARSE_ERROR;
1028 				}
1029 
1030 			} else {
1031 
1032 				r_err_str = "Invalid input event type.";
1033 				return ERR_PARSE_ERROR;
1034 			}
1035 
1036 			value = ie;
1037 #endif
1038 		} else if (id == "PoolByteArray" || id == "ByteArray") {
1039 
1040 			Vector<uint8_t> args;
1041 			Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str);
1042 			if (err)
1043 				return err;
1044 
1045 			PoolVector<uint8_t> arr;
1046 			{
1047 				int len = args.size();
1048 				arr.resize(len);
1049 				PoolVector<uint8_t>::Write w = arr.write();
1050 				for (int i = 0; i < len; i++) {
1051 					w[i] = args[i];
1052 				}
1053 			}
1054 
1055 			value = arr;
1056 
1057 		} else if (id == "PoolIntArray" || id == "IntArray") {
1058 
1059 			Vector<int> args;
1060 			Error err = _parse_construct<int>(p_stream, args, line, r_err_str);
1061 			if (err)
1062 				return err;
1063 
1064 			PoolVector<int> arr;
1065 			{
1066 				int len = args.size();
1067 				arr.resize(len);
1068 				PoolVector<int>::Write w = arr.write();
1069 				for (int i = 0; i < len; i++) {
1070 					w[i] = int(args[i]);
1071 				}
1072 			}
1073 
1074 			value = arr;
1075 
1076 		} else if (id == "PoolRealArray" || id == "FloatArray") {
1077 
1078 			Vector<float> args;
1079 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
1080 			if (err)
1081 				return err;
1082 
1083 			PoolVector<float> arr;
1084 			{
1085 				int len = args.size();
1086 				arr.resize(len);
1087 				PoolVector<float>::Write w = arr.write();
1088 				for (int i = 0; i < len; i++) {
1089 					w[i] = args[i];
1090 				}
1091 			}
1092 
1093 			value = arr;
1094 
1095 		} else if (id == "PoolStringArray" || id == "StringArray") {
1096 
1097 			get_token(p_stream, token, line, r_err_str);
1098 			if (token.type != TK_PARENTHESIS_OPEN) {
1099 				r_err_str = "Expected '('";
1100 				return ERR_PARSE_ERROR;
1101 			}
1102 
1103 			Vector<String> cs;
1104 
1105 			bool first = true;
1106 			while (true) {
1107 
1108 				if (!first) {
1109 					get_token(p_stream, token, line, r_err_str);
1110 					if (token.type == TK_COMMA) {
1111 						//do none
1112 					} else if (token.type == TK_PARENTHESIS_CLOSE) {
1113 						break;
1114 					} else {
1115 						r_err_str = "Expected ',' or ')'";
1116 						return ERR_PARSE_ERROR;
1117 					}
1118 				}
1119 				get_token(p_stream, token, line, r_err_str);
1120 
1121 				if (token.type == TK_PARENTHESIS_CLOSE) {
1122 					break;
1123 				} else if (token.type != TK_STRING) {
1124 					r_err_str = "Expected string";
1125 					return ERR_PARSE_ERROR;
1126 				}
1127 
1128 				first = false;
1129 				cs.push_back(token.value);
1130 			}
1131 
1132 			PoolVector<String> arr;
1133 			{
1134 				int len = cs.size();
1135 				arr.resize(len);
1136 				PoolVector<String>::Write w = arr.write();
1137 				for (int i = 0; i < len; i++) {
1138 					w[i] = cs[i];
1139 				}
1140 			}
1141 
1142 			value = arr;
1143 
1144 		} else if (id == "PoolVector2Array" || id == "Vector2Array") {
1145 
1146 			Vector<float> args;
1147 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
1148 			if (err)
1149 				return err;
1150 
1151 			PoolVector<Vector2> arr;
1152 			{
1153 				int len = args.size() / 2;
1154 				arr.resize(len);
1155 				PoolVector<Vector2>::Write w = arr.write();
1156 				for (int i = 0; i < len; i++) {
1157 					w[i] = Vector2(args[i * 2 + 0], args[i * 2 + 1]);
1158 				}
1159 			}
1160 
1161 			value = arr;
1162 
1163 		} else if (id == "PoolVector3Array" || id == "Vector3Array") {
1164 
1165 			Vector<float> args;
1166 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
1167 			if (err)
1168 				return err;
1169 
1170 			PoolVector<Vector3> arr;
1171 			{
1172 				int len = args.size() / 3;
1173 				arr.resize(len);
1174 				PoolVector<Vector3>::Write w = arr.write();
1175 				for (int i = 0; i < len; i++) {
1176 					w[i] = Vector3(args[i * 3 + 0], args[i * 3 + 1], args[i * 3 + 2]);
1177 				}
1178 			}
1179 
1180 			value = arr;
1181 
1182 		} else if (id == "PoolColorArray" || id == "ColorArray") {
1183 
1184 			Vector<float> args;
1185 			Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
1186 			if (err)
1187 				return err;
1188 
1189 			PoolVector<Color> arr;
1190 			{
1191 				int len = args.size() / 4;
1192 				arr.resize(len);
1193 				PoolVector<Color>::Write w = arr.write();
1194 				for (int i = 0; i < len; i++) {
1195 					w[i] = Color(args[i * 4 + 0], args[i * 4 + 1], args[i * 4 + 2], args[i * 4 + 3]);
1196 				}
1197 			}
1198 
1199 			value = arr;
1200 		} else {
1201 			r_err_str = "Unexpected identifier: '" + id + "'.";
1202 			return ERR_PARSE_ERROR;
1203 		}
1204 
1205 		// All above branches end up here unless they had an early return.
1206 		return OK;
1207 	} else if (token.type == TK_NUMBER) {
1208 
1209 		value = token.value;
1210 		return OK;
1211 	} else if (token.type == TK_STRING) {
1212 
1213 		value = token.value;
1214 		return OK;
1215 	} else if (token.type == TK_COLOR) {
1216 
1217 		value = token.value;
1218 		return OK;
1219 	} else {
1220 		r_err_str = "Expected value, got " + String(tk_name[token.type]) + ".";
1221 		return ERR_PARSE_ERROR;
1222 	}
1223 }
1224 
_parse_array(Array & array,Stream * p_stream,int & line,String & r_err_str,ResourceParser * p_res_parser)1225 Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
1226 
1227 	Token token;
1228 	bool need_comma = false;
1229 
1230 	while (true) {
1231 
1232 		if (p_stream->is_eof()) {
1233 			r_err_str = "Unexpected End of File while parsing array";
1234 			return ERR_FILE_CORRUPT;
1235 		}
1236 
1237 		Error err = get_token(p_stream, token, line, r_err_str);
1238 		if (err != OK)
1239 			return err;
1240 
1241 		if (token.type == TK_BRACKET_CLOSE) {
1242 
1243 			return OK;
1244 		}
1245 
1246 		if (need_comma) {
1247 
1248 			if (token.type != TK_COMMA) {
1249 
1250 				r_err_str = "Expected ','";
1251 				return ERR_PARSE_ERROR;
1252 			} else {
1253 				need_comma = false;
1254 				continue;
1255 			}
1256 		}
1257 
1258 		Variant v;
1259 		err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser);
1260 		if (err)
1261 			return err;
1262 
1263 		array.push_back(v);
1264 		need_comma = true;
1265 	}
1266 }
1267 
_parse_dictionary(Dictionary & object,Stream * p_stream,int & line,String & r_err_str,ResourceParser * p_res_parser)1268 Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
1269 
1270 	bool at_key = true;
1271 	Variant key;
1272 	Token token;
1273 	bool need_comma = false;
1274 
1275 	while (true) {
1276 
1277 		if (p_stream->is_eof()) {
1278 			r_err_str = "Unexpected End of File while parsing dictionary";
1279 			return ERR_FILE_CORRUPT;
1280 		}
1281 
1282 		if (at_key) {
1283 
1284 			Error err = get_token(p_stream, token, line, r_err_str);
1285 			if (err != OK)
1286 				return err;
1287 
1288 			if (token.type == TK_CURLY_BRACKET_CLOSE) {
1289 
1290 				return OK;
1291 			}
1292 
1293 			if (need_comma) {
1294 
1295 				if (token.type != TK_COMMA) {
1296 
1297 					r_err_str = "Expected '}' or ','";
1298 					return ERR_PARSE_ERROR;
1299 				} else {
1300 					need_comma = false;
1301 					continue;
1302 				}
1303 			}
1304 
1305 			err = parse_value(token, key, p_stream, line, r_err_str, p_res_parser);
1306 
1307 			if (err)
1308 				return err;
1309 
1310 			err = get_token(p_stream, token, line, r_err_str);
1311 
1312 			if (err != OK)
1313 				return err;
1314 			if (token.type != TK_COLON) {
1315 
1316 				r_err_str = "Expected ':'";
1317 				return ERR_PARSE_ERROR;
1318 			}
1319 			at_key = false;
1320 		} else {
1321 
1322 			Error err = get_token(p_stream, token, line, r_err_str);
1323 			if (err != OK)
1324 				return err;
1325 
1326 			Variant v;
1327 			err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser);
1328 			if (err)
1329 				return err;
1330 			object[key] = v;
1331 			need_comma = true;
1332 			at_key = true;
1333 		}
1334 	}
1335 }
1336 
_parse_tag(Token & token,Stream * p_stream,int & line,String & r_err_str,Tag & r_tag,ResourceParser * p_res_parser,bool p_simple_tag)1337 Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) {
1338 
1339 	r_tag.fields.clear();
1340 
1341 	if (token.type != TK_BRACKET_OPEN) {
1342 		r_err_str = "Expected '['";
1343 		return ERR_PARSE_ERROR;
1344 	}
1345 
1346 	if (p_simple_tag) {
1347 
1348 		r_tag.name = "";
1349 		r_tag.fields.clear();
1350 
1351 		while (true) {
1352 
1353 			CharType c = p_stream->get_char();
1354 			if (p_stream->is_eof()) {
1355 				r_err_str = "Unexpected EOF while parsing simple tag";
1356 				return ERR_PARSE_ERROR;
1357 			}
1358 			if (c == ']')
1359 				break;
1360 			r_tag.name += String::chr(c);
1361 		}
1362 
1363 		r_tag.name = r_tag.name.strip_edges();
1364 
1365 		return OK;
1366 	}
1367 
1368 	get_token(p_stream, token, line, r_err_str);
1369 
1370 	if (token.type != TK_IDENTIFIER) {
1371 		r_err_str = "Expected identifier (tag name)";
1372 		return ERR_PARSE_ERROR;
1373 	}
1374 
1375 	r_tag.name = token.value;
1376 	bool parsing_tag = true;
1377 
1378 	while (true) {
1379 
1380 		if (p_stream->is_eof()) {
1381 			r_err_str = "Unexpected End of File while parsing tag: " + r_tag.name;
1382 			return ERR_FILE_CORRUPT;
1383 		}
1384 
1385 		get_token(p_stream, token, line, r_err_str);
1386 		if (token.type == TK_BRACKET_CLOSE)
1387 			break;
1388 
1389 		if (parsing_tag && token.type == TK_PERIOD) {
1390 			r_tag.name += "."; //support tags such as [someprop.Android] for specific platforms
1391 			get_token(p_stream, token, line, r_err_str);
1392 		} else if (parsing_tag && token.type == TK_COLON) {
1393 			r_tag.name += ":"; //support tags such as [someprop.Android] for specific platforms
1394 			get_token(p_stream, token, line, r_err_str);
1395 		} else {
1396 			parsing_tag = false;
1397 		}
1398 
1399 		if (token.type != TK_IDENTIFIER) {
1400 			r_err_str = "Expected Identifier";
1401 			return ERR_PARSE_ERROR;
1402 		}
1403 
1404 		String id = token.value;
1405 
1406 		if (parsing_tag) {
1407 			r_tag.name += id;
1408 			continue;
1409 		}
1410 
1411 		get_token(p_stream, token, line, r_err_str);
1412 		if (token.type != TK_EQUAL) {
1413 			return ERR_PARSE_ERROR;
1414 		}
1415 
1416 		get_token(p_stream, token, line, r_err_str);
1417 		Variant value;
1418 		Error err = parse_value(token, value, p_stream, line, r_err_str, p_res_parser);
1419 		if (err)
1420 			return err;
1421 
1422 		r_tag.fields[id] = value;
1423 	}
1424 
1425 	return OK;
1426 }
1427 
parse_tag(Stream * p_stream,int & line,String & r_err_str,Tag & r_tag,ResourceParser * p_res_parser,bool p_simple_tag)1428 Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) {
1429 
1430 	Token token;
1431 	get_token(p_stream, token, line, r_err_str);
1432 
1433 	if (token.type == TK_EOF) {
1434 		return ERR_FILE_EOF;
1435 	}
1436 
1437 	if (token.type != TK_BRACKET_OPEN) {
1438 		r_err_str = "Expected '['";
1439 		return ERR_PARSE_ERROR;
1440 	}
1441 
1442 	return _parse_tag(token, p_stream, line, r_err_str, r_tag, p_res_parser, p_simple_tag);
1443 }
1444 
parse_tag_assign_eof(Stream * p_stream,int & line,String & r_err_str,Tag & r_tag,String & r_assign,Variant & r_value,ResourceParser * p_res_parser,bool p_simple_tag)1445 Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser, bool p_simple_tag) {
1446 
1447 	//assign..
1448 	r_assign = "";
1449 	String what;
1450 
1451 	while (true) {
1452 
1453 		CharType c;
1454 		if (p_stream->saved) {
1455 			c = p_stream->saved;
1456 			p_stream->saved = 0;
1457 
1458 		} else {
1459 			c = p_stream->get_char();
1460 		}
1461 
1462 		if (p_stream->is_eof())
1463 			return ERR_FILE_EOF;
1464 
1465 		if (c == ';') { //comment
1466 			while (true) {
1467 				CharType ch = p_stream->get_char();
1468 				if (p_stream->is_eof()) {
1469 					return ERR_FILE_EOF;
1470 				}
1471 				if (ch == '\n')
1472 					break;
1473 			}
1474 			continue;
1475 		}
1476 
1477 		if (c == '[' && what.length() == 0) {
1478 			//it's a tag!
1479 			p_stream->saved = '['; //go back one
1480 
1481 			Error err = parse_tag(p_stream, line, r_err_str, r_tag, p_res_parser, p_simple_tag);
1482 
1483 			return err;
1484 		}
1485 
1486 		if (c > 32) {
1487 			if (c == '"') { //quoted
1488 				p_stream->saved = '"';
1489 				Token tk;
1490 				Error err = get_token(p_stream, tk, line, r_err_str);
1491 				if (err)
1492 					return err;
1493 				if (tk.type != TK_STRING) {
1494 					r_err_str = "Error reading quoted string";
1495 					return ERR_INVALID_DATA;
1496 				}
1497 
1498 				what = tk.value;
1499 
1500 			} else if (c != '=') {
1501 				what += String::chr(c);
1502 			} else {
1503 				r_assign = what;
1504 				Token token;
1505 				get_token(p_stream, token, line, r_err_str);
1506 				Error err = parse_value(token, r_value, p_stream, line, r_err_str, p_res_parser);
1507 				return err;
1508 			}
1509 		} else if (c == '\n') {
1510 			line++;
1511 		}
1512 	}
1513 }
1514 
parse(Stream * p_stream,Variant & r_ret,String & r_err_str,int & r_err_line,ResourceParser * p_res_parser)1515 Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser) {
1516 
1517 	Token token;
1518 	Error err = get_token(p_stream, token, r_err_line, r_err_str);
1519 	if (err)
1520 		return err;
1521 
1522 	if (token.type == TK_EOF) {
1523 		return ERR_FILE_EOF;
1524 	}
1525 
1526 	return parse_value(token, r_ret, p_stream, r_err_line, r_err_str, p_res_parser);
1527 }
1528 
1529 //////////////////////////////////////////////////////////////////////////////////
1530 //////////////////////////////////////////////////////////////////////////////////
1531 ////////////////////////////////////////////////////////////////////////////////
1532 
rtosfix(double p_value)1533 static String rtosfix(double p_value) {
1534 
1535 	if (p_value == 0.0)
1536 		return "0"; //avoid negative zero (-0) being written, which may annoy git, svn, etc. for changes when they don't exist.
1537 	else
1538 		return rtoss(p_value);
1539 }
1540 
write(const Variant & p_variant,StoreStringFunc p_store_string_func,void * p_store_string_ud,EncodeResourceFunc p_encode_res_func,void * p_encode_res_ud)1541 Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) {
1542 
1543 	switch (p_variant.get_type()) {
1544 
1545 		case Variant::NIL: {
1546 			p_store_string_func(p_store_string_ud, "null");
1547 		} break;
1548 		case Variant::BOOL: {
1549 
1550 			p_store_string_func(p_store_string_ud, p_variant.operator bool() ? "true" : "false");
1551 		} break;
1552 		case Variant::INT: {
1553 
1554 			p_store_string_func(p_store_string_ud, itos(p_variant.operator int64_t()));
1555 		} break;
1556 		case Variant::REAL: {
1557 
1558 			String s = rtosfix(p_variant.operator real_t());
1559 			if (s != "inf" && s != "nan") {
1560 				if (s.find(".") == -1 && s.find("e") == -1)
1561 					s += ".0";
1562 			}
1563 			p_store_string_func(p_store_string_ud, s);
1564 		} break;
1565 		case Variant::STRING: {
1566 
1567 			String str = p_variant;
1568 
1569 			str = "\"" + str.c_escape_multiline() + "\"";
1570 			p_store_string_func(p_store_string_ud, str);
1571 		} break;
1572 		case Variant::VECTOR2: {
1573 
1574 			Vector2 v = p_variant;
1575 			p_store_string_func(p_store_string_ud, "Vector2( " + rtosfix(v.x) + ", " + rtosfix(v.y) + " )");
1576 		} break;
1577 		case Variant::RECT2: {
1578 
1579 			Rect2 aabb = p_variant;
1580 			p_store_string_func(p_store_string_ud, "Rect2( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + " )");
1581 
1582 		} break;
1583 		case Variant::VECTOR3: {
1584 
1585 			Vector3 v = p_variant;
1586 			p_store_string_func(p_store_string_ud, "Vector3( " + rtosfix(v.x) + ", " + rtosfix(v.y) + ", " + rtosfix(v.z) + " )");
1587 		} break;
1588 		case Variant::PLANE: {
1589 
1590 			Plane p = p_variant;
1591 			p_store_string_func(p_store_string_ud, "Plane( " + rtosfix(p.normal.x) + ", " + rtosfix(p.normal.y) + ", " + rtosfix(p.normal.z) + ", " + rtosfix(p.d) + " )");
1592 
1593 		} break;
1594 		case Variant::AABB: {
1595 
1596 			AABB aabb = p_variant;
1597 			p_store_string_func(p_store_string_ud, "AABB( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + " )");
1598 
1599 		} break;
1600 		case Variant::QUAT: {
1601 
1602 			Quat quat = p_variant;
1603 			p_store_string_func(p_store_string_ud, "Quat( " + rtosfix(quat.x) + ", " + rtosfix(quat.y) + ", " + rtosfix(quat.z) + ", " + rtosfix(quat.w) + " )");
1604 
1605 		} break;
1606 		case Variant::TRANSFORM2D: {
1607 
1608 			String s = "Transform2D( ";
1609 			Transform2D m3 = p_variant;
1610 			for (int i = 0; i < 3; i++) {
1611 				for (int j = 0; j < 2; j++) {
1612 
1613 					if (i != 0 || j != 0)
1614 						s += ", ";
1615 					s += rtosfix(m3.elements[i][j]);
1616 				}
1617 			}
1618 
1619 			p_store_string_func(p_store_string_ud, s + " )");
1620 
1621 		} break;
1622 		case Variant::BASIS: {
1623 
1624 			String s = "Basis( ";
1625 			Basis m3 = p_variant;
1626 			for (int i = 0; i < 3; i++) {
1627 				for (int j = 0; j < 3; j++) {
1628 
1629 					if (i != 0 || j != 0)
1630 						s += ", ";
1631 					s += rtosfix(m3.elements[i][j]);
1632 				}
1633 			}
1634 
1635 			p_store_string_func(p_store_string_ud, s + " )");
1636 
1637 		} break;
1638 		case Variant::TRANSFORM: {
1639 
1640 			String s = "Transform( ";
1641 			Transform t = p_variant;
1642 			Basis &m3 = t.basis;
1643 			for (int i = 0; i < 3; i++) {
1644 				for (int j = 0; j < 3; j++) {
1645 
1646 					if (i != 0 || j != 0)
1647 						s += ", ";
1648 					s += rtosfix(m3.elements[i][j]);
1649 				}
1650 			}
1651 
1652 			s = s + ", " + rtosfix(t.origin.x) + ", " + rtosfix(t.origin.y) + ", " + rtosfix(t.origin.z);
1653 
1654 			p_store_string_func(p_store_string_ud, s + " )");
1655 		} break;
1656 
1657 		// misc types
1658 		case Variant::COLOR: {
1659 
1660 			Color c = p_variant;
1661 			p_store_string_func(p_store_string_ud, "Color( " + rtosfix(c.r) + ", " + rtosfix(c.g) + ", " + rtosfix(c.b) + ", " + rtosfix(c.a) + " )");
1662 
1663 		} break;
1664 		case Variant::NODE_PATH: {
1665 
1666 			String str = p_variant;
1667 
1668 			str = "NodePath(\"" + str.c_escape() + "\")";
1669 			p_store_string_func(p_store_string_ud, str);
1670 
1671 		} break;
1672 
1673 		case Variant::OBJECT: {
1674 
1675 			Object *obj = p_variant;
1676 
1677 			if (!obj) {
1678 				p_store_string_func(p_store_string_ud, "null");
1679 				break; // don't save it
1680 			}
1681 
1682 			RES res = p_variant;
1683 			if (res.is_valid()) {
1684 				//is resource
1685 				String res_text;
1686 
1687 				//try external function
1688 				if (p_encode_res_func) {
1689 
1690 					res_text = p_encode_res_func(p_encode_res_ud, res);
1691 				}
1692 
1693 				//try path because it's a file
1694 				if (res_text == String() && res->get_path().is_resource_file()) {
1695 
1696 					//external resource
1697 					String path = res->get_path();
1698 					res_text = "Resource( \"" + path + "\")";
1699 				}
1700 
1701 				//could come up with some sort of text
1702 				if (res_text != String()) {
1703 					p_store_string_func(p_store_string_ud, res_text);
1704 					break;
1705 				}
1706 			}
1707 
1708 			//store as generic object
1709 
1710 			p_store_string_func(p_store_string_ud, "Object(" + obj->get_class() + ",");
1711 
1712 			List<PropertyInfo> props;
1713 			obj->get_property_list(&props);
1714 			bool first = true;
1715 			for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
1716 
1717 				if (E->get().usage & PROPERTY_USAGE_STORAGE || E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE) {
1718 					//must be serialized
1719 
1720 					if (first) {
1721 						first = false;
1722 					} else {
1723 						p_store_string_func(p_store_string_ud, ",");
1724 					}
1725 
1726 					p_store_string_func(p_store_string_ud, "\"" + E->get().name + "\":");
1727 					write(obj->get(E->get().name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
1728 				}
1729 			}
1730 
1731 			p_store_string_func(p_store_string_ud, ")\n");
1732 
1733 		} break;
1734 
1735 		case Variant::DICTIONARY: {
1736 
1737 			Dictionary dict = p_variant;
1738 
1739 			List<Variant> keys;
1740 			dict.get_key_list(&keys);
1741 			keys.sort();
1742 
1743 			p_store_string_func(p_store_string_ud, "{\n");
1744 			for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
1745 
1746 				/*
1747 				if (!_check_type(dict[E->get()]))
1748 					continue;
1749 				*/
1750 				write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
1751 				p_store_string_func(p_store_string_ud, ": ");
1752 				write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
1753 				if (E->next())
1754 					p_store_string_func(p_store_string_ud, ",\n");
1755 			}
1756 
1757 			p_store_string_func(p_store_string_ud, "\n}");
1758 
1759 		} break;
1760 		case Variant::ARRAY: {
1761 
1762 			p_store_string_func(p_store_string_ud, "[ ");
1763 			Array array = p_variant;
1764 			int len = array.size();
1765 			for (int i = 0; i < len; i++) {
1766 
1767 				if (i > 0)
1768 					p_store_string_func(p_store_string_ud, ", ");
1769 				write(array[i], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
1770 			}
1771 			p_store_string_func(p_store_string_ud, " ]");
1772 
1773 		} break;
1774 
1775 		case Variant::POOL_BYTE_ARRAY: {
1776 
1777 			p_store_string_func(p_store_string_ud, "PoolByteArray( ");
1778 			String s;
1779 			PoolVector<uint8_t> data = p_variant;
1780 			int len = data.size();
1781 			PoolVector<uint8_t>::Read r = data.read();
1782 			const uint8_t *ptr = r.ptr();
1783 			for (int i = 0; i < len; i++) {
1784 
1785 				if (i > 0)
1786 					p_store_string_func(p_store_string_ud, ", ");
1787 
1788 				p_store_string_func(p_store_string_ud, itos(ptr[i]));
1789 			}
1790 
1791 			p_store_string_func(p_store_string_ud, " )");
1792 
1793 		} break;
1794 		case Variant::POOL_INT_ARRAY: {
1795 
1796 			p_store_string_func(p_store_string_ud, "PoolIntArray( ");
1797 			PoolVector<int> data = p_variant;
1798 			int len = data.size();
1799 			PoolVector<int>::Read r = data.read();
1800 			const int *ptr = r.ptr();
1801 
1802 			for (int i = 0; i < len; i++) {
1803 
1804 				if (i > 0)
1805 					p_store_string_func(p_store_string_ud, ", ");
1806 
1807 				p_store_string_func(p_store_string_ud, itos(ptr[i]));
1808 			}
1809 
1810 			p_store_string_func(p_store_string_ud, " )");
1811 
1812 		} break;
1813 		case Variant::POOL_REAL_ARRAY: {
1814 
1815 			p_store_string_func(p_store_string_ud, "PoolRealArray( ");
1816 			PoolVector<real_t> data = p_variant;
1817 			int len = data.size();
1818 			PoolVector<real_t>::Read r = data.read();
1819 			const real_t *ptr = r.ptr();
1820 
1821 			for (int i = 0; i < len; i++) {
1822 
1823 				if (i > 0)
1824 					p_store_string_func(p_store_string_ud, ", ");
1825 				p_store_string_func(p_store_string_ud, rtosfix(ptr[i]));
1826 			}
1827 
1828 			p_store_string_func(p_store_string_ud, " )");
1829 
1830 		} break;
1831 		case Variant::POOL_STRING_ARRAY: {
1832 
1833 			p_store_string_func(p_store_string_ud, "PoolStringArray( ");
1834 			PoolVector<String> data = p_variant;
1835 			int len = data.size();
1836 			PoolVector<String>::Read r = data.read();
1837 			const String *ptr = r.ptr();
1838 			String s;
1839 			//write_string("\n");
1840 
1841 			for (int i = 0; i < len; i++) {
1842 
1843 				if (i > 0)
1844 					p_store_string_func(p_store_string_ud, ", ");
1845 				String str = ptr[i];
1846 				p_store_string_func(p_store_string_ud, "\"" + str.c_escape() + "\"");
1847 			}
1848 
1849 			p_store_string_func(p_store_string_ud, " )");
1850 
1851 		} break;
1852 		case Variant::POOL_VECTOR2_ARRAY: {
1853 
1854 			p_store_string_func(p_store_string_ud, "PoolVector2Array( ");
1855 			PoolVector<Vector2> data = p_variant;
1856 			int len = data.size();
1857 			PoolVector<Vector2>::Read r = data.read();
1858 			const Vector2 *ptr = r.ptr();
1859 
1860 			for (int i = 0; i < len; i++) {
1861 
1862 				if (i > 0)
1863 					p_store_string_func(p_store_string_ud, ", ");
1864 				p_store_string_func(p_store_string_ud, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y));
1865 			}
1866 
1867 			p_store_string_func(p_store_string_ud, " )");
1868 
1869 		} break;
1870 		case Variant::POOL_VECTOR3_ARRAY: {
1871 
1872 			p_store_string_func(p_store_string_ud, "PoolVector3Array( ");
1873 			PoolVector<Vector3> data = p_variant;
1874 			int len = data.size();
1875 			PoolVector<Vector3>::Read r = data.read();
1876 			const Vector3 *ptr = r.ptr();
1877 
1878 			for (int i = 0; i < len; i++) {
1879 
1880 				if (i > 0)
1881 					p_store_string_func(p_store_string_ud, ", ");
1882 				p_store_string_func(p_store_string_ud, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y) + ", " + rtosfix(ptr[i].z));
1883 			}
1884 
1885 			p_store_string_func(p_store_string_ud, " )");
1886 
1887 		} break;
1888 		case Variant::POOL_COLOR_ARRAY: {
1889 
1890 			p_store_string_func(p_store_string_ud, "PoolColorArray( ");
1891 
1892 			PoolVector<Color> data = p_variant;
1893 			int len = data.size();
1894 			PoolVector<Color>::Read r = data.read();
1895 			const Color *ptr = r.ptr();
1896 
1897 			for (int i = 0; i < len; i++) {
1898 
1899 				if (i > 0)
1900 					p_store_string_func(p_store_string_ud, ", ");
1901 
1902 				p_store_string_func(p_store_string_ud, rtosfix(ptr[i].r) + ", " + rtosfix(ptr[i].g) + ", " + rtosfix(ptr[i].b) + ", " + rtosfix(ptr[i].a));
1903 			}
1904 			p_store_string_func(p_store_string_ud, " )");
1905 
1906 		} break;
1907 		default: {
1908 		}
1909 	}
1910 
1911 	return OK;
1912 }
1913 
_write_to_str(void * ud,const String & p_string)1914 static Error _write_to_str(void *ud, const String &p_string) {
1915 
1916 	String *str = (String *)ud;
1917 	(*str) += p_string;
1918 	return OK;
1919 }
1920 
write_to_string(const Variant & p_variant,String & r_string,EncodeResourceFunc p_encode_res_func,void * p_encode_res_ud)1921 Error VariantWriter::write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) {
1922 
1923 	r_string = String();
1924 
1925 	return write(p_variant, _write_to_str, &r_string, p_encode_res_func, p_encode_res_ud);
1926 }
1927