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:
parent
d25ab1b961
commit
0809c46534
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue