/src/serenity/Userland/Libraries/LibCompress/PackBitsDecoder.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include "PackBitsDecoder.h" |
8 | | #include <AK/MemoryStream.h> |
9 | | |
10 | | namespace Compress::PackBits { |
11 | | |
12 | | ErrorOr<ByteBuffer> decode_all(ReadonlyBytes bytes, Optional<u64> expected_output_size, CompatibilityMode mode) |
13 | 4.15k | { |
14 | | // This implementation uses unsigned values for the selector, as described in the PDF spec. |
15 | | // Note that this remains compatible with other implementations based on signed numbers. |
16 | | |
17 | 4.15k | auto memory_stream = make<FixedMemoryStream>(bytes); |
18 | | |
19 | 4.15k | ByteBuffer decoded_bytes; |
20 | | |
21 | 4.15k | if (expected_output_size.has_value()) |
22 | 4.00k | TRY(decoded_bytes.try_ensure_capacity(*expected_output_size)); |
23 | | |
24 | 1.71M | while (memory_stream->remaining() > 0 && decoded_bytes.size() < expected_output_size.value_or(NumericLimits<u64>::max())) { |
25 | 1.71M | auto const length = TRY(memory_stream->read_value<u8>()); |
26 | | |
27 | 1.71M | if (length < 128) { |
28 | 1.91M | for (u8 i = 0; i <= length; ++i) |
29 | 1.67M | TRY(decoded_bytes.try_append(TRY(memory_stream->read_value<u8>()))); |
30 | 1.47M | } else if (length > 128) { |
31 | 1.47M | auto const next_byte = TRY(memory_stream->read_value<u8>()); |
32 | | |
33 | 128M | for (u8 i = 0; i < 257 - length; ++i) |
34 | 127M | TRY(decoded_bytes.try_append(next_byte)); |
35 | 1.47M | } else { |
36 | 1.45k | VERIFY(length == 128); |
37 | 1.45k | if (mode == CompatibilityMode::PDF) |
38 | 0 | break; |
39 | 1.45k | } |
40 | 1.71M | } |
41 | | |
42 | 4.08k | return decoded_bytes; |
43 | 4.15k | } |
44 | | |
45 | | } |