Merge pull request #100386 from hpvb/core-ubsan

Core: Fix UBSAN reports
This commit is contained in:
Rémi Verschelde 2024-12-18 17:23:32 +01:00
commit 851d8e49e8
No known key found for this signature in database
GPG key ID: C3336907360768E1
40 changed files with 373 additions and 248 deletions

View file

@ -898,7 +898,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S
if (!p_custom_features.is_empty()) {
// Store how many properties are saved, add one for custom features, which must always go first.
file->store_32(count + 1);
file->store_32(uint32_t(count + 1));
String key = CoreStringName(_custom_features);
file->store_pascal_string(key);
@ -911,12 +911,12 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S
err = encode_variant(p_custom_features, buff.ptrw(), len, false);
ERR_FAIL_COND_V(err != OK, err);
file->store_32(len);
file->store_32(uint32_t(len));
file->store_buffer(buff.ptr(), buff.size());
} else {
// Store how many properties are saved.
file->store_32(count);
file->store_32(uint32_t(count));
}
for (const KeyValue<String, List<String>> &E : p_props) {
@ -943,7 +943,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S
err = encode_variant(value, buff.ptrw(), len, true);
ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
file->store_32(len);
file->store_32(uint32_t(len));
file->store_buffer(buff.ptr(), buff.size());
}
}

View file

@ -47,10 +47,8 @@ public:
typedef HashMap<String, Variant> CustomMap;
static const String PROJECT_DATA_DIR_NAME_SUFFIX;
enum {
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
NO_BUILTIN_ORDER_BASE = 1 << 16
};
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;
#ifdef TOOLS_ENABLED
const static PackedStringArray get_required_features();

View file

@ -38,7 +38,7 @@ class AESContext : public RefCounted {
GDCLASS(AESContext, RefCounted);
public:
enum Mode {
enum Mode : int32_t {
MODE_ECB_ENCRYPT,
MODE_ECB_DECRYPT,
MODE_CBC_ENCRYPT,

View file

@ -37,7 +37,7 @@ class HashingContext : public RefCounted {
GDCLASS(HashingContext, RefCounted);
public:
enum HashType {
enum HashType : int32_t {
HASH_MD5,
HASH_SHA1,
HASH_SHA256

View file

@ -31,6 +31,8 @@
#ifndef INPUT_ENUMS_H
#define INPUT_ENUMS_H
#include "core/error/error_macros.h"
enum class HatDir {
UP = 0,
RIGHT = 1,
@ -131,6 +133,8 @@ enum class MouseButtonMask {
};
inline MouseButtonMask mouse_button_to_mask(MouseButton button) {
ERR_FAIL_COND_V(button == MouseButton::NONE, MouseButtonMask::NONE);
return MouseButtonMask(1 << ((int)button - 1));
}

View file

@ -43,7 +43,7 @@ public:
static int zstd_window_log_size;
static int gzip_chunk;
enum Mode {
enum Mode : int32_t {
MODE_FASTLZ,
MODE_DEFLATE,
MODE_ZSTD,

View file

@ -40,7 +40,7 @@ class DirAccess : public RefCounted {
GDCLASS(DirAccess, RefCounted);
public:
enum AccessType {
enum AccessType : int32_t {
ACCESS_RESOURCES,
ACCESS_USERDATA,
ACCESS_FILESYSTEM,

View file

@ -383,7 +383,7 @@ double FileAccess::get_double() const {
String FileAccess::get_token() const {
CharString token;
char32_t c = get_8();
uint8_t c = get_8();
while (!eof_reached()) {
if (c <= ' ') {
@ -391,7 +391,7 @@ String FileAccess::get_token() const {
break;
}
} else {
token += c;
token += char(c);
}
c = get_8();
}
@ -448,14 +448,14 @@ public:
String FileAccess::get_line() const {
CharBuffer line;
char32_t c = get_8();
uint8_t c = get_8();
while (!eof_reached()) {
if (c == '\n' || c == '\0') {
line.push_back(0);
return String::utf8(line.get_data());
} else if (c != '\r') {
line.push_back(c);
line.push_back(char(c));
}
c = get_8();
@ -786,7 +786,7 @@ bool FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
err = encode_variant(p_var, &w[0], len, p_full_objects);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error when trying to encode Variant.");
return store_32(len) && store_buffer(buff);
return store_32(uint32_t(len)) && store_buffer(buff);
}
Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) {

View file

@ -46,7 +46,7 @@ class FileAccess : public RefCounted {
GDCLASS(FileAccess, RefCounted);
public:
enum AccessType {
enum AccessType : int32_t {
ACCESS_RESOURCES,
ACCESS_USERDATA,
ACCESS_FILESYSTEM,
@ -54,14 +54,14 @@ public:
ACCESS_MAX
};
enum ModeFlags {
enum ModeFlags : int32_t {
READ = 1,
WRITE = 2,
READ_WRITE = 3,
WRITE_READ = 7,
};
enum UnixPermissionFlags {
enum UnixPermissionFlags : int32_t {
UNIX_EXECUTE_OTHER = 0x001,
UNIX_WRITE_OTHER = 0x002,
UNIX_READ_OTHER = 0x004,
@ -76,7 +76,7 @@ public:
UNIX_SET_USER_ID = 0x800,
};
enum CompressionMode {
enum CompressionMode : int32_t {
COMPRESSION_FASTLZ = Compression::MODE_FASTLZ,
COMPRESSION_DEFLATE = Compression::MODE_DEFLATE,
COMPRESSION_ZSTD = Compression::MODE_ZSTD,

View file

@ -125,7 +125,7 @@ void FileAccessCompressed::_close() {
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //write header 4
f->store_32(cmode); //write compression mode 4
f->store_32(block_size); //write block size 4
f->store_32(write_max); //max amount of data written 4
f->store_32(uint32_t(write_max)); //max amount of data written 4
uint32_t bc = (write_max / block_size) + 1;
for (uint32_t i = 0; i < bc; i++) {
@ -147,7 +147,7 @@ void FileAccessCompressed::_close() {
f->seek(16); //ok write block sizes
for (uint32_t i = 0; i < bc; i++) {
f->store_32(block_sizes[i]);
f->store_32(uint32_t(block_sizes[i]));
}
f->seek_end();
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
@ -310,7 +310,9 @@ bool FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length)
write_ptr = buffer.ptrw();
}
memcpy(write_ptr + write_pos, p_src, p_length);
if (p_length) {
memcpy(write_ptr + write_pos, p_src, p_length);
}
write_pos += p_length;
return true;

View file

@ -210,10 +210,16 @@ bool FileAccessEncrypted::eof_reached() const {
}
uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
if (!p_length) {
return 0;
}
ERR_FAIL_NULL_V(p_dst, -1);
uint64_t to_copy = MIN(p_length, get_length() - pos);
memcpy(p_dst, data.ptr() + pos, to_copy);
pos += to_copy;
@ -230,7 +236,12 @@ Error FileAccessEncrypted::get_error() const {
bool FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V_MSG(!writing, false, "File has not been opened in write mode.");
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
if (!p_length) {
return true;
}
ERR_FAIL_NULL_V(p_src, false);
if (pos + p_length >= get_length()) {
ERR_FAIL_COND_V(data.resize(pos + p_length) != OK, false);
@ -238,6 +249,7 @@ bool FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length)
memcpy(data.ptrw() + pos, p_src, p_length);
pos += p_length;
return true;
}

View file

@ -37,7 +37,7 @@
class FileAccessEncrypted : public FileAccess {
public:
enum Mode {
enum Mode : int32_t {
MODE_READ,
MODE_WRITE_AES256,
MODE_MAX

View file

@ -123,7 +123,11 @@ bool FileAccessMemory::eof_reached() const {
}
uint64_t FileAccessMemory::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (!p_length) {
return 0;
}
ERR_FAIL_NULL_V(p_dst, -1);
ERR_FAIL_NULL_V(data, -1);
uint64_t left = length - pos;
@ -148,7 +152,11 @@ void FileAccessMemory::flush() {
}
bool FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
if (!p_length) {
return true;
}
ERR_FAIL_NULL_V(p_src, false);
uint64_t left = length - pos;
uint64_t write = MIN(p_length, left);

View file

@ -70,7 +70,7 @@ public:
MAX_PIXELS = 268435456 // 16384 ^ 2
};
enum Format {
enum Format : int32_t {
FORMAT_L8, // Luminance
FORMAT_LA8, // Luminance-Alpha
FORMAT_R8,

View file

@ -71,14 +71,18 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
return itos(p_var);
case Variant::FLOAT: {
double num = p_var;
if (p_full_precision) {
// Store unreliable digits (17) instead of just reliable
// digits (14) so that the value can be decoded exactly.
return String::num(num, 17 - (int)floor(log10(num)));
} else {
// Store only reliable digits (14) by default.
return String::num(num, 14 - (int)floor(log10(num)));
// Only for exactly 0. If we have approximately 0 let the user decide how much
// precision they want.
if (num == double(0)) {
return String("0.0");
}
double magnitude = log10(Math::abs(num));
int total_digits = p_full_precision ? 17 : 14;
int precision = MAX(1, total_digits - (int)Math::floor(magnitude));
return String::num(num, precision);
}
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY:

View file

@ -217,7 +217,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::INT: {
if (header & HEADER_DATA_FLAG_64) {
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
int64_t val = decode_uint64(buf);
int64_t val = int64_t(decode_uint64(buf));
r_variant = val;
if (r_len) {
(*r_len) += 8;
@ -225,7 +225,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} else {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t val = decode_uint32(buf);
int32_t val = int32_t(decode_uint32(buf));
r_variant = val;
if (r_len) {
(*r_len) += 4;
@ -1450,13 +1450,13 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (header & HEADER_DATA_FLAG_64) {
// 64 bits.
if (buf) {
encode_uint64(p_variant.operator int64_t(), buf);
encode_uint64(p_variant.operator uint64_t(), buf);
}
r_len += 8;
} else {
if (buf) {
encode_uint32(p_variant.operator int32_t(), buf);
encode_uint32(p_variant.operator uint32_t(), buf);
}
r_len += 4;

View file

@ -41,13 +41,13 @@ protected:
public:
static NetSocket *create();
enum PollType {
enum PollType : int32_t {
POLL_TYPE_IN,
POLL_TYPE_OUT,
POLL_TYPE_IN_OUT
};
enum Type {
enum Type : int32_t {
TYPE_NONE,
TYPE_TCP,
TYPE_UDP,

View file

@ -182,7 +182,7 @@ Error PCKPacker::flush(bool p_verbose) {
}
// write the index
file->store_32(files.size());
file->store_32(uint32_t(files.size()));
Ref<FileAccessEncrypted> fae;
Ref<FileAccess> fhead = file;
@ -201,7 +201,7 @@ Error PCKPacker::flush(bool p_verbose) {
int string_len = files[i].path.utf8().length();
int pad = _get_pad(4, string_len);
fhead->store_32(string_len + pad);
fhead->store_32(uint32_t(string_len + pad));
fhead->store_buffer((const uint8_t *)files[i].path.utf8().get_data(), string_len);
for (int j = 0; j < pad; j++) {
fhead->store_8(0);
@ -231,7 +231,7 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_8(0);
}
int64_t file_base = file->get_position();
uint64_t file_base = file->get_position();
file->seek(file_base_ofs);
file->store_64(file_base); // update files base
file->seek(file_base);

View file

@ -237,7 +237,7 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int
tcp_client->poll();
ERR_FAIL_COND_V_MSG(tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED, ERR_CONNECTION_ERROR, "Remote filesystem server disconnected after sending header.");
uint32_t file_count = tcp_client->get_32();
uint32_t file_count = tcp_client->get_u32();
ERR_FAIL_COND_V_MSG(tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED, ERR_CONNECTION_ERROR, "Remote filesystem server disconnected while waiting for file list");

View file

@ -911,7 +911,7 @@ void ResourceLoaderBinary::set_translation_remapped(bool p_remapped) {
static void save_ustring(Ref<FileAccess> f, const String &p_string) {
CharString utf8 = p_string.utf8();
f->store_32(utf8.length() + 1);
f->store_32(uint32_t(utf8.length() + 1));
f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
@ -1051,7 +1051,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
f->real_is_double = (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_REAL_T_IS_DOUBLE) != 0;
if (using_uids) {
uid = f->get_64();
uid = ResourceUID::ID(f->get_64());
} else {
f->get_64(); // skip over uid field
uid = ResourceUID::INVALID_ID;
@ -1084,7 +1084,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
er.type = get_unicode_string();
er.path = get_unicode_string();
if (using_uids) {
er.uid = f->get_64();
er.uid = ResourceUID::ID(f->get_64());
if (!p_keep_uuid_paths && er.uid != ResourceUID::INVALID_ID) {
if (ResourceUID::get_singleton()->has_id(er.uid)) {
// If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
@ -1477,7 +1477,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
if (using_uids) {
ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(full_path);
fw->store_64(uid);
fw->store_64(uint64_t(uid));
}
}
@ -1609,11 +1609,11 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
int64_t val = p_property;
if (val > 0x7FFFFFFF || val < -(int64_t)0x80000000) {
f->store_32(VARIANT_INT64);
f->store_64(val);
f->store_64(uint64_t(val));
} else {
f->store_32(VARIANT_INT);
f->store_32(int32_t(p_property));
f->store_32(uint32_t(p_property));
}
} break;
@ -1645,8 +1645,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
case Variant::VECTOR2I: {
f->store_32(VARIANT_VECTOR2I);
Vector2i val = p_property;
f->store_32(val.x);
f->store_32(val.y);
f->store_32(uint32_t(val.x));
f->store_32(uint32_t(val.y));
} break;
case Variant::RECT2: {
@ -1661,10 +1661,10 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
case Variant::RECT2I: {
f->store_32(VARIANT_RECT2I);
Rect2i val = p_property;
f->store_32(val.position.x);
f->store_32(val.position.y);
f->store_32(val.size.x);
f->store_32(val.size.y);
f->store_32(uint32_t(val.position.x));
f->store_32(uint32_t(val.position.y));
f->store_32(uint32_t(val.size.x));
f->store_32(uint32_t(val.size.y));
} break;
case Variant::VECTOR3: {
@ -1678,9 +1678,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
case Variant::VECTOR3I: {
f->store_32(VARIANT_VECTOR3I);
Vector3i val = p_property;
f->store_32(val.x);
f->store_32(val.y);
f->store_32(val.z);
f->store_32(uint32_t(val.x));
f->store_32(uint32_t(val.y));
f->store_32(uint32_t(val.z));
} break;
case Variant::VECTOR4: {
@ -1695,10 +1695,10 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
case Variant::VECTOR4I: {
f->store_32(VARIANT_VECTOR4I);
Vector4i val = p_property;
f->store_32(val.x);
f->store_32(val.y);
f->store_32(val.z);
f->store_32(val.w);
f->store_32(uint32_t(val.x));
f->store_32(uint32_t(val.y));
f->store_32(uint32_t(val.z));
f->store_32(uint32_t(val.w));
} break;
case Variant::PLANE: {
@ -1821,14 +1821,14 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_16(snc);
for (int i = 0; i < np.get_name_count(); i++) {
if (string_map.has(np.get_name(i))) {
f->store_32(string_map[np.get_name(i)]);
f->store_32(uint32_t(string_map[np.get_name(i)]));
} else {
save_unicode_string(f, np.get_name(i), true);
}
}
for (int i = 0; i < np.get_subname_count(); i++) {
if (string_map.has(np.get_subname(i))) {
f->store_32(string_map[np.get_subname(i)]);
f->store_32(uint32_t(string_map[np.get_subname(i)]));
} else {
save_unicode_string(f, np.get_subname(i), true);
}
@ -1839,7 +1839,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_RID);
WARN_PRINT("Can't save RIDs.");
RID val = p_property;
f->store_32(val.get_id());
f->store_32(uint32_t(val.get_id()));
} break;
case Variant::OBJECT: {
f->store_32(VARIANT_OBJECT);
@ -1851,7 +1851,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
if (!res->is_built_in()) {
f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX);
f->store_32(external_resources[res]);
f->store_32(uint32_t(external_resources[res]));
} else {
if (!resource_map.has(res)) {
f->store_32(OBJECT_EMPTY);
@ -1859,7 +1859,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
}
f->store_32(OBJECT_INTERNAL_RESOURCE);
f->store_32(resource_map[res]);
f->store_32(uint32_t(resource_map[res]));
//internal resource
}
@ -1900,7 +1900,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_BYTE_ARRAY);
Vector<uint8_t> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const uint8_t *r = arr.ptr();
f->store_buffer(r, len);
_pad_buffer(f, len);
@ -1910,10 +1910,10 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_INT32_ARRAY);
Vector<int32_t> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const int32_t *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_32(r[i]);
f->store_32(uint32_t(r[i]));
}
} break;
@ -1921,10 +1921,10 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_INT64_ARRAY);
Vector<int64_t> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const int64_t *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_64(r[i]);
f->store_64(uint64_t(r[i]));
}
} break;
@ -1932,7 +1932,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_FLOAT32_ARRAY);
Vector<float> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const float *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_float(r[i]);
@ -1943,7 +1943,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_FLOAT64_ARRAY);
Vector<double> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const double *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_double(r[i]);
@ -1954,7 +1954,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_STRING_ARRAY);
Vector<String> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const String *r = arr.ptr();
for (int i = 0; i < len; i++) {
save_unicode_string(f, r[i]);
@ -1965,7 +1965,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_VECTOR2_ARRAY);
Vector<Vector2> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const Vector2 *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_real(r[i].x);
@ -1977,7 +1977,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_VECTOR3_ARRAY);
Vector<Vector3> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const Vector3 *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_real(r[i].x);
@ -1990,7 +1990,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_COLOR_ARRAY);
Vector<Color> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const Color *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_float(r[i].r);
@ -2004,7 +2004,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(VARIANT_PACKED_VECTOR4_ARRAY);
Vector<Vector4> arr = p_property;
int len = arr.size();
f->store_32(len);
f->store_32(uint32_t(len));
const Vector4 *r = arr.ptr();
for (int i = 0; i < len; i++) {
f->store_real(r[i].x);
@ -2115,9 +2115,9 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
void ResourceFormatSaverBinaryInstance::save_unicode_string(Ref<FileAccess> p_f, const String &p_string, bool p_bit_on_len) {
CharString utf8 = p_string.utf8();
if (p_bit_on_len) {
p_f->store_32((utf8.length() + 1) | 0x80000000);
p_f->store_32(uint32_t((utf8.length() + 1) | 0x80000000));
} else {
p_f->store_32(utf8.length() + 1);
p_f->store_32(uint32_t(utf8.length() + 1));
}
p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
@ -2218,7 +2218,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
f->store_32(format_flags);
}
ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p_path, true);
f->store_64(uid);
f->store_64(uint64_t(uid));
if (!script_class.is_empty()) {
save_unicode_string(f, script_class);
}
@ -2284,7 +2284,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
}
}
f->store_32(strings.size()); //string table size
f->store_32(uint32_t(strings.size())); //string table size
for (int i = 0; i < strings.size(); i++) {
save_unicode_string(f, strings[i]);
}
@ -2304,10 +2304,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
res_path = relative_paths ? local_path.path_to_file(res_path) : res_path;
save_unicode_string(f, res_path);
ResourceUID::ID ruid = ResourceSaver::get_resource_id_for_path(save_order[i]->get_path(), false);
f->store_64(ruid);
f->store_64(uint64_t(ruid));
}
// save internal resource table
f->store_32(saved_resources.size()); //amount of internal resources
f->store_32(uint32_t(saved_resources.size())); //amount of internal resources
Vector<uint64_t> ofs_pos;
HashSet<String> used_unique_ids;
@ -2362,10 +2362,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
for (const ResourceData &rd : resources) {
ofs_table.push_back(f->get_position());
save_unicode_string(f, rd.type);
f->store_32(rd.properties.size());
f->store_32(uint32_t(rd.properties.size()));
for (const Property &p : rd.properties) {
f->store_32(p.name_idx);
f->store_32(uint32_t(p.name_idx));
write_variant(f, p.value, resource_map, external_resources, string_map, p.pi);
}
}
@ -2473,7 +2473,7 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
f->get_64(); // Skip previous UID
fw->store_32(flags);
fw->store_64(p_uid);
fw->store_64(uint64_t(p_uid));
if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
save_ustring(fw, get_ustring(f));

View file

@ -46,7 +46,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
String importer;
String group_file;
Variant metadata;
uint64_t uid = ResourceUID::INVALID_ID;
ResourceUID::ID uid = ResourceUID::INVALID_ID;
};
Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid = nullptr) const;

View file

@ -200,7 +200,7 @@ Error ResourceUID::save_to_cache() {
cache_entries = 0;
for (KeyValue<ID, Cache> &E : unique_ids) {
f->store_64(E.key);
f->store_64(uint64_t(E.key));
uint32_t s = E.value.cs.length();
f->store_32(s);
f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
@ -263,7 +263,7 @@ Error ResourceUID::update_cache() {
}
f->seek_end();
}
f->store_64(E.key);
f->store_64(uint64_t(E.key));
uint32_t s = E.value.cs.length();
f->store_32(s);
f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);

View file

@ -39,9 +39,7 @@ class ResourceUID : public Object {
GDCLASS(ResourceUID, Object)
public:
typedef int64_t ID;
enum {
INVALID_ID = -1
};
constexpr const static ID INVALID_ID = -1;
static String get_cache_file();

View file

@ -204,11 +204,13 @@ void StreamPeer::put_float(float p_val) {
void StreamPeer::put_double(double p_val) {
uint8_t buf[8];
encode_double(p_val, buf);
if (big_endian) {
uint64_t *p64 = (uint64_t *)buf;
*p64 = BSWAP64(*p64);
}
put_data(buf, 8);
}
@ -243,75 +245,87 @@ uint8_t StreamPeer::get_u8() {
int8_t StreamPeer::get_8() {
uint8_t buf[1] = {};
get_data(buf, 1);
return buf[0];
return int8_t(buf[0]);
}
uint16_t StreamPeer::get_u16() {
uint8_t buf[2];
get_data(buf, 2);
uint16_t r = decode_uint16(buf);
if (big_endian) {
r = BSWAP16(r);
}
return r;
}
int16_t StreamPeer::get_16() {
uint8_t buf[2];
get_data(buf, 2);
uint16_t r = decode_uint16(buf);
if (big_endian) {
r = BSWAP16(r);
}
return r;
return int16_t(r);
}
uint32_t StreamPeer::get_u32() {
uint8_t buf[4];
get_data(buf, 4);
uint32_t r = decode_uint32(buf);
if (big_endian) {
r = BSWAP32(r);
}
return r;
}
int32_t StreamPeer::get_32() {
uint8_t buf[4];
get_data(buf, 4);
uint32_t r = decode_uint32(buf);
if (big_endian) {
r = BSWAP32(r);
}
return r;
return int32_t(r);
}
uint64_t StreamPeer::get_u64() {
uint8_t buf[8];
get_data(buf, 8);
uint64_t r = decode_uint64(buf);
if (big_endian) {
r = BSWAP64(r);
}
return r;
}
int64_t StreamPeer::get_64() {
uint8_t buf[8];
get_data(buf, 8);
uint64_t r = decode_uint64(buf);
if (big_endian) {
r = BSWAP64(r);
}
return r;
return int64_t(r);
}
float StreamPeer::get_half() {
uint8_t buf[2];
get_data(buf, 2);
uint16_t *p16 = (uint16_t *)buf;
if (big_endian) {
uint16_t *p16 = (uint16_t *)buf;
*p16 = BSWAP16(*p16);
}
@ -344,7 +358,7 @@ double StreamPeer::get_double() {
String StreamPeer::get_string(int p_bytes) {
if (p_bytes < 0) {
p_bytes = get_u32();
p_bytes = get_32();
}
ERR_FAIL_COND_V(p_bytes < 0, String());
@ -359,7 +373,7 @@ String StreamPeer::get_string(int p_bytes) {
String StreamPeer::get_utf8_string(int p_bytes) {
if (p_bytes < 0) {
p_bytes = get_u32();
p_bytes = get_32();
}
ERR_FAIL_COND_V(p_bytes < 0, String());
@ -498,7 +512,7 @@ void StreamPeerBuffer::_bind_methods() {
}
Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) {
if (p_bytes <= 0) {
if (p_bytes <= 0 || !p_data) {
return OK;
}
@ -529,6 +543,11 @@ Error StreamPeerBuffer::get_data(uint8_t *p_buffer, int p_bytes) {
}
Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
if (!p_bytes) {
r_received = 0;
return OK;
}
if (pointer + p_bytes > data.size()) {
r_received = data.size() - pointer;
if (r_received <= 0) {

View file

@ -37,7 +37,7 @@ struct ItemPairs {
return n;
}
}
return -1;
return uint32_t(-1);
}
bool contains_pair_to(BVHHandle h) const {

View file

@ -109,9 +109,7 @@ struct BVHHandle {
template <typename T>
class BVH_IterativeInfo {
public:
enum {
ALLOCA_STACK_SIZE = 128
};
constexpr static const size_t ALLOCA_STACK_SIZE = 128;
int32_t depth = 1;
int32_t threshold = ALLOCA_STACK_SIZE - 2;

View file

@ -147,7 +147,7 @@ struct [[nodiscard]] Color {
// of the mantissa, rounding the truncated bits.
union {
float f;
int32_t i;
uint32_t i;
} R, G, B, E;
E.f = MaxChannel;
@ -168,7 +168,7 @@ struct [[nodiscard]] Color {
// Combine the fields. RGB floats have unwanted data in the upper 9
// bits. Only red needs to mask them off because green and blue shift
// it out to the left.
return E.i | (B.i << 18) | (G.i << 9) | (R.i & 511);
return E.i | (B.i << 18U) | (G.i << 9U) | (R.i & 511U);
}
_FORCE_INLINE_ Color blend(const Color &p_over) const {

View file

@ -80,5 +80,5 @@ int RandomPCG::random(int p_from, int p_to) {
if (p_from == p_to) {
return p_from;
}
return rand(abs(p_from - p_to) + 1) + MIN(p_from, p_to);
return int(rand(uint32_t(Math::abs(p_from - p_to)) + 1U)) + MIN(p_from, p_to);
}

View file

@ -454,7 +454,7 @@ uint32_t ClassDB::get_api_hash(APIType p_api) {
for (const StringName &F : snames) {
hash = hash_murmur3_one_64(F.hash(), hash);
hash = hash_murmur3_one_64(t->constant_map[F], hash);
hash = hash_murmur3_one_64(uint64_t(t->constant_map[F]), hash);
}
}

View file

@ -46,7 +46,7 @@ public:
_ALWAYS_INLINE_ bool is_valid() const { return id != 0; }
_ALWAYS_INLINE_ bool is_null() const { return id == 0; }
_ALWAYS_INLINE_ operator uint64_t() const { return id; }
_ALWAYS_INLINE_ operator int64_t() const { return id; }
_ALWAYS_INLINE_ operator int64_t() const { return (int64_t)id; }
_ALWAYS_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
_ALWAYS_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }

View file

@ -87,7 +87,9 @@ void *Memory::realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_pr
}
void *ret = alloc_aligned_static(p_bytes, p_alignment);
memcpy(ret, p_memory, p_prev_bytes);
if (ret) {
memcpy(ret, p_memory, p_prev_bytes);
}
free_aligned_static(p_memory);
return ret;
}

View file

@ -118,7 +118,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const c
template <int SHORT_BUFFER_SIZE>
StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::reserve(int p_size) {
if (p_size < SHORT_BUFFER_SIZE || p_size < buffer.size()) {
if (p_size < SHORT_BUFFER_SIZE || p_size < buffer.size() || !p_size) {
return *this;
}

View file

@ -42,10 +42,6 @@
#include "core/variant/variant.h"
#include "core/version_generated.gen.h"
#include <stdio.h>
#include <stdlib.h>
#include <cstdint>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS // to disable build-time warning which suggested to use strcpy_s instead strcpy
#endif
@ -1804,6 +1800,10 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
}
String String::num_real(double p_num, bool p_trailing) {
if (Math::is_nan(p_num) || Math::is_inf(p_num)) {
return num(p_num, 0);
}
if (p_num == (double)(int64_t)p_num) {
if (p_trailing) {
return num_int64((int64_t)p_num) + ".0";
@ -1811,6 +1811,7 @@ String String::num_real(double p_num, bool p_trailing) {
return num_int64((int64_t)p_num);
}
}
int decimals = 14;
// We want to align the digits to the above sane default, so we only need
// to subtract log10 for numbers with a positive power of ten magnitude.
@ -1818,10 +1819,15 @@ String String::num_real(double p_num, bool p_trailing) {
if (abs_num > 10) {
decimals -= (int)floor(log10(abs_num));
}
return num(p_num, decimals);
}
String String::num_real(float p_num, bool p_trailing) {
if (Math::is_nan(p_num) || Math::is_inf(p_num)) {
return num(p_num, 0);
}
if (p_num == (float)(int64_t)p_num) {
if (p_trailing) {
return num_int64((int64_t)p_num) + ".0";
@ -1840,16 +1846,8 @@ String String::num_real(float p_num, bool p_trailing) {
}
String String::num_scientific(double p_num) {
if (Math::is_nan(p_num)) {
return "nan";
}
if (Math::is_inf(p_num)) {
if (signbit(p_num)) {
return "-inf";
} else {
return "inf";
}
if (Math::is_nan(p_num) || Math::is_inf(p_num)) {
return num(p_num, 0);
}
char buf[256];
@ -1947,7 +1945,7 @@ CharString String::ascii(bool p_allow_extended) const {
for (int i = 0; i < size(); i++) {
char32_t c = this_ptr[i];
if ((c <= 0x7f) || (c <= 0xff && p_allow_extended)) {
cs_ptrw[i] = c;
cs_ptrw[i] = char(c);
} else {
print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as ASCII/Latin-1", (uint32_t)c));
cs_ptrw[i] = 0x20; // ASCII doesn't have a replacement character like unicode, 0x1a is sometimes used but is kinda arcane.
@ -2487,6 +2485,42 @@ int64_t String::bin_to_int() const {
return binary * sign;
}
template <typename C, typename T>
_ALWAYS_INLINE_ int64_t _to_int(const T &p_in, int to) {
// Accumulate the total number in an unsigned integer as the range is:
// +9223372036854775807 to -9223372036854775808 and the smallest negative
// number does not fit inside an int64_t. So we accumulate the positive
// number in an unsigned, and then at the very end convert to its signed
// form.
uint64_t integer = 0;
uint8_t digits = 0;
bool positive = true;
for (int i = 0; i < to; i++) {
C c = p_in[i];
if (is_digit(c)) {
// No need to do expensive checks unless we're approaching INT64_MAX / INT64_MIN.
if (unlikely(digits > 18)) {
bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((positive && c > '7') || (!positive && c > '8')));
ERR_FAIL_COND_V_MSG(overflow, positive ? INT64_MAX : INT64_MIN, "Cannot represent " + String(p_in) + " as a 64-bit signed integer, since the value is " + (positive ? "too large." : "too small."));
}
integer *= 10;
integer += c - '0';
++digits;
} else if (integer == 0 && c == '-') {
positive = !positive;
}
}
if (positive) {
return int64_t(integer);
} else {
return int64_t(integer * uint64_t(-1));
}
}
int64_t String::to_int() const {
if (length() == 0) {
return 0;
@ -2494,23 +2528,7 @@ int64_t String::to_int() const {
int to = (find_char('.') >= 0) ? find_char('.') : length();
int64_t integer = 0;
int64_t sign = 1;
for (int i = 0; i < to; i++) {
char32_t c = operator[](i);
if (is_digit(c)) {
bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as a 64-bit signed integer, since the value is " + (sign == 1 ? "too large." : "too small."));
integer *= 10;
integer += c - '0';
} else if (integer == 0 && c == '-') {
sign = -sign;
}
}
return integer * sign;
return _to_int<char32_t>(*this, to);
}
int64_t String::to_int(const char *p_str, int p_len) {
@ -2523,25 +2541,7 @@ int64_t String::to_int(const char *p_str, int p_len) {
}
}
int64_t integer = 0;
int64_t sign = 1;
for (int i = 0; i < to; i++) {
char c = p_str[i];
if (is_digit(c)) {
bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as a 64-bit signed integer, since the value is " + (sign == 1 ? "too large." : "too small."));
integer *= 10;
integer += c - '0';
} else if (c == '-' && integer == 0) {
sign = -sign;
} else if (c != ' ') {
break;
}
}
return integer * sign;
return _to_int<char>(p_str, to);
}
int64_t String::to_int(const wchar_t *p_str, int p_len) {
@ -2554,25 +2554,7 @@ int64_t String::to_int(const wchar_t *p_str, int p_len) {
}
}
int64_t integer = 0;
int64_t sign = 1;
for (int i = 0; i < to; i++) {
wchar_t c = p_str[i];
if (is_digit(c)) {
bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as a 64-bit signed integer, since the value is " + (sign == 1 ? "too large." : "too small."));
integer *= 10;
integer += c - '0';
} else if (c == '-' && integer == 0) {
sign = -sign;
} else if (c != ' ') {
break;
}
}
return integer * sign;
return _to_int<wchar_t>(p_str, to);
}
bool String::is_numeric() const {
@ -3969,7 +3951,7 @@ static String _replace_common(const String &p_this, const String &p_key, const S
return p_this;
}
const int key_length = p_key.length();
const size_t key_length = p_key.length();
int search_from = 0;
int result = 0;
@ -3978,6 +3960,7 @@ static String _replace_common(const String &p_this, const String &p_key, const S
while ((result = (p_case_insensitive ? p_this.findn(p_key, search_from) : p_this.find(p_key, search_from))) >= 0) {
found.push_back(result);
ERR_FAIL_COND_V_MSG((result + key_length) > INT32_MAX, p_this, "Key length too long");
search_from = result + key_length;
}
@ -3990,7 +3973,7 @@ static String _replace_common(const String &p_this, const String &p_key, const S
const int with_length = p_with.length();
const int old_length = p_this.length();
new_string.resize(old_length + found.size() * (with_length - key_length) + 1);
new_string.resize(old_length + int(found.size()) * (with_length - key_length) + 1);
char32_t *new_ptrw = new_string.ptrw();
const char32_t *old_ptr = p_this.ptr();
@ -4021,7 +4004,7 @@ static String _replace_common(const String &p_this, const String &p_key, const S
}
static String _replace_common(const String &p_this, char const *p_key, char const *p_with, bool p_case_insensitive) {
int key_length = strlen(p_key);
size_t key_length = strlen(p_key);
if (key_length == 0 || p_this.is_empty()) {
return p_this;
@ -4034,6 +4017,7 @@ static String _replace_common(const String &p_this, char const *p_key, char cons
while ((result = (p_case_insensitive ? p_this.findn(p_key, search_from) : p_this.find(p_key, search_from))) >= 0) {
found.push_back(result);
ERR_FAIL_COND_V_MSG((result + key_length) > INT32_MAX, p_this, "Key length too long");
search_from = result + key_length;
}
@ -4048,7 +4032,7 @@ static String _replace_common(const String &p_this, char const *p_key, char cons
const int with_length = with_string.length();
const int old_length = p_this.length();
new_string.resize(old_length + found.size() * (with_length - key_length) + 1);
new_string.resize(old_length + int(found.size()) * (with_length - key_length) + 1);
char32_t *new_ptrw = new_string.ptrw();
const char32_t *old_ptr = p_this.ptr();
@ -4639,8 +4623,9 @@ bool String::is_valid_string() const {
String String::uri_encode() const {
const CharString temp = utf8();
String res;
for (int i = 0; i < temp.length(); ++i) {
uint8_t ord = temp[i];
uint8_t ord = uint8_t(temp[i]);
if (ord == '.' || ord == '-' || ord == '~' || is_ascii_identifier_char(ord)) {
res += ord;
} else {

View file

@ -339,7 +339,9 @@ class CommandQueueMT {
template <typename T>
T *allocate() {
// alloc size is size+T+safeguard
uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1));
static_assert(sizeof(T) < UINT32_MAX, "Type too large to fit in the command queue.");
uint32_t alloc_size = ((sizeof(T) + 8U - 1U) & ~(8U - 1U));
uint64_t size = command_mem.size();
command_mem.resize(size + alloc_size + 8);
*(uint64_t *)&command_mem[size] = alloc_size;

View file

@ -323,9 +323,9 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); }
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); }
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.get_data()); }
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
@ -333,31 +333,31 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); }
static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); }
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) {
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) {
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
h = hash_murmur3_one_32(p_vec.z, h);
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
h = hash_murmur3_one_32(uint32_t(p_vec.z), h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) {
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
h = hash_murmur3_one_32(p_vec.z, h);
h = hash_murmur3_one_32(p_vec.w, h);
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
h = hash_murmur3_one_32(uint32_t(p_vec.z), h);
h = hash_murmur3_one_32(uint32_t(p_vec.w), h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
@ -379,10 +379,10 @@ struct HashMapHasherDefault {
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
uint32_t h = hash_murmur3_one_32(p_rect.position.x);
h = hash_murmur3_one_32(p_rect.position.y, h);
h = hash_murmur3_one_32(p_rect.size.x, h);
h = hash_murmur3_one_32(p_rect.size.y, h);
uint32_t h = hash_murmur3_one_32(uint32_t(p_rect.position.x));
h = hash_murmur3_one_32(uint32_t(p_rect.position.y), h);
h = hash_murmur3_one_32(uint32_t(p_rect.size.x), h);
h = hash_murmur3_one_32(uint32_t(p_rect.size.y), h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) {

View file

@ -297,7 +297,9 @@ public:
Vector<T> ret;
ret.resize(size());
T *w = ret.ptrw();
memcpy(w, data, sizeof(T) * count);
if (w) {
memcpy(w, data, sizeof(T) * count);
}
return ret;
}
@ -305,7 +307,9 @@ public:
Vector<uint8_t> ret;
ret.resize(count * sizeof(T));
uint8_t *w = ret.ptrw();
memcpy(w, data, sizeof(T) * count);
if (w) {
memcpy(w, data, sizeof(T) * count);
}
return ret;
}

View file

@ -156,8 +156,11 @@ public:
if (is_empty()) {
return ret;
}
ret.resize(size() * sizeof(T));
memcpy(ret.ptrw(), ptr(), sizeof(T) * size());
size_t alloc_size = size() * sizeof(T);
ret.resize(alloc_size);
if (alloc_size) {
memcpy(ret.ptrw(), ptr(), alloc_size);
}
return ret;
}

View file

@ -1494,11 +1494,11 @@ Variant::operator int64_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return int64_t(_data._int);
case FLOAT:
return _data._float;
return int64_t(_data._float);
case STRING:
return operator String().to_int();
return int64_t(operator String().to_int());
default: {
return 0;
}
@ -1512,11 +1512,11 @@ Variant::operator int32_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return int32_t(_data._int);
case FLOAT:
return _data._float;
return int32_t(_data._float);
case STRING:
return operator String().to_int();
return int32_t(operator String().to_int());
default: {
return 0;
}
@ -1530,11 +1530,11 @@ Variant::operator int16_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return int16_t(_data._int);
case FLOAT:
return _data._float;
return int16_t(_data._float);
case STRING:
return operator String().to_int();
return int16_t(operator String().to_int());
default: {
return 0;
}
@ -1548,11 +1548,11 @@ Variant::operator int8_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return int8_t(_data._int);
case FLOAT:
return _data._float;
return int8_t(_data._float);
case STRING:
return operator String().to_int();
return int8_t(operator String().to_int());
default: {
return 0;
}
@ -1566,11 +1566,11 @@ Variant::operator uint64_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return uint64_t(_data._int);
case FLOAT:
return _data._float;
return uint64_t(_data._float);
case STRING:
return operator String().to_int();
return uint64_t(operator String().to_int());
default: {
return 0;
}
@ -1584,11 +1584,11 @@ Variant::operator uint32_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return uint32_t(_data._int);
case FLOAT:
return _data._float;
return uint32_t(_data._float);
case STRING:
return operator String().to_int();
return uint32_t(operator String().to_int());
default: {
return 0;
}
@ -1602,11 +1602,11 @@ Variant::operator uint16_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return uint16_t(_data._int);
case FLOAT:
return _data._float;
return uint16_t(_data._float);
case STRING:
return operator String().to_int();
return uint16_t(operator String().to_int());
default: {
return 0;
}
@ -1620,11 +1620,11 @@ Variant::operator uint8_t() const {
case BOOL:
return _data._bool ? 1 : 0;
case INT:
return _data._int;
return uint8_t(_data._int);
case FLOAT:
return _data._float;
return uint8_t(_data._float);
case STRING:
return operator String().to_int();
return uint8_t(operator String().to_int());
default: {
return 0;
}
@ -2484,22 +2484,22 @@ Variant::Variant(int8_t p_int8) :
Variant::Variant(uint64_t p_uint64) :
type(INT) {
_data._int = p_uint64;
_data._int = int64_t(p_uint64);
}
Variant::Variant(uint32_t p_uint32) :
type(INT) {
_data._int = p_uint32;
_data._int = int64_t(p_uint32);
}
Variant::Variant(uint16_t p_uint16) :
type(INT) {
_data._int = p_uint16;
_data._int = int64_t(p_uint16);
}
Variant::Variant(uint8_t p_uint8) :
type(INT) {
_data._int = p_uint8;
_data._int = int64_t(p_uint8);
}
Variant::Variant(float p_float) :
@ -2514,7 +2514,7 @@ Variant::Variant(double p_double) :
Variant::Variant(const ObjectID &p_id) :
type(INT) {
_data._int = p_id;
_data._int = int64_t(p_id);
}
Variant::Variant(const StringName &p_string) :

View file

@ -99,6 +99,7 @@ bool VariantParser::StreamString::_is_eof() const {
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);
ERR_FAIL_NULL_V(p_buffer, 0);
int available = MAX(s.length() - pos, 0);
if (available >= (int)p_num_chars) {

View file

@ -232,6 +232,91 @@ TEST_CASE("[JSON] Parsing escape sequences") {
ERR_PRINT_ON
}
}
TEST_CASE("[JSON] Serialization") {
JSON json;
struct FpTestCase {
double number;
String json;
};
struct IntTestCase {
int64_t number;
String json;
};
struct UIntTestCase {
uint64_t number;
String json;
};
static FpTestCase fp_tests_default_precision[] = {
{ 0.0, "0.0" },
{ 1000.1234567890123456789, "1000.12345678901" },
{ -1000.1234567890123456789, "-1000.12345678901" },
{ DBL_MAX, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" },
{ DBL_MAX - 1, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" },
{ pow(2, 53), "9007199254740992.0" },
{ -pow(2, 53), "-9007199254740992.0" },
{ 0.00000000000000011, "0.00000000000000011" },
{ -0.00000000000000011, "-0.00000000000000011" },
{ 1.0 / 3.0, "0.333333333333333" },
{ 0.9999999999999999, "1.0" },
{ 1.0000000000000001, "1.0" },
};
static FpTestCase fp_tests_full_precision[] = {
{ 0.0, "0.0" },
{ 1000.1234567890123456789, "1000.12345678901238" },
{ -1000.1234567890123456789, "-1000.12345678901238" },
{ DBL_MAX, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" },
{ DBL_MAX - 1, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" },
{ pow(2, 53), "9007199254740992.0" },
{ -pow(2, 53), "-9007199254740992.0" },
{ 0.00000000000000011, "0.00000000000000011" },
{ -0.00000000000000011, "-0.00000000000000011" },
{ 1.0 / 3.0, "0.333333333333333315" },
{ 0.9999999999999999, "0.999999999999999889" },
{ 1.0000000000000001, "1.0" },
};
static IntTestCase int_tests[] = {
{ 0, "0" },
{ INT64_MAX, "9223372036854775807" },
{ INT64_MIN, "-9223372036854775808" },
};
SUBCASE("Floating point default precision") {
for (FpTestCase &test : fp_tests_default_precision) {
String json_value = json.stringify(test.number, "", true, false);
CHECK_MESSAGE(
json_value == test.json,
vformat("Serializing `%.20d` to JSON should return the expected value.", test.number));
}
}
SUBCASE("Floating point full precision") {
for (FpTestCase &test : fp_tests_full_precision) {
String json_value = json.stringify(test.number, "", true, true);
CHECK_MESSAGE(
json_value == test.json,
vformat("Serializing `%20f` to JSON should return the expected value.", test.number));
}
}
SUBCASE("Signed integer") {
for (IntTestCase &test : int_tests) {
String json_value = json.stringify(test.number, "", true, true);
CHECK_MESSAGE(
json_value == test.json,
vformat("Serializing `%d` to JSON should return the expected value.", test.number));
}
}
}
} // namespace TestJSON
#endif // TEST_JSON_H