mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 21:47:46 +00:00
AK: Port LEB128
to the new AK::Stream
This commit is contained in:
parent
31f59855b4
commit
787f4d639a
10 changed files with 120 additions and 209 deletions
42
AK/LEB128.h
42
AK/LEB128.h
|
@ -6,36 +6,32 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/DeprecatedStream.h>
|
||||
#include <AK/NumericLimits.h>
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/Types.h>
|
||||
|
||||
namespace AK {
|
||||
|
||||
struct LEB128 {
|
||||
template<typename ValueType = size_t>
|
||||
static bool read_unsigned(DeprecatedInputStream& stream, ValueType& result)
|
||||
static ErrorOr<void> read_unsigned(AK::Stream& stream, ValueType& result)
|
||||
{
|
||||
result = 0;
|
||||
size_t num_bytes = 0;
|
||||
while (true) {
|
||||
if (stream.unreliable_eof()) {
|
||||
stream.set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
u8 byte = 0;
|
||||
stream >> byte;
|
||||
if (stream.has_any_error())
|
||||
return false;
|
||||
if (stream.is_eof())
|
||||
return Error::from_string_literal("Stream reached end-of-file while reading LEB128 value");
|
||||
|
||||
auto byte = TRY(stream.read_value<u8>());
|
||||
|
||||
ValueType masked_byte = byte & ~(1 << 7);
|
||||
bool const shift_too_large_for_result = num_bytes * 7 > sizeof(ValueType) * 8;
|
||||
if (shift_too_large_for_result)
|
||||
return false;
|
||||
return Error::from_string_literal("Read value contains more bits than fit the chosen ValueType");
|
||||
|
||||
bool const shift_too_large_for_byte = ((masked_byte << (num_bytes * 7)) >> (num_bytes * 7)) != masked_byte;
|
||||
if (shift_too_large_for_byte)
|
||||
return false;
|
||||
return Error::from_string_literal("Read byte is too large to fit the chosen ValueType");
|
||||
|
||||
result = (result) | (masked_byte << (num_bytes * 7));
|
||||
if (!(byte & (1 << 7)))
|
||||
|
@ -43,11 +39,11 @@ struct LEB128 {
|
|||
++num_bytes;
|
||||
}
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename ValueType = ssize_t>
|
||||
static bool read_signed(DeprecatedInputStream& stream, ValueType& result)
|
||||
static ErrorOr<void> read_signed(AK::Stream& stream, ValueType& result)
|
||||
{
|
||||
// Note: We read into a u64 to simplify the parsing logic;
|
||||
// result is range checked into ValueType after parsing.
|
||||
|
@ -59,24 +55,20 @@ struct LEB128 {
|
|||
result = 0;
|
||||
|
||||
do {
|
||||
if (stream.unreliable_eof()) {
|
||||
stream.set_fatal_error();
|
||||
return false;
|
||||
}
|
||||
if (stream.is_eof())
|
||||
return Error::from_string_literal("Stream reached end-of-file while reading LEB128 value");
|
||||
|
||||
stream >> byte;
|
||||
if (stream.has_any_error())
|
||||
return false;
|
||||
byte = TRY(stream.read_value<u8>());
|
||||
|
||||
// note: 64 bit assumptions!
|
||||
u64 masked_byte = byte & ~(1 << 7);
|
||||
bool const shift_too_large_for_result = num_bytes * 7 >= 64;
|
||||
if (shift_too_large_for_result)
|
||||
return false;
|
||||
return Error::from_string_literal("Read value contains more bits than fit the chosen ValueType");
|
||||
|
||||
bool const shift_too_large_for_byte = (num_bytes * 7) == 63 && masked_byte != 0x00 && masked_byte != 0x7Fu;
|
||||
if (shift_too_large_for_byte)
|
||||
return false;
|
||||
return Error::from_string_literal("Read byte is too large to fit the chosen ValueType");
|
||||
|
||||
temp = (temp) | (masked_byte << (num_bytes * 7));
|
||||
++num_bytes;
|
||||
|
@ -90,12 +82,12 @@ struct LEB128 {
|
|||
// Now that we've accumulated into an i64, make sure it fits into result
|
||||
if constexpr (sizeof(ValueType) < sizeof(u64)) {
|
||||
if (temp > NumericLimits<ValueType>::max() || temp < NumericLimits<ValueType>::min())
|
||||
return false;
|
||||
return Error::from_string_literal("Temporary value does not fit the result type");
|
||||
}
|
||||
|
||||
result = static_cast<ValueType>(temp);
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue