15a645f22SBen Gras ///////////////////////////////////////////////////////////////////////////////
25a645f22SBen Gras //
35a645f22SBen Gras /// \file stream_buffer_decoder.c
45a645f22SBen Gras /// \brief Single-call .xz Stream decoder
55a645f22SBen Gras //
65a645f22SBen Gras // Author: Lasse Collin
75a645f22SBen Gras //
85a645f22SBen Gras // This file has been put into the public domain.
95a645f22SBen Gras // You can do whatever you want with this file.
105a645f22SBen Gras //
115a645f22SBen Gras ///////////////////////////////////////////////////////////////////////////////
125a645f22SBen Gras
135a645f22SBen Gras #include "stream_decoder.h"
145a645f22SBen Gras
155a645f22SBen Gras
165a645f22SBen Gras extern LZMA_API(lzma_ret)
lzma_stream_buffer_decode(uint64_t * memlimit,uint32_t flags,const lzma_allocator * allocator,const uint8_t * in,size_t * in_pos,size_t in_size,uint8_t * out,size_t * out_pos,size_t out_size)175a645f22SBen Gras lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
18*0a6a1f1dSLionel Sambuc const lzma_allocator *allocator,
195a645f22SBen Gras const uint8_t *in, size_t *in_pos, size_t in_size,
205a645f22SBen Gras uint8_t *out, size_t *out_pos, size_t out_size)
215a645f22SBen Gras {
225a645f22SBen Gras // Sanity checks
235a645f22SBen Gras if (in_pos == NULL || (in == NULL && *in_pos != in_size)
245a645f22SBen Gras || *in_pos > in_size || out_pos == NULL
255a645f22SBen Gras || (out == NULL && *out_pos != out_size)
265a645f22SBen Gras || *out_pos > out_size)
275a645f22SBen Gras return LZMA_PROG_ERROR;
285a645f22SBen Gras
295a645f22SBen Gras // Catch flags that are not allowed in buffer-to-buffer decoding.
305a645f22SBen Gras if (flags & LZMA_TELL_ANY_CHECK)
315a645f22SBen Gras return LZMA_PROG_ERROR;
325a645f22SBen Gras
335a645f22SBen Gras // Initialize the Stream decoder.
345a645f22SBen Gras // TODO: We need something to tell the decoder that it can use the
355a645f22SBen Gras // output buffer as workspace, and thus save significant amount of RAM.
365a645f22SBen Gras lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
375a645f22SBen Gras lzma_ret ret = lzma_stream_decoder_init(
385a645f22SBen Gras &stream_decoder, allocator, *memlimit, flags);
395a645f22SBen Gras
405a645f22SBen Gras if (ret == LZMA_OK) {
415a645f22SBen Gras // Save the positions so that we can restore them in case
425a645f22SBen Gras // an error occurs.
435a645f22SBen Gras const size_t in_start = *in_pos;
445a645f22SBen Gras const size_t out_start = *out_pos;
455a645f22SBen Gras
465a645f22SBen Gras // Do the actual decoding.
475a645f22SBen Gras ret = stream_decoder.code(stream_decoder.coder, allocator,
485a645f22SBen Gras in, in_pos, in_size, out, out_pos, out_size,
495a645f22SBen Gras LZMA_FINISH);
505a645f22SBen Gras
515a645f22SBen Gras if (ret == LZMA_STREAM_END) {
525a645f22SBen Gras ret = LZMA_OK;
535a645f22SBen Gras } else {
545a645f22SBen Gras // Something went wrong, restore the positions.
555a645f22SBen Gras *in_pos = in_start;
565a645f22SBen Gras *out_pos = out_start;
575a645f22SBen Gras
585a645f22SBen Gras if (ret == LZMA_OK) {
595a645f22SBen Gras // Either the input was truncated or the
605a645f22SBen Gras // output buffer was too small.
615a645f22SBen Gras assert(*in_pos == in_size
625a645f22SBen Gras || *out_pos == out_size);
635a645f22SBen Gras
645a645f22SBen Gras // If all the input was consumed, then the
655a645f22SBen Gras // input is truncated, even if the output
665a645f22SBen Gras // buffer is also full. This is because
675a645f22SBen Gras // processing the last byte of the Stream
685a645f22SBen Gras // never produces output.
695a645f22SBen Gras if (*in_pos == in_size)
705a645f22SBen Gras ret = LZMA_DATA_ERROR;
715a645f22SBen Gras else
725a645f22SBen Gras ret = LZMA_BUF_ERROR;
735a645f22SBen Gras
745a645f22SBen Gras } else if (ret == LZMA_MEMLIMIT_ERROR) {
755a645f22SBen Gras // Let the caller know how much memory would
765a645f22SBen Gras // have been needed.
775a645f22SBen Gras uint64_t memusage;
785a645f22SBen Gras (void)stream_decoder.memconfig(
795a645f22SBen Gras stream_decoder.coder,
805a645f22SBen Gras memlimit, &memusage, 0);
815a645f22SBen Gras }
825a645f22SBen Gras }
835a645f22SBen Gras }
845a645f22SBen Gras
855a645f22SBen Gras // Free the decoder memory. This needs to be done even if
865a645f22SBen Gras // initialization fails, because the internal API doesn't
875a645f22SBen Gras // require the initialization function to free its memory on error.
885a645f22SBen Gras lzma_next_end(&stream_decoder, allocator);
895a645f22SBen Gras
905a645f22SBen Gras return ret;
915a645f22SBen Gras }
92