/* * Copyright (c) 2023, Lucas Chollet * * SPDX-License-Identifier: BSD-2-Clause */ #include "PackBitsDecoder.h" #include namespace Compress::PackBits { ErrorOr decode_all(ReadonlyBytes bytes, Optional expected_output_size, CompatibilityMode mode) { // This implementation uses unsigned values for the selector, as described in the PDF spec. // Note that this remains compatible with other implementations based on signed numbers. auto memory_stream = make(bytes); ByteBuffer decoded_bytes; if (expected_output_size.has_value()) TRY(decoded_bytes.try_ensure_capacity(*expected_output_size)); while (memory_stream->remaining() > 0 && decoded_bytes.size() < expected_output_size.value_or(NumericLimits::max())) { auto const length = TRY(memory_stream->read_value()); if (length < 128) { for (u8 i = 0; i <= length; ++i) TRY(decoded_bytes.try_append(TRY(memory_stream->read_value()))); } else if (length > 128) { auto const next_byte = TRY(memory_stream->read_value()); for (u8 i = 0; i < 257 - length; ++i) TRY(decoded_bytes.try_append(next_byte)); } else { VERIFY(length == 128); if (mode == CompatibilityMode::PDF) break; } } return decoded_bytes; } }