Add limit of lc + lp <= 4. Now we can allocate the

literal coder as part of the main LZMA encoder or
decoder structure.

Make the LZMA decoder to rely on the current internal API
to free the allocated memory in case an error occurs.
This commit is contained in:
Lasse Collin 2008-06-19 16:35:08 +03:00
parent d25ab1b961
commit 0809c46534
6 changed files with 43 additions and 91 deletions

View File

@ -167,7 +167,7 @@ typedef struct {
*/ */
uint32_t literal_context_bits; uint32_t literal_context_bits;
# define LZMA_LITERAL_CONTEXT_BITS_MIN 0 # define LZMA_LITERAL_CONTEXT_BITS_MIN 0
# define LZMA_LITERAL_CONTEXT_BITS_MAX 8 # define LZMA_LITERAL_CONTEXT_BITS_MAX 4
# define LZMA_LITERAL_CONTEXT_BITS_DEFAULT 3 # define LZMA_LITERAL_CONTEXT_BITS_DEFAULT 3
/** /**
@ -278,6 +278,14 @@ typedef struct {
} lzma_options_lzma; } lzma_options_lzma;
/**
* \brief Maximum sum of literal_context_bits and literal_pos_bits
*
* literal_context_bits + literal_pos_bits <= LZMA_LITERAL_BITS_MAX
*/
#define LZMA_LITERAL_BITS_MAX 4
/** /**
* \brief Available LZMA encoding modes * \brief Available LZMA encoding modes
* *

View File

@ -115,7 +115,7 @@ struct lzma_coder_s {
uint32_t pos_mask; uint32_t pos_mask;
uint32_t now_pos; // Lowest 32-bits are enough here. uint32_t now_pos; // Lowest 32-bits are enough here.
lzma_literal_coder *literal_coder; lzma_literal_coder literal_coder;
/// If 1, it's a match. Otherwise it's a single 8-bit literal. /// If 1, it's a match. Otherwise it's a single 8-bit literal.
probability is_match[STATES][POS_STATES_MAX]; probability is_match[STATES][POS_STATES_MAX];
@ -651,7 +651,6 @@ lzma_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{ {
lzma_next_coder_end(&coder->next, allocator); lzma_next_coder_end(&coder->next, allocator);
lzma_lz_decoder_end(&coder->lz, allocator); lzma_lz_decoder_end(&coder->lz, allocator);
lzma_literal_end(&coder->literal_coder, allocator);
lzma_free(coder, allocator); lzma_free(coder, allocator);
return; return;
} }
@ -661,6 +660,9 @@ extern lzma_ret
lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters) const lzma_filter_info *filters)
{ {
// LZMA can only be the last filter in the chain.
assert(filters[1].init == NULL);
// Validate pos_bits. Other options are validated by the // Validate pos_bits. Other options are validated by the
// respective initialization functions. // respective initialization functions.
const lzma_options_lzma *options = filters[0].options; const lzma_options_lzma *options = filters[0].options;
@ -673,43 +675,25 @@ lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
if (next->coder == NULL) if (next->coder == NULL)
return LZMA_MEM_ERROR; return LZMA_MEM_ERROR;
// Initialize variables so that we know later that we don't next->code = &lzma_lz_decode;
// have an existing decoder initialized. next->end = &lzma_decoder_end;
next->coder->next = LZMA_NEXT_CODER_INIT; next->coder->next = LZMA_NEXT_CODER_INIT;
next->coder->lz = LZMA_LZ_DECODER_INIT; next->coder->lz = LZMA_LZ_DECODER_INIT;
next->coder->literal_coder = NULL;
} }
// Store the pos_bits and calculate pos_mask. // Store the pos_bits and calculate pos_mask.
next->coder->pos_bits = options->pos_bits; next->coder->pos_bits = options->pos_bits;
next->coder->pos_mask = (1U << next->coder->pos_bits) - 1; next->coder->pos_mask = (1U << next->coder->pos_bits) - 1;
// Allocate (if needed) and initialize the literal decoder. // Initialize the literal decoder.
{ return_if_error(lzma_literal_init(&next->coder->literal_coder,
const lzma_ret ret = lzma_literal_init(
&next->coder->literal_coder, allocator,
options->literal_context_bits, options->literal_context_bits,
options->literal_pos_bits); options->literal_pos_bits));
if (ret != LZMA_OK) {
lzma_free(next->coder, allocator);
next->coder = NULL;
return ret;
}
}
// Allocate and initialize the LZ decoder. // Allocate and initialize the LZ decoder.
{ return_if_error(lzma_lz_decoder_reset(&next->coder->lz, allocator,
const lzma_ret ret = lzma_lz_decoder_reset( &decode_real, options->dictionary_size,
&next->coder->lz, allocator, &decode_real, MATCH_MAX_LEN));
options->dictionary_size, MATCH_MAX_LEN);
if (ret != LZMA_OK) {
lzma_literal_end(&next->coder->literal_coder,
allocator);
lzma_free(next->coder, allocator);
next->coder = NULL;
return ret;
}
}
// State // State
next->coder->state = 0; next->coder->state = 0;
@ -769,20 +753,6 @@ lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->has_produced_output = false; next->coder->has_produced_output = false;
// Initialize the next decoder in the chain, if any.
{
const lzma_ret ret = lzma_next_filter_init(&next->coder->next,
allocator, filters + 1);
if (ret != LZMA_OK) {
lzma_decoder_end(next->coder, allocator);
return ret;
}
}
// Initialization successful. Set the function pointers.
next->code = &lzma_lz_decode;
next->end = &lzma_decoder_end;
return LZMA_OK; return LZMA_OK;
} }
@ -808,5 +778,6 @@ lzma_lzma_decode_properties(lzma_options_lzma *options, uint8_t byte)
options->literal_pos_bits = byte / 9; options->literal_pos_bits = byte / 9;
options->literal_context_bits = byte - options->literal_pos_bits * 9; options->literal_context_bits = byte - options->literal_pos_bits * 9;
return false; return options->literal_context_bits + options->literal_pos_bits
> LZMA_LITERAL_BITS_MAX;
} }

View File

@ -52,7 +52,6 @@ static void
lzma_lzma_encoder_end(lzma_coder *coder, lzma_allocator *allocator) lzma_lzma_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{ {
lzma_lz_encoder_end(&coder->lz, allocator); lzma_lz_encoder_end(&coder->lz, allocator);
lzma_literal_end(&coder->literal_coder, allocator);
lzma_free(coder, allocator); lzma_free(coder, allocator);
return; return;
} }
@ -69,7 +68,6 @@ lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->next = LZMA_NEXT_CODER_INIT; next->coder->next = LZMA_NEXT_CODER_INIT;
next->coder->lz = LZMA_LZ_ENCODER_INIT; next->coder->lz = LZMA_LZ_ENCODER_INIT;
next->coder->literal_coder = NULL;
} }
// Validate options that aren't validated elsewhere. // Validate options that aren't validated elsewhere.
@ -99,14 +97,12 @@ lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Initialize literal coder. // Initialize literal coder.
{ {
const lzma_ret ret = lzma_literal_init( const lzma_ret ret = lzma_literal_init(
&next->coder->literal_coder, allocator, &next->coder->literal_coder,
options->literal_context_bits, options->literal_context_bits,
options->literal_pos_bits); options->literal_pos_bits);
if (ret != LZMA_OK) { if (ret != LZMA_OK)
lzma_lzma_encoder_end(next->coder, allocator);
return ret; return ret;
} }
}
// Initialize LZ encoder. // Initialize LZ encoder.
{ {
@ -218,7 +214,10 @@ lzma_lzma_encode_properties(const lzma_options_lzma *options, uint8_t *byte)
if (options->literal_context_bits > LZMA_LITERAL_CONTEXT_BITS_MAX if (options->literal_context_bits > LZMA_LITERAL_CONTEXT_BITS_MAX
|| options->literal_pos_bits || options->literal_pos_bits
> LZMA_LITERAL_POS_BITS_MAX > LZMA_LITERAL_POS_BITS_MAX
|| options->pos_bits > LZMA_POS_BITS_MAX) || options->pos_bits > LZMA_POS_BITS_MAX
|| options->literal_context_bits
+ options->literal_pos_bits
> LZMA_LITERAL_BITS_MAX)
return true; return true;
*byte = (options->pos_bits * 5 + options->literal_pos_bits) * 9 *byte = (options->pos_bits * 5 + options->literal_pos_bits) * 9

View File

@ -95,7 +95,7 @@ struct lzma_coder_s {
bool write_eopm; bool write_eopm;
// Literal encoder // Literal encoder
lzma_literal_coder *literal_coder; lzma_literal_coder literal_coder;
// Bit encoders // Bit encoders
probability is_match[STATES][POS_STATES_MAX]; probability is_match[STATES][POS_STATES_MAX];

View File

@ -22,7 +22,7 @@
extern lzma_ret extern lzma_ret
lzma_literal_init(lzma_literal_coder **coder, lzma_allocator *allocator, lzma_literal_init(lzma_literal_coder *coder,
uint32_t literal_context_bits, uint32_t literal_pos_bits) uint32_t literal_context_bits, uint32_t literal_pos_bits)
{ {
// Verify that arguments are sane. // Verify that arguments are sane.
@ -34,41 +34,18 @@ lzma_literal_init(lzma_literal_coder **coder, lzma_allocator *allocator,
const uint32_t states = literal_states( const uint32_t states = literal_states(
literal_pos_bits, literal_context_bits); literal_pos_bits, literal_context_bits);
// Allocate a new literal coder, if needed.
if (*coder == NULL || (**coder).literal_context_bits
!= literal_context_bits
|| (**coder).literal_pos_bits != literal_pos_bits) {
// Free the old coder, if any.
lzma_free(*coder, allocator);
// Allocate a new one.
*coder = lzma_alloc(sizeof(lzma_literal_coder)
+ states * LIT_SIZE * sizeof(probability),
allocator);
if (*coder == NULL)
return LZMA_MEM_ERROR;
// Store the new settings. // Store the new settings.
(**coder).literal_context_bits = literal_context_bits; coder->literal_context_bits = literal_context_bits;
(**coder).literal_pos_bits = literal_pos_bits; coder->literal_pos_bits = literal_pos_bits;
// Calculate also the literal_pos_mask. It's not changed // Calculate also the literal_pos_mask. It's not changed
// anywhere else than here. // anywhere else than here.
(**coder).literal_pos_mask = (1 << literal_pos_bits) - 1; coder->literal_pos_mask = (1 << literal_pos_bits) - 1;
}
// Reset the literal coder. // Reset the literal coder.
for (uint32_t i = 0; i < states; ++i) for (uint32_t i = 0; i < states; ++i)
for (uint32_t j = 0; j < LIT_SIZE; ++j) for (uint32_t j = 0; j < LIT_SIZE; ++j)
bit_reset((**coder).coders[i][j]); bit_reset(coder->coders[i][j]);
return LZMA_OK; return LZMA_OK;
} }
extern void
lzma_literal_end(lzma_literal_coder **coder, lzma_allocator *allocator)
{
lzma_free(*coder, allocator);
*coder = NULL;
}

View File

@ -45,9 +45,9 @@
/// byte; and /// byte; and
/// - the highest literal_context_bits bits of the previous byte. /// - the highest literal_context_bits bits of the previous byte.
#define literal_get_subcoder(literal_coder, pos, prev_byte) \ #define literal_get_subcoder(literal_coder, pos, prev_byte) \
(literal_coder)->coders[(((pos) & (literal_coder)->literal_pos_mask) \ (literal_coder).coders[(((pos) & (literal_coder).literal_pos_mask) \
<< (literal_coder)->literal_context_bits) \ << (literal_coder).literal_context_bits) \
+ ((prev_byte) >> (8 - (literal_coder)->literal_context_bits))] + ((prev_byte) >> (8 - (literal_coder).literal_context_bits))]
typedef struct { typedef struct {
@ -59,16 +59,13 @@ typedef struct {
/// There are (1 << (literal_pos_bits + literal_context_bits)) /// There are (1 << (literal_pos_bits + literal_context_bits))
/// literal coders. /// literal coders.
probability coders[][LIT_SIZE]; probability coders[1 << LZMA_LITERAL_BITS_MAX][LIT_SIZE];
} lzma_literal_coder; } lzma_literal_coder;
extern lzma_ret lzma_literal_init( extern lzma_ret lzma_literal_init(
lzma_literal_coder **coder, lzma_allocator *allocator, lzma_literal_coder *coder,
uint32_t literal_context_bits, uint32_t literal_pos_bits); uint32_t literal_context_bits, uint32_t literal_pos_bits);
extern void lzma_literal_end(
lzma_literal_coder **coder, lzma_allocator *allocator);
#endif #endif