From bd98aad3fa5385d1bbac4ff8f1ed23463e842849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Wed, 9 Apr 2025 09:58:29 +0300 Subject: [PATCH] Remove misleading and incorrect notes about endianness. Fix FileAccess and StreamPeer not doing what name suggests. --- core/io/file_access.cpp | 36 +++++++++ core/io/file_access.h | 4 + core/io/resource_format_binary.cpp | 18 ++--- core/io/stream_peer.cpp | 113 +++++++++++++++++++++++++++++ core/io/stream_peer.h | 4 + doc/classes/FileAccess.xml | 3 +- doc/classes/PackedByteArray.xml | 4 +- 7 files changed, 166 insertions(+), 16 deletions(-) diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index ac4ebfdd8b8..5141032bddf 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -313,9 +313,15 @@ uint16_t FileAccess::get_16() const { uint16_t data = 0; get_buffer(reinterpret_cast(&data), sizeof(uint16_t)); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + data = BSWAP16(data); + } +#else if (big_endian) { data = BSWAP16(data); } +#endif return data; } @@ -324,9 +330,15 @@ uint32_t FileAccess::get_32() const { uint32_t data = 0; get_buffer(reinterpret_cast(&data), sizeof(uint32_t)); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + data = BSWAP32(data); + } +#else if (big_endian) { data = BSWAP32(data); } +#endif return data; } @@ -335,9 +347,15 @@ uint64_t FileAccess::get_64() const { uint64_t data = 0; get_buffer(reinterpret_cast(&data), sizeof(uint64_t)); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + data = BSWAP64(data); + } +#else if (big_endian) { data = BSWAP64(data); } +#endif return data; } @@ -574,25 +592,43 @@ bool FileAccess::store_8(uint8_t p_dest) { } bool FileAccess::store_16(uint16_t p_dest) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_dest = BSWAP16(p_dest); + } +#else if (big_endian) { p_dest = BSWAP16(p_dest); } +#endif return store_buffer(reinterpret_cast(&p_dest), sizeof(uint16_t)); } bool FileAccess::store_32(uint32_t p_dest) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_dest = BSWAP32(p_dest); + } +#else if (big_endian) { p_dest = BSWAP32(p_dest); } +#endif return store_buffer(reinterpret_cast(&p_dest), sizeof(uint32_t)); } bool FileAccess::store_64(uint64_t p_dest) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_dest = BSWAP64(p_dest); + } +#else if (big_endian) { p_dest = BSWAP64(p_dest); } +#endif return store_buffer(reinterpret_cast(&p_dest), sizeof(uint64_t)); } diff --git a/core/io/file_access.h b/core/io/file_access.h index 0a7244dfe1e..1947da853da 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -86,7 +86,11 @@ public: typedef void (*FileCloseFailNotify)(const String &); typedef Ref (*CreateFunc)(); +#ifdef BIG_ENDIAN_ENABLED + bool big_endian = true; +#else bool big_endian = false; +#endif bool real_is_double = false; virtual BitField _get_unix_permissions(const String &p_file) = 0; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index ef5e600c314..98511f02bb5 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1342,13 +1342,10 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons bool use_real64 = f->get_32(); f->set_big_endian(big_endian != 0); //read big endian if saved as big endian -#ifdef BIG_ENDIAN_ENABLED - fw->store_32(!big_endian); -#else + fw->store_32(big_endian); -#endif - fw->set_big_endian(big_endian != 0); fw->store_32(use_real64); //use real64 + fw->set_big_endian(big_endian != 0); uint32_t ver_major = f->get_32(); uint32_t ver_minor = f->get_32(); @@ -2168,12 +2165,12 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Refstore_32(1); - f->set_big_endian(true); } else { f->store_32(0); } - f->store_32(0); //64 bits file, false for now + f->set_big_endian(big_endian); + f->store_32(GODOT_VERSION_MAJOR); f->store_32(GODOT_VERSION_MINOR); f->store_32(FORMAT_VERSION); @@ -2412,13 +2409,10 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU big_endian = f->get_32(); bool use_real64 = f->get_32(); f->set_big_endian(big_endian != 0); //read big endian if saved as big endian -#ifdef BIG_ENDIAN_ENABLED - fw->store_32(!big_endian); -#else + fw->store_32(big_endian); -#endif - fw->set_big_endian(big_endian != 0); fw->store_32(use_real64); //use real64 + fw->set_big_endian(big_endian != 0); uint32_t ver_major = f->get_32(); uint32_t ver_minor = f->get_32(); diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index dab446af3fa..2f2c1d3086f 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -125,54 +125,90 @@ void StreamPeer::put_8(int8_t p_val) { } void StreamPeer::put_u16(uint16_t p_val) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_val = BSWAP16(p_val); + } +#else if (big_endian) { p_val = BSWAP16(p_val); } +#endif uint8_t buf[2]; encode_uint16(p_val, buf); put_data(buf, 2); } void StreamPeer::put_16(int16_t p_val) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_val = BSWAP16(p_val); + } +#else if (big_endian) { p_val = BSWAP16(p_val); } +#endif uint8_t buf[2]; encode_uint16(p_val, buf); put_data(buf, 2); } void StreamPeer::put_u32(uint32_t p_val) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_val = BSWAP32(p_val); + } +#else if (big_endian) { p_val = BSWAP32(p_val); } +#endif uint8_t buf[4]; encode_uint32(p_val, buf); put_data(buf, 4); } void StreamPeer::put_32(int32_t p_val) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_val = BSWAP32(p_val); + } +#else if (big_endian) { p_val = BSWAP32(p_val); } +#endif uint8_t buf[4]; encode_uint32(p_val, buf); put_data(buf, 4); } void StreamPeer::put_u64(uint64_t p_val) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_val = BSWAP64(p_val); + } +#else if (big_endian) { p_val = BSWAP64(p_val); } +#endif uint8_t buf[8]; encode_uint64(p_val, buf); put_data(buf, 8); } void StreamPeer::put_64(int64_t p_val) { +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + p_val = BSWAP64(p_val); + } +#else if (big_endian) { p_val = BSWAP64(p_val); } +#endif uint8_t buf[8]; encode_uint64(p_val, buf); put_data(buf, 8); @@ -183,9 +219,15 @@ void StreamPeer::put_half(float p_val) { encode_half(p_val, buf); uint16_t *p16 = (uint16_t *)buf; +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + *p16 = BSWAP16(*p16); + } +#else if (big_endian) { *p16 = BSWAP16(*p16); } +#endif put_data(buf, 2); } @@ -194,10 +236,17 @@ void StreamPeer::put_float(float p_val) { uint8_t buf[4]; encode_float(p_val, buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + uint32_t *p32 = (uint32_t *)buf; + *p32 = BSWAP32(*p32); + } +#else if (big_endian) { uint32_t *p32 = (uint32_t *)buf; *p32 = BSWAP32(*p32); } +#endif put_data(buf, 4); } @@ -206,10 +255,17 @@ void StreamPeer::put_double(double p_val) { uint8_t buf[8]; encode_double(p_val, buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + uint64_t *p64 = (uint64_t *)buf; + *p64 = BSWAP64(*p64); + } +#else if (big_endian) { uint64_t *p64 = (uint64_t *)buf; *p64 = BSWAP64(*p64); } +#endif put_data(buf, 8); } @@ -253,9 +309,15 @@ uint16_t StreamPeer::get_u16() { get_data(buf, 2); uint16_t r = decode_uint16(buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + r = BSWAP16(r); + } +#else if (big_endian) { r = BSWAP16(r); } +#endif return r; } @@ -265,9 +327,15 @@ int16_t StreamPeer::get_16() { get_data(buf, 2); uint16_t r = decode_uint16(buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + r = BSWAP16(r); + } +#else if (big_endian) { r = BSWAP16(r); } +#endif return int16_t(r); } @@ -277,9 +345,15 @@ uint32_t StreamPeer::get_u32() { get_data(buf, 4); uint32_t r = decode_uint32(buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + r = BSWAP32(r); + } +#else if (big_endian) { r = BSWAP32(r); } +#endif return r; } @@ -289,9 +363,15 @@ int32_t StreamPeer::get_32() { get_data(buf, 4); uint32_t r = decode_uint32(buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + r = BSWAP32(r); + } +#else if (big_endian) { r = BSWAP32(r); } +#endif return int32_t(r); } @@ -301,9 +381,15 @@ uint64_t StreamPeer::get_u64() { get_data(buf, 8); uint64_t r = decode_uint64(buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + r = BSWAP64(r); + } +#else if (big_endian) { r = BSWAP64(r); } +#endif return r; } @@ -313,9 +399,15 @@ int64_t StreamPeer::get_64() { get_data(buf, 8); uint64_t r = decode_uint64(buf); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + r = BSWAP64(r); + } +#else if (big_endian) { r = BSWAP64(r); } +#endif return int64_t(r); } @@ -324,10 +416,17 @@ float StreamPeer::get_half() { uint8_t buf[2]; get_data(buf, 2); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + uint16_t *p16 = (uint16_t *)buf; + *p16 = BSWAP16(*p16); + } +#else if (big_endian) { uint16_t *p16 = (uint16_t *)buf; *p16 = BSWAP16(*p16); } +#endif return decode_half(buf); } @@ -336,10 +435,17 @@ float StreamPeer::get_float() { uint8_t buf[4]; get_data(buf, 4); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + uint32_t *p32 = (uint32_t *)buf; + *p32 = BSWAP32(*p32); + } +#else if (big_endian) { uint32_t *p32 = (uint32_t *)buf; *p32 = BSWAP32(*p32); } +#endif return decode_float(buf); } @@ -348,10 +454,17 @@ double StreamPeer::get_double() { uint8_t buf[8]; get_data(buf, 8); +#ifdef BIG_ENDIAN_ENABLED + if (!big_endian) { + uint64_t *p64 = (uint64_t *)buf; + *p64 = BSWAP64(*p64); + } +#else if (big_endian) { uint64_t *p64 = (uint64_t *)buf; *p64 = BSWAP64(*p64); } +#endif return decode_double(buf); } diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 0bda96d0961..a73e92d248b 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -49,7 +49,11 @@ protected: Array _get_data(int p_bytes); Array _get_partial_data(int p_bytes); +#ifdef BIG_ENDIAN_ENABLED + bool big_endian = true; +#else bool big_endian = false; +#endif public: virtual Error put_data(const uint8_t *p_data, int p_bytes) = 0; ///< put a whole chunk of data, blocking until it sent diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml index f94645b5e09..25bf45e6060 100644 --- a/doc/classes/FileAccess.xml +++ b/doc/classes/FileAccess.xml @@ -569,8 +569,7 @@ If [code]true[/code], the file is read with big-endian [url=https://en.wikipedia.org/wiki/Endianness]endianness[/url]. If [code]false[/code], the file is read with little-endian endianness. If in doubt, leave this to [code]false[/code] as most files are written with little-endian endianness. - [b]Note:[/b] [member big_endian] is only about the file format, not the CPU type. The CPU endianness doesn't affect the default endianness for files written. - [b]Note:[/b] This is always reset to [code]false[/code] whenever you open the file. Therefore, you must set [member big_endian] [i]after[/i] opening the file, not before. + [b]Note:[/b] This is always reset to system endianness, which is little-endian on all supported platforms, whenever you open the file. Therefore, you must set [member big_endian] [i]after[/i] opening the file, not before. diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 5a0ba4ce082..bf5e9e399bd 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -346,13 +346,13 @@ - Converts UTF-16 encoded array to [String]. If the BOM is missing, system endianness is assumed. Returns empty string if source array is not valid UTF-16 string. This is the inverse of [method String.to_utf16_buffer]. + Converts UTF-16 encoded array to [String]. If the BOM is missing, little-endianness is assumed. Returns empty string if source array is not valid UTF-16 string. This is the inverse of [method String.to_utf16_buffer]. - Converts UTF-32 encoded array to [String]. System endianness is assumed. Returns empty string if source array is not valid UTF-32 string. This is the inverse of [method String.to_utf32_buffer]. + Converts UTF-32 encoded array to [String]. Returns empty string if source array is not valid UTF-32 string. This is the inverse of [method String.to_utf32_buffer].