Skip to content

Commit

Permalink
Backported from godot4: Save PackedByteArrays as base64 encoded.
Browse files Browse the repository at this point in the history
  • Loading branch information
Relintai committed Apr 14, 2024
1 parent ed22429 commit 6faa98c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 9 deletions.
90 changes: 83 additions & 7 deletions core/variant/variant_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,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/os/keyboard.h"
Expand Down Expand Up @@ -564,6 +565,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;
Expand Down Expand Up @@ -998,7 +1075,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
} else if (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;
}
Expand Down Expand Up @@ -1874,12 +1951,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
int len = data.size();
PoolVector<uint8_t>::Read r = data.read();
const uint8_t *ptr = r.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(ptr, len));
p_store_string_func(p_store_string_ud, "\"");
}

p_store_string_func(p_store_string_ud, " )");
Expand Down
1 change: 1 addition & 0 deletions core/variant/variant_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class VariantParser {

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);
Expand Down
5 changes: 3 additions & 2 deletions scene/resources/resource_format_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@
#include "core/os/dir_access.h"
#include "core/version.h"

//version 2: changed names for basis, aabb, poolvectors, etc.
#define FORMAT_VERSION 2
// Version 2: changed names for basis, aabb, poolvectors, etc.
// Version 3: PoolByteArray is now stored as base64 encoded.
#define FORMAT_VERSION 3

#include "core/os/dir_access.h"
#include "core/version.h"
Expand Down

0 comments on commit 6faa98c

Please sign in to comment.