From e68b158a52ae9b9eee8b0ca36dd157a4e17ed64c Mon Sep 17 00:00:00 2001 From: asynts Date: Fri, 28 Aug 2020 18:24:00 +0200 Subject: [PATCH] AK: Don't swap endianness when writing endian wrappers to stream. --- AK/Endian.h | 25 ++++++++++++++++++++++++ AK/Stream.h | 43 ++++++++++++++++------------------------- AK/Tests/TestStream.cpp | 13 +++++++++++++ 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/AK/Endian.h b/AK/Endian.h index e5265a5148..a93e79eb25 100644 --- a/AK/Endian.h +++ b/AK/Endian.h @@ -26,6 +26,7 @@ #pragma once +#include #include namespace AK { @@ -70,10 +71,22 @@ ALWAYS_INLINE T convert_between_host_and_network_endian(T value) return convert_between_host_and_big_endian(value); } +template +class LittleEndian; + +template +InputStream& operator>>(InputStream&, LittleEndian&); + +template +OutputStream& operator<<(OutputStream&, LittleEndian); + template class [[gnu::packed]] LittleEndian { public: + friend InputStream& operator>>(InputStream&, LittleEndian&); + friend OutputStream& operator<<(OutputStream&, LittleEndian); + LittleEndian() { } LittleEndian(T value) @@ -87,10 +100,22 @@ private: T m_value { 0 }; }; +template +class BigEndian; + +template +InputStream& operator>>(InputStream&, BigEndian&); + +template +OutputStream& operator<<(OutputStream&, BigEndian); + template class [[gnu::packed]] BigEndian { public: + friend InputStream& operator>>(InputStream&, BigEndian&); + friend OutputStream& operator<<(OutputStream&, BigEndian); + BigEndian() { } BigEndian(T value) diff --git a/AK/Stream.h b/AK/Stream.h index 10807407d8..a769e7f432 100644 --- a/AK/Stream.h +++ b/AK/Stream.h @@ -76,33 +76,36 @@ class DuplexStream , public OutputStream { }; +inline InputStream& operator>>(InputStream& stream, Bytes bytes) +{ + stream.read_or_error(bytes); + return stream; +} +inline OutputStream& operator<<(OutputStream& stream, ReadonlyBytes bytes) +{ + stream.write_or_error(bytes); + return stream; +} + template InputStream& operator>>(InputStream& stream, LittleEndian& value) { - T temporary; - stream >> temporary; - value = temporary; - return stream; + return stream >> Bytes { &value.m_value, sizeof(value.m_value) }; } template -InputStream& operator<<(InputStream& stream, LittleEndian value) +OutputStream& operator<<(OutputStream& stream, LittleEndian value) { - stream << static_cast(value); - return stream; + return stream << ReadonlyBytes { &value.m_value, sizeof(value.m_value) }; } template InputStream& operator>>(InputStream& stream, BigEndian& value) { - T temporary; - stream >> temporary; - value = temporary; - return stream; + return stream >> Bytes { &value.m_value, sizeof(value.m_value) }; } template -InputStream& operator<<(InputStream& stream, BigEndian value) +OutputStream& operator<<(OutputStream& stream, BigEndian value) { - stream << static_cast(value); - return stream; + return stream << ReadonlyBytes { &value.m_value, sizeof(value.m_value) }; } template @@ -177,18 +180,6 @@ inline OutputStream& operator<<(OutputStream& stream, bool value) return stream; } -inline InputStream& operator>>(InputStream& stream, Bytes bytes) -{ - stream.read_or_error(bytes); - return stream; -} - -inline OutputStream& operator<<(OutputStream& stream, ReadonlyBytes bytes) -{ - stream.write_or_error(bytes); - return stream; -} - class InputMemoryStream final : public InputStream { friend InputMemoryStream& operator>>(InputMemoryStream& stream, String& string); diff --git a/AK/Tests/TestStream.cpp b/AK/Tests/TestStream.cpp index aa547d3caa..5a1e6681d1 100644 --- a/AK/Tests/TestStream.cpp +++ b/AK/Tests/TestStream.cpp @@ -181,4 +181,17 @@ TEST_CASE(duplex_wild_seeking) EXPECT(stream.eof()); } +TEST_CASE(read_endian_values) +{ + const u8 input[] { 0, 1, 2, 3, 4, 5, 6, 7 }; + InputMemoryStream stream { { input, sizeof(input) } }; + + LittleEndian value1; + BigEndian value2; + stream >> value1 >> value2; + + EXPECT_EQ(value1, 0x03020100u); + EXPECT_EQ(value2, 0x04050607u); +} + TEST_MAIN(Stream)