155714Skris///////////////////////////////////////////////////////////////////////////////
2280304Sjkim//
3280304Sjkim/// \file       alone_encoder.c
4280304Sjkim/// \brief      Encoder for LZMA_Alone files
555714Skris//
655714Skris//  Author:     Lasse Collin
755714Skris//
855714Skris//  This file has been put into the public domain.
955714Skris//  You can do whatever you want with this file.
1055714Skris//
1155714Skris///////////////////////////////////////////////////////////////////////////////
1255714Skris
1355714Skris#include "common.h"
14280304Sjkim#include "lzma_encoder.h"
1555714Skris
1655714Skris
1755714Skris#define ALONE_HEADER_SIZE (1 + 4 + 8)
1855714Skris
1955714Skris
2055714Skristypedef struct {
2155714Skris	lzma_next_coder next;
2255714Skris
2355714Skris	enum {
2455714Skris		SEQ_HEADER,
2555714Skris		SEQ_CODE,
2655714Skris	} sequence;
2755714Skris
2855714Skris	size_t header_pos;
2955714Skris	uint8_t header[ALONE_HEADER_SIZE];
3055714Skris} lzma_alone_coder;
3155714Skris
3255714Skris
3355714Skrisstatic lzma_ret
3455714Skrisalone_encode(void *coder_ptr, const lzma_allocator *allocator,
3555714Skris		const uint8_t *restrict in, size_t *restrict in_pos,
3655714Skris		size_t in_size, uint8_t *restrict out,
3755714Skris		size_t *restrict out_pos, size_t out_size,
3855714Skris		lzma_action action)
3955714Skris{
4055714Skris	lzma_alone_coder *coder = coder_ptr;
4155714Skris
4255714Skris	while (*out_pos < out_size)
4355714Skris	switch (coder->sequence) {
4455714Skris	case SEQ_HEADER:
4555714Skris		lzma_bufcpy(coder->header, &coder->header_pos,
4655714Skris				ALONE_HEADER_SIZE,
4755714Skris				out, out_pos, out_size);
4855714Skris		if (coder->header_pos < ALONE_HEADER_SIZE)
4955714Skris			return LZMA_OK;
5055714Skris
5155714Skris		coder->sequence = SEQ_CODE;
5255714Skris		break;
5355714Skris
5455714Skris	case SEQ_CODE:
5555714Skris		return coder->next.code(coder->next.coder,
5655714Skris				allocator, in, in_pos, in_size,
5755714Skris				out, out_pos, out_size, action);
5855714Skris
5955714Skris	default:
6055714Skris		assert(0);
6155714Skris		return LZMA_PROG_ERROR;
6255714Skris	}
6355714Skris
6455714Skris	return LZMA_OK;
6555714Skris}
6659191Skris
6759191Skris
6868651Skrisstatic void
6955714Skrisalone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
70280304Sjkim{
71280304Sjkim	lzma_alone_coder *coder = coder_ptr;
7255714Skris	lzma_next_end(&coder->next, allocator);
7355714Skris	lzma_free(coder, allocator);
7455714Skris	return;
7555714Skris}
76280304Sjkim
77280304Sjkim
78280304Sjkim// At least for now, this is not used by any internal function.
79280304Sjkimstatic lzma_ret
80280304Sjkimalone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
81280304Sjkim		const lzma_options_lzma *options)
82280304Sjkim{
83280304Sjkim	lzma_next_coder_init(&alone_encoder_init, next, allocator);
84280304Sjkim
8555714Skris	lzma_alone_coder *coder = next->coder;
8655714Skris
87280304Sjkim	if (coder == NULL) {
88280304Sjkim		coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
8955714Skris		if (coder == NULL)
90280304Sjkim			return LZMA_MEM_ERROR;
9155714Skris
9255714Skris		next->coder = coder;
93280304Sjkim		next->code = &alone_encode;
94280304Sjkim		next->end = &alone_encoder_end;
95238405Sjkim		coder->next = LZMA_NEXT_CODER_INIT;
96280304Sjkim	}
97238405Sjkim
98238405Sjkim	// Basic initializations
9955714Skris	coder->sequence = SEQ_HEADER;
100280304Sjkim	coder->header_pos = 0;
101280304Sjkim
102280304Sjkim	// Encode the header:
103280304Sjkim	// - Properties (1 byte)
104280304Sjkim	if (lzma_lzma_lclppb_encode(options, coder->header))
105280304Sjkim		return LZMA_OPTIONS_ERROR;
106280304Sjkim
107280304Sjkim	// - Dictionary size (4 bytes)
108280304Sjkim	if (options->dict_size < LZMA_DICT_SIZE_MIN)
109280304Sjkim		return LZMA_OPTIONS_ERROR;
110280304Sjkim
111280304Sjkim	// Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
112280304Sjkim	// one is the next unless it is UINT32_MAX. While the header would
113280304Sjkim	// allow any 32-bit integer, we do this to keep the decoder of liblzma
114280304Sjkim	// accepting the resulting files.
11555714Skris	uint32_t d = options->dict_size - 1;
11655714Skris	d |= d >> 2;
117238405Sjkim	d |= d >> 3;
11855714Skris	d |= d >> 4;
119280304Sjkim	d |= d >> 8;
120280304Sjkim	d |= d >> 16;
121280304Sjkim	if (d != UINT32_MAX)
122280304Sjkim		++d;
12355714Skris
12455714Skris	write32le(coder->header + 1, d);
12555714Skris
12655714Skris	// - Uncompressed size (always unknown and using EOPM)
127280304Sjkim	memset(coder->header + 1 + 4, 0xFF, 8);
128280304Sjkim
129280304Sjkim	// Initialize the LZMA encoder.
130280304Sjkim	const lzma_filter_info filters[2] = {
13155714Skris		{
13255714Skris			.init = &lzma_lzma_encoder_init,
13355714Skris			.options = (void *)(options),
13455714Skris		}, {
135280304Sjkim			.init = NULL,
136280304Sjkim		}
137238405Sjkim	};
138280304Sjkim
139280304Sjkim	return lzma_next_filter_init(&coder->next, allocator, filters);
140280304Sjkim}
141280304Sjkim
142280304Sjkim
143280304Sjkim/*
144280304Sjkimextern lzma_ret
145280304Sjkimlzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
146280304Sjkim		const lzma_options_alone *options)
147280304Sjkim{
148280304Sjkim	lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
149280304Sjkim}
150280304Sjkim*/
151280304Sjkim
152280304Sjkim
15355714Skrisextern LZMA_API(lzma_ret)
15455714Skrislzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
15555714Skris{
15655714Skris	lzma_next_strm_init(alone_encoder_init, strm, options);
157280304Sjkim
158280304Sjkim	strm->internal->supported_actions[LZMA_RUN] = true;
15955714Skris	strm->internal->supported_actions[LZMA_FINISH] = true;
16055714Skris
16155714Skris	return LZMA_OK;
16255714Skris}
163280304Sjkim