From 48260b50542f8c294cccc84d41803bd8d3568142 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Tue, 27 Apr 2021 00:09:02 +0430 Subject: [PATCH] AK: Move the LEB128 logic to AK and make it usable with InputStream --- AK/LEB128.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++ AK/MemoryStream.h | 54 ++---------------------------- 2 files changed, 88 insertions(+), 51 deletions(-) create mode 100644 AK/LEB128.h diff --git a/AK/LEB128.h b/AK/LEB128.h new file mode 100644 index 0000000000..653d38a24e --- /dev/null +++ b/AK/LEB128.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020-2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace AK { + +struct LEB128 { + template + static bool read_unsigned(StreamT& stream, size_t& result) + { + [[maybe_unused]] size_t backup_offset = 0; + if constexpr (requires { stream.offset(); }) + backup_offset = stream.offset(); + InputStream& input_stream { stream }; + + result = 0; + size_t num_bytes = 0; + while (true) { + if (input_stream.unreliable_eof()) { + if constexpr (requires { stream.seek(backup_offset); }) + stream.seek(backup_offset); + input_stream.set_fatal_error(); + return false; + } + + u8 byte = 0; + input_stream >> byte; + if (input_stream.has_any_error()) + return false; + + result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); + if (!(byte & (1 << 7))) + break; + ++num_bytes; + } + + return true; + } + + template + static bool read_signed(StreamT& stream, ssize_t& result) + { + [[maybe_unused]] size_t backup_offset = 0; + if constexpr (requires { stream.offset(); }) + backup_offset = stream.offset(); + InputStream& input_stream { stream }; + + result = 0; + size_t num_bytes = 0; + u8 byte = 0; + + do { + if (input_stream.unreliable_eof()) { + if constexpr (requires { stream.seek(backup_offset); }) + stream.seek(backup_offset); + input_stream.set_fatal_error(); + return false; + } + + input_stream >> byte; + if (input_stream.has_any_error()) + return false; + result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); + ++num_bytes; + } while (byte & (1 << 7)); + + if (num_bytes * 7 < sizeof(size_t) * 4 && (byte & 0x40)) { + // sign extend + result |= ((size_t)(-1) << (num_bytes * 7)); + } + + return true; + } +}; + +} + +using AK::LEB128; diff --git a/AK/MemoryStream.h b/AK/MemoryStream.h index f53792315a..4f92621800 100644 --- a/AK/MemoryStream.h +++ b/AK/MemoryStream.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -73,58 +74,9 @@ public: return m_bytes[m_offset]; } - bool read_LEB128_unsigned(size_t& result) - { - const auto backup = m_offset; + bool read_LEB128_unsigned(size_t& result) { return LEB128::read_unsigned(*this, result); } - result = 0; - size_t num_bytes = 0; - while (true) { - if (eof()) { - m_offset = backup; - set_recoverable_error(); - return false; - } - - const u8 byte = m_bytes[m_offset]; - result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); - ++m_offset; - if (!(byte & (1 << 7))) - break; - ++num_bytes; - } - - return true; - } - - bool read_LEB128_signed(ssize_t& result) - { - const auto backup = m_offset; - - result = 0; - size_t num_bytes = 0; - u8 byte = 0; - - do { - if (eof()) { - m_offset = backup; - set_recoverable_error(); - return false; - } - - byte = m_bytes[m_offset]; - result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); - ++m_offset; - ++num_bytes; - } while (byte & (1 << 7)); - - if (num_bytes * 7 < sizeof(size_t) * 4 && (byte & 0x40)) { - // sign extend - result |= ((size_t)(-1) << (num_bytes * 7)); - } - - return true; - } + bool read_LEB128_signed(ssize_t& result) { return LEB128::read_signed(*this, result); } ReadonlyBytes bytes() const { return m_bytes; } size_t offset() const { return m_offset; }