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