aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common/alone_encoder.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/liblzma/common/alone_encoder.c99
1 files changed, 47 insertions, 52 deletions
diff --git a/src/liblzma/common/alone_encoder.c b/src/liblzma/common/alone_encoder.c
index 7629aa77..f94a21c1 100644
--- a/src/liblzma/common/alone_encoder.c
+++ b/src/liblzma/common/alone_encoder.c
@@ -21,19 +21,19 @@
#include "lzma_encoder.h"
+#define ALONE_HEADER_SIZE (1 + 4 + 8)
+
+
struct lzma_coder_s {
lzma_next_coder next;
enum {
- SEQ_PROPERTIES,
- SEQ_DICTIONARY_SIZE,
- SEQ_UNCOMPRESSED_SIZE,
+ SEQ_HEADER,
SEQ_CODE,
} sequence;
- size_t pos;
-
- lzma_options_alone options;
+ size_t header_pos;
+ uint8_t header[ALONE_HEADER_SIZE];
};
@@ -47,47 +47,23 @@ alone_encode(lzma_coder *coder,
{
while (*out_pos < out_size)
switch (coder->sequence) {
- case SEQ_PROPERTIES:
- if (lzma_lzma_encode_properties(
- &coder->options.lzma, out + *out_pos)) {
- return LZMA_PROG_ERROR;
- }
-
- coder->sequence = SEQ_DICTIONARY_SIZE;
- ++*out_pos;
- break;
-
- case SEQ_DICTIONARY_SIZE:
- out[*out_pos] = coder->options.lzma.dictionary_size
- >> (coder->pos * 8);
-
- if (++coder->pos == 4) {
- coder->pos = 0;
- coder->sequence = SEQ_UNCOMPRESSED_SIZE;
- }
-
- ++*out_pos;
- break;
-
- case SEQ_UNCOMPRESSED_SIZE:
- out[*out_pos] = coder->options.uncompressed_size
- >> (coder->pos * 8);
-
- if (++coder->pos == 8) {
- coder->pos = 0;
- coder->sequence = SEQ_CODE;
- }
-
- ++*out_pos;
+ case SEQ_HEADER:
+ bufcpy(coder->header, &coder->header_pos,
+ ALONE_HEADER_SIZE,
+ out, out_pos, out_size);
+ if (coder->header_pos < ALONE_HEADER_SIZE)
+ return LZMA_OK;
+
+ coder->sequence = SEQ_CODE;
break;
- case SEQ_CODE: {
+ case SEQ_CODE:
return coder->next.code(coder->next.coder,
allocator, in, in_pos, in_size,
out, out_pos, out_size, action);
- }
default:
+ assert(0);
return LZMA_PROG_ERROR;
}
@@ -107,7 +83,7 @@ alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
// At least for now, this is not used by any internal function.
static lzma_ret
alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_options_alone *options)
+ const lzma_options_lzma *options)
{
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
@@ -119,23 +95,42 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->next = LZMA_NEXT_CODER_INIT;
}
- // Initialize the LZMA_Alone coder variables.
- next->coder->sequence = SEQ_PROPERTIES;
- next->coder->pos = 0;
- next->coder->options = *options;
+ // Basic initializations
+ next->coder->sequence = SEQ_HEADER;
+ next->coder->header_pos = 0;
- // Verify uncompressed_size since the other functions assume that
- // it is valid.
- if (!lzma_vli_is_valid(next->coder->options.uncompressed_size))
+ // Encode the header:
+ // - Properties (1 byte)
+ if (lzma_lzma_encode_properties(options, next->coder->header))
return LZMA_PROG_ERROR;
+ // - Dictionary size (4 bytes)
+ if (options->dictionary_size < LZMA_DICTIONARY_SIZE_MIN
+ || options->dictionary_size > LZMA_DICTIONARY_SIZE_MAX)
+ return LZMA_PROG_ERROR;
+
+ // Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
+ // 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.
+ uint32_t d = options->dictionary_size - 1;
+ d |= d >> 2;
+ d |= d >> 3;
+ d |= d >> 4;
+ d |= d >> 8;
+ d |= d >> 16;
+ ++d;
+
+ integer_write_32(next->coder->header + 1, d);
+
+ // - Uncompressed size (always unknown and using EOPM)
+ memset(next->coder->header + 1 + 4, 0xFF, 8);
+
// Initialize the LZMA encoder.
const lzma_filter_info filters[2] = {
{
.init = &lzma_lzma_encoder_init,
- .options = &next->coder->options.lzma,
- .uncompressed_size = next->coder->options
- .uncompressed_size,
+ .options = (void *)(options),
}, {
.init = NULL,
}
@@ -156,7 +151,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_alone *options)
+lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
{
lzma_next_strm_init(strm, alone_encoder_init, options);