diff options
Diffstat (limited to 'core/variant/variant_parser.cpp')
-rw-r--r-- | core/variant/variant_parser.cpp | 167 |
1 files changed, 119 insertions, 48 deletions
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 34653310b1..87874deb8d 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* variant_parser.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* variant_parser.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "variant_parser.h" @@ -35,39 +35,93 @@ #include "core/os/keyboard.h" #include "core/string/string_buffer.h" -char32_t VariantParser::StreamFile::get_char() { - return f->get_8(); +char32_t VariantParser::Stream::get_char() { + // is within buffer? + if (readahead_pointer < readahead_filled) { + return readahead_buffer[readahead_pointer++]; + } + + // attempt to readahead + readahead_filled = _read_buffer(readahead_buffer, readahead_enabled ? READAHEAD_SIZE : 1); + if (readahead_filled) { + readahead_pointer = 0; + } else { + // EOF + readahead_pointer = 1; + eof = true; + return 0; + } + return get_char(); +} + +bool VariantParser::Stream::is_eof() const { + if (readahead_enabled) { + return eof; + } + return _is_eof(); } bool VariantParser::StreamFile::is_utf8() const { return true; } -bool VariantParser::StreamFile::is_eof() const { +bool VariantParser::StreamFile::_is_eof() const { return f->eof_reached(); } -char32_t VariantParser::StreamString::get_char() { - if (pos > s.length()) { - return 0; - } else if (pos == s.length()) { - // You need to try to read again when you have reached the end for EOF to be reported, - // so this works the same as files (like StreamFile does) - pos++; - return 0; - } else { - return s[pos++]; +uint32_t VariantParser::StreamFile::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) { + // The buffer is assumed to include at least one character (for null terminator) + ERR_FAIL_COND_V(!p_num_chars, 0); + + uint8_t *temp = (uint8_t *)alloca(p_num_chars); + uint64_t num_read = f->get_buffer(temp, p_num_chars); + ERR_FAIL_COND_V(num_read == UINT64_MAX, 0); + + // translate to wchar + for (uint32_t n = 0; n < num_read; n++) { + p_buffer[n] = temp[n]; } + + // could be less than p_num_chars, or zero + return num_read; } bool VariantParser::StreamString::is_utf8() const { return false; } -bool VariantParser::StreamString::is_eof() const { +bool VariantParser::StreamString::_is_eof() const { return pos > s.length(); } +uint32_t VariantParser::StreamString::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) { + // The buffer is assumed to include at least one character (for null terminator) + ERR_FAIL_COND_V(!p_num_chars, 0); + + int available = MAX(s.length() - pos, 0); + if (available >= (int)p_num_chars) { + const char32_t *src = s.ptr(); + src += pos; + memcpy(p_buffer, src, p_num_chars * sizeof(char32_t)); + pos += p_num_chars; + + return p_num_chars; + } + + // going to reach EOF + if (available) { + const char32_t *src = s.ptr(); + src += pos; + memcpy(p_buffer, src, available * sizeof(char32_t)); + pos += available; + } + + // add a zero + p_buffer[available] = 0; + + return available; +} + ///////////////////////////////////////////////////////////////////////////////////////////////// const char *VariantParser::tk_name[TK_MAX] = { @@ -1283,7 +1337,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int Variant v; err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); - if (err) { + if (err && err != ERR_FILE_MISSING_DEPENDENCIES) { return err; } object[key] = v; @@ -1304,6 +1358,7 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin if (p_simple_tag) { r_tag.name = ""; r_tag.fields.clear(); + bool escaping = false; if (p_stream->is_utf8()) { CharString cs; @@ -1314,7 +1369,15 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin return ERR_PARSE_ERROR; } if (c == ']') { - break; + if (escaping) { + escaping = false; + } else { + break; + } + } else if (c == '\\') { + escaping = true; + } else { + escaping = false; } cs += c; } @@ -1327,7 +1390,15 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin return ERR_PARSE_ERROR; } if (c == ']') { - break; + if (escaping) { + escaping = false; + } else { + break; + } + } else if (c == '\\') { + escaping = true; + } else { + escaping = false; } r_tag.name += String::chr(c); } @@ -1651,7 +1722,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str if (i != 0 || j != 0) { s += ", "; } - s += rtos_fix(t.matrix[i][j]); + s += rtos_fix(t.columns[i][j]); } } @@ -1680,7 +1751,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::OBJECT: { - Object *obj = p_variant; + Object *obj = p_variant.get_validated_object(); if (!obj) { p_store_string_func(p_store_string_ud, "null"); |