PackBitsDecoder.cpp 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. /*
  2. * Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "PackBitsDecoder.h"
  7. #include <AK/MemoryStream.h>
  8. namespace Compress::PackBits {
  9. ErrorOr<ByteBuffer> decode_all(ReadonlyBytes bytes, Optional<u64> expected_output_size, CompatibilityMode mode)
  10. {
  11. // This implementation uses unsigned values for the selector, as described in the PDF spec.
  12. // Note that this remains compatible with other implementations based on signed numbers.
  13. auto memory_stream = make<FixedMemoryStream>(bytes);
  14. ByteBuffer decoded_bytes;
  15. if (expected_output_size.has_value())
  16. TRY(decoded_bytes.try_ensure_capacity(*expected_output_size));
  17. while (memory_stream->remaining() > 0 && decoded_bytes.size() < expected_output_size.value_or(NumericLimits<u64>::max())) {
  18. auto const length = TRY(memory_stream->read_value<u8>());
  19. if (length < 128) {
  20. for (u8 i = 0; i <= length; ++i)
  21. TRY(decoded_bytes.try_append(TRY(memory_stream->read_value<u8>())));
  22. } else if (length > 128) {
  23. auto const next_byte = TRY(memory_stream->read_value<u8>());
  24. for (u8 i = 0; i < 257 - length; ++i)
  25. TRY(decoded_bytes.try_append(next_byte));
  26. } else {
  27. VERIFY(length == 128);
  28. if (mode == CompatibilityMode::PDF)
  29. break;
  30. }
  31. }
  32. return decoded_bytes;
  33. }
  34. }