Bläddra i källkod

Save PackedByteArrays as base64 encoded

Gilles Roudière 1 år sedan
förälder
incheckning
de5073519e

+ 82 - 11
core/variant/variant_parser.cpp

@@ -30,6 +30,7 @@
 
 #include "variant_parser.h"
 
+#include "core/crypto/crypto_core.h"
 #include "core/input/input_event.h"
 #include "core/io/resource_loader.h"
 #include "core/object/script_language.h"
@@ -595,6 +596,82 @@ Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct,
 	return OK;
 }
 
+Error VariantParser::_parse_byte_array(Stream *p_stream, Vector<uint8_t> &r_construct, int &line, String &r_err_str) {
+	Token token;
+	get_token(p_stream, token, line, r_err_str);
+	if (token.type != TK_PARENTHESIS_OPEN) {
+		r_err_str = "Expected '(' in constructor";
+		return ERR_PARSE_ERROR;
+	}
+
+	get_token(p_stream, token, line, r_err_str);
+	if (token.type == TK_STRING) {
+		// Base64 encoded array.
+		String base64_encoded_string = token.value;
+		int strlen = base64_encoded_string.length();
+		CharString cstr = base64_encoded_string.ascii();
+
+		size_t arr_len = 0;
+		r_construct.resize(strlen / 4 * 3 + 1);
+		uint8_t *w = r_construct.ptrw();
+		Error err = CryptoCore::b64_decode(&w[0], r_construct.size(), &arr_len, (unsigned char *)cstr.get_data(), strlen);
+		if (err) {
+			r_err_str = "Invalid base64-encoded string";
+			return ERR_PARSE_ERROR;
+		}
+		r_construct.resize(arr_len);
+
+		get_token(p_stream, token, line, r_err_str);
+		if (token.type != TK_PARENTHESIS_CLOSE) {
+			r_err_str = "Expected ')' in constructor";
+			return ERR_PARSE_ERROR;
+		}
+
+	} else if (token.type == TK_NUMBER || token.type == TK_IDENTIFIER) {
+		// Individual elements.
+		while (true) {
+			if (token.type != TK_NUMBER) {
+				bool valid = false;
+				if (token.type == TK_IDENTIFIER) {
+					double real = stor_fix(token.value);
+					if (real != -1) {
+						token.type = TK_NUMBER;
+						token.value = real;
+						valid = true;
+					}
+				}
+				if (!valid) {
+					r_err_str = "Expected number in constructor";
+					return ERR_PARSE_ERROR;
+				}
+			}
+
+			r_construct.push_back(token.value);
+
+			get_token(p_stream, token, line, r_err_str);
+
+			if (token.type == TK_COMMA) {
+				//do none
+			} else if (token.type == TK_PARENTHESIS_CLOSE) {
+				break;
+			} else {
+				r_err_str = "Expected ',' or ')' in constructor";
+				return ERR_PARSE_ERROR;
+			}
+
+			get_token(p_stream, token, line, r_err_str);
+		}
+	} else if (token.type == TK_PARENTHESIS_CLOSE) {
+		// Empty array.
+		return OK;
+	} else {
+		r_err_str = "Expected base64 string, or list of numbers in constructor";
+		return ERR_PARSE_ERROR;
+	}
+
+	return OK;
+}
+
 Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
 	if (token.type == TK_CURLY_BRACKET_OPEN) {
 		Dictionary d;
@@ -1148,7 +1225,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 			value = array;
 		} else if (id == "PackedByteArray" || id == "PoolByteArray" || id == "ByteArray") {
 			Vector<uint8_t> args;
-			Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str);
+			Error err = _parse_byte_array(p_stream, args, line, r_err_str);
 			if (err) {
 				return err;
 			}
@@ -2031,17 +2108,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 		case Variant::PACKED_BYTE_ARRAY: {
 			p_store_string_func(p_store_string_ud, "PackedByteArray(");
 			Vector<uint8_t> data = p_variant;
-			int len = data.size();
-			const uint8_t *ptr = data.ptr();
-
-			for (int i = 0; i < len; i++) {
-				if (i > 0) {
-					p_store_string_func(p_store_string_ud, ", ");
-				}
-
-				p_store_string_func(p_store_string_ud, itos(ptr[i]));
+			if (data.size() > 0) {
+				p_store_string_func(p_store_string_ud, "\"");
+				p_store_string_func(p_store_string_ud, CryptoCore::b64_encode_str(data.ptr(), data.size()));
+				p_store_string_func(p_store_string_ud, "\"");
 			}
-
 			p_store_string_func(p_store_string_ud, ")");
 		} break;
 		case Variant::PACKED_INT32_ARRAY: {

+ 1 - 0
core/variant/variant_parser.h

@@ -141,6 +141,7 @@ private:
 
 	template <class T>
 	static Error _parse_construct(Stream *p_stream, Vector<T> &r_construct, int &line, String &r_err_str);
+	static Error _parse_byte_array(Stream *p_stream, Vector<uint8_t> &r_construct, int &line, String &r_err_str);
 	static Error _parse_enginecfg(Stream *p_stream, Vector<String> &strings, int &line, String &r_err_str);
 	static Error _parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser = nullptr);
 	static Error _parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser = nullptr);

+ 2 - 1
scene/resources/resource_format_text.cpp

@@ -39,7 +39,8 @@
 
 // Version 2: changed names for Basis, AABB, Vectors, etc.
 // Version 3: new string ID for ext/subresources, breaks forward compat.
-#define FORMAT_VERSION 3
+// Version 4: PackedByteArray is now stored as base64 encoded.
+#define FORMAT_VERSION 4
 
 #define BINARY_FORMAT_VERSION 4