(root)/
xz-5.4.5/
src/
liblzma/
common/
block_buffer_decoder.c
       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  }