(root)/
xz-5.4.5/
src/
liblzma/
common/
alone_encoder.c
       1  ///////////////////////////////////////////////////////////////////////////////
       2  //
       3  /// \file       alone_encoder.c
       4  /// \brief      Encoder for LZMA_Alone files
       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 "common.h"
      14  #include "lzma_encoder.h"
      15  
      16  
      17  #define ALONE_HEADER_SIZE (1 + 4 + 8)
      18  
      19  
      20  typedef struct {
      21  	lzma_next_coder next;
      22  
      23  	enum {
      24  		SEQ_HEADER,
      25  		SEQ_CODE,
      26  	} sequence;
      27  
      28  	size_t header_pos;
      29  	uint8_t header[ALONE_HEADER_SIZE];
      30  } lzma_alone_coder;
      31  
      32  
      33  static lzma_ret
      34  alone_encode(void *coder_ptr, const lzma_allocator *allocator,
      35  		const uint8_t *restrict in, size_t *restrict in_pos,
      36  		size_t in_size, uint8_t *restrict out,
      37  		size_t *restrict out_pos, size_t out_size,
      38  		lzma_action action)
      39  {
      40  	lzma_alone_coder *coder = coder_ptr;
      41  
      42  	while (*out_pos < out_size)
      43  	switch (coder->sequence) {
      44  	case SEQ_HEADER:
      45  		lzma_bufcpy(coder->header, &coder->header_pos,
      46  				ALONE_HEADER_SIZE,
      47  				out, out_pos, out_size);
      48  		if (coder->header_pos < ALONE_HEADER_SIZE)
      49  			return LZMA_OK;
      50  
      51  		coder->sequence = SEQ_CODE;
      52  		break;
      53  
      54  	case SEQ_CODE:
      55  		return coder->next.code(coder->next.coder,
      56  				allocator, in, in_pos, in_size,
      57  				out, out_pos, out_size, action);
      58  
      59  	default:
      60  		assert(0);
      61  		return LZMA_PROG_ERROR;
      62  	}
      63  
      64  	return LZMA_OK;
      65  }
      66  
      67  
      68  static void
      69  alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
      70  {
      71  	lzma_alone_coder *coder = coder_ptr;
      72  	lzma_next_end(&coder->next, allocator);
      73  	lzma_free(coder, allocator);
      74  	return;
      75  }
      76  
      77  
      78  static lzma_ret
      79  alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
      80  		const lzma_options_lzma *options)
      81  {
      82  	lzma_next_coder_init(&alone_encoder_init, next, allocator);
      83  
      84  	lzma_alone_coder *coder = next->coder;
      85  
      86  	if (coder == NULL) {
      87  		coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
      88  		if (coder == NULL)
      89  			return LZMA_MEM_ERROR;
      90  
      91  		next->coder = coder;
      92  		next->code = &alone_encode;
      93  		next->end = &alone_encoder_end;
      94  		coder->next = LZMA_NEXT_CODER_INIT;
      95  	}
      96  
      97  	// Basic initializations
      98  	coder->sequence = SEQ_HEADER;
      99  	coder->header_pos = 0;
     100  
     101  	// Encode the header:
     102  	// - Properties (1 byte)
     103  	if (lzma_lzma_lclppb_encode(options, coder->header))
     104  		return LZMA_OPTIONS_ERROR;
     105  
     106  	// - Dictionary size (4 bytes)
     107  	if (options->dict_size < LZMA_DICT_SIZE_MIN)
     108  		return LZMA_OPTIONS_ERROR;
     109  
     110  	// Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
     111  	// one is the next unless it is UINT32_MAX. While the header would
     112  	// allow any 32-bit integer, we do this to keep the decoder of liblzma
     113  	// accepting the resulting files.
     114  	uint32_t d = options->dict_size - 1;
     115  	d |= d >> 2;
     116  	d |= d >> 3;
     117  	d |= d >> 4;
     118  	d |= d >> 8;
     119  	d |= d >> 16;
     120  	if (d != UINT32_MAX)
     121  		++d;
     122  
     123  	write32le(coder->header + 1, d);
     124  
     125  	// - Uncompressed size (always unknown and using EOPM)
     126  	memset(coder->header + 1 + 4, 0xFF, 8);
     127  
     128  	// Initialize the LZMA encoder.
     129  	const lzma_filter_info filters[2] = {
     130  		{
     131  			.id = LZMA_FILTER_LZMA1,
     132  			.init = &lzma_lzma_encoder_init,
     133  			.options = (void *)(options),
     134  		}, {
     135  			.init = NULL,
     136  		}
     137  	};
     138  
     139  	return lzma_next_filter_init(&coder->next, allocator, filters);
     140  }
     141  
     142  
     143  extern LZMA_API(lzma_ret)
     144  lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
     145  {
     146  	lzma_next_strm_init(alone_encoder_init, strm, options);
     147  
     148  	strm->internal->supported_actions[LZMA_RUN] = true;
     149  	strm->internal->supported_actions[LZMA_FINISH] = true;
     150  
     151  	return LZMA_OK;
     152  }