1 | // SPDX-License-Identifier: 0BSD
|
---|
2 |
|
---|
3 | ///////////////////////////////////////////////////////////////////////////////
|
---|
4 | //
|
---|
5 | /// \file block_buffer_decoder.c
|
---|
6 | /// \brief Single-call .xz Block decoder
|
---|
7 | //
|
---|
8 | // Author: Lasse Collin
|
---|
9 | //
|
---|
10 | ///////////////////////////////////////////////////////////////////////////////
|
---|
11 |
|
---|
12 | #include "block_decoder.h"
|
---|
13 |
|
---|
14 |
|
---|
15 | extern LZMA_API(lzma_ret)
|
---|
16 | lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator,
|
---|
17 | const uint8_t *in, size_t *in_pos, size_t in_size,
|
---|
18 | uint8_t *out, size_t *out_pos, size_t out_size)
|
---|
19 | {
|
---|
20 | if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|
---|
21 | || *in_pos > in_size || out_pos == NULL
|
---|
22 | || (out == NULL && *out_pos != out_size)
|
---|
23 | || *out_pos > out_size)
|
---|
24 | return LZMA_PROG_ERROR;
|
---|
25 |
|
---|
26 | // Initialize the Block decoder.
|
---|
27 | lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT;
|
---|
28 | lzma_ret ret = lzma_block_decoder_init(
|
---|
29 | &block_decoder, allocator, block);
|
---|
30 |
|
---|
31 | if (ret == LZMA_OK) {
|
---|
32 | // Save the positions so that we can restore them in case
|
---|
33 | // an error occurs.
|
---|
34 | const size_t in_start = *in_pos;
|
---|
35 | const size_t out_start = *out_pos;
|
---|
36 |
|
---|
37 | // Do the actual decoding.
|
---|
38 | ret = block_decoder.code(block_decoder.coder, allocator,
|
---|
39 | in, in_pos, in_size, out, out_pos, out_size,
|
---|
40 | LZMA_FINISH);
|
---|
41 |
|
---|
42 | if (ret == LZMA_STREAM_END) {
|
---|
43 | ret = LZMA_OK;
|
---|
44 | } else {
|
---|
45 | if (ret == LZMA_OK) {
|
---|
46 | // Either the input was truncated or the
|
---|
47 | // output buffer was too small.
|
---|
48 | assert(*in_pos == in_size
|
---|
49 | || *out_pos == out_size);
|
---|
50 |
|
---|
51 | // If all the input was consumed, then the
|
---|
52 | // input is truncated, even if the output
|
---|
53 | // buffer is also full. This is because
|
---|
54 | // processing the last byte of the Block
|
---|
55 | // never produces output.
|
---|
56 | //
|
---|
57 | // NOTE: This assumption may break when new
|
---|
58 | // filters are added, if the end marker of
|
---|
59 | // the filter doesn't consume at least one
|
---|
60 | // complete byte.
|
---|
61 | if (*in_pos == in_size)
|
---|
62 | ret = LZMA_DATA_ERROR;
|
---|
63 | else
|
---|
64 | ret = LZMA_BUF_ERROR;
|
---|
65 | }
|
---|
66 |
|
---|
67 | // Restore the positions.
|
---|
68 | *in_pos = in_start;
|
---|
69 | *out_pos = out_start;
|
---|
70 | }
|
---|
71 | }
|
---|
72 |
|
---|
73 | // Free the decoder memory. This needs to be done even if
|
---|
74 | // initialization fails, because the internal API doesn't
|
---|
75 | // require the initialization function to free its memory on error.
|
---|
76 | lzma_next_end(&block_decoder, allocator);
|
---|
77 |
|
---|
78 | return ret;
|
---|
79 | }
|
---|