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