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