1 | ///////////////////////////////////////////////////////////////////////////////
|
---|
2 | //
|
---|
3 | /// \file alone_encoder.c
|
---|
4 | /// \brief Encoder for LZMA_Alone files
|
---|
5 | //
|
---|
6 | // Author: Lasse Collin
|
---|
7 | //
|
---|
8 | // This file has been put into the public domain.
|
---|
9 | // You can do whatever you want with this file.
|
---|
10 | //
|
---|
11 | ///////////////////////////////////////////////////////////////////////////////
|
---|
12 |
|
---|
13 | #include "common.h"
|
---|
14 | #include "lzma_encoder.h"
|
---|
15 |
|
---|
16 |
|
---|
17 | #define ALONE_HEADER_SIZE (1 + 4 + 8)
|
---|
18 |
|
---|
19 |
|
---|
20 | typedef struct {
|
---|
21 | lzma_next_coder next;
|
---|
22 |
|
---|
23 | enum {
|
---|
24 | SEQ_HEADER,
|
---|
25 | SEQ_CODE,
|
---|
26 | } sequence;
|
---|
27 |
|
---|
28 | size_t header_pos;
|
---|
29 | uint8_t header[ALONE_HEADER_SIZE];
|
---|
30 | } lzma_alone_coder;
|
---|
31 |
|
---|
32 |
|
---|
33 | static lzma_ret
|
---|
34 | alone_encode(void *coder_ptr, const lzma_allocator *allocator,
|
---|
35 | const uint8_t *restrict in, size_t *restrict in_pos,
|
---|
36 | size_t in_size, uint8_t *restrict out,
|
---|
37 | size_t *restrict out_pos, size_t out_size,
|
---|
38 | lzma_action action)
|
---|
39 | {
|
---|
40 | lzma_alone_coder *coder = coder_ptr;
|
---|
41 |
|
---|
42 | while (*out_pos < out_size)
|
---|
43 | switch (coder->sequence) {
|
---|
44 | case SEQ_HEADER:
|
---|
45 | lzma_bufcpy(coder->header, &coder->header_pos,
|
---|
46 | ALONE_HEADER_SIZE,
|
---|
47 | out, out_pos, out_size);
|
---|
48 | if (coder->header_pos < ALONE_HEADER_SIZE)
|
---|
49 | return LZMA_OK;
|
---|
50 |
|
---|
51 | coder->sequence = SEQ_CODE;
|
---|
52 | break;
|
---|
53 |
|
---|
54 | case SEQ_CODE:
|
---|
55 | return coder->next.code(coder->next.coder,
|
---|
56 | allocator, in, in_pos, in_size,
|
---|
57 | out, out_pos, out_size, action);
|
---|
58 |
|
---|
59 | default:
|
---|
60 | assert(0);
|
---|
61 | return LZMA_PROG_ERROR;
|
---|
62 | }
|
---|
63 |
|
---|
64 | return LZMA_OK;
|
---|
65 | }
|
---|
66 |
|
---|
67 |
|
---|
68 | static void
|
---|
69 | alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
---|
70 | {
|
---|
71 | lzma_alone_coder *coder = coder_ptr;
|
---|
72 | lzma_next_end(&coder->next, allocator);
|
---|
73 | lzma_free(coder, allocator);
|
---|
74 | return;
|
---|
75 | }
|
---|
76 |
|
---|
77 |
|
---|
78 | // At least for now, this is not used by any internal function.
|
---|
79 | static lzma_ret
|
---|
80 | alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
---|
81 | const lzma_options_lzma *options)
|
---|
82 | {
|
---|
83 | lzma_next_coder_init(&alone_encoder_init, next, allocator);
|
---|
84 |
|
---|
85 | lzma_alone_coder *coder = next->coder;
|
---|
86 |
|
---|
87 | if (coder == NULL) {
|
---|
88 | coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
|
---|
89 | if (coder == NULL)
|
---|
90 | return LZMA_MEM_ERROR;
|
---|
91 |
|
---|
92 | next->coder = coder;
|
---|
93 | next->code = &alone_encode;
|
---|
94 | next->end = &alone_encoder_end;
|
---|
95 | coder->next = LZMA_NEXT_CODER_INIT;
|
---|
96 | }
|
---|
97 |
|
---|
98 | // Basic initializations
|
---|
99 | coder->sequence = SEQ_HEADER;
|
---|
100 | coder->header_pos = 0;
|
---|
101 |
|
---|
102 | // Encode the header:
|
---|
103 | // - Properties (1 byte)
|
---|
104 | if (lzma_lzma_lclppb_encode(options, coder->header))
|
---|
105 | return LZMA_OPTIONS_ERROR;
|
---|
106 |
|
---|
107 | // - Dictionary size (4 bytes)
|
---|
108 | if (options->dict_size < LZMA_DICT_SIZE_MIN)
|
---|
109 | return LZMA_OPTIONS_ERROR;
|
---|
110 |
|
---|
111 | // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
|
---|
112 | // one is the next unless it is UINT32_MAX. While the header would
|
---|
113 | // allow any 32-bit integer, we do this to keep the decoder of liblzma
|
---|
114 | // accepting the resulting files.
|
---|
115 | uint32_t d = options->dict_size - 1;
|
---|
116 | d |= d >> 2;
|
---|
117 | d |= d >> 3;
|
---|
118 | d |= d >> 4;
|
---|
119 | d |= d >> 8;
|
---|
120 | d |= d >> 16;
|
---|
121 | if (d != UINT32_MAX)
|
---|
122 | ++d;
|
---|
123 |
|
---|
124 | write32le(coder->header + 1, d);
|
---|
125 |
|
---|
126 | // - Uncompressed size (always unknown and using EOPM)
|
---|
127 | memset(coder->header + 1 + 4, 0xFF, 8);
|
---|
128 |
|
---|
129 | // Initialize the LZMA encoder.
|
---|
130 | const lzma_filter_info filters[2] = {
|
---|
131 | {
|
---|
132 | .id = LZMA_FILTER_LZMA1,
|
---|
133 | .init = &lzma_lzma_encoder_init,
|
---|
134 | .options = (void *)(options),
|
---|
135 | }, {
|
---|
136 | .init = NULL,
|
---|
137 | }
|
---|
138 | };
|
---|
139 |
|
---|
140 | return lzma_next_filter_init(&coder->next, allocator, filters);
|
---|
141 | }
|
---|
142 |
|
---|
143 |
|
---|
144 | /*
|
---|
145 | extern lzma_ret
|
---|
146 | lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
---|
147 | const lzma_options_alone *options)
|
---|
148 | {
|
---|
149 | lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
|
---|
150 | }
|
---|
151 | */
|
---|
152 |
|
---|
153 |
|
---|
154 | extern LZMA_API(lzma_ret)
|
---|
155 | lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
|
---|
156 | {
|
---|
157 | lzma_next_strm_init(alone_encoder_init, strm, options);
|
---|
158 |
|
---|
159 | strm->internal->supported_actions[LZMA_RUN] = true;
|
---|
160 | strm->internal->supported_actions[LZMA_FINISH] = true;
|
---|
161 |
|
---|
162 | return LZMA_OK;
|
---|
163 | }
|
---|