lzma2_encoder.c (292588) | lzma2_encoder.c (312518) |
---|---|
1/////////////////////////////////////////////////////////////////////////////// 2// 3/// \file lzma2_encoder.c 4/// \brief LZMA2 encoder 5/// 6// Authors: Igor Pavlov 7// Lasse Collin 8// 9// This file has been put into the public domain. 10// You can do whatever you want with this file. 11// 12/////////////////////////////////////////////////////////////////////////////// 13 14#include "lz_encoder.h" 15#include "lzma_encoder.h" 16#include "fastpos.h" 17#include "lzma2_encoder.h" 18 19 | 1/////////////////////////////////////////////////////////////////////////////// 2// 3/// \file lzma2_encoder.c 4/// \brief LZMA2 encoder 5/// 6// Authors: Igor Pavlov 7// Lasse Collin 8// 9// This file has been put into the public domain. 10// You can do whatever you want with this file. 11// 12/////////////////////////////////////////////////////////////////////////////// 13 14#include "lz_encoder.h" 15#include "lzma_encoder.h" 16#include "fastpos.h" 17#include "lzma2_encoder.h" 18 19 |
20struct lzma_coder_s { | 20typedef struct { |
21 enum { 22 SEQ_INIT, 23 SEQ_LZMA_ENCODE, 24 SEQ_LZMA_COPY, 25 SEQ_UNCOMPRESSED_HEADER, 26 SEQ_UNCOMPRESSED_COPY, 27 } sequence; 28 29 /// LZMA encoder | 21 enum { 22 SEQ_INIT, 23 SEQ_LZMA_ENCODE, 24 SEQ_LZMA_COPY, 25 SEQ_UNCOMPRESSED_HEADER, 26 SEQ_UNCOMPRESSED_COPY, 27 } sequence; 28 29 /// LZMA encoder |
30 lzma_coder *lzma; | 30 void *lzma; |
31 32 /// LZMA options currently in use. 33 lzma_options_lzma opt_cur; 34 35 bool need_properties; 36 bool need_state_reset; 37 bool need_dictionary_reset; 38 --- 4 unchanged lines hidden (view full) --- 43 /// to indicate the end of buf[] in SEQ_LZMA_COPY. 44 size_t compressed_size; 45 46 /// Read position in buf[] 47 size_t buf_pos; 48 49 /// Buffer to hold the chunk header and LZMA compressed data 50 uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX]; | 31 32 /// LZMA options currently in use. 33 lzma_options_lzma opt_cur; 34 35 bool need_properties; 36 bool need_state_reset; 37 bool need_dictionary_reset; 38 --- 4 unchanged lines hidden (view full) --- 43 /// to indicate the end of buf[] in SEQ_LZMA_COPY. 44 size_t compressed_size; 45 46 /// Read position in buf[] 47 size_t buf_pos; 48 49 /// Buffer to hold the chunk header and LZMA compressed data 50 uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX]; |
51}; | 51} lzma_lzma2_coder; |
52 53 54static void | 52 53 54static void |
55lzma2_header_lzma(lzma_coder *coder) | 55lzma2_header_lzma(lzma_lzma2_coder *coder) |
56{ 57 assert(coder->uncompressed_size > 0); 58 assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX); 59 assert(coder->compressed_size > 0); 60 assert(coder->compressed_size <= LZMA2_CHUNK_MAX); 61 62 size_t pos; 63 --- 39 unchanged lines hidden (view full) --- 103 // of coder->buf[], so we need add the maximum size of the header here. 104 coder->compressed_size += LZMA2_HEADER_MAX; 105 106 return; 107} 108 109 110static void | 56{ 57 assert(coder->uncompressed_size > 0); 58 assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX); 59 assert(coder->compressed_size > 0); 60 assert(coder->compressed_size <= LZMA2_CHUNK_MAX); 61 62 size_t pos; 63 --- 39 unchanged lines hidden (view full) --- 103 // of coder->buf[], so we need add the maximum size of the header here. 104 coder->compressed_size += LZMA2_HEADER_MAX; 105 106 return; 107} 108 109 110static void |
111lzma2_header_uncompressed(lzma_coder *coder) | 111lzma2_header_uncompressed(lzma_lzma2_coder *coder) |
112{ 113 assert(coder->uncompressed_size > 0); 114 assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX); 115 116 // If this is the first chunk, we need to include dictionary 117 // reset indicator. 118 if (coder->need_dictionary_reset) 119 coder->buf[0] = 1; --- 8 unchanged lines hidden (view full) --- 128 129 // Set the start position for copying. 130 coder->buf_pos = 0; 131 return; 132} 133 134 135static lzma_ret | 112{ 113 assert(coder->uncompressed_size > 0); 114 assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX); 115 116 // If this is the first chunk, we need to include dictionary 117 // reset indicator. 118 if (coder->need_dictionary_reset) 119 coder->buf[0] = 1; --- 8 unchanged lines hidden (view full) --- 128 129 // Set the start position for copying. 130 coder->buf_pos = 0; 131 return; 132} 133 134 135static lzma_ret |
136lzma2_encode(lzma_coder *restrict coder, lzma_mf *restrict mf, | 136lzma2_encode(void *coder_ptr, lzma_mf *restrict mf, |
137 uint8_t *restrict out, size_t *restrict out_pos, 138 size_t out_size) 139{ | 137 uint8_t *restrict out, size_t *restrict out_pos, 138 size_t out_size) 139{ |
140 lzma_lzma2_coder *restrict coder = coder_ptr; 141 |
|
140 while (*out_pos < out_size) 141 switch (coder->sequence) { 142 case SEQ_INIT: 143 // If there's no input left and we are flushing or finishing, 144 // don't start a new chunk. 145 if (mf_unencoded(mf) == 0) { 146 // Write end of payload marker if finishing. 147 if (mf->action == LZMA_FINISH) --- 109 unchanged lines hidden (view full) --- 257 break; 258 } 259 260 return LZMA_OK; 261} 262 263 264static void | 142 while (*out_pos < out_size) 143 switch (coder->sequence) { 144 case SEQ_INIT: 145 // If there's no input left and we are flushing or finishing, 146 // don't start a new chunk. 147 if (mf_unencoded(mf) == 0) { 148 // Write end of payload marker if finishing. 149 if (mf->action == LZMA_FINISH) --- 109 unchanged lines hidden (view full) --- 259 break; 260 } 261 262 return LZMA_OK; 263} 264 265 266static void |
265lzma2_encoder_end(lzma_coder *coder, const lzma_allocator *allocator) | 267lzma2_encoder_end(void *coder_ptr, const lzma_allocator *allocator) |
266{ | 268{ |
269 lzma_lzma2_coder *coder = coder_ptr; |
|
267 lzma_free(coder->lzma, allocator); 268 lzma_free(coder, allocator); 269 return; 270} 271 272 273static lzma_ret | 270 lzma_free(coder->lzma, allocator); 271 lzma_free(coder, allocator); 272 return; 273} 274 275 276static lzma_ret |
274lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter) | 277lzma2_encoder_options_update(void *coder_ptr, const lzma_filter *filter) |
275{ | 278{ |
279 lzma_lzma2_coder *coder = coder_ptr; 280 |
|
276 // New options can be set only when there is no incomplete chunk. 277 // This is the case at the beginning of the raw stream and right 278 // after LZMA_SYNC_FLUSH. 279 if (filter->options == NULL || coder->sequence != SEQ_INIT) 280 return LZMA_PROG_ERROR; 281 282 // Look if there are new options. At least for now, 283 // only lc/lp/pb can be changed. --- 21 unchanged lines hidden (view full) --- 305 306static lzma_ret 307lzma2_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator, 308 const void *options, lzma_lz_options *lz_options) 309{ 310 if (options == NULL) 311 return LZMA_PROG_ERROR; 312 | 281 // New options can be set only when there is no incomplete chunk. 282 // This is the case at the beginning of the raw stream and right 283 // after LZMA_SYNC_FLUSH. 284 if (filter->options == NULL || coder->sequence != SEQ_INIT) 285 return LZMA_PROG_ERROR; 286 287 // Look if there are new options. At least for now, 288 // only lc/lp/pb can be changed. --- 21 unchanged lines hidden (view full) --- 310 311static lzma_ret 312lzma2_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator, 313 const void *options, lzma_lz_options *lz_options) 314{ 315 if (options == NULL) 316 return LZMA_PROG_ERROR; 317 |
313 if (lz->coder == NULL) { 314 lz->coder = lzma_alloc(sizeof(lzma_coder), allocator); 315 if (lz->coder == NULL) | 318 lzma_lzma2_coder *coder = lz->coder; 319 if (coder == NULL) { 320 coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator); 321 if (coder == NULL) |
316 return LZMA_MEM_ERROR; 317 | 322 return LZMA_MEM_ERROR; 323 |
324 lz->coder = coder; |
|
318 lz->code = &lzma2_encode; 319 lz->end = &lzma2_encoder_end; 320 lz->options_update = &lzma2_encoder_options_update; 321 | 325 lz->code = &lzma2_encode; 326 lz->end = &lzma2_encoder_end; 327 lz->options_update = &lzma2_encoder_options_update; 328 |
322 lz->coder->lzma = NULL; | 329 coder->lzma = NULL; |
323 } 324 | 330 } 331 |
325 lz->coder->opt_cur = *(const lzma_options_lzma *)(options); | 332 coder->opt_cur = *(const lzma_options_lzma *)(options); |
326 | 333 |
327 lz->coder->sequence = SEQ_INIT; 328 lz->coder->need_properties = true; 329 lz->coder->need_state_reset = false; 330 lz->coder->need_dictionary_reset 331 = lz->coder->opt_cur.preset_dict == NULL 332 || lz->coder->opt_cur.preset_dict_size == 0; | 334 coder->sequence = SEQ_INIT; 335 coder->need_properties = true; 336 coder->need_state_reset = false; 337 coder->need_dictionary_reset 338 = coder->opt_cur.preset_dict == NULL 339 || coder->opt_cur.preset_dict_size == 0; |
333 334 // Initialize LZMA encoder | 340 341 // Initialize LZMA encoder |
335 return_if_error(lzma_lzma_encoder_create(&lz->coder->lzma, allocator, 336 &lz->coder->opt_cur, lz_options)); | 342 return_if_error(lzma_lzma_encoder_create(&coder->lzma, allocator, 343 &coder->opt_cur, lz_options)); |
337 338 // Make sure that we will always have enough history available in 339 // case we need to use uncompressed chunks. They are used when the 340 // compressed size of a chunk is not smaller than the uncompressed 341 // size, so we need to have at least LZMA2_COMPRESSED_MAX bytes 342 // history available. 343 if (lz_options->before_size + lz_options->dict_size < LZMA2_CHUNK_MAX) 344 lz_options->before_size --- 14 unchanged lines hidden (view full) --- 359 360extern uint64_t 361lzma_lzma2_encoder_memusage(const void *options) 362{ 363 const uint64_t lzma_mem = lzma_lzma_encoder_memusage(options); 364 if (lzma_mem == UINT64_MAX) 365 return UINT64_MAX; 366 | 344 345 // Make sure that we will always have enough history available in 346 // case we need to use uncompressed chunks. They are used when the 347 // compressed size of a chunk is not smaller than the uncompressed 348 // size, so we need to have at least LZMA2_COMPRESSED_MAX bytes 349 // history available. 350 if (lz_options->before_size + lz_options->dict_size < LZMA2_CHUNK_MAX) 351 lz_options->before_size --- 14 unchanged lines hidden (view full) --- 366 367extern uint64_t 368lzma_lzma2_encoder_memusage(const void *options) 369{ 370 const uint64_t lzma_mem = lzma_lzma_encoder_memusage(options); 371 if (lzma_mem == UINT64_MAX) 372 return UINT64_MAX; 373 |
367 return sizeof(lzma_coder) + lzma_mem; | 374 return sizeof(lzma_lzma2_coder) + lzma_mem; |
368} 369 370 371extern lzma_ret 372lzma_lzma2_props_encode(const void *options, uint8_t *out) 373{ 374 const lzma_options_lzma *const opt = options; 375 uint32_t d = my_max(opt->dict_size, LZMA_DICT_SIZE_MIN); --- 28 unchanged lines hidden --- | 375} 376 377 378extern lzma_ret 379lzma_lzma2_props_encode(const void *options, uint8_t *out) 380{ 381 const lzma_options_lzma *const opt = options; 382 uint32_t d = my_max(opt->dict_size, LZMA_DICT_SIZE_MIN); --- 28 unchanged lines hidden --- |