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;
# 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
/**
@ -278,6 +278,14 @@ typedef struct {
} 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
*

View File

@ -115,7 +115,7 @@ struct lzma_coder_s {
uint32_t pos_mask;
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.
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_lz_decoder_end(&coder->lz, allocator);
lzma_literal_end(&coder->literal_coder, allocator);
lzma_free(coder, allocator);
return;
}
@ -661,6 +660,9 @@ extern lzma_ret
lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
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
// respective initialization functions.
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)
return LZMA_MEM_ERROR;
// Initialize variables so that we know later that we don't
// have an existing decoder initialized.
next->code = &lzma_lz_decode;
next->end = &lzma_decoder_end;
next->coder->next = LZMA_NEXT_CODER_INIT;
next->coder->lz = LZMA_LZ_DECODER_INIT;
next->coder->literal_coder = NULL;
}
// Store the pos_bits and calculate pos_mask.
next->coder->pos_bits = options->pos_bits;
next->coder->pos_mask = (1U << next->coder->pos_bits) - 1;
// Allocate (if needed) and initialize the literal decoder.
{
const lzma_ret ret = lzma_literal_init(
&next->coder->literal_coder, allocator,
// Initialize the literal decoder.
return_if_error(lzma_literal_init(&next->coder->literal_coder,
options->literal_context_bits,
options->literal_pos_bits);
if (ret != LZMA_OK) {
lzma_free(next->coder, allocator);
next->coder = NULL;
return ret;
}
}
options->literal_pos_bits));
// Allocate and initialize the LZ decoder.
{
const lzma_ret ret = lzma_lz_decoder_reset(
&next->coder->lz, allocator, &decode_real,
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;
}
}
return_if_error(lzma_lz_decoder_reset(&next->coder->lz, allocator,
&decode_real, options->dictionary_size,
MATCH_MAX_LEN));
// State
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;
// 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;
}
@ -808,5 +778,6 @@ lzma_lzma_decode_properties(lzma_options_lzma *options, uint8_t byte)
options->literal_pos_bits = byte / 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_lz_encoder_end(&coder->lz, allocator);
lzma_literal_end(&coder->literal_coder, allocator);
lzma_free(coder, allocator);
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->lz = LZMA_LZ_ENCODER_INIT;
next->coder->literal_coder = NULL;
}
// Validate options that aren't validated elsewhere.
@ -99,13 +97,11 @@ lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Initialize literal coder.
{
const lzma_ret ret = lzma_literal_init(
&next->coder->literal_coder, allocator,
&next->coder->literal_coder,
options->literal_context_bits,
options->literal_pos_bits);
if (ret != LZMA_OK) {
lzma_lzma_encoder_end(next->coder, allocator);
if (ret != LZMA_OK)
return ret;
}
}
// 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
|| options->literal_pos_bits
> 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;
*byte = (options->pos_bits * 5 + options->literal_pos_bits) * 9

View File

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

View File

@ -22,7 +22,7 @@
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)
{
// 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(
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);
// Store the new settings.
coder->literal_context_bits = literal_context_bits;
coder->literal_pos_bits = literal_pos_bits;
// 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.
(**coder).literal_context_bits = literal_context_bits;
(**coder).literal_pos_bits = literal_pos_bits;
// Calculate also the literal_pos_mask. It's not changed
// anywhere else than here.
(**coder).literal_pos_mask = (1 << literal_pos_bits) - 1;
}
// Calculate also the literal_pos_mask. It's not changed
// anywhere else than here.
coder->literal_pos_mask = (1 << literal_pos_bits) - 1;
// Reset the literal coder.
for (uint32_t i = 0; i < states; ++i)
for (uint32_t j = 0; j < LIT_SIZE; ++j)
bit_reset((**coder).coders[i][j]);
bit_reset(coder->coders[i][j]);
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
/// - the highest literal_context_bits bits of the previous byte.
#define literal_get_subcoder(literal_coder, pos, prev_byte) \
(literal_coder)->coders[(((pos) & (literal_coder)->literal_pos_mask) \
<< (literal_coder)->literal_context_bits) \
+ ((prev_byte) >> (8 - (literal_coder)->literal_context_bits))]
(literal_coder).coders[(((pos) & (literal_coder).literal_pos_mask) \
<< (literal_coder).literal_context_bits) \
+ ((prev_byte) >> (8 - (literal_coder).literal_context_bits))]
typedef struct {
@ -59,16 +59,13 @@ typedef struct {
/// There are (1 << (literal_pos_bits + literal_context_bits))
/// literal coders.
probability coders[][LIT_SIZE];
probability coders[1 << LZMA_LITERAL_BITS_MAX][LIT_SIZE];
} lzma_literal_coder;
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);
extern void lzma_literal_end(
lzma_literal_coder **coder, lzma_allocator *allocator);
#endif