Added LZMA_SYNC_FLUSH support to the Copy filter.

This commit is contained in:
Lasse Collin 2007-12-09 21:43:15 +02:00
parent 329c272d50
commit 2ab8adb516
1 changed files with 57 additions and 35 deletions

View File

@ -23,12 +23,12 @@
struct lzma_coder_s { struct lzma_coder_s {
lzma_next_coder next; lzma_next_coder next;
lzma_vli uncompressed_size; lzma_vli uncompressed_size;
bool is_encoder;
}; };
#ifdef HAVE_ENCODER
static lzma_ret static lzma_ret
copy_code(lzma_coder *coder, lzma_allocator *allocator, copy_encode(lzma_coder *coder, lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos, const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size, uint8_t *restrict out, size_t in_size, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size, lzma_action action) size_t *restrict out_pos, size_t out_size, lzma_action action)
@ -43,48 +43,71 @@ copy_code(lzma_coder *coder, lzma_allocator *allocator,
action); action);
// If we get here, we are the last filter in the chain. // If we get here, we are the last filter in the chain.
assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
const size_t in_avail = in_size - *in_pos; const size_t in_avail = in_size - *in_pos;
if (coder->is_encoder) { // Check that we don't have too much input.
// Check that we don't have too much input. if ((lzma_vli)(in_avail) > coder->uncompressed_size)
if ((lzma_vli)(in_avail) > coder->uncompressed_size) return LZMA_DATA_ERROR;
return LZMA_DATA_ERROR;
// Check that once LZMA_FINISH has been given, the // Check that once LZMA_FINISH has been given, the amount of input
// amount of input matches uncompressed_size if it // matches uncompressed_size, which is always known.
// is known. if (action == LZMA_FINISH
if (action == LZMA_FINISH && coder->uncompressed_size && coder->uncompressed_size != (lzma_vli)(in_avail))
!= LZMA_VLI_VALUE_UNKNOWN return LZMA_DATA_ERROR;
&& coder->uncompressed_size
!= (lzma_vli)(in_avail))
return LZMA_DATA_ERROR;
} else {
// Limit in_size so that we don't copy too much.
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
in_size = *in_pos + (size_t)(coder->uncompressed_size);
}
// Store the old input position, which is needed to update
// coder->uncompressed_size.
const size_t in_start = *in_pos;
// We are the last coder in the chain. // We are the last coder in the chain.
// Just copy as much data as possible. // Just copy as much data as possible.
bufcpy(in, in_pos, in_size, out, out_pos, out_size); const size_t in_used = bufcpy(
in, in_pos, in_size, out, out_pos, out_size);
// Update uncompressed_size if it is known. // Update uncompressed_size if it is known.
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->uncompressed_size -= *in_pos - in_start; coder->uncompressed_size -= in_used;
// action can be LZMA_FINISH only in the encoder. // LZMA_SYNC_FLUSH and LZMA_FINISH are the same thing for us.
if ((action == LZMA_FINISH && *in_pos == in_size) if ((action != LZMA_RUN && *in_pos == in_size)
|| coder->uncompressed_size == 0) || coder->uncompressed_size == 0)
return LZMA_STREAM_END; return LZMA_STREAM_END;
return LZMA_OK; return LZMA_OK;
} }
#endif
#ifdef HAVE_DECODER
static lzma_ret
copy_decode(lzma_coder *coder, lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size, lzma_action action)
{
if (coder->next.code != NULL)
return coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
const size_t in_avail = in_size - *in_pos;
// Limit in_size so that we don't copy too much.
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
in_size = *in_pos + (size_t)(coder->uncompressed_size);
// We are the last coder in the chain.
// Just copy as much data as possible.
const size_t in_used = bufcpy(
in, in_pos, in_size, out, out_pos, out_size);
// Update uncompressed_size if it is known.
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->uncompressed_size -= in_used;
return coder->uncompressed_size == 0 ? LZMA_STREAM_END : LZMA_OK;
}
#endif
static void static void
@ -98,7 +121,7 @@ copy_coder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret static lzma_ret
copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator, copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder) const lzma_filter_info *filters, lzma_code_function encode)
{ {
// Allocate memory for the decoder if needed. // Allocate memory for the decoder if needed.
if (next->coder == NULL) { if (next->coder == NULL) {
@ -106,7 +129,7 @@ copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
if (next->coder == NULL) if (next->coder == NULL)
return LZMA_MEM_ERROR; return LZMA_MEM_ERROR;
next->code = &copy_code; next->code = encode;
next->end = &copy_coder_end; next->end = &copy_coder_end;
next->coder->next = LZMA_NEXT_CODER_INIT; next->coder->next = LZMA_NEXT_CODER_INIT;
} }
@ -114,9 +137,6 @@ copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Copy Uncompressed Size which is used to limit the output size. // Copy Uncompressed Size which is used to limit the output size.
next->coder->uncompressed_size = filters[0].uncompressed_size; next->coder->uncompressed_size = filters[0].uncompressed_size;
// The coder acts slightly differently as encoder and decoder.
next->coder->is_encoder = is_encoder;
// Initialize the next decoder in the chain, if any. // Initialize the next decoder in the chain, if any.
return lzma_next_filter_init( return lzma_next_filter_init(
&next->coder->next, allocator, filters + 1); &next->coder->next, allocator, filters + 1);
@ -128,7 +148,8 @@ extern lzma_ret
lzma_copy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_copy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters) const lzma_filter_info *filters)
{ {
lzma_next_coder_init(copy_coder_init, next, allocator, filters, true); lzma_next_coder_init(copy_coder_init, next, allocator, filters,
&copy_encode);
} }
#endif #endif
@ -138,6 +159,7 @@ extern lzma_ret
lzma_copy_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_copy_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters) const lzma_filter_info *filters)
{ {
lzma_next_coder_init(copy_coder_init, next, allocator, filters, false); lzma_next_coder_init(copy_coder_init, next, allocator, filters,
&copy_decode);
} }
#endif #endif