aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/liblzma/common')
-rw-r--r--src/liblzma/common/Makefile.am51
-rw-r--r--src/liblzma/common/alignment.c4
-rw-r--r--src/liblzma/common/allocator.c58
-rw-r--r--src/liblzma/common/alone_decoder.c49
-rw-r--r--src/liblzma/common/alone_decoder.h9
-rw-r--r--src/liblzma/common/alone_encoder.c13
-rw-r--r--src/liblzma/common/auto_decoder.c38
-rw-r--r--src/liblzma/common/block_decoder.c67
-rw-r--r--src/liblzma/common/block_decoder.h2
-rw-r--r--src/liblzma/common/block_encoder.c42
-rw-r--r--src/liblzma/common/block_encoder.h2
-rw-r--r--src/liblzma/common/block_header_decoder.c6
-rw-r--r--src/liblzma/common/block_header_encoder.c9
-rw-r--r--src/liblzma/common/block_util.c10
-rw-r--r--src/liblzma/common/common.c (renamed from src/liblzma/common/code.c)129
-rw-r--r--src/liblzma/common/common.h237
-rw-r--r--src/liblzma/common/delta_common.c66
-rw-r--r--src/liblzma/common/delta_decoder.c61
-rw-r--r--src/liblzma/common/delta_decoder.h28
-rw-r--r--src/liblzma/common/delta_encoder.c98
-rw-r--r--src/liblzma/common/easy.c18
-rw-r--r--src/liblzma/common/features.c66
-rw-r--r--src/liblzma/common/filter_common.c262
-rw-r--r--src/liblzma/common/filter_common.h52
-rw-r--r--src/liblzma/common/filter_decoder.c236
-rw-r--r--src/liblzma/common/filter_decoder.h (renamed from src/liblzma/common/raw_common.h)23
-rw-r--r--src/liblzma/common/filter_encoder.c308
-rw-r--r--src/liblzma/common/filter_encoder.h (renamed from src/liblzma/common/delta_common.h)32
-rw-r--r--src/liblzma/common/filter_flags_decoder.c185
-rw-r--r--src/liblzma/common/filter_flags_encoder.c261
-rw-r--r--src/liblzma/common/index_decoder.c14
-rw-r--r--src/liblzma/common/index_encoder.c16
-rw-r--r--src/liblzma/common/index_hash.c8
-rw-r--r--src/liblzma/common/init_encoder.c2
-rw-r--r--src/liblzma/common/memory_usage.c112
-rw-r--r--src/liblzma/common/next_coder.c65
-rw-r--r--src/liblzma/common/raw_common.c127
-rw-r--r--src/liblzma/common/raw_decoder.c116
-rw-r--r--src/liblzma/common/raw_decoder.h29
-rw-r--r--src/liblzma/common/raw_encoder.c111
-rw-r--r--src/liblzma/common/raw_encoder.h29
-rw-r--r--src/liblzma/common/stream_common.c23
-rw-r--r--src/liblzma/common/stream_decoder.c238
-rw-r--r--src/liblzma/common/stream_decoder.h4
-rw-r--r--src/liblzma/common/stream_encoder.c35
-rw-r--r--src/liblzma/common/stream_encoder.h2
-rw-r--r--src/liblzma/common/stream_flags_common.c (renamed from src/liblzma/common/stream_flags_equal.c)14
-rw-r--r--src/liblzma/common/stream_flags_common.h (renamed from src/liblzma/common/stream_common.h)8
-rw-r--r--src/liblzma/common/stream_flags_decoder.c2
-rw-r--r--src/liblzma/common/stream_flags_encoder.c2
-rw-r--r--src/liblzma/common/version.c25
-rw-r--r--src/liblzma/common/vli_decoder.c29
-rw-r--r--src/liblzma/common/vli_encoder.c23
-rw-r--r--src/liblzma/common/vli_size.c (renamed from src/liblzma/common/delta_encoder.h)27
54 files changed, 1583 insertions, 1900 deletions
diff --git a/src/liblzma/common/Makefile.am b/src/liblzma/common/Makefile.am
index 40b42250..3ec2e270 100644
--- a/src/liblzma/common/Makefile.am
+++ b/src/liblzma/common/Makefile.am
@@ -16,62 +16,43 @@ noinst_LTLIBRARIES = libcommon.la
libcommon_la_CPPFLAGS = \
-I@top_srcdir@/src/liblzma/api \
-I@top_srcdir@/src/liblzma/check \
+ -I@top_srcdir@/src/liblzma/rangecoder \
-I@top_srcdir@/src/liblzma/lz \
-I@top_srcdir@/src/liblzma/lzma \
- -I@top_srcdir@/src/liblzma/simple \
-I@top_srcdir@/src/liblzma/subblock \
- -I@top_srcdir@/src/liblzma/rangecoder
+ -I@top_srcdir@/src/liblzma/delta \
+ -I@top_srcdir@/src/liblzma/simple
+
libcommon_la_SOURCES = \
+ common.c \
common.h \
bsr.h \
- allocator.c \
block_util.c \
block_private.h \
- features.c \
+ filter_common.c \
+ filter_common.h \
index.c \
+ index.h \
init.c \
memory_limiter.c \
- memory_usage.c \
- next_coder.c \
- raw_common.c \
- raw_common.h \
- stream_flags_equal.c \
- code.c \
- version.c
-
-if COND_FILTER_DELTA
-libcommon_la_SOURCES += \
- delta_common.c \
- delta_common.h
-if COND_MAIN_ENCODER
-libcommon_la_SOURCES += \
- delta_encoder.c \
- delta_encoder.h
-endif
-if COND_MAIN_DECODER
-libcommon_la_SOURCES += \
- delta_decoder.c \
- delta_decoder.h
-endif
-endif
+ stream_flags_common.c \
+ stream_flags_common.h \
+ vli_size.c
if COND_MAIN_ENCODER
libcommon_la_SOURCES += \
alignment.c \
- auto_decoder.c \
alone_encoder.c \
block_encoder.c \
block_encoder.h \
block_header_encoder.c \
easy.c \
+ filter_encoder.c \
+ filter_encoder.h \
filter_flags_encoder.c \
index_encoder.c \
index_encoder.h \
init_encoder.c \
- raw_encoder.c \
- raw_encoder.h \
- stream_common.c \
- stream_common.h \
stream_encoder.c \
stream_encoder.h \
stream_flags_encoder.c \
@@ -82,16 +63,18 @@ if COND_MAIN_DECODER
libcommon_la_SOURCES += \
alone_decoder.c \
alone_decoder.h \
+ auto_decoder.c \
block_decoder.c \
block_decoder.h \
block_header_decoder.c \
+ filter_decoder.c \
+ filter_decoder.h \
filter_flags_decoder.c \
index_decoder.c \
index_hash.c \
init_decoder.c \
- raw_decoder.c \
- raw_decoder.h \
stream_decoder.c \
+ stream_decoder.h \
stream_flags_decoder.c \
stream_flags_decoder.h \
vli_decoder.c
diff --git a/src/liblzma/common/alignment.c b/src/liblzma/common/alignment.c
index c80e5fab..ba9ecb03 100644
--- a/src/liblzma/common/alignment.c
+++ b/src/liblzma/common/alignment.c
@@ -21,7 +21,7 @@
extern LZMA_API uint32_t
-lzma_alignment_input(const lzma_options_filter *filters, uint32_t guess)
+lzma_alignment_input(const lzma_filter *filters, uint32_t guess)
{
for (size_t i = 0; filters[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
switch (filters[i].id) {
@@ -66,7 +66,7 @@ lzma_alignment_input(const lzma_options_filter *filters, uint32_t guess)
extern LZMA_API uint32_t
-lzma_alignment_output(const lzma_options_filter *filters, uint32_t guess)
+lzma_alignment_output(const lzma_filter *filters, uint32_t guess)
{
if (filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
return UINT32_MAX;
diff --git a/src/liblzma/common/allocator.c b/src/liblzma/common/allocator.c
deleted file mode 100644
index 5ced9d16..00000000
--- a/src/liblzma/common/allocator.c
+++ /dev/null
@@ -1,58 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file allocator.c
-/// \brief Allocating and freeing memory
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-
-#undef lzma_free
-
-extern void * lzma_attribute((malloc))
-lzma_alloc(size_t size, lzma_allocator *allocator)
-{
- // Some malloc() variants return NULL if called with size == 0.
- if (size == 0)
- size = 1;
-
- void *ptr;
-
- if (allocator != NULL && allocator->alloc != NULL)
- ptr = allocator->alloc(allocator->opaque, 1, size);
- else
- ptr = malloc(size);
-
-#ifndef NDEBUG
- // This helps to catch some stupid mistakes, but also hides them from
- // Valgrind. Uncomment when useful.
-// if (ptr != NULL)
-// memset(ptr, 0xFD, size);
-#endif
-
- return ptr;
-}
-
-
-extern void
-lzma_free(void *ptr, lzma_allocator *allocator)
-{
- if (allocator != NULL && allocator->free != NULL)
- allocator->free(allocator->opaque, ptr);
- else
- free(ptr);
-
- return;
-}
diff --git a/src/liblzma/common/alone_decoder.c b/src/liblzma/common/alone_decoder.c
index 062f6fab..006740f4 100644
--- a/src/liblzma/common/alone_decoder.c
+++ b/src/liblzma/common/alone_decoder.c
@@ -19,6 +19,7 @@
#include "alone_decoder.h"
#include "lzma_decoder.h"
+#include "lz_decoder.h"
struct lzma_coder_s {
@@ -38,6 +39,9 @@ struct lzma_coder_s {
/// Uncompressed size decoded from the header
lzma_vli uncompressed_size;
+ /// Memory usage limit
+ uint64_t memlimit;
+
/// Options decoded from the header needed to initialize
/// the LZMA decoder
lzma_options_lzma options;
@@ -56,7 +60,7 @@ alone_decode(lzma_coder *coder,
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
switch (coder->sequence) {
case SEQ_PROPERTIES:
- if (lzma_lzma_decode_properties(&coder->options, in[*in_pos]))
+ if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
return LZMA_FORMAT_ERROR;
coder->sequence = SEQ_DICTIONARY_SIZE;
@@ -69,8 +73,6 @@ alone_decode(lzma_coder *coder,
if (++coder->pos == 4) {
if (coder->options.dictionary_size
- < LZMA_DICTIONARY_SIZE_MIN
- || coder->options.dictionary_size
> LZMA_DICTIONARY_SIZE_MAX)
return LZMA_FORMAT_ERROR;
@@ -119,7 +121,20 @@ alone_decode(lzma_coder *coder,
break;
case SEQ_CODER_INIT: {
- // Two is enough because there won't be implicit filters.
+ // FIXME It is unfair that this doesn't add a fixed amount
+ // like lzma_memusage_common() does.
+ const uint64_t memusage
+ = lzma_lzma_decoder_memusage(&coder->options);
+
+ // Use LZMA_PROG_ERROR since LZMA_Alone decoder cannot be
+ // built without LZMA support.
+ // FIXME TODO Make the above comment true.
+ if (memusage == UINT64_MAX)
+ return LZMA_PROG_ERROR;
+
+ if (memusage > coder->memlimit)
+ return LZMA_MEMLIMIT_ERROR;
+
lzma_filter_info filters[2] = {
{
.init = &lzma_lzma_decoder_init,
@@ -135,7 +150,7 @@ alone_decode(lzma_coder *coder,
return ret;
// Use a hack to set the uncompressed size.
- lzma_lzma_decoder_uncompressed_size(&coder->next,
+ lzma_lz_decoder_uncompressed(coder->next.coder,
coder->uncompressed_size);
coder->sequence = SEQ_CODE;
@@ -160,15 +175,18 @@ alone_decode(lzma_coder *coder,
static void
alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->next, allocator);
+ lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
-static lzma_ret
-alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
+extern lzma_ret
+lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ uint64_t memlimit)
{
+ lzma_next_coder_init(lzma_alone_decoder_init, next, allocator);
+
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
@@ -183,25 +201,20 @@ alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
next->coder->pos = 0;
next->coder->options.dictionary_size = 0;
next->coder->uncompressed_size = 0;
+ next->coder->memlimit = memlimit;
return LZMA_OK;
}
-extern lzma_ret
-lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
-{
- lzma_next_coder_init0(alone_decoder_init, next, allocator);
-}
-
-
extern LZMA_API lzma_ret
-lzma_alone_decoder(lzma_stream *strm)
+lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
{
- lzma_next_strm_init0(strm, alone_decoder_init);
+ lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit);
strm->internal->supported_actions[LZMA_RUN] = true;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+// strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; FIXME
+ strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;
}
diff --git a/src/liblzma/common/alone_decoder.h b/src/liblzma/common/alone_decoder.h
index a9b7e84b..13284043 100644
--- a/src/liblzma/common/alone_decoder.h
+++ b/src/liblzma/common/alone_decoder.h
@@ -17,8 +17,13 @@
//
///////////////////////////////////////////////////////////////////////////////
+#ifndef LZMA_ALONE_DECODER_H
+#define LZMA_ALONE_DECODER_H
+
#include "common.h"
-extern lzma_ret lzma_alone_decoder_init(
- lzma_next_coder *next, lzma_allocator *allocator);
+extern lzma_ret lzma_alone_decoder_init(lzma_next_coder *next,
+ lzma_allocator *allocator, uint64_t memlimit);
+
+#endif
diff --git a/src/liblzma/common/alone_encoder.c b/src/liblzma/common/alone_encoder.c
index f94a21c1..7fb11570 100644
--- a/src/liblzma/common/alone_encoder.c
+++ b/src/liblzma/common/alone_encoder.c
@@ -48,7 +48,7 @@ alone_encode(lzma_coder *coder,
while (*out_pos < out_size)
switch (coder->sequence) {
case SEQ_HEADER:
- bufcpy(coder->header, &coder->header_pos,
+ lzma_bufcpy(coder->header, &coder->header_pos,
ALONE_HEADER_SIZE,
out, out_pos, out_size);
if (coder->header_pos < ALONE_HEADER_SIZE)
@@ -74,7 +74,7 @@ alone_encode(lzma_coder *coder,
static void
alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->next, allocator);
+ lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
@@ -85,6 +85,8 @@ static lzma_ret
alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_lzma *options)
{
+ lzma_next_coder_init(alone_encoder_init, next, allocator);
+
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
@@ -101,7 +103,7 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Encode the header:
// - Properties (1 byte)
- if (lzma_lzma_encode_properties(options, next->coder->header))
+ if (lzma_lzma_lclppb_encode(options, next->coder->header))
return LZMA_PROG_ERROR;
// - Dictionary size (4 bytes)
@@ -113,6 +115,9 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// one is the next. While the header would allow any 32-bit integer,
// we do this to keep the decoder of liblzma accepting the resulting
// files.
+ //
+ // FIXME Maybe LZMA_Alone needs some lower limit for maximum
+ // dictionary size? Must check decoders from old LZMA SDK version.
uint32_t d = options->dictionary_size - 1;
d |= d >> 2;
d |= d >> 3;
@@ -153,7 +158,7 @@ lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API lzma_ret
lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
{
- lzma_next_strm_init(strm, alone_encoder_init, options);
+ lzma_next_strm_init(alone_encoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/src/liblzma/common/auto_decoder.c b/src/liblzma/common/auto_decoder.c
index 765a27b1..5fcdf168 100644
--- a/src/liblzma/common/auto_decoder.c
+++ b/src/liblzma/common/auto_decoder.c
@@ -23,6 +23,8 @@
struct lzma_coder_s {
lzma_next_coder next;
+ uint64_t memlimit;
+ uint32_t flags;
bool initialized;
};
@@ -41,9 +43,11 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
if (in[*in_pos] == 0xFF)
ret = lzma_stream_decoder_init(
- &coder->next, allocator);
+ &coder->next, allocator,
+ coder->memlimit, coder->flags);
else
- ret = lzma_alone_decoder_init(&coder->next, allocator);
+ ret = lzma_alone_decoder_init(&coder->next,
+ allocator, coder->memlimit);
if (ret != LZMA_OK)
return ret;
@@ -59,15 +63,21 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->next, allocator);
+ lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
static lzma_ret
-auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
+auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ uint64_t memlimit, uint32_t flags)
{
+ lzma_next_coder_init(auto_decoder_init, next, allocator);
+
+ if (flags & ~LZMA_SUPPORTED_FLAGS)
+ return LZMA_HEADER_ERROR;
+
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
@@ -78,30 +88,22 @@ auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
next->coder->next = LZMA_NEXT_CODER_INIT;
}
+ next->coder->memlimit = memlimit;
+ next->coder->flags = flags;
next->coder->initialized = false;
return LZMA_OK;
}
-/*
-extern lzma_ret
-lzma_auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_extra **header, lzma_extra **footer)
-{
- lzma_next_coder_init(
- auto_decoder_init, next, allocator, header, footer);
-}
-*/
-
-
extern LZMA_API lzma_ret
-lzma_auto_decoder(lzma_stream *strm)
+lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{
- lzma_next_strm_init0(strm, auto_decoder_init);
+ lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+// strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; FIXME
+ strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;
}
diff --git a/src/liblzma/common/block_decoder.c b/src/liblzma/common/block_decoder.c
index f07c4e06..2c16a204 100644
--- a/src/liblzma/common/block_decoder.c
+++ b/src/liblzma/common/block_decoder.c
@@ -19,7 +19,7 @@
#include "block_decoder.h"
#include "block_private.h"
-#include "raw_decoder.h"
+#include "filter_decoder.h"
#include "check.h"
@@ -35,7 +35,7 @@ struct lzma_coder_s {
/// Decoding options; we also write Compressed Size and Uncompressed
/// Size back to this structure when the encoding has been finished.
- lzma_options_block *options;
+ lzma_block *options;
/// Compressed Size calculated while encoding
lzma_vli compressed_size;
@@ -52,7 +52,7 @@ struct lzma_coder_s {
size_t check_pos;
/// Check of the uncompressed data
- lzma_check check;
+ lzma_check_state check;
};
@@ -64,9 +64,6 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
{
switch (coder->sequence) {
case SEQ_CODE: {
- if (*out_pos >= out_size)
- return LZMA_OK;
-
const size_t in_start = *in_pos;
const size_t out_start = *out_pos;
@@ -98,7 +95,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through
case SEQ_PADDING:
- // If Compressed Data is padded to a multiple of four bytes.
+ // Compressed Data is padded to a multiple of four bytes.
while (coder->compressed_size & 3) {
if (*in_pos >= in_size)
return LZMA_OK;
@@ -132,19 +129,29 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through
- case SEQ_CHECK:
+ case SEQ_CHECK: {
+ const bool chksup = lzma_check_is_supported(
+ coder->options->check);
+
while (*in_pos < in_size) {
- if (in[(*in_pos)++] != coder->check.buffer[
- coder->check_pos])
+ // coder->check.buffer[] may be uninitialized when
+ // the Check ID is not supported.
+ if (chksup && coder->check.buffer.u8[coder->check_pos]
+ != in[*in_pos]) {
+ ++*in_pos;
return LZMA_DATA_ERROR;
+ }
- if (++coder->check_pos == lzma_check_sizes[
- coder->options->check])
+ ++*in_pos;
+
+ if (++coder->check_pos == lzma_check_size(
+ coder->options->check))
return LZMA_STREAM_END;
}
return LZMA_OK;
}
+ }
return LZMA_PROG_ERROR;
}
@@ -153,21 +160,28 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->next, allocator);
+ lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
-static lzma_ret
-block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_options_block *options)
+extern lzma_ret
+lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_block *options)
{
+ lzma_next_coder_init(lzma_block_decoder_init, next, allocator);
+
// While lzma_block_total_size_get() is meant to calculate the Total
// Size, it also validates the options excluding the filters.
if (lzma_block_total_size_get(options) == 0)
return LZMA_PROG_ERROR;
+ // options->check is used for array indexing so we need to know that
+ // it is in the valid range.
+ if ((unsigned)(options->check) > LZMA_CHECK_ID_MAX)
+ return LZMA_PROG_ERROR;
+
// Allocate and initialize *next->coder if needed.
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
@@ -192,30 +206,25 @@ block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
= options->compressed_size == LZMA_VLI_VALUE_UNKNOWN
? (LZMA_VLI_VALUE_MAX & ~LZMA_VLI_C(3))
- options->header_size
- - lzma_check_sizes[options->check]
+ - lzma_check_size(options->check)
: options->compressed_size;
- // Initialize the check
+ // Initialize the check. It's caller's problem if the Check ID is not
+ // supported, and the Block decoder cannot verify the Check field.
+ // Caller can test lzma_checks[options->check].
next->coder->check_pos = 0;
- return_if_error(lzma_check_init(&next->coder->check, options->check));
+ lzma_check_init(&next->coder->check, options->check);
+ // Initialize the filter chain.
return lzma_raw_decoder_init(&next->coder->next, allocator,
options->filters);
}
-extern lzma_ret
-lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_options_block *options)
-{
- lzma_next_coder_init(block_decoder_init, next, allocator, options);
-}
-
-
extern LZMA_API lzma_ret
-lzma_block_decoder(lzma_stream *strm, lzma_options_block *options)
+lzma_block_decoder(lzma_stream *strm, lzma_block *options)
{
- lzma_next_strm_init(strm, block_decoder_init, options);
+ lzma_next_strm_init(lzma_block_decoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
diff --git a/src/liblzma/common/block_decoder.h b/src/liblzma/common/block_decoder.h
index af71128d..999aa748 100644
--- a/src/liblzma/common/block_decoder.h
+++ b/src/liblzma/common/block_decoder.h
@@ -24,6 +24,6 @@
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_options_block *options);
+ lzma_allocator *allocator, lzma_block *options);
#endif
diff --git a/src/liblzma/common/block_encoder.c b/src/liblzma/common/block_encoder.c
index 3add45a9..5aa3626b 100644
--- a/src/liblzma/common/block_encoder.c
+++ b/src/liblzma/common/block_encoder.c
@@ -19,7 +19,7 @@
#include "block_encoder.h"
#include "block_private.h"
-#include "raw_encoder.h"
+#include "filter_encoder.h"
#include "check.h"
@@ -30,7 +30,7 @@ struct lzma_coder_s {
/// Encoding options; we also write Total Size, Compressed Size, and
/// Uncompressed Size back to this structure when the encoding has
/// been finished.
- lzma_options_block *options;
+ lzma_block *options;
enum {
SEQ_CODE,
@@ -48,7 +48,7 @@ struct lzma_coder_s {
size_t check_pos;
/// Check of the uncompressed data
- lzma_check check;
+ lzma_check_state check;
};
@@ -147,11 +147,11 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through
case SEQ_CHECK:
- out[*out_pos] = coder->check.buffer[coder->check_pos];
+ out[*out_pos] = coder->check.buffer.u8[coder->check_pos];
++*out_pos;
if (++coder->check_pos
- == lzma_check_sizes[coder->options->check])
+ == lzma_check_size(coder->options->check))
return LZMA_STREAM_END;
break;
@@ -167,21 +167,31 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
static void
block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->next, allocator);
+ lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
-static lzma_ret
-block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_options_block *options)
+extern lzma_ret
+lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_block *options)
{
+ lzma_next_coder_init(lzma_block_encoder_init, next, allocator);
+
// While lzma_block_total_size_get() is meant to calculate the Total
// Size, it also validates the options excluding the filters.
if (lzma_block_total_size_get(options) == 0)
return LZMA_PROG_ERROR;
+ // If the Check ID is not supported, we cannot calculate the check and
+ // thus not create a proper Block.
+ if ((unsigned)(options->check) > LZMA_CHECK_ID_MAX)
+ return LZMA_PROG_ERROR;
+
+ if (!lzma_check_is_supported(options->check))
+ return LZMA_UNSUPPORTED_CHECK;
+
// Allocate and initialize *next->coder if needed.
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
@@ -201,7 +211,7 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Initialize the check
next->coder->check_pos = 0;
- return_if_error(lzma_check_init(&next->coder->check, options->check));
+ lzma_check_init(&next->coder->check, options->check);
// Initialize the requested filters.
return lzma_raw_encoder_init(&next->coder->next, allocator,
@@ -209,18 +219,10 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
}
-extern lzma_ret
-lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_options_block *options)
-{
- lzma_next_coder_init(block_encoder_init, next, allocator, options);
-}
-
-
extern LZMA_API lzma_ret
-lzma_block_encoder(lzma_stream *strm, lzma_options_block *options)
+lzma_block_encoder(lzma_stream *strm, lzma_block *options)
{
- lzma_next_strm_init(strm, block_encoder_init, options);
+ lzma_next_strm_init(lzma_block_encoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/src/liblzma/common/block_encoder.h b/src/liblzma/common/block_encoder.h
index eafcc618..7bc40139 100644
--- a/src/liblzma/common/block_encoder.h
+++ b/src/liblzma/common/block_encoder.h
@@ -24,6 +24,6 @@
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_options_block *options);
+ lzma_allocator *allocator, lzma_block *options);
#endif
diff --git a/src/liblzma/common/block_header_decoder.c b/src/liblzma/common/block_header_decoder.c
index b9e072e0..1d75f335 100644
--- a/src/liblzma/common/block_header_decoder.c
+++ b/src/liblzma/common/block_header_decoder.c
@@ -22,7 +22,7 @@
static void
-free_properties(lzma_options_block *options, lzma_allocator *allocator)
+free_properties(lzma_block *options, lzma_allocator *allocator)
{
// Free allocated filter options. The last array member is not
// touched after the initialization in the beginning of
@@ -38,12 +38,12 @@ free_properties(lzma_options_block *options, lzma_allocator *allocator)
extern LZMA_API lzma_ret
-lzma_block_header_decode(lzma_options_block *options,
+lzma_block_header_decode(lzma_block *options,
lzma_allocator *allocator, const uint8_t *in)
{
// NOTE: We consider the header to be corrupt not only when the
// CRC32 doesn't match, but also when variable-length integers
- // are invalid or not over 63 bits, or if the header is too small
+ // are invalid or over 63 bits, or if the header is too small
// to contain the claimed information.
// Initialize the filter options array. This way the caller can
diff --git a/src/liblzma/common/block_header_encoder.c b/src/liblzma/common/block_header_encoder.c
index ed0c88ba..3a16e6c3 100644
--- a/src/liblzma/common/block_header_encoder.c
+++ b/src/liblzma/common/block_header_encoder.c
@@ -22,7 +22,7 @@
extern LZMA_API lzma_ret
-lzma_block_header_size(lzma_options_block *options)
+lzma_block_header_size(lzma_block *options)
{
// Block Header Size + Block Flags + CRC32.
size_t size = 1 + 1 + 4;
@@ -77,7 +77,7 @@ lzma_block_header_size(lzma_options_block *options)
extern LZMA_API lzma_ret
-lzma_block_header_encode(const lzma_options_block *options, uint8_t *out)
+lzma_block_header_encode(const lzma_block *options, uint8_t *out)
{
if ((options->header_size & 3)
|| options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
@@ -127,8 +127,9 @@ lzma_block_header_encode(const lzma_options_block *options, uint8_t *out)
if (filter_count == 4)
return LZMA_PROG_ERROR;
- return_if_error(lzma_filter_flags_encode(out, &out_pos,
- out_size, options->filters + filter_count));
+ return_if_error(lzma_filter_flags_encode(
+ options->filters + filter_count,
+ out, &out_pos, out_size));
} while (options->filters[++filter_count].id
!= LZMA_VLI_VALUE_UNKNOWN);
diff --git a/src/liblzma/common/block_util.c b/src/liblzma/common/block_util.c
index 6bffc2f1..798163bb 100644
--- a/src/liblzma/common/block_util.c
+++ b/src/liblzma/common/block_util.c
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file block_header.c
-/// \brief Utility functions to handle lzma_options_block
+/// \brief Utility functions to handle lzma_block
//
// Copyright (C) 2008 Lasse Collin
//
@@ -21,7 +21,7 @@
extern LZMA_API lzma_ret
-lzma_block_total_size_set(lzma_options_block *options, lzma_vli total_size)
+lzma_block_total_size_set(lzma_block *options, lzma_vli total_size)
{
// Validate.
if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
@@ -32,7 +32,7 @@ lzma_block_total_size_set(lzma_options_block *options, lzma_vli total_size)
return LZMA_PROG_ERROR;
const uint32_t container_size = options->header_size
- + lzma_check_sizes[options->check];
+ + lzma_check_size(options->check);
// Validate that Compressed Size will be greater than zero.
if (container_size <= total_size)
@@ -45,7 +45,7 @@ lzma_block_total_size_set(lzma_options_block *options, lzma_vli total_size)
extern LZMA_API lzma_vli
-lzma_block_total_size_get(const lzma_options_block *options)
+lzma_block_total_size_get(const lzma_block *options)
{
// Validate the values that we are interested in.
if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
@@ -61,7 +61,7 @@ lzma_block_total_size_get(const lzma_options_block *options)
const lzma_vli total_size = options->compressed_size
+ options->header_size
- + lzma_check_sizes[options->check];
+ + lzma_check_size(options->check);
// Validate the calculated Total Size.
if (options->compressed_size > LZMA_VLI_VALUE_MAX
diff --git a/src/liblzma/common/code.c b/src/liblzma/common/common.c
index 0e3929b6..feac9cbf 100644
--- a/src/liblzma/common/code.c
+++ b/src/liblzma/common/common.c
@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file code.c
-/// \brief zlib-like API wrapper for liblzma's internal API
+/// \file common.h
+/// \brief Common functions needed in many places in liblzma
//
-// Copyright (C) 2007 Lasse Collin
+// Copyright (C) 2007-2008 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -20,19 +20,117 @@
#include "common.h"
-LZMA_API const lzma_stream LZMA_STREAM_INIT_VAR = {
- .next_in = NULL,
- .avail_in = 0,
- .total_in = 0,
- .next_out = NULL,
- .avail_out = 0,
- .total_out = 0,
- .allocator = NULL,
- .internal = NULL,
-};
+/////////////
+// Version //
+/////////////
+
+extern LZMA_API uint32_t
+lzma_version_number(void)
+{
+ return LZMA_VERSION;
+}
+
+
+extern LZMA_API const char *
+lzma_version_string(void)
+{
+ return PACKAGE_VERSION;
+}
+
+
+///////////////////////
+// Memory allocation //
+///////////////////////
+
+extern void * lzma_attribute((malloc))
+lzma_alloc(size_t size, lzma_allocator *allocator)
+{
+ // Some malloc() variants return NULL if called with size == 0.
+ if (size == 0)
+ size = 1;
+
+ void *ptr;
+
+ if (allocator != NULL && allocator->alloc != NULL)
+ ptr = allocator->alloc(allocator->opaque, 1, size);
+ else
+ ptr = malloc(size);
+
+ return ptr;
+}
+
+
+extern void
+lzma_free(void *ptr, lzma_allocator *allocator)
+{
+ if (allocator != NULL && allocator->free != NULL)
+ allocator->free(allocator->opaque, ptr);
+ else
+ free(ptr);
+
+ return;
+}
+
+
+//////////
+// Misc //
+//////////
+
+extern size_t
+lzma_bufcpy(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)
+{
+ const size_t in_avail = in_size - *in_pos;
+ const size_t out_avail = out_size - *out_pos;
+ const size_t copy_size = MIN(in_avail, out_avail);
+
+ memcpy(out + *out_pos, in + *in_pos, copy_size);
+
+ *in_pos += copy_size;
+ *out_pos += copy_size;
+
+ return copy_size;
+}
extern lzma_ret
+lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter_info *filters)
+{
+ lzma_next_coder_init(filters[0].init, next, allocator);
+
+ return filters[0].init == NULL
+ ? LZMA_OK : filters[0].init(next, allocator, filters);
+}
+
+
+extern void
+lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
+{
+ if (next->init != (uintptr_t)(NULL)) {
+ // To avoid tiny end functions that simply call
+ // lzma_free(coder, allocator), we allow leaving next->end
+ // NULL and call lzma_free() here.
+ if (next->end != NULL)
+ next->end(next->coder, allocator);
+ else
+ lzma_free(next->coder, allocator);
+
+ // Reset the variables so the we don't accidentally think
+ // that it is an already initialized coder.
+ *next = LZMA_NEXT_CODER_INIT;
+ }
+
+ return;
+}
+
+
+//////////////////////////////////////
+// External to internal API wrapper //
+//////////////////////////////////////
+
+extern lzma_ret
lzma_strm_init(lzma_stream *strm)
{
if (strm == NULL)
@@ -191,10 +289,7 @@ extern LZMA_API void
lzma_end(lzma_stream *strm)
{
if (strm != NULL && strm->internal != NULL) {
- if (strm->internal->next.end != NULL)
- strm->internal->next.end(strm->internal->next.coder,
- strm->allocator);
-
+ lzma_next_end(&strm->internal->next, strm->allocator);
lzma_free(strm->internal, strm->allocator);
strm->internal = NULL;
}
diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h
index 4f30427d..81f2a9a4 100644
--- a/src/liblzma/common/common.h
+++ b/src/liblzma/common/common.h
@@ -3,7 +3,7 @@
/// \file common.h
/// \brief Definitions common to the whole liblzma library
//
-// Copyright (C) 2007 Lasse Collin
+// Copyright (C) 2007-2008 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -46,16 +46,32 @@
#define LZMA_BUFFER_SIZE 4096
+/// Start of internal Filter ID space. These IDs must never be used
+/// in Streams.
+#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
+
+
/// Internal helper filter used by Subblock decoder. It is mapped to an
/// otherwise invalid Filter ID, which is impossible to get from any input
/// file (even if malicious file).
-#define LZMA_FILTER_SUBBLOCK_HELPER (UINT64_MAX - 2)
+#define LZMA_FILTER_SUBBLOCK_HELPER (LZMA_FILTER_RESERVED_START + 1)
+
+
+/// Supported flags that can be passed to lzma_stream_decoder()
+/// or lzma_auto_decoder().
+#define LZMA_SUPPORTED_FLAGS \
+ (LZMA_WARN_NO_CHECK \
+ | LZMA_WARN_UNSUPPORTED_CHECK \
+ | LZMA_TELL_CHECK \
+ | LZMA_CONCATENATED)
///////////
// Types //
///////////
+/// Type of encoder/decoder specific data; the actual structure is defined
+/// differently in different coders.
typedef struct lzma_coder_s lzma_coder;
typedef struct lzma_next_coder_s lzma_next_coder;
@@ -63,10 +79,15 @@ typedef struct lzma_next_coder_s lzma_next_coder;
typedef struct lzma_filter_info_s lzma_filter_info;
+/// Type of a function used to initialize a filter encoder or decoder
typedef lzma_ret (*lzma_init_function)(
lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters);
+/// Type of a function to do some kind of coding work (filters, Stream,
+/// Block encoders/decoders etc.). Some special coders use don't use both
+/// input and output buffers, but for simplicity they still use this same
+/// function prototype.
typedef lzma_ret (*lzma_code_function)(
lzma_coder *coder, lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos,
@@ -74,10 +95,24 @@ typedef lzma_ret (*lzma_code_function)(
size_t *restrict out_pos, size_t out_size,
lzma_action action);
+/// Type of a function to free the memory allocated for the coder
typedef void (*lzma_end_function)(
lzma_coder *coder, lzma_allocator *allocator);
+/// Raw coder validates and converts an array of lzma_filter structures to
+/// an array of lzma_filter_info structures. This array is used with
+/// lzma_next_filter_init to initialize the filter chain.
+struct lzma_filter_info_s {
+ /// Pointer to function used to initialize the filter.
+ /// This is NULL to indicate end of array.
+ lzma_init_function init;
+
+ /// Pointer to filter's options structure
+ void *options;
+};
+
+
/// Hold data and function pointers of the next filter in the chain.
struct lzma_next_coder_s {
/// Pointer to coder-specific data
@@ -85,28 +120,48 @@ struct lzma_next_coder_s {
/// "Pointer" to init function. This is never called here.
/// We need only to detect if we are initializing a coder
- /// that was allocated earlier. See code.c and next_coder.c.
+ /// that was allocated earlier. See lzma_next_coder_init and
+ /// lzma_next_strm_init macros in this file.
uintptr_t init;
/// Pointer to function to do the actual coding
lzma_code_function code;
- /// Pointer to function to free lzma_next_coder.coder
+ /// Pointer to function to free lzma_next_coder.coder. This can
+ /// be NULL; in that case, lzma_free is called to free
+ /// lzma_next_coder.coder.
lzma_end_function end;
+
+ /// Pointer to function to return the type of the integrity check.
+ /// Most coders won't support this.
+ lzma_check (*see_check)(const lzma_coder *coder);
+
+// uint64_t (*memconfig)(
+// lzma_coder *coder, uint64_t memlimit, bool change);
};
+
+/// Macro to initialize lzma_next_coder structure
#define LZMA_NEXT_CODER_INIT \
(lzma_next_coder){ \
.coder = NULL, \
- .init = 0, \
+ .init = (uintptr_t)(NULL), \
.code = NULL, \
.end = NULL, \
+ .see_check = NULL, \
}
+/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to
+/// this is stored in lzma_stream.
struct lzma_internal_s {
+ /// The actual coder that should do something useful
lzma_next_coder next;
+ /// Track the state of the coder. This is used to validate arguments
+ /// so that the actual coders can rely on e.g. that LZMA_SYNC_FLUSH
+ /// is used on every call to lzma_code until next.code has returned
+ /// LZMA_STREAM_END.
enum {
ISEQ_RUN,
ISEQ_SYNC_FLUSH,
@@ -116,33 +171,20 @@ struct lzma_internal_s {
ISEQ_ERROR,
} sequence;
- bool supported_actions[4];
- bool allow_buf_error;
+ /// A copy of lzma_stream avail_in. This is used to verify that the
+ /// amount of input doesn't change once e.g. LZMA_FINISH has been
+ /// used.
size_t avail_in;
-};
-
-struct lzma_filter_info_s {
- /// Pointer to function used to initialize the filter.
- /// This is NULL to indicate end of array.
- lzma_init_function init;
+ /// Indicates which lzma_action values are allowed by next.code.
+ bool supported_actions[4];
- /// Pointer to filter's options structure
- void *options;
+ /// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
+ /// made (no input consumed and no output produced by next.code).
+ bool allow_buf_error;
};
-/*
-typedef struct {
- lzma_init_function init;
- uint32_t (*input_alignment)(lzma_vli id, const void *options);
- uint32_t (*output_alignment)(lzma_vli id, const void *options);
- bool changes_uncompressed_size;
- bool supports_eopm;
-} lzma_filter_hook;
-*/
-
-
///////////////
// Functions //
///////////////
@@ -154,126 +196,69 @@ extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
/// Frees memory
extern void lzma_free(void *ptr, lzma_allocator *allocator);
-/// Initializes lzma_stream FIXME desc
+
+/// Allocates strm->internal if it is NULL, and initializes *strm and
+/// strm->internal. This function is only called via lzma_next_strm_init macro.
extern lzma_ret lzma_strm_init(lzma_stream *strm);
-///
+/// Initializes the next filter in the chain, if any. This takes care of
+/// freeing the memory of previously initialized filter if it is different
+/// than the filter being initialized now. This way the actual filter
+/// initialization functions don't need to use lzma_next_coder_init macro.
extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters);
-///
-extern void lzma_next_coder_end(lzma_next_coder *next,
- lzma_allocator *allocator);
+/// Frees the memory allocated for next->coder either using next->end or,
+/// if next->end is NULL, using lzma_free.
+extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
-/// \brief Wrapper for memcpy()
-///
-/// This function copies as much data as possible from in[] to out[] and
-/// updates *in_pos and *out_pos accordingly.
-///
-static inline size_t
-bufcpy(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)
-{
- const size_t in_avail = in_size - *in_pos;
- const size_t out_avail = out_size - *out_pos;
- const size_t copy_size = MIN(in_avail, out_avail);
-
- memcpy(out + *out_pos, in + *in_pos, copy_size);
-
- *in_pos += copy_size;
- *out_pos += copy_size;
-
- return copy_size;
-}
+/// Copy as much data as possible from in[] to out[] and update *in_pos
+/// and *out_pos accordingly. Returns the number of bytes copied.
+extern size_t lzma_bufcpy(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);
-/// \brief Initializing the next coder
-///
-/// lzma_next_coder can point to different types of coders. The existing
-/// coder may be different than what we are initializing now. In that case
-/// we must git rid of the old coder first. Otherwise we reuse the existing
-/// coder structure.
+/// \brief Return if expression doesn't evaluate to LZMA_OK
///
-#define lzma_next_coder_init2(next, allocator, cmpfunc, func, ...) \
+/// There are several situations where we want to return immediatelly
+/// with the value of expr if it isn't LZMA_OK. This macro shortens
+/// the code a little.
+#define return_if_error(expr) \
do { \
- if ((uintptr_t)(&cmpfunc) != (next)->init) \
- lzma_next_coder_end(next, allocator); \
- const lzma_ret ret = func(next, __VA_ARGS__); \
- if (ret == LZMA_OK) { \
- (next)->init = (uintptr_t)(&cmpfunc); \
- assert((next)->code != NULL); \
- assert((next)->end != NULL); \
- } else { \
- lzma_next_coder_end(next, allocator); \
- } \
- return ret; \
+ const lzma_ret ret_ = (expr); \
+ if (ret_ != LZMA_OK) \
+ return ret_; \
} while (0)
-/// \brief Initializing lzma_next_coder
-///
-/// Call the initialization function, which must take at least one
-/// argument in addition to lzma_next_coder and lzma_allocator.
-#define lzma_next_coder_init(func, next, allocator, ...) \
- lzma_next_coder_init2(next, allocator, \
- func, func, allocator, __VA_ARGS__)
-
-/// \brief Initializing lzma_next_coder
-///
-/// Call the initialization function, which takes no other arguments than
-/// lzma_next_coder and lzma_allocator.
-#define lzma_next_coder_init0(func, next, allocator) \
- lzma_next_coder_init2(next, allocator, func, func, allocator)
-
-/// \brief Initializing lzma_stream
-///
-/// lzma_strm initialization with more detailed options.
-#define lzma_next_strm_init2(strm, cmpfunc, func, ...) \
+/// If next isn't already initialized, free the previous coder. Then mark
+/// that next is _possibly_ initialized for the coder using this macro.
+/// "Possibly" means that if e.g. allocation of next->coder fails, the
+/// structure isn't actually initialized for this coder, but leaving
+/// next->init to func is still OK.
+#define lzma_next_coder_init(func, next, allocator) \
do { \
- lzma_ret ret = lzma_strm_init(strm); \
- if (ret != LZMA_OK) \
- return ret; \
- if ((uintptr_t)(&cmpfunc) != (strm)->internal->next.init) \
- lzma_next_coder_end(\
- &(strm)->internal->next, (strm)->allocator); \
- ret = func(&(strm)->internal->next, __VA_ARGS__); \
- if (ret != LZMA_OK) { \
- lzma_end(strm); \
- return ret; \
- } \
- (strm)->internal->next.init = (uintptr_t)(&cmpfunc); \
- assert((strm)->internal->next.code != NULL); \
- assert((strm)->internal->next.end != NULL); \
+ if ((uintptr_t)(&func) != (next)->init) \
+ lzma_next_end(next, allocator); \
+ (next)->init = (uintptr_t)(&func); \
} while (0)
-/// \brief Initializing lzma_stream
-///
-/// Call the initialization function, which must take at least one
-/// argument in addition to lzma_next_coder and lzma_allocator.
-#define lzma_next_strm_init(strm, func, ...) \
- lzma_next_strm_init2(strm, func, func, (strm)->allocator, __VA_ARGS__)
-/// \brief Initializing lzma_stream
-///
-/// Call the initialization function, which takes no other arguments than
-/// lzma_next_coder and lzma_allocator.
-#define lzma_next_strm_init0(strm, func) \
- lzma_next_strm_init2(strm, func, func, (strm)->allocator)
-
-
-/// \brief Return if expression doesn't evaluate to LZMA_OK
-///
-/// There are several situations where we want to return immediatelly
-/// with the value of expr if it isn't LZMA_OK. This macro shortens
-/// the code a bit.
-///
-#define return_if_error(expr) \
+/// Initializes lzma_strm and calls func() to initialize strm->internal->next.
+/// (The function being called will use lzma_next_coder_init()). If
+/// initialization fails, memory that wasn't freed by func() is freed
+/// along strm->internal.
+#define lzma_next_strm_init(func, strm, ...) \
do { \
- const lzma_ret ret_ = expr; \
- if (ret_ != LZMA_OK) \
+ return_if_error(lzma_strm_init(strm)); \
+ const lzma_ret ret_ = func(&(strm)->internal->next, \
+ (strm)->allocator, __VA_ARGS__); \
+ if (ret_ != LZMA_OK) { \
+ lzma_end(strm); \
return ret_; \
+ } \
} while (0)
#endif
diff --git a/src/liblzma/common/delta_common.c b/src/liblzma/common/delta_common.c
deleted file mode 100644
index acd31e14..00000000
--- a/src/liblzma/common/delta_common.c
+++ /dev/null
@@ -1,66 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file delta_common.c
-/// \brief Common stuff for Delta encoder and decoder
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "delta_common.h"
-
-
-static void
-delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
-{
- lzma_next_coder_end(&coder->next, allocator);
- lzma_free(coder, allocator);
- return;
-}
-
-
-extern lzma_ret
-lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters, lzma_code_function code)
-{
- // Allocate memory for the decoder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
- return LZMA_MEM_ERROR;
-
- // End function is the same for encoder and decoder.
- next->end = &delta_coder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
- }
-
- // Coding function is different for encoder and decoder.
- next->code = code;
-
- // Set the delta distance.
- if (filters[0].options == NULL)
- return LZMA_PROG_ERROR;
- next->coder->distance = ((lzma_options_delta *)(filters[0].options))
- ->distance;
- if (next->coder->distance < LZMA_DELTA_DISTANCE_MIN
- || next->coder->distance > LZMA_DELTA_DISTANCE_MAX)
- return LZMA_HEADER_ERROR;
-
- // Initialize the rest of the variables.
- next->coder->pos = 0;
- memzero(next->coder->history, LZMA_DELTA_DISTANCE_MAX);
-
- // Initialize the next decoder in the chain, if any.
- return lzma_next_filter_init(&next->coder->next,
- allocator, filters + 1);
-}
diff --git a/src/liblzma/common/delta_decoder.c b/src/liblzma/common/delta_decoder.c
deleted file mode 100644
index 8f5a4cbf..00000000
--- a/src/liblzma/common/delta_decoder.c
+++ /dev/null
@@ -1,61 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file delta_decoder.c
-/// \brief Delta filter decoder
-//
-// Copyright (C) 2007, 2008 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "delta_decoder.h"
-#include "delta_common.h"
-
-
-static void
-decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
-{
- const size_t distance = coder->distance;
-
- for (size_t i = 0; i < size; ++i) {
- buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
- coder->history[coder->pos-- & 0xFF] = buffer[i];
- }
-}
-
-
-static lzma_ret
-delta_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)
-{
- assert(coder->next.code != NULL);
-
- const size_t out_start = *out_pos;
-
- const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
- in, in_pos, in_size, out, out_pos, out_size,
- action);
-
- decode_buffer(coder, out + out_start, *out_pos - out_start);
-
- return ret;
-}
-
-
-extern lzma_ret
-lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters)
-{
- return lzma_delta_coder_init(next, allocator, filters, &delta_decode);
-}
diff --git a/src/liblzma/common/delta_decoder.h b/src/liblzma/common/delta_decoder.h
deleted file mode 100644
index bef9f58a..00000000
--- a/src/liblzma/common/delta_decoder.h
+++ /dev/null
@@ -1,28 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file delta_decoder.h
-/// \brief Delta filter decoder
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef LZMA_DELTA_DECODER_H
-#define LZMA_DELTA_DECODER_H
-
-#include "common.h"
-
-extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
-
-#endif
diff --git a/src/liblzma/common/delta_encoder.c b/src/liblzma/common/delta_encoder.c
deleted file mode 100644
index a8bb9341..00000000
--- a/src/liblzma/common/delta_encoder.c
+++ /dev/null
@@ -1,98 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file delta_encoder.c
-/// \brief Delta filter encoder
-//
-// Copyright (C) 2007, 2008 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "delta_encoder.h"
-#include "delta_common.h"
-
-
-/// Copies and encodes the data at the same time. This is used when Delta
-/// is the first filter in the chain (and thus the last filter in the
-/// encoder's filter stack).
-static void
-copy_and_encode(lzma_coder *coder,
- const uint8_t *restrict in, uint8_t *restrict out, size_t size)
-{
- const size_t distance = coder->distance;
-
- for (size_t i = 0; i < size; ++i) {
- const uint8_t tmp = coder->history[
- (distance + coder->pos) & 0xFF];
- coder->history[coder->pos-- & 0xFF] = in[i];
- out[i] = in[i] - tmp;
- }
-}
-
-
-/// Encodes the data in place. This is used when we are the last filter
-/// in the chain (and thus non-last filter in the encoder's filter stack).
-static void
-encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
-{
- const size_t distance = coder->distance;
-
- for (size_t i = 0; i < size; ++i) {
- const uint8_t tmp = coder->history[
- (distance + coder->pos) & 0xFF];
- coder->history[coder->pos-- & 0xFF] = buffer[i];
- buffer[i] -= tmp;
- }
-}
-
-
-static lzma_ret
-delta_encode(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)
-{
- lzma_ret ret;
-
- if (coder->next.code == NULL) {
- const size_t in_avail = in_size - *in_pos;
- const size_t out_avail = out_size - *out_pos;
- const size_t size = MIN(in_avail, out_avail);
-
- copy_and_encode(coder, in + *in_pos, out + *out_pos, size);
-
- *in_pos += size;
- *out_pos += size;
-
- ret = action != LZMA_RUN && *in_pos == in_size
- ? LZMA_STREAM_END : LZMA_OK;
-
- } else {
- const size_t out_start = *out_pos;
-
- ret = coder->next.code(coder->next.coder, allocator,
- in, in_pos, in_size, out, out_pos, out_size,
- action);
-
- encode_in_place(coder, out + out_start, *out_pos - out_start);
- }
-
- return ret;
-}
-
-
-extern lzma_ret
-lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters)
-{
- return lzma_delta_coder_init(next, allocator, filters, &delta_encode);
-}
diff --git a/src/liblzma/common/easy.c b/src/liblzma/common/easy.c
index 6c258204..ae0e4f74 100644
--- a/src/liblzma/common/easy.c
+++ b/src/liblzma/common/easy.c
@@ -25,12 +25,12 @@ struct lzma_coder_s {
/// We need to keep the filters array available in case
/// LZMA_FULL_FLUSH is used.
- lzma_options_filter filters[5];
+ lzma_filter filters[5];
};
static bool
-easy_set_filters(lzma_options_filter *filters, uint32_t level)
+easy_set_filters(lzma_filter *filters, uint32_t level)
{
bool error = false;
@@ -38,9 +38,9 @@ easy_set_filters(lzma_options_filter *filters, uint32_t level)
// TODO FIXME Use Subblock or LZMA2 with no compression.
error = true;
-#ifdef HAVE_FILTER_LZMA
+#ifdef HAVE_ENCODER_LZMA2
} else if (level <= 9) {
- filters[0].id = LZMA_FILTER_LZMA;
+ filters[0].id = LZMA_FILTER_LZMA2;
filters[0].options = (void *)(&lzma_preset_lzma[level - 1]);
filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
#endif
@@ -68,7 +68,7 @@ easy_encode(lzma_coder *coder, lzma_allocator *allocator,
static void
easy_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->stream_encoder, allocator);
+ lzma_next_end(&coder->stream_encoder, allocator);
lzma_free(coder, allocator);
return;
}
@@ -78,6 +78,8 @@ static lzma_ret
easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_easy_level level)
{
+ lzma_next_coder_init(easy_encoder_init, next, allocator);
+
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
@@ -100,7 +102,7 @@ easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API lzma_ret
lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
{
- lzma_next_strm_init(strm, easy_encoder_init, level);
+ lzma_next_strm_init(easy_encoder_init, strm, level);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
@@ -114,9 +116,9 @@ lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
extern LZMA_API uint32_t
lzma_easy_memory_usage(lzma_easy_level level)
{
- lzma_options_filter filters[5];
+ lzma_filter filters[5];
if (easy_set_filters(filters, level))
return UINT32_MAX;
- return lzma_memory_usage(filters, true);
+ return lzma_memusage_encoder(filters);
}
diff --git a/src/liblzma/common/features.c b/src/liblzma/common/features.c
deleted file mode 100644
index a02949d9..00000000
--- a/src/liblzma/common/features.c
+++ /dev/null
@@ -1,66 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file features.c
-/// \brief Information about features enabled at compile time
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-
-
-static const lzma_vli filters[] = {
-#ifdef HAVE_FILTER_SUBBLOCK
- LZMA_FILTER_SUBBLOCK,
-#endif
-
-#ifdef HAVE_FILTER_X86
- LZMA_FILTER_X86,
-#endif
-
-#ifdef HAVE_FILTER_POWERPC
- LZMA_FILTER_POWERPC,
-#endif
-
-#ifdef HAVE_FILTER_IA64
- LZMA_FILTER_IA64,
-#endif
-
-#ifdef HAVE_FILTER_ARM
- LZMA_FILTER_ARM,
-#endif
-
-#ifdef HAVE_FILTER_ARMTHUMB
- LZMA_FILTER_ARMTHUMB,
-#endif
-
-#ifdef HAVE_FILTER_SPARC
- LZMA_FILTER_SPARC,
-#endif
-
-#ifdef HAVE_FILTER_DELTA
- LZMA_FILTER_DELTA,
-#endif
-
-#ifdef HAVE_FILTER_LZMA
- LZMA_FILTER_LZMA,
-#endif
-
- LZMA_VLI_VALUE_UNKNOWN
-};
-
-
-LZMA_API const lzma_vli *const lzma_available_filter_encoders = filters;
-
-LZMA_API const lzma_vli *const lzma_available_filter_decoders = filters;
diff --git a/src/liblzma/common/filter_common.c b/src/liblzma/common/filter_common.c
new file mode 100644
index 00000000..886ddb53
--- /dev/null
+++ b/src/liblzma/common/filter_common.c
@@ -0,0 +1,262 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file filter_common.c
+/// \brief Filter-specific stuff common for both encoder and decoder
+//
+// Copyright (C) 2008 Lasse Collin
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_common.h"
+
+
+static const struct {
+ /// Filter ID
+ lzma_vli id;
+
+ /// True if it is OK to use this filter as non-last filter in
+ /// the chain.
+ bool non_last_ok;
+
+ /// True if it is OK to use this filter as the last filter in
+ /// the chain.
+ bool last_ok;
+
+ /// True if the filter may change the size of the data (that is, the
+ /// amount of encoded output can be different than the amount of
+ /// uncompressed input).
+ bool changes_size;
+
+} features[] = {
+#if defined (HAVE_ENCODER_LZMA) || defined(HAVE_DECODER_LZMA)
+ {
+ .id = LZMA_FILTER_LZMA,
+ .non_last_ok = false,
+ .last_ok = true,
+ .changes_size = true,
+ },
+#endif
+#ifdef HAVE_DECODER_LZMA2
+ {
+ .id = LZMA_FILTER_LZMA2,
+ .non_last_ok = false,
+ .last_ok = true,
+ .changes_size = true,
+ },
+#endif
+#if defined(HAVE_ENCODER_SUBBLOCK) || defined(HAVE_DECODER_SUBBLOCK)
+ {
+ .id = LZMA_FILTER_SUBBLOCK,
+ .non_last_ok = true,
+ .last_ok = true,
+ .changes_size = true,
+ },
+#endif
+#ifdef HAVE_DECODER_X86
+ {
+ .id = LZMA_FILTER_X86,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
+ {
+ .id = LZMA_FILTER_POWERPC,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+#ifdef HAVE_DECODER_IA64
+ {
+ .id = LZMA_FILTER_IA64,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
+ {
+ .id = LZMA_FILTER_ARM,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
+ {
+ .id = LZMA_FILTER_ARMTHUMB,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
+ {
+ .id = LZMA_FILTER_SPARC,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
+ {
+ .id = LZMA_FILTER_DELTA,
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
+ },
+#endif
+ {
+ .id = LZMA_VLI_VALUE_UNKNOWN
+ }
+};
+
+
+static lzma_ret
+validate_chain(const lzma_filter *filters, size_t *count)
+{
+ // There must be at least one filter.
+ if (filters == NULL || filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
+ return LZMA_PROG_ERROR;
+
+ // Number of non-last filters that may change the size of the data
+ // significantly (that is, more than 1-2 % or so).
+ size_t changes_size_count = 0;
+
+ // True if it is OK to add a new filter after the current filter.
+ bool non_last_ok = true;
+
+ // True if the last filter in the given chain is actually usable as
+ // the last filter. Only filters that support embedding End of Payload
+ // Marker can be used as the last filter in the chain.
+ bool last_ok = false;
+
+ size_t i = 0;
+ do {
+ size_t j;
+ for (j = 0; filters[i].id != features[j].id; ++j)
+ if (features[j].id == LZMA_VLI_VALUE_UNKNOWN)
+ return LZMA_HEADER_ERROR;
+
+ // If the previous filter in the chain cannot be a non-last
+ // filter, the chain is invalid.
+ if (!non_last_ok)
+ return LZMA_HEADER_ERROR;
+
+ non_last_ok = features[j].non_last_ok;
+ last_ok = features[j].last_ok;
+ changes_size_count += features[j].changes_size;
+
+ } while (filters[++i].id != LZMA_VLI_VALUE_UNKNOWN);
+
+ // There must be 1-4 filters. The last filter must be usable as
+ // the last filter in the chain. At maximum of three filters are
+ // allowed to change the size of the data.
+ if (i > LZMA_BLOCK_FILTERS_MAX || !last_ok || changes_size_count > 3)
+ return LZMA_HEADER_ERROR;
+
+ *count = i;
+ return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter *options,
+ lzma_filter_find coder_find, bool is_encoder)
+{
+ // Do some basic validation and get the number of filters.
+ size_t count;
+ return_if_error(validate_chain(options, &count));
+
+ // Set the filter functions and copy the options pointer.
+ lzma_filter_info filters[LZMA_BLOCK_FILTERS_MAX + 1];
+ if (is_encoder) {
+ for (size_t i = 0; i < count; ++i) {
+ // The order of the filters is reversed in the
+ // encoder. It allows more efficient handling
+ // of the uncompressed data.
+ const size_t j = count - i - 1;
+
+ const lzma_filter_coder *const fc
+ = coder_find(options[i].id);
+ if (fc == NULL || fc->init == NULL)
+ return LZMA_HEADER_ERROR;
+
+ filters[j].init = fc->init;
+ filters[j].options = options[i].options;
+ }
+ } else {
+ for (size_t i = 0; i < count; ++i) {
+ const lzma_filter_coder *const fc
+ = coder_find(options[i].id);
+ if (fc == NULL || fc->init == NULL)
+ return LZMA_HEADER_ERROR;
+
+ filters[i].init = fc->init;
+ filters[i].options = options[i].options;
+ }
+ }
+
+ // Terminate the array.
+ filters[count].init = NULL;
+
+ // Initialize the filters.
+ const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
+ if (ret != LZMA_OK)
+ lzma_next_end(next, allocator);
+
+ return ret;
+}
+
+
+extern uint64_t
+lzma_memusage_coder(lzma_filter_find coder_find,
+ const lzma_filter *filters)
+{
+ // The chain has to have at least one filter.
+ if (filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
+ return UINT64_MAX;
+
+ uint64_t total = 0;
+ size_t i = 0;
+
+ do {
+ const lzma_filter_coder *const fc
+ = coder_find(filters[i].id);
+ if (fc == NULL)
+ return UINT64_MAX; // Unsupported Filter ID
+
+ if (fc->memusage == NULL) {
+ // This filter doesn't have a function to calculate
+ // the memory usage. Such filters need only little
+ // memory, so we use 1 KiB as a good estimate.
+ total += 1024;
+ } else {
+ // Call the filter-specific memory usage calculation
+ // function.
+ const uint64_t usage
+ = fc->memusage(filters[i].options);
+ if (usage == UINT64_MAX)
+ return UINT64_MAX; // Invalid options
+
+ total += usage;
+ }
+ } while (filters[++i].id != LZMA_VLI_VALUE_UNKNOWN);
+
+ // Add some fixed amount of extra. It's to compensate memory usage
+ // of Stream, Block etc. coders, malloc() overhead, stack etc.
+ return total + (1U << 15);
+}
diff --git a/src/liblzma/common/filter_common.h b/src/liblzma/common/filter_common.h
new file mode 100644
index 00000000..9def50b9
--- /dev/null
+++ b/src/liblzma/common/filter_common.h
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file filter_common.c
+/// \brief Filter-specific stuff common for both encoder and decoder
+//
+// Copyright (C) 2008 Lasse Collin
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_COMMON_H
+#define LZMA_FILTER_COMMON_H
+
+#include "common.h"
+
+
+/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
+typedef struct {
+ /// Initializes the filter encoder and calls lzma_next_filter_init()
+ /// for filters + 1.
+ lzma_init_function init;
+
+ /// Calculates memory usage of the encoder. If the options are
+ /// invalid, UINT64_MAX is returned.
+ uint64_t (*memusage)(const void *options);
+
+} lzma_filter_coder;
+
+
+typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
+
+
+extern lzma_ret lzma_raw_coder_init(
+ lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter *filters,
+ lzma_filter_find coder_find, bool is_encoder);
+
+
+extern uint64_t lzma_memusage_coder(lzma_filter_find coder_find,
+ const lzma_filter *filters);
+
+
+#endif
diff --git a/src/liblzma/common/filter_decoder.c b/src/liblzma/common/filter_decoder.c
new file mode 100644
index 00000000..9fe94f7b
--- /dev/null
+++ b/src/liblzma/common/filter_decoder.c
@@ -0,0 +1,236 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file filter_decoder.c
+/// \brief Filter ID mapping to filter-specific functions
+//
+// Copyright (C) 2008 Lasse Collin
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+#include "filter_common.h"
+#include "lzma_decoder.h"
+#include "lzma2_decoder.h"
+#include "subblock_decoder.h"
+#include "subblock_decoder_helper.h"
+#include "simple_decoder.h"
+#include "delta_decoder.h"
+
+
+typedef struct {
+ /// Initializes the filter encoder and calls lzma_next_filter_init()
+ /// for filters + 1.
+ lzma_init_function init;
+
+ /// Calculates memory usage of the encoder. If the options are
+ /// invalid, UINT64_MAX is returned.
+ uint64_t (*memusage)(const void *options);
+
+ /// Decodes Filter Properties.
+ ///
+ /// \return - LZMA_OK: Properties decoded successfully.
+ /// - LZMA_HEADER_ERROR: Unsupported properties
+ /// - LZMA_MEM_ERROR: Memory allocation failed.
+ lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
+ const uint8_t *props, size_t props_size);
+
+} lzma_filter_decoder;
+
+
+static const lzma_vli ids[] = {
+#ifdef HAVE_DECODER_LZMA
+ LZMA_FILTER_LZMA,
+#endif
+
+#ifdef HAVE_DECODER_LZMA2
+ LZMA_FILTER_LZMA2,
+#endif
+
+#ifdef HAVE_DECODER_SUBBLOCK
+ LZMA_FILTER_SUBBLOCK,
+ LZMA_FILTER_SUBBLOCK_HELPER,
+#endif
+
+#ifdef HAVE_DECODER_X86
+ LZMA_FILTER_X86,
+#endif
+
+#ifdef HAVE_DECODER_POWERPC
+ LZMA_FILTER_POWERPC,
+#endif
+
+#ifdef HAVE_DECODER_IA64
+ LZMA_FILTER_IA64,
+#endif
+
+#ifdef HAVE_DECODER_ARM
+ LZMA_FILTER_ARM,
+#endif
+
+#ifdef HAVE_DECODER_ARMTHUMB
+ LZMA_FILTER_ARMTHUMB,
+#endif
+
+#ifdef HAVE_DECODER_SPARC
+ LZMA_FILTER_SPARC,
+#endif
+
+#ifdef HAVE_DECODER_DELTA
+ LZMA_FILTER_DELTA,
+#endif
+
+ LZMA_VLI_VALUE_UNKNOWN
+};
+
+
+// Using a pointer to avoid putting the size of the array to API/ABI.
+LZMA_API const lzma_vli *const lzma_filter_decoders = ids;
+
+
+// These must be in the same order as ids[].
+static const lzma_filter_decoder funcs[] = {
+#ifdef HAVE_DECODER_LZMA
+ {
+ .init = &lzma_lzma_decoder_init,
+ .memusage = &lzma_lzma_decoder_memusage,
+ .props_decode = &lzma_lzma_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_LZMA2
+ {
+ .init = &lzma_lzma2_decoder_init,
+ .memusage = &lzma_lzma2_decoder_memusage,
+ .props_decode = &lzma_lzma2_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_SUBBLOCK
+ {
+ .init = &lzma_subblock_decoder_init,
+// .memusage = &lzma_subblock_decoder_memusage,
+ .props_decode = NULL,
+ },
+ {
+ .init = &lzma_subblock_decoder_helper_init,
+ .memusage = NULL,
+ .props_decode = NULL,
+ },
+#endif
+#ifdef HAVE_DECODER_X86
+ {
+ .init = &lzma_simple_x86_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_POWERPC
+ {
+ .init = &lzma_simple_powerpc_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_IA64
+ {
+ .init = &lzma_simple_ia64_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_ARM
+ {
+ .init = &lzma_simple_arm_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_ARMTHUMB
+ {
+ .init = &lzma_simple_armthumb_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_SPARC
+ {
+ .init = &lzma_simple_sparc_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
+ },
+#endif
+#ifdef HAVE_DECODER_DELTA
+ {
+ .init = &lzma_delta_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_delta_props_decode,
+ },
+#endif
+};
+
+
+static const lzma_filter_decoder *
+decoder_find(lzma_vli id)
+{
+ for (size_t i = 0; ids[i] != LZMA_VLI_VALUE_UNKNOWN; ++i)
+ if (ids[i] == id)
+ return funcs + i;
+
+ return NULL;
+}
+
+
+extern lzma_ret
+lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter *options)
+{
+ return lzma_raw_coder_init(next, allocator,
+ options, (lzma_filter_find)(&decoder_find), false);
+}
+
+
+extern LZMA_API lzma_ret
+lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
+{
+ lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
+
+ strm->internal->supported_actions[LZMA_RUN] = true;
+ strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+
+ return LZMA_OK;
+}
+
+
+extern LZMA_API uint64_t
+lzma_memusage_decoder(const lzma_filter *filters)
+{
+ return lzma_memusage_coder(
+ (lzma_filter_find)(&decoder_find), filters);
+}
+
+
+extern LZMA_API lzma_ret
+lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
+ const uint8_t *props, size_t props_size)
+{
+ // Make it always NULL so that the caller can always safely free() it.
+ filter->options = NULL;
+
+ const lzma_filter_decoder *const fd = decoder_find(filter->id);
+ if (fd == NULL)
+ return LZMA_HEADER_ERROR;
+
+ if (fd->props_decode == NULL)
+ return props_size == 0 ? LZMA_OK : LZMA_HEADER_ERROR;
+
+ return fd->props_decode(
+ &filter->options, allocator, props, props_size);
+}
diff --git a/src/liblzma/common/raw_common.h b/src/liblzma/common/filter_decoder.h
index 0a27f3dc..33e491d1 100644
--- a/src/liblzma/common/raw_common.h
+++ b/src/liblzma/common/filter_decoder.h
@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file raw_common.h
-/// \brief Stuff shared between raw encoder and raw decoder
+/// \file filter_decoder.c
+/// \brief Filter ID mapping to filter-specific functions
//
-// Copyright (C) 2007 Lasse Collin
+// Copyright (C) 2008 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -17,14 +17,19 @@
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef LZMA_RAW_COMMON_H
-#define LZMA_RAW_COMMON_H
+#ifndef LZMA_FILTER_DECODER_H
+#define LZMA_FILTER_DECODER_H
#include "common.h"
-extern lzma_ret lzma_raw_coder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_options_filter *options,
- lzma_init_function (*get_function)(lzma_vli id),
- bool is_encoder);
+// FIXME !!! Public API
+extern lzma_ret lzma_properties_decode(
+ lzma_filter *filter, lzma_allocator *allocator,
+ const uint8_t *props, size_t props_size);
+
+
+extern lzma_ret lzma_raw_decoder_init(
+ lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter *options);
#endif
diff --git a/src/liblzma/common/filter_encoder.c b/src/liblzma/common/filter_encoder.c
new file mode 100644
index 00000000..55862e18
--- /dev/null
+++ b/src/liblzma/common/filter_encoder.c
@@ -0,0 +1,308 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file filter_decoder.c
+/// \brief Filter ID mapping to filter-specific functions
+//
+// Copyright (C) 2008 Lasse Collin
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+#include "filter_common.h"
+#include "lzma_encoder.h"
+#include "lzma2_encoder.h"
+#include "subblock_encoder.h"
+#include "simple_encoder.h"
+#include "delta_encoder.h"
+
+
+typedef struct {
+ /// Initializes the filter encoder and calls lzma_next_filter_init()
+ /// for filters + 1.
+ lzma_init_function init;
+
+ /// Calculates memory usage of the encoder. If the options are
+ /// invalid, UINT64_MAX is returned.
+ uint64_t (*memusage)(const void *options);
+
+ /// Calculates the minimum sane size for Blocks (or other types of
+ /// chunks) to which the input data can be splitted to make
+ /// multithreaded encoding possible. If this is NULL, it is assumed
+ /// that the encoder is fast enough with single thread.
+ lzma_vli (*chunk_size)(const void *options);
+
+ /// Tells the size of the Filter Properties field. If options are
+ /// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed
+ /// is used.
+ lzma_ret (*props_size_get)(uint32_t *size, const void *options);
+ uint32_t props_size_fixed;
+
+ /// Encodes Filter Properties.
+ ///
+ /// \return - LZMA_OK: Properties encoded sucessfully.
+ /// - LZMA_HEADER_ERROR: Unsupported options
+ /// - LZMA_PROG_ERROR: Invalid options or not enough
+ /// output space
+ lzma_ret (*props_encode)(const void *options, uint8_t *out);
+
+} lzma_filter_encoder;
+
+
+static const lzma_vli ids[] = {
+#ifdef HAVE_ENCODER_LZMA
+ LZMA_FILTER_LZMA,
+#endif
+
+#ifdef HAVE_ENCODER_LZMA2
+ LZMA_FILTER_LZMA2,
+#endif
+
+#ifdef HAVE_ENCODER_SUBBLOCK
+ LZMA_FILTER_SUBBLOCK,
+#endif
+
+#ifdef HAVE_ENCODER_X86
+ LZMA_FILTER_X86,
+#endif
+
+#ifdef HAVE_ENCODER_POWERPC
+ LZMA_FILTER_POWERPC,
+#endif
+
+#ifdef HAVE_ENCODER_IA64
+ LZMA_FILTER_IA64,
+#endif
+
+#ifdef HAVE_ENCODER_ARM
+ LZMA_FILTER_ARM,
+#endif
+
+#ifdef HAVE_ENCODER_ARMTHUMB
+ LZMA_FILTER_ARMTHUMB,
+#endif
+
+#ifdef HAVE_ENCODER_SPARC
+ LZMA_FILTER_SPARC,
+#endif
+
+#ifdef HAVE_ENCODER_DELTA
+ LZMA_FILTER_DELTA,
+#endif
+
+ LZMA_VLI_VALUE_UNKNOWN
+};
+
+
+// Using a pointer to avoid putting the size of the array to API/ABI.
+LZMA_API const lzma_vli *const lzma_filter_encoders = ids;
+
+
+// These must be in the same order as ids[].
+static const lzma_filter_encoder funcs[] = {
+#ifdef HAVE_ENCODER_LZMA
+ {
+ .init = &lzma_lzma_encoder_init,
+ .memusage = &lzma_lzma_encoder_memusage,
+ .chunk_size = NULL, // FIXME
+ .props_size_get = NULL,
+ .props_size_fixed = 5,
+ .props_encode = &lzma_lzma_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_LZMA2
+ {
+ .init = &lzma_lzma2_encoder_init,
+ .memusage = &lzma_lzma2_encoder_memusage,
+ .chunk_size = NULL, // FIXME
+ .props_size_get = NULL,
+ .props_size_fixed = 1,
+ .props_encode = &lzma_lzma2_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_SUBBLOCK
+ {
+ .init = &lzma_subblock_encoder_init,
+// .memusage = &lzma_subblock_encoder_memusage,
+ .chunk_size = NULL,
+ .props_size_get = NULL,
+ .props_size_fixed = 0,
+ .props_encode = NULL,
+ },
+#endif
+#ifdef HAVE_ENCODER_X86
+ {
+ .init = &lzma_simple_x86_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_POWERPC
+ {
+ .init = &lzma_simple_powerpc_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_IA64
+ {
+ .init = &lzma_simple_ia64_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_ARM
+ {
+ .init = &lzma_simple_arm_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_ARMTHUMB
+ {
+ .init = &lzma_simple_armthumb_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_SPARC
+ {
+ .init = &lzma_simple_sparc_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
+ },
+#endif
+#ifdef HAVE_ENCODER_DELTA
+ {
+ .init = &lzma_delta_encoder_init,
+ .memusage = NULL,
+ .chunk_size = NULL,
+ .props_size_get = NULL,
+ .props_size_fixed = 1,
+ .props_encode = &lzma_delta_props_encode,
+ },
+#endif
+};
+
+
+static const lzma_filter_encoder *
+encoder_find(lzma_vli id)
+{
+ for (size_t i = 0; ids[i] != LZMA_VLI_VALUE_UNKNOWN; ++i)
+ if (ids[i] == id)
+ return funcs + i;
+
+ return NULL;
+}
+
+
+extern lzma_ret
+lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter *options)
+{
+ return lzma_raw_coder_init(next, allocator,
+ options, (lzma_filter_find)(&encoder_find), true);
+}
+
+
+extern LZMA_API lzma_ret
+lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
+{
+ lzma_next_strm_init(lzma_raw_coder_init, strm, options,
+ (lzma_filter_find)(&encoder_find), true);
+
+ strm->internal->supported_actions[LZMA_RUN] = true;
+ strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FINISH] = true;
+
+ return LZMA_OK;
+}
+
+
+extern LZMA_API uint64_t
+lzma_memusage_encoder(const lzma_filter *filters)
+{
+ return lzma_memusage_coder(
+ (lzma_filter_find)(&encoder_find), filters);
+}
+
+
+extern LZMA_API lzma_vli
+lzma_chunk_size(const lzma_filter *filters)
+{
+ uint64_t max = 0;
+
+ for (size_t i = 0; filters[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
+ const lzma_filter_encoder *const fe
+ = encoder_find(filters[i].id);
+ if (fe->chunk_size != NULL) {
+ const lzma_vli size
+ = fe->chunk_size(filters[i].options);
+ if (size == LZMA_VLI_VALUE_UNKNOWN)
+ return LZMA_VLI_VALUE_UNKNOWN;
+
+ if (size > max)
+ max = size;
+ }
+ }
+
+ return max;
+}
+
+
+extern LZMA_API lzma_ret
+lzma_properties_size(uint32_t *size, const lzma_filter *filter)
+{
+ const lzma_filter_encoder *const fe = encoder_find(filter->id);
+ if (fe == NULL) {
+ // Unknown filter - if the Filter ID is a proper VLI,
+ // return LZMA_HEADER_ERROR instead of LZMA_PROG_ERROR,
+ // because it's possible that we just don't have support
+ // compiled in for the requested filter.
+ return filter->id <= LZMA_VLI_VALUE_MAX
+ ? LZMA_HEADER_ERROR : LZMA_PROG_ERROR;
+ }
+
+ if (fe->props_size_get == NULL) {
+ // No props_size() function, use props_size_fixed.
+ *size = fe->props_size_fixed;
+ return LZMA_OK;
+ }
+
+ return fe->props_size_get(size, filter->options);
+}
+
+
+extern LZMA_API lzma_ret
+lzma_properties_encode(const lzma_filter *filter, uint8_t *props)
+{
+ const lzma_filter_encoder *const fe = encoder_find(filter->id);
+ if (fe == NULL)
+ return LZMA_PROG_ERROR;
+
+ if (fe->props_encode == NULL)
+ return LZMA_OK;
+
+ return fe->props_encode(filter->options, props);
+}
diff --git a/src/liblzma/common/delta_common.h b/src/liblzma/common/filter_encoder.h
index 1d58899d..b2bf851d 100644
--- a/src/liblzma/common/delta_common.h
+++ b/src/liblzma/common/filter_encoder.h
@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file delta_common.h
-/// \brief Common stuff for Delta encoder and decoder
+/// \file filter_encoder.c
+/// \brief Filter ID mapping to filter-specific functions
//
-// Copyright (C) 2007 Lasse Collin
+// Copyright (C) 2008 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -17,28 +17,22 @@
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef LZMA_DELTA_COMMON_H
-#define LZMA_DELTA_COMMON_H
+#ifndef LZMA_FILTER_ENCODER_H
+#define LZMA_FILTER_ENCODER_H
#include "common.h"
-struct lzma_coder_s {
- /// Next coder in the chain
- lzma_next_coder next;
- /// Delta distance
- size_t distance;
+// FIXME !!! Public API
+extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
+extern lzma_ret lzma_properties_size(
+ uint32_t *size, const lzma_filter *filter);
+extern lzma_ret lzma_properties_encode(
+ const lzma_filter *filter, uint8_t *props);
- /// Position in history[]
- uint8_t pos;
- /// Buffer to hold history of the original data
- uint8_t history[LZMA_DELTA_DISTANCE_MAX];
-};
-
-
-extern lzma_ret lzma_delta_coder_init(
+extern lzma_ret lzma_raw_encoder_init(
lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters, lzma_code_function code);
+ const lzma_filter *options);
#endif
diff --git a/src/liblzma/common/filter_flags_decoder.c b/src/liblzma/common/filter_flags_decoder.c
index 498b2ad6..c2247312 100644
--- a/src/liblzma/common/filter_flags_decoder.c
+++ b/src/liblzma/common/filter_flags_decoder.c
@@ -17,192 +17,37 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "common.h"
-#include "lzma_decoder.h"
-
-
-#ifdef HAVE_FILTER_SUBBLOCK
-static lzma_ret
-properties_subblock(lzma_options_filter *options, lzma_allocator *allocator,
- const uint8_t *props lzma_attribute((unused)),
- size_t prop_size lzma_attribute((unused)))
-{
- if (prop_size != 0)
- return LZMA_HEADER_ERROR;
-
- options->options = lzma_alloc(
- sizeof(lzma_options_subblock), allocator);
- if (options->options == NULL)
- return LZMA_MEM_ERROR;
-
- ((lzma_options_subblock *)(options->options))->allow_subfilters = true;
- return LZMA_OK;
-}
-#endif
-
-
-#ifdef HAVE_FILTER_SIMPLE
-static lzma_ret
-properties_simple(lzma_options_filter *options, lzma_allocator *allocator,
- const uint8_t *props, size_t prop_size)
-{
- if (prop_size == 0)
- return LZMA_OK;
-
- if (prop_size != 4)
- return LZMA_HEADER_ERROR;
-
- lzma_options_simple *simple = lzma_alloc(
- sizeof(lzma_options_simple), allocator);
- if (simple == NULL)
- return LZMA_MEM_ERROR;
-
- simple->start_offset = integer_read_32(props);
-
- // Don't leave an options structure allocated if start_offset is zero.
- if (simple->start_offset == 0)
- lzma_free(simple, allocator);
- else
- options->options = simple;
-
- return LZMA_OK;
-}
-#endif
-
-
-#ifdef HAVE_FILTER_DELTA
-static lzma_ret
-properties_delta(lzma_options_filter *options, lzma_allocator *allocator,
- const uint8_t *props, size_t prop_size)
-{
- if (prop_size != 1)
- return LZMA_HEADER_ERROR;
-
- options->options = lzma_alloc(sizeof(lzma_options_delta), allocator);
- if (options->options == NULL)
- return LZMA_MEM_ERROR;
-
- ((lzma_options_delta *)(options->options))->distance
- = (uint32_t)(props[0]) + 1;
-
- return LZMA_OK;
-}
-#endif
-
-
-#ifdef HAVE_FILTER_LZMA
-static lzma_ret
-properties_lzma(lzma_options_filter *options, lzma_allocator *allocator,
- const uint8_t *props, size_t prop_size)
-{
- // LZMA properties are always two bytes (at least for now).
- if (prop_size != 2)
- return LZMA_HEADER_ERROR;
-
- lzma_options_lzma *lzma = lzma_alloc(
- sizeof(lzma_options_lzma), allocator);
- if (lzma == NULL)
- return LZMA_MEM_ERROR;
-
- // Decode lc, lp, and pb.
- if (lzma_lzma_decode_properties(lzma, props[0]))
- goto error;
-
- // Check that reserved bits are unset.
- if (props[1] & 0xC0)
- goto error;
-
- // Decode the dictionary size.
- // FIXME The specification says that maximum is 4 GiB.
- if (props[1] > 36)
- goto error;
-#if LZMA_DICTIONARY_SIZE_MAX != UINT32_C(1) << 30
-# error Update the if()-condition a few lines
-# error above to match LZMA_DICTIONARY_SIZE_MAX.
-#endif
-
- lzma->dictionary_size = 2 | (props[1] & 1);
- lzma->dictionary_size <<= props[1] / 2 + 11;
-
- options->options = lzma;
- return LZMA_OK;
-
-error:
- lzma_free(lzma, allocator);
- return LZMA_HEADER_ERROR;
-}
-#endif
+#include "filter_decoder.h"
extern LZMA_API lzma_ret
lzma_filter_flags_decode(
- lzma_options_filter *options, lzma_allocator *allocator,
+ lzma_filter *filter, lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
{
// Set the pointer to NULL so the caller can always safely free it.
- options->options = NULL;
+ filter->options = NULL;
// Filter ID
- return_if_error(lzma_vli_decode(&options->id, NULL,
+ return_if_error(lzma_vli_decode(&filter->id, NULL,
in, in_pos, in_size));
+ if (filter->id >= LZMA_FILTER_RESERVED_START)
+ return LZMA_DATA_ERROR;
+
// Size of Properties
- lzma_vli prop_size;
- return_if_error(lzma_vli_decode(&prop_size, NULL,
+ lzma_vli props_size;
+ return_if_error(lzma_vli_decode(&props_size, NULL,
in, in_pos, in_size));
- // Check that we have enough input.
- if (prop_size > in_size - *in_pos)
+ // Filter Properties
+ if (in_size - *in_pos < props_size)
return LZMA_DATA_ERROR;
- // Determine the function to decode the properties.
- lzma_ret (*get_properties)(lzma_options_filter *options,
- lzma_allocator *allocator, const uint8_t *props,
- size_t prop_size);
+ const lzma_ret ret = lzma_properties_decode(
+ filter, allocator, in + *in_pos, props_size);
- switch (options->id) {
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK:
- get_properties = &properties_subblock;
- break;
-#endif
-#ifdef HAVE_FILTER_SIMPLE
-# ifdef HAVE_FILTER_X86
- case LZMA_FILTER_X86:
-# endif
-# ifdef HAVE_FILTER_POWERPC
- case LZMA_FILTER_POWERPC:
-# endif
-# ifdef HAVE_FILTER_IA64
- case LZMA_FILTER_IA64:
-# endif
-# ifdef HAVE_FILTER_ARM
- case LZMA_FILTER_ARM:
-# endif
-# ifdef HAVE_FILTER_ARMTHUMB
- case LZMA_FILTER_ARMTHUMB:
-# endif
-# ifdef HAVE_FILTER_SPARC
- case LZMA_FILTER_SPARC:
-# endif
- get_properties = &properties_simple;
- break;
-#endif
-#ifdef HAVE_FILTER_DELTA
- case LZMA_FILTER_DELTA:
- get_properties = &properties_delta;
- break;
-#endif
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA:
- get_properties = &properties_lzma;
- break;
-#endif
- default:
- return LZMA_HEADER_ERROR;
- }
+ *in_pos += props_size;
- const uint8_t *props = in + *in_pos;
- *in_pos += prop_size;
- return get_properties(options, allocator, props, prop_size);
+ return ret;
}
diff --git a/src/liblzma/common/filter_flags_encoder.c b/src/liblzma/common/filter_flags_encoder.c
index 45fbbb00..46464c0f 100644
--- a/src/liblzma/common/filter_flags_encoder.c
+++ b/src/liblzma/common/filter_flags_encoder.c
@@ -17,267 +17,46 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "common.h"
-#include "lzma_encoder.h"
-#include "fastpos.h"
-
-
-/// Calculate the size of the Filter Properties field
-static lzma_ret
-get_properties_size(uint32_t *size, const lzma_options_filter *options)
-{
- lzma_ret ret = LZMA_OK;
-
- switch (options->id) {
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK:
- *size = 0;
- break;
-#endif
-
-#ifdef HAVE_FILTER_SIMPLE
-# ifdef HAVE_FILTER_X86
- case LZMA_FILTER_X86:
-# endif
-# ifdef HAVE_FILTER_POWERPC
- case LZMA_FILTER_POWERPC:
-# endif
-# ifdef HAVE_FILTER_IA64
- case LZMA_FILTER_IA64:
-# endif
-# ifdef HAVE_FILTER_ARM
- case LZMA_FILTER_ARM:
-# endif
-# ifdef HAVE_FILTER_ARMTHUMB
- case LZMA_FILTER_ARMTHUMB:
-# endif
-# ifdef HAVE_FILTER_SPARC
- case LZMA_FILTER_SPARC:
-# endif
- if (options->options == NULL || ((const lzma_options_simple *)(
- options->options))->start_offset == 0)
- *size = 0;
- else
- *size = 4;
- break;
-#endif
-
-#ifdef HAVE_FILTER_DELTA
- case LZMA_FILTER_DELTA:
- *size = 1;
- break;
-#endif
-
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA:
- *size = 2;
- break;
-#endif
-
- default:
- // Unknown filter - if the Filter ID is a proper VLI,
- // return LZMA_HEADER_ERROR instead of LZMA_PROG_ERROR,
- // because it's possible that we just don't have support
- // compiled in for the requested filter.
- ret = options->id <= LZMA_VLI_VALUE_MAX
- ? LZMA_HEADER_ERROR : LZMA_PROG_ERROR;
- break;
- }
-
- return ret;
-}
+#include "filter_encoder.h"
extern LZMA_API lzma_ret
-lzma_filter_flags_size(uint32_t *size, const lzma_options_filter *options)
-{
- // Get size of Filter Properties. This also validates the Filter ID.
- uint32_t prop_size;
- return_if_error(get_properties_size(&prop_size, options));
-
- // Calculate the size of the Filter ID and Size of Properties fields.
- // These cannot fail since get_properties_size() already succeeded.
- *size = lzma_vli_size(options->id) + lzma_vli_size(prop_size)
- + prop_size;
-
- return LZMA_OK;
-}
-
-
-#ifdef HAVE_FILTER_SIMPLE
-/// Encodes Filter Properties of the so called simple filters
-static lzma_ret
-properties_simple(uint8_t *out, size_t *out_pos, size_t out_size,
- const lzma_options_simple *options)
-{
- if (options == NULL || options->start_offset == 0)
- return LZMA_OK;
-
- if (out_size - *out_pos < 4)
- return LZMA_PROG_ERROR;
-
- integer_write_32(out + *out_pos, options->start_offset);
- *out_pos += 4;
-
- return LZMA_OK;
-}
-#endif
-
-
-#ifdef HAVE_FILTER_DELTA
-/// Encodes Filter Properties of the Delta filter
-static lzma_ret
-properties_delta(uint8_t *out, size_t *out_pos, size_t out_size,
- const lzma_options_delta *options)
-{
- if (options == NULL)
- return LZMA_PROG_ERROR;
-
- // It's possible that newer liblzma versions will support larger
- // distance values.
- if (options->distance < LZMA_DELTA_DISTANCE_MIN
- || options->distance > LZMA_DELTA_DISTANCE_MAX)
- return LZMA_HEADER_ERROR;
-
- if (out_size - *out_pos < 1)
- return LZMA_PROG_ERROR;
-
- out[*out_pos] = options->distance - LZMA_DELTA_DISTANCE_MIN;
- ++*out_pos;
-
- return LZMA_OK;
-}
-#endif
-
-
-#ifdef HAVE_FILTER_LZMA
-/// Encodes LZMA Properties and Dictionary Flags (two bytes)
-static lzma_ret
-properties_lzma(uint8_t *out, size_t *out_pos, size_t out_size,
- const lzma_options_lzma *options)
+lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter)
{
- if (options == NULL)
- return LZMA_PROG_ERROR;
-
- if (out_size - *out_pos < 2)
- return LZMA_PROG_ERROR;
-
- // LZMA Properties
- if (lzma_lzma_encode_properties(options, out + *out_pos))
- return LZMA_HEADER_ERROR;
-
- ++*out_pos;
+ return_if_error(lzma_properties_size(size, filter));
- // Dictionary flags
- //
- // Dictionary size is encoded using similar encoding that is used
- // internally by LZMA.
- //
- // This won't work if dictionary size can be zero:
-# if LZMA_DICTIONARY_SIZE_MIN < 1
-# error LZMA_DICTIONARY_SIZE_MIN cannot be zero.
-# endif
-
- uint32_t d = options->dictionary_size;
-
- // Validate it:
- if (d < LZMA_DICTIONARY_SIZE_MIN || d > LZMA_DICTIONARY_SIZE_MAX)
- return LZMA_HEADER_ERROR;
-
- // Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
- // one is the next:
- --d;
- d |= d >> 2;
- d |= d >> 3;
- d |= d >> 4;
- d |= d >> 8;
- d |= d >> 16;
- ++d;
-
- // Get the highest two bits using the proper encoding:
- out[*out_pos] = get_pos_slot(d) - 24;
- ++*out_pos;
+ // lzma_properties_size() validates the Filter ID as a side-effect,
+ // so we know that it is a valid VLI.
+ *size += lzma_vli_size(filter->id) + lzma_vli_size(*size);
return LZMA_OK;
}
-#endif
extern LZMA_API lzma_ret
-lzma_filter_flags_encode(uint8_t *out, size_t *out_pos, size_t out_size,
- const lzma_options_filter *options)
+lzma_filter_flags_encode(const lzma_filter *filter,
+ uint8_t *out, size_t *out_pos, size_t out_size)
{
- // Minimum output is one byte (everything fits into Misc).
- // The caller should have checked that there is enough output space,
- // so we return LZMA_PROG_ERROR instead of LZMA_BUF_ERROR.
- if (*out_pos >= out_size)
- return LZMA_PROG_ERROR;
-
- // Get size of Filter Properties.
- uint32_t prop_size;
- return_if_error(get_properties_size(&prop_size, options));
-
// Filter ID
- return_if_error(lzma_vli_encode(options->id, NULL,
+ if (filter->id >= LZMA_FILTER_RESERVED_START)
+ return LZMA_HEADER_ERROR;
+
+ return_if_error(lzma_vli_encode(filter->id, NULL,
out, out_pos, out_size));
// Size of Properties
- return_if_error(lzma_vli_encode(prop_size, NULL,
+ uint32_t props_size;
+ return_if_error(lzma_properties_size(&props_size, filter));
+ return_if_error(lzma_vli_encode(props_size, NULL,
out, out_pos, out_size));
// Filter Properties
- lzma_ret ret;
- switch (options->id) {
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK:
- assert(prop_size == 0);
- ret = LZMA_OK;
- break;
-#endif
-
-#ifdef HAVE_FILTER_SIMPLE
-# ifdef HAVE_FILTER_X86
- case LZMA_FILTER_X86:
-# endif
-# ifdef HAVE_FILTER_POWERPC
- case LZMA_FILTER_POWERPC:
-# endif
-# ifdef HAVE_FILTER_IA64
- case LZMA_FILTER_IA64:
-# endif
-# ifdef HAVE_FILTER_ARM
- case LZMA_FILTER_ARM:
-# endif
-# ifdef HAVE_FILTER_ARMTHUMB
- case LZMA_FILTER_ARMTHUMB:
-# endif
-# ifdef HAVE_FILTER_SPARC
- case LZMA_FILTER_SPARC:
-# endif
- ret = properties_simple(out, out_pos, out_size,
- options->options);
- break;
-#endif
-
-#ifdef HAVE_FILTER_DELTA
- case LZMA_FILTER_DELTA:
- ret = properties_delta(out, out_pos, out_size,
- options->options);
- break;
-#endif
+ if (out_size - *out_pos < props_size)
+ return LZMA_PROG_ERROR;
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA:
- ret = properties_lzma(out, out_pos, out_size,
- options->options);
- break;
-#endif
+ return_if_error(lzma_properties_encode(filter, out + *out_pos));
- default:
- assert(0);
- ret = LZMA_PROG_ERROR;
- break;
- }
+ *out_pos += props_size;
- return ret;
+ return LZMA_OK;
}
diff --git a/src/liblzma/common/index_decoder.c b/src/liblzma/common/index_decoder.c
index 1635948c..ae66595a 100644
--- a/src/liblzma/common/index_decoder.c
+++ b/src/liblzma/common/index_decoder.c
@@ -201,6 +201,8 @@ static lzma_ret
index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_index **i)
{
+ lzma_next_coder_init(index_decoder_init, next, allocator);
+
if (i == NULL)
return LZMA_PROG_ERROR;
@@ -231,20 +233,10 @@ index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
}
-/*
-extern lzma_ret
-lzma_index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_index **i)
-{
- lzma_next_coder_init(index_decoder_init, next, allocator, i);
-}
-*/
-
-
extern LZMA_API lzma_ret
lzma_index_decoder(lzma_stream *strm, lzma_index **i)
{
- lzma_next_strm_init(strm, index_decoder_init, i);
+ lzma_next_strm_init(index_decoder_init, strm, i);
strm->internal->supported_actions[LZMA_RUN] = true;
diff --git a/src/liblzma/common/index_encoder.c b/src/liblzma/common/index_encoder.c
index 5a7d8c8c..3005f835 100644
--- a/src/liblzma/common/index_encoder.c
+++ b/src/liblzma/common/index_encoder.c
@@ -176,10 +176,12 @@ index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
}
-static lzma_ret
-index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+extern lzma_ret
+lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_index *i)
{
+ lzma_next_coder_init(lzma_index_encoder_init, next, allocator);
+
if (i == NULL)
return LZMA_PROG_ERROR;
@@ -203,18 +205,10 @@ index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
}
-extern lzma_ret
-lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- lzma_index *i)
-{
- lzma_next_coder_init(index_encoder_init, next, allocator, i);
-}
-
-
extern LZMA_API lzma_ret
lzma_index_encoder(lzma_stream *strm, lzma_index *i)
{
- lzma_next_strm_init(strm, index_encoder_init, i);
+ lzma_next_strm_init(lzma_index_encoder_init, strm, i);
strm->internal->supported_actions[LZMA_RUN] = true;
diff --git a/src/liblzma/common/index_hash.c b/src/liblzma/common/index_hash.c
index 35dea41f..dc533f9e 100644
--- a/src/liblzma/common/index_hash.c
+++ b/src/liblzma/common/index_hash.c
@@ -36,7 +36,7 @@ typedef struct {
lzma_vli index_list_size;
/// Check calculated from Total Sizes and Uncompressed Sizes.
- lzma_check check;
+ lzma_check_state check;
} lzma_index_hash_info;
@@ -300,9 +300,9 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
// Finish the hashes and compare them.
lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST);
lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST);
- if (memcmp(index_hash->blocks.check.buffer,
- index_hash->records.check.buffer,
- lzma_check_sizes[LZMA_CHECK_BEST]) != 0)
+ if (memcmp(index_hash->blocks.check.buffer.u8,
+ index_hash->records.check.buffer.u8,
+ lzma_check_size(LZMA_CHECK_BEST)) != 0)
return LZMA_DATA_ERROR;
// Finish the CRC32 calculation.
diff --git a/src/liblzma/common/init_encoder.c b/src/liblzma/common/init_encoder.c
index 8a1644be..c5f12a91 100644
--- a/src/liblzma/common/init_encoder.c
+++ b/src/liblzma/common/init_encoder.c
@@ -31,7 +31,7 @@ lzma_init_encoder(void)
lzma_init_check();
-#if defined(HAVE_SMALL) && defined(HAVE_ENCODER) && defined(HAVE_FILTER_LZMA)
+#if defined(HAVE_SMALL) && defined(HAVE_ENCODER_LZMA)
lzma_rc_init();
#endif
diff --git a/src/liblzma/common/memory_usage.c b/src/liblzma/common/memory_usage.c
deleted file mode 100644
index 8244c404..00000000
--- a/src/liblzma/common/memory_usage.c
+++ /dev/null
@@ -1,112 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file memory_usage.c
-/// \brief Calculate rough amount of memory required by filters
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-#include "lz_encoder.h"
-#include "lzma_literal.h"
-
-
-static uint64_t
-get_usage(const lzma_options_filter *filter, bool is_encoder)
-{
- uint64_t ret;
-
- switch (filter->id) {
- case LZMA_FILTER_X86:
- case LZMA_FILTER_POWERPC:
- case LZMA_FILTER_IA64:
- case LZMA_FILTER_ARM:
- case LZMA_FILTER_ARMTHUMB:
- case LZMA_FILTER_SPARC:
- case LZMA_FILTER_DELTA:
- // These don't require any significant amount of memory.
- ret = 0;
- break;
-
- case LZMA_FILTER_SUBBLOCK:
- if (is_encoder) {
- const lzma_options_subblock *options = filter->options;
- ret = options->subblock_data_size;
- } else {
- ret = 0;
- }
- break;
-
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA: {
- const lzma_options_lzma *options = filter->options;
-
- // Literal coder - this can be signficant if both values are
- // big, or if sizeof(probability) is big.
- ret = literal_states(options->literal_context_bits,
- options->literal_pos_bits) * LIT_SIZE
- * sizeof(probability);
-
- // Dictionary base size
- ret += options->dictionary_size;
-
- if (is_encoder) {
-# ifdef HAVE_ENCODER
- // This is rough, but should be accurate enough
- // in practice.
- ret += options->dictionary_size / 2;
-
- uint32_t dummy1;
- uint32_t dummy2;
- uint32_t num_items;
- if (lzma_lz_encoder_hash_properties(
- options->match_finder,
- options->dictionary_size,
- &dummy1, &dummy2, &num_items))
- return UINT64_MAX;
-
- ret += (uint64_t)(num_items) * sizeof(uint32_t);
-# else
- return UINT64_MAX;
-# endif
- }
-
- break;
- }
-#endif
-
- default:
- return UINT64_MAX;
- }
-
- return ret;
-}
-
-
-extern LZMA_API uint32_t
-lzma_memory_usage(const lzma_options_filter *filters, lzma_bool is_encoder)
-{
- uint64_t usage = 0;
-
- for (size_t i = 0; filters[i].id != UINT64_MAX; ++i) {
- const uint64_t ret = get_usage(filters + i, is_encoder);
- if (ret == UINT64_MAX)
- return UINT32_MAX;
-
- usage += ret;
- }
-
- // Convert to mebibytes with rounding.
- return usage / (1024 * 1024) + (usage % (1024 * 1024) >= 512 ? 1 : 0);
-}
diff --git a/src/liblzma/common/next_coder.c b/src/liblzma/common/next_coder.c
deleted file mode 100644
index c10fe24d..00000000
--- a/src/liblzma/common/next_coder.c
+++ /dev/null
@@ -1,65 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file next_coder.c
-/// \brief Initializing and freeing the next coder in the chain
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-
-extern lzma_ret
-lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters)
-{
- lzma_ret ret = LZMA_OK;
-
- // Free the existing coder if it is different than the current one.
- if ((uintptr_t)(filters[0].init) != next->init)
- lzma_next_coder_end(next, allocator);
-
- if (filters[0].init != NULL) {
- // Initialize the new coder.
- ret = filters[0].init(next, allocator, filters);
-
- // Set the init function pointer if initialization was
- // successful. next->code and next->end are set by the
- // initialization function itself.
- if (ret == LZMA_OK) {
- next->init = (uintptr_t)(filters[0].init);
- assert(next->code != NULL);
- assert(next->end != NULL);
- } else {
- lzma_next_coder_end(next, allocator);
- }
- }
-
- return ret;
-}
-
-
-extern void
-lzma_next_coder_end(lzma_next_coder *next, lzma_allocator *allocator)
-{
- if (next != NULL) {
- if (next->end != NULL)
- next->end(next->coder, allocator);
-
- // Reset the variables so the we don't accidentally think
- // that it is an already initialized coder.
- *next = LZMA_NEXT_CODER_INIT;
- }
-
- return;
-}
diff --git a/src/liblzma/common/raw_common.c b/src/liblzma/common/raw_common.c
deleted file mode 100644
index 35252fc2..00000000
--- a/src/liblzma/common/raw_common.c
+++ /dev/null
@@ -1,127 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file raw_common.c
-/// \brief Stuff shared between raw encoder and raw decoder
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "raw_common.h"
-
-
-static lzma_ret
-validate_options(const lzma_options_filter *options, size_t *count)
-{
- if (options == NULL)
- return LZMA_PROG_ERROR;
-
- // Number of non-last filters that may change the size of the data
- // significantly (that is, more than 1-2 % or so).
- size_t change = 0;
-
- // True if the last filter in the given chain is actually usable as
- // the last filter. Only filters that support embedding End of Payload
- // Marker can be used as the last filter in the chain.
- bool last_ok = false;
-
- size_t i;
- for (i = 0; options[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
- switch (options[i].id) {
- // Not #ifdeffing these for simplicity.
- case LZMA_FILTER_X86:
- case LZMA_FILTER_POWERPC:
- case LZMA_FILTER_IA64:
- case LZMA_FILTER_ARM:
- case LZMA_FILTER_ARMTHUMB:
- case LZMA_FILTER_SPARC:
- case LZMA_FILTER_DELTA:
- // These don't change the size of the data and cannot
- // be used as the last filter in the chain.
- last_ok = false;
- break;
-
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK:
- last_ok = true;
- ++change;
- break;
-#endif
-
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA:
- last_ok = true;
- break;
-#endif
-
- default:
- return LZMA_HEADER_ERROR;
- }
- }
-
- // There must be 1-4 filters and the last filter must be usable as
- // the last filter in the chain.
- if (i == 0 || i > 4 || !last_ok)
- return LZMA_HEADER_ERROR;
-
- // At maximum of two non-last filters are allowed to change the
- // size of the data.
- if (change > 2)
- return LZMA_HEADER_ERROR;
-
- *count = i;
- return LZMA_OK;
-}
-
-
-extern lzma_ret
-lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_filter *options,
- lzma_init_function (*get_function)(lzma_vli id),
- bool is_encoder)
-{
- // Do some basic validation and get the number of filters.
- size_t count;
- return_if_error(validate_options(options, &count));
-
- // Set the filter functions and copy the options pointer.
- lzma_filter_info filters[count + 1];
- if (is_encoder) {
- for (size_t i = 0; i < count; ++i) {
- // The order of the filters is reversed in the
- // encoder. It allows more efficient handling
- // of the uncompressed data.
- const size_t j = count - i - 1;
-
- filters[j].init = get_function(options[i].id);
- if (filters[j].init == NULL)
- return LZMA_HEADER_ERROR;
-
- filters[j].options = options[i].options;
- }
- } else {
- for (size_t i = 0; i < count; ++i) {
- filters[i].init = get_function(options[i].id);
- if (filters[i].init == NULL)
- return LZMA_HEADER_ERROR;
-
- filters[i].options = options[i].options;
- }
- }
-
- // Terminate the array.
- filters[count].init = NULL;
-
- // Initialize the filters.
- return lzma_next_filter_init(next, allocator, filters);
-}
diff --git a/src/liblzma/common/raw_decoder.c b/src/liblzma/common/raw_decoder.c
deleted file mode 100644
index 4fb7111c..00000000
--- a/src/liblzma/common/raw_decoder.c
+++ /dev/null
@@ -1,116 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file raw_decoder.c
-/// \brief Raw decoder initialization API
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "raw_decoder.h"
-#include "simple_coder.h"
-#include "subblock_decoder.h"
-#include "subblock_decoder_helper.h"
-#include "delta_decoder.h"
-#include "lzma_decoder.h"
-
-
-static lzma_init_function
-get_function(lzma_vli id)
-{
- switch (id) {
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK:
- return &lzma_subblock_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_X86
- case LZMA_FILTER_X86:
- return &lzma_simple_x86_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_POWERPC
- case LZMA_FILTER_POWERPC:
- return &lzma_simple_powerpc_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_IA64
- case LZMA_FILTER_IA64:
- return &lzma_simple_ia64_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_ARM
- case LZMA_FILTER_ARM:
- return &lzma_simple_arm_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_ARMTHUMB
- case LZMA_FILTER_ARMTHUMB:
- return &lzma_simple_armthumb_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_SPARC
- case LZMA_FILTER_SPARC:
- return &lzma_simple_sparc_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_DELTA
- case LZMA_FILTER_DELTA:
- return &lzma_delta_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA:
- return &lzma_lzma_decoder_init;
-#endif
-
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK_HELPER:
- return &lzma_subblock_decoder_helper_init;
-#endif
- }
-
- return NULL;
-}
-
-
-extern lzma_ret
-lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_filter *options)
-{
- const lzma_ret ret = lzma_raw_coder_init(next, allocator,
- options, &get_function, false);
-
- if (ret != LZMA_OK)
- lzma_next_coder_end(next, allocator);
-
- return ret;
-}
-
-
-extern LZMA_API lzma_ret
-lzma_raw_decoder(lzma_stream *strm, const lzma_options_filter *options)
-{
- return_if_error(lzma_strm_init(strm));
-
- strm->internal->supported_actions[LZMA_RUN] = true;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
-
- const lzma_ret ret = lzma_raw_coder_init(&strm->internal->next,
- strm->allocator, options, &get_function, false);
-
- if (ret != LZMA_OK)
- lzma_end(strm);
-
- return ret;
-}
diff --git a/src/liblzma/common/raw_decoder.h b/src/liblzma/common/raw_decoder.h
deleted file mode 100644
index c0e626a8..00000000
--- a/src/liblzma/common/raw_decoder.h
+++ /dev/null
@@ -1,29 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file raw_decoder.h
-/// \brief Raw decoder initialization API
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef LZMA_RAW_DECODER_H
-#define LZMA_RAW_DECODER_H
-
-#include "raw_common.h"
-
-
-extern lzma_ret lzma_raw_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_options_filter *options);
-
-#endif
diff --git a/src/liblzma/common/raw_encoder.c b/src/liblzma/common/raw_encoder.c
deleted file mode 100644
index 9b8cbfae..00000000
--- a/src/liblzma/common/raw_encoder.c
+++ /dev/null
@@ -1,111 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file raw_encoder.c
-/// \brief Raw encoder initialization API
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "raw_encoder.h"
-#include "simple_coder.h"
-#include "subblock_encoder.h"
-#include "delta_encoder.h"
-#include "lzma_encoder.h"
-
-
-static lzma_init_function
-get_function(lzma_vli id)
-{
- switch (id) {
-#ifdef HAVE_FILTER_SUBBLOCK
- case LZMA_FILTER_SUBBLOCK:
- return &lzma_subblock_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_X86
- case LZMA_FILTER_X86:
- return &lzma_simple_x86_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_POWERPC
- case LZMA_FILTER_POWERPC:
- return &lzma_simple_powerpc_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_IA64
- case LZMA_FILTER_IA64:
- return &lzma_simple_ia64_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_ARM
- case LZMA_FILTER_ARM:
- return &lzma_simple_arm_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_ARMTHUMB
- case LZMA_FILTER_ARMTHUMB:
- return &lzma_simple_armthumb_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_SPARC
- case LZMA_FILTER_SPARC:
- return &lzma_simple_sparc_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_DELTA
- case LZMA_FILTER_DELTA:
- return &lzma_delta_encoder_init;
-#endif
-
-#ifdef HAVE_FILTER_LZMA
- case LZMA_FILTER_LZMA:
- return &lzma_lzma_encoder_init;
-#endif
- }
-
- return NULL;
-}
-
-
-extern lzma_ret
-lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_filter *options)
-{
- const lzma_ret ret = lzma_raw_coder_init(next, allocator,
- options, &get_function, true);
-
- if (ret != LZMA_OK)
- lzma_next_coder_end(next, allocator);
-
- return ret;
-}
-
-
-extern LZMA_API lzma_ret
-lzma_raw_encoder(lzma_stream *strm, const lzma_options_filter *options)
-{
- return_if_error(lzma_strm_init(strm));
-
- strm->internal->supported_actions[LZMA_RUN] = true;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
- strm->internal->supported_actions[LZMA_FINISH] = true;
-
- const lzma_ret ret = lzma_raw_coder_init(&strm->internal->next,
- strm->allocator, options, &get_function, true);
-
- if (ret != LZMA_OK)
- lzma_end(strm);
-
- return ret;
-}
diff --git a/src/liblzma/common/raw_encoder.h b/src/liblzma/common/raw_encoder.h
deleted file mode 100644
index 4e148489..00000000
--- a/src/liblzma/common/raw_encoder.h
+++ /dev/null
@@ -1,29 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file raw_encoder.h
-/// \brief Raw encoder initialization API
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef LZMA_RAW_ENCODER_H
-#define LZMA_RAW_ENCODER_H
-
-#include "raw_common.h"
-
-
-extern lzma_ret lzma_raw_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_options_filter *options);
-
-#endif
diff --git a/src/liblzma/common/stream_common.c b/src/liblzma/common/stream_common.c
deleted file mode 100644
index 121a6674..00000000
--- a/src/liblzma/common/stream_common.c
+++ /dev/null
@@ -1,23 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file stream_common.c
-/// \brief Common stuff for Stream coders
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "stream_common.h"
-
-const uint8_t lzma_header_magic[6] = { 0xFF, 0x4C, 0x5A, 0x4D, 0x41, 0x00 };
-const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };
diff --git a/src/liblzma/common/stream_decoder.c b/src/liblzma/common/stream_decoder.c
index 1bf7f1f8..5b46819d 100644
--- a/src/liblzma/common/stream_decoder.c
+++ b/src/liblzma/common/stream_decoder.c
@@ -17,8 +17,8 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_common.h"
#include "stream_decoder.h"
+#include "stream_flags_common.h"
#include "check.h"
#include "stream_flags_decoder.h"
#include "block_decoder.h"
@@ -31,6 +31,7 @@ struct lzma_coder_s {
SEQ_BLOCK,
SEQ_INDEX,
SEQ_STREAM_FOOTER,
+ SEQ_STREAM_PADDING,
} sequence;
/// Block or Metadata decoder. This takes little memory and the same
@@ -40,7 +41,7 @@ struct lzma_coder_s {
/// Block options decoded by the Block Header decoder and used by
/// the Block decoder.
- lzma_options_block block_options;
+ lzma_block block_options;
/// Stream Flags from Stream Header
lzma_stream_flags stream_flags;
@@ -49,8 +50,35 @@ struct lzma_coder_s {
/// with O(1) memory usage.
lzma_index_hash *index_hash;
- /// Write position in buffer[]
- size_t buffer_pos;
+ /// Memory usage limit
+ uint64_t memlimit;
+
+ /// If true, LZMA_NO_CHECK is returned if the Stream has
+ /// no integrity check.
+ bool warn_no_check;
+
+ /// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
+ /// an integrity check that isn't supported by this liblzma build.
+ bool warn_unsupported_check;
+
+ /// If true, LZMA_SEE_CHECK is returned after decoding Stream Header.
+ bool tell_check;
+
+ /// If true, we will decode concatenated Streams that possibly have
+ /// Stream Padding between or after them. LZMA_STREAM_END is returned
+ /// once the application isn't giving us any new input and we aren't
+ /// in the middle of a Stream and possible Stream Padding is a
+ /// multiple of four bytes. FIXME
+ bool concatenated;
+
+ /// When decoding concatenated Streams, this is true as long as we
+ /// are decoding the first Stream. This is needed to avoid misleading
+ /// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
+ /// bytes.
+ bool first_stream;
+
+ /// Write position in buffer[] and position in Stream Padding
+ size_t pos;
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
/// Block Header has biggest maximum size.
@@ -59,6 +87,23 @@ struct lzma_coder_s {
static lzma_ret
+stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
+{
+ // Initialize the Index hash used to verify the Index.
+ coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
+ if (coder->index_hash == NULL)
+ return LZMA_MEM_ERROR;
+
+ // Reset the rest of the variables.
+ coder->sequence = SEQ_STREAM_HEADER;
+ coder->block_options.filters = NULL;
+ coder->pos = 0;
+
+ return LZMA_OK;
+}
+
+
+static lzma_ret
stream_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,
@@ -66,43 +111,56 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
{
// When decoding the actual Block, it may be able to produce more
// output even if we don't give it any new input.
- while (*out_pos < out_size && (*in_pos < in_size
- || coder->sequence == SEQ_BLOCK))
+ while (true)
switch (coder->sequence) {
case SEQ_STREAM_HEADER: {
// Copy the Stream Header to the internal buffer.
- bufcpy(in, in_pos, in_size, coder->buffer, &coder->buffer_pos,
+ lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE);
// Return if we didn't get the whole Stream Header yet.
- if (coder->buffer_pos < LZMA_STREAM_HEADER_SIZE)
+ if (coder->pos < LZMA_STREAM_HEADER_SIZE)
return LZMA_OK;
- coder->buffer_pos = 0;
+ coder->pos = 0;
// Decode the Stream Header.
- return_if_error(lzma_stream_header_decode(
- &coder->stream_flags, coder->buffer));
+ const lzma_ret ret = lzma_stream_header_decode(
+ &coder->stream_flags, coder->buffer);
+ if (ret != LZMA_OK)
+ return ret == LZMA_FORMAT_ERROR && !coder->first_stream
+ ? LZMA_DATA_ERROR : ret;
// Copy the type of the Check so that Block Header and Block
// decoders see it.
coder->block_options.check = coder->stream_flags.check;
- // Even if we return LZMA_UNSUPPORTED_CHECK below, we want
+ // Even if we return LZMA_*_CHECK below, we want
// to continue from Block Header decoding.
coder->sequence = SEQ_BLOCK_HEADER;
- // Detect if the Check type is supported and give appropriate
- // warning if it isn't. We don't warn every time a new Block
- // is started.
- if (!lzma_available_checks[coder->block_options.check])
+ // Detect if there's no integrity check or if it is
+ // unsupported if those were requested by the application.
+ if (coder->warn_no_check && coder->stream_flags.check
+ == LZMA_CHECK_NONE)
+ return LZMA_NO_CHECK;
+
+ if (coder->warn_unsupported_check
+ && !lzma_check_is_supported(
+ coder->stream_flags.check))
return LZMA_UNSUPPORTED_CHECK;
+ if (coder->tell_check)
+ return LZMA_SEE_CHECK;
+
break;
}
case SEQ_BLOCK_HEADER: {
- if (coder->buffer_pos == 0) {
+ if (*in_pos >= in_size)
+ return LZMA_OK;
+
+ if (coder->pos == 0) {
// Detect if it's Index.
if (in[*in_pos] == 0x00) {
coder->sequence = SEQ_INDEX;
@@ -118,29 +176,41 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
}
// Copy the Block Header to the internal buffer.
- bufcpy(in, in_pos, in_size, coder->buffer, &coder->buffer_pos,
+ lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
coder->block_options.header_size);
// Return if we didn't get the whole Block Header yet.
- if (coder->buffer_pos < coder->block_options.header_size)
+ if (coder->pos < coder->block_options.header_size)
return LZMA_OK;
- coder->buffer_pos = 0;
+ coder->pos = 0;
// Set up a buffer to hold the filter chain. Block Header
// decoder will initialize all members of this array so
// we don't need to do it here.
- lzma_options_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
+ lzma_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
coder->block_options.filters = filters;
// Decode the Block Header.
return_if_error(lzma_block_header_decode(&coder->block_options,
allocator, coder->buffer));
- // Initialize the Block decoder.
- const lzma_ret ret = lzma_block_decoder_init(
- &coder->block_decoder,
- allocator, &coder->block_options);
+ // Check the memory usage limit.
+ const uint64_t memusage = lzma_memusage_decoder(filters);
+ lzma_ret ret;
+
+ if (memusage == UINT64_MAX) {
+ // One or more unknown Filter IDs.
+ ret = LZMA_HEADER_ERROR;
+ } else if (memusage > coder->memlimit) {
+ // The chain would need too much memory.
+ ret = LZMA_MEMLIMIT_ERROR;
+ } else {
+ // Memory usage is OK. Initialize the Block decoder.
+ ret = lzma_block_decoder_init(
+ &coder->block_decoder,
+ allocator, &coder->block_options);
+ }
// Free the allocated filter options since they are needed
// only to initialize the Block decoder.
@@ -149,10 +219,9 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->block_options.filters = NULL;
- // Check if Block enocoder initialization succeeded. Don't
- // warn about unsupported check anymore since we did it
- // earlier if it was needed.
- if (ret != LZMA_OK && ret != LZMA_UNSUPPORTED_CHECK)
+ // Check if memory usage calculation and Block enocoder
+ // initialization succeeded.
+ if (ret != LZMA_OK)
return ret;
coder->sequence = SEQ_BLOCK;
@@ -160,7 +229,7 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
}
case SEQ_BLOCK: {
- lzma_ret ret = coder->block_decoder.code(
+ const lzma_ret ret = coder->block_decoder.code(
coder->block_decoder.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
@@ -180,6 +249,12 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
}
case SEQ_INDEX: {
+ // If we don't have any input, don't call
+ // lzma_index_hash_decode() since it would return
+ // LZMA_BUF_ERROR, which we must not do here.
+ if (*in_pos >= in_size)
+ return LZMA_OK;
+
// Decode the Index and compare it to the hash calculated
// from the sizes of the Blocks (if any).
const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
@@ -193,14 +268,17 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_STREAM_FOOTER:
// Copy the Stream Footer to the internal buffer.
- bufcpy(in, in_pos, in_size, coder->buffer, &coder->buffer_pos,
+ lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE);
// Return if we didn't get the whole Stream Footer yet.
- if (coder->buffer_pos < LZMA_STREAM_HEADER_SIZE)
+ if (coder->pos < LZMA_STREAM_HEADER_SIZE)
return LZMA_OK;
+ coder->pos = 0;
+
// Decode the Stream Footer.
+ // FIXME LZMA_FORMAT_ERROR doesn't make sense here.
lzma_stream_flags footer_flags;
return_if_error(lzma_stream_footer_decode(
&footer_flags, coder->buffer));
@@ -217,7 +295,48 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
&footer_flags))
return LZMA_DATA_ERROR;
- return LZMA_STREAM_END;
+ if (!coder->concatenated)
+ return LZMA_STREAM_END;
+
+ coder->sequence = SEQ_STREAM_PADDING;
+ break;
+
+ case SEQ_STREAM_PADDING:
+ assert(coder->concatenated);
+
+ while (true) {
+ if (*in_pos >= in_size) {
+ // Unless LZMA_FINISH was used, we cannot
+ // know if there's more input coming later.
+ if (action != LZMA_FINISH)
+ return LZMA_OK;
+
+ // Stream Padding must be a multiple of
+ // four bytes.
+ return coder->pos == 0
+ ? LZMA_STREAM_END
+ : LZMA_DATA_ERROR;
+ }
+
+ if (in[*in_pos] != 0x00) {
+ if (coder->pos != 0) {
+ // Stream Padding is not a multiple of
+ // four bytes.
+ ++*in_pos;
+ return LZMA_DATA_ERROR;
+ }
+
+ // Prepare to decode the next Stream.
+ return_if_error(stream_decoder_reset(
+ coder, allocator));
+ break;
+ }
+
+ ++*in_pos;
+ coder->pos = (coder->pos + 1) & 3;
+ }
+
+ break;
default:
assert(0);
@@ -231,16 +350,29 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->block_decoder, allocator);
+ lzma_next_end(&coder->block_decoder, allocator);
lzma_index_hash_end(coder->index_hash, allocator);
lzma_free(coder, allocator);
return;
}
-static lzma_ret
-stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
+static lzma_check
+stream_decoder_see_check(const lzma_coder *coder)
{
+ return coder->stream_flags.check;
+}
+
+
+extern lzma_ret
+lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ uint64_t memlimit, uint32_t flags)
+{
+ lzma_next_coder_init(lzma_stream_decoder_init, next, allocator);
+
+ if (flags & ~LZMA_SUPPORTED_FLAGS)
+ return LZMA_HEADER_ERROR;
+
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
@@ -248,40 +380,32 @@ stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
next->code = &stream_decode;
next->end = &stream_decoder_end;
+ next->see_check = &stream_decoder_see_check;
next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
next->coder->index_hash = NULL;
}
- // Initialize the Index hash used to verify the Index.
- next->coder->index_hash = lzma_index_hash_init(
- next->coder->index_hash, allocator);
- if (next->coder->index_hash == NULL)
- return LZMA_MEM_ERROR;
-
- // Reset the rest of the variables.
- next->coder->sequence = SEQ_STREAM_HEADER;
- next->coder->block_options.filters = NULL;
- next->coder->buffer_pos = 0;
+ next->coder->memlimit = memlimit;
+ next->coder->warn_no_check = (flags & LZMA_WARN_NO_CHECK) != 0;
+ next->coder->warn_unsupported_check
+ = (flags & LZMA_WARN_UNSUPPORTED_CHECK) != 0;
+ next->coder->tell_check = (flags & LZMA_TELL_CHECK) != 0;
+ next->coder->concatenated
+ = (flags & LZMA_CONCATENATED) != 0;
- return LZMA_OK;
-}
-
-
-extern lzma_ret
-lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
-{
- lzma_next_coder_init0(stream_decoder_init, next, allocator);
+ return stream_decoder_reset(next->coder, allocator);
}
extern LZMA_API lzma_ret
-lzma_stream_decoder(lzma_stream *strm)
+lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{
- lzma_next_strm_init0(strm, stream_decoder_init);
+ lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+// strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; // FIXME
+ strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;
}
diff --git a/src/liblzma/common/stream_decoder.h b/src/liblzma/common/stream_decoder.h
index dcda387d..59d58c6f 100644
--- a/src/liblzma/common/stream_decoder.h
+++ b/src/liblzma/common/stream_decoder.h
@@ -22,7 +22,7 @@
#include "common.h"
-extern lzma_ret lzma_stream_decoder_init(
- lzma_next_coder *next, lzma_allocator *allocator);
+extern lzma_ret lzma_stream_decoder_init(lzma_next_coder *next,
+ lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
#endif
diff --git a/src/liblzma/common/stream_encoder.c b/src/liblzma/common/stream_encoder.c
index 767b8014..9d56c899 100644
--- a/src/liblzma/common/stream_encoder.c
+++ b/src/liblzma/common/stream_encoder.c
@@ -17,8 +17,8 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_common.h"
#include "stream_encoder.h"
+#include "stream_flags_common.h"
#include "block_encoder.h"
#include "index_encoder.h"
@@ -37,7 +37,7 @@ struct lzma_coder_s {
lzma_next_coder block_encoder;
/// Options for the Block encoder
- lzma_options_block block_options;
+ lzma_block block_options;
/// Index encoder. This is separate from Block encoder, because this
/// doesn't take much memory, and when encoding multiple Streams
@@ -86,8 +86,8 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_STREAM_HEADER:
case SEQ_BLOCK_HEADER:
case SEQ_STREAM_FOOTER:
- bufcpy(coder->buffer, &coder->buffer_pos, coder->buffer_size,
- out, out_pos, out_size);
+ lzma_bufcpy(coder->buffer, &coder->buffer_pos,
+ coder->buffer_size, out, out_pos, out_size);
if (coder->buffer_pos < coder->buffer_size)
return LZMA_OK;
@@ -202,18 +202,20 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
static void
stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
- lzma_next_coder_end(&coder->block_encoder, allocator);
- lzma_next_coder_end(&coder->index_encoder, allocator);
+ lzma_next_end(&coder->block_encoder, allocator);
+ lzma_next_end(&coder->index_encoder, allocator);
lzma_index_end(coder->index, allocator);
lzma_free(coder, allocator);
return;
}
-static lzma_ret
-stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_filter *filters, lzma_check_type check)
+extern lzma_ret
+lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ const lzma_filter *filters, lzma_check check)
{
+ lzma_next_coder_init(lzma_stream_encoder_init, next, allocator);
+
if (filters == NULL)
return LZMA_PROG_ERROR;
@@ -233,7 +235,7 @@ stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Basic initializations
next->coder->sequence = SEQ_STREAM_HEADER;
next->coder->block_options.check = check;
- next->coder->block_options.filters = (lzma_options_filter *)(filters);
+ next->coder->block_options.filters = (lzma_filter *)(filters);
// Initialize the Index
next->coder->index = lzma_index_init(next->coder->index, allocator);
@@ -258,20 +260,11 @@ stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
}
-extern lzma_ret
-lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_filter *filters, lzma_check_type check)
-{
- lzma_next_coder_init(stream_encoder_init, next, allocator,
- filters, check);
-}
-
-
extern LZMA_API lzma_ret
lzma_stream_encoder(lzma_stream *strm,
- const lzma_options_filter *filters, lzma_check_type check)
+ const lzma_filter *filters, lzma_check check)
{
- lzma_next_strm_init(strm, stream_encoder_init, filters, check);
+ lzma_next_strm_init(lzma_stream_encoder_init, strm, filters, check);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
diff --git a/src/liblzma/common/stream_encoder.h b/src/liblzma/common/stream_encoder.h
index 3ce29561..cec2e5b5 100644
--- a/src/liblzma/common/stream_encoder.h
+++ b/src/liblzma/common/stream_encoder.h
@@ -25,6 +25,6 @@
extern lzma_ret lzma_stream_encoder_init(
lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_filter *filters, lzma_check_type check);
+ const lzma_filter *filters, lzma_check check);
#endif
diff --git a/src/liblzma/common/stream_flags_equal.c b/src/liblzma/common/stream_flags_common.c
index db22567f..c44b3ff2 100644
--- a/src/liblzma/common/stream_flags_equal.c
+++ b/src/liblzma/common/stream_flags_common.c
@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file stream_flags_equal.c
-/// \brief Compare Stream Header and Stream Footer
+/// \file stream_flags_common.c
+/// \brief Common stuff for Stream flags coders
//
-// Copyright (C) 2008 Lasse Collin
+// Copyright (C) 2007-2008 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -17,11 +17,15 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "common.h"
+#include "stream_flags_common.h"
+
+
+const uint8_t lzma_header_magic[6] = { 0xFF, 0x4C, 0x5A, 0x4D, 0x41, 0x00 };
+const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };
extern LZMA_API lzma_bool
-lzma_stream_flags_equal(const lzma_stream_flags *a, lzma_stream_flags *b)
+lzma_stream_flags_equal(const lzma_stream_flags *a, const lzma_stream_flags *b)
{
if (a->check != b->check)
return false;
diff --git a/src/liblzma/common/stream_common.h b/src/liblzma/common/stream_flags_common.h
index 4f83fc58..6e57857b 100644
--- a/src/liblzma/common/stream_common.h
+++ b/src/liblzma/common/stream_flags_common.h
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file stream_common.h
-/// \brief Common stuff for Stream coders
+/// \file stream_flags_common.h
+/// \brief Common stuff for Stream flags coders
//
// Copyright (C) 2007 Lasse Collin
//
@@ -17,8 +17,8 @@
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef LZMA_STREAM_COMMON_H
-#define LZMA_STREAM_COMMON_H
+#ifndef LZMA_STREAM_FLAGS_COMMON_H
+#define LZMA_STREAM_FLAGS_COMMON_H
#include "common.h"
diff --git a/src/liblzma/common/stream_flags_decoder.c b/src/liblzma/common/stream_flags_decoder.c
index 0270875a..ccc1539d 100644
--- a/src/liblzma/common/stream_flags_decoder.c
+++ b/src/liblzma/common/stream_flags_decoder.c
@@ -17,7 +17,7 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_common.h"
+#include "stream_flags_common.h"
static bool
diff --git a/src/liblzma/common/stream_flags_encoder.c b/src/liblzma/common/stream_flags_encoder.c
index 4efbb6f4..1d736a8a 100644
--- a/src/liblzma/common/stream_flags_encoder.c
+++ b/src/liblzma/common/stream_flags_encoder.c
@@ -17,7 +17,7 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_common.h"
+#include "stream_flags_common.h"
static bool
diff --git a/src/liblzma/common/version.c b/src/liblzma/common/version.c
deleted file mode 100644
index dffec7ff..00000000
--- a/src/liblzma/common/version.c
+++ /dev/null
@@ -1,25 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file version.c
-/// \brief liblzma version number
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-
-
-LZMA_API const uint32_t lzma_version_number = LZMA_VERSION;
-
-LZMA_API const char *const lzma_version_string = PACKAGE_VERSION;
diff --git a/src/liblzma/common/vli_decoder.c b/src/liblzma/common/vli_decoder.c
index faff6ccb..60874baa 100644
--- a/src/liblzma/common/vli_decoder.c
+++ b/src/liblzma/common/vli_decoder.c
@@ -27,17 +27,30 @@ lzma_vli_decode(lzma_vli *restrict vli, size_t *restrict vli_pos,
{
// If we haven't been given vli_pos, work in single-call mode.
size_t vli_pos_internal = 0;
- if (vli_pos == NULL)
+ if (vli_pos == NULL) {
vli_pos = &vli_pos_internal;
-
- // Initialize *vli when starting to decode a new integer.
- if (*vli_pos == 0)
*vli = 0;
- // Validate the arguments.
- if (*vli_pos >= LZMA_VLI_BYTES_MAX || *in_pos >= in_size
- || (*vli >> (*vli_pos * 7)) != 0)
- return LZMA_PROG_ERROR;;
+ // If there's no input, use LZMA_DATA_ERROR. This way it is
+ // easy to decode VLIs from buffers that have known size,
+ // and get the correct error code in case the buffer is
+ // too short.
+ if (*in_pos >= in_size)
+ return LZMA_DATA_ERROR;
+
+ } else {
+ // Initialize *vli when starting to decode a new integer.
+ if (*vli_pos == 0)
+ *vli = 0;
+
+ // Validate the arguments.
+ if (*vli_pos >= LZMA_VLI_BYTES_MAX
+ || (*vli >> (*vli_pos * 7)) != 0)
+ return LZMA_PROG_ERROR;;
+
+ if (*in_pos >= in_size)
+ return LZMA_BUF_ERROR;
+ }
do {
// Read the next byte.
diff --git a/src/liblzma/common/vli_encoder.c b/src/liblzma/common/vli_encoder.c
index c48d6474..53022f16 100644
--- a/src/liblzma/common/vli_encoder.c
+++ b/src/liblzma/common/vli_encoder.c
@@ -31,10 +31,12 @@ lzma_vli_encode(lzma_vli vli, size_t *restrict vli_pos,
vli_pos = &vli_pos_internal;
// Validate the arguments.
- if (*vli_pos >= LZMA_VLI_BYTES_MAX || *out_pos >= out_size
- || vli > LZMA_VLI_VALUE_MAX)
+ if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_VALUE_MAX)
return LZMA_PROG_ERROR;
+ if (*out_pos >= out_size)
+ return LZMA_BUF_ERROR;
+
// Write the non-last bytes in a loop.
while ((vli >> (*vli_pos * 7)) >= 0x80) {
out[*out_pos] = (uint8_t)(vli >> (*vli_pos * 7)) | 0x80;
@@ -55,20 +57,3 @@ lzma_vli_encode(lzma_vli vli, size_t *restrict vli_pos,
return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END;
}
-
-
-extern LZMA_API uint32_t
-lzma_vli_size(lzma_vli vli)
-{
- if (vli > LZMA_VLI_VALUE_MAX)
- return 0;
-
- uint32_t i = 0;
- do {
- vli >>= 7;
- ++i;
- } while (vli != 0);
-
- assert(i <= LZMA_VLI_BYTES_MAX);
- return i;
-}
diff --git a/src/liblzma/common/delta_encoder.h b/src/liblzma/common/vli_size.c
index c669458d..547bba0b 100644
--- a/src/liblzma/common/delta_encoder.h
+++ b/src/liblzma/common/vli_size.c
@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file delta_encoder.h
-/// \brief Delta filter encoder
+/// \file vli_size.c
+/// \brief Calculates the encoded size of a variable-length integer
//
-// Copyright (C) 2007 Lasse Collin
+// Copyright (C) 2007-2008 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -17,12 +17,21 @@
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef LZMA_DELTA_ENCODER_H
-#define LZMA_DELTA_ENCODER_H
-
#include "common.h"
-extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
-#endif
+extern LZMA_API uint32_t
+lzma_vli_size(lzma_vli vli)
+{
+ if (vli > LZMA_VLI_VALUE_MAX)
+ return 0;
+
+ uint32_t i = 0;
+ do {
+ vli >>= 7;
+ ++i;
+ } while (vli != 0);
+
+ assert(i <= LZMA_VLI_BYTES_MAX);
+ return i;
+}