]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/lzma/lzma_encoder_init.c
Imported to git.
[icculus/xz.git] / src / liblzma / lzma / lzma_encoder_init.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       lzma_encoder_init.c
4 /// \brief      Creating, resetting and destroying the LZMA encoder
5 //
6 //  Copyright (C) 1999-2006 Igor Pavlov
7 //  Copyright (C) 2007 Lasse Collin
8 //
9 //  This library is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU Lesser General Public
11 //  License as published by the Free Software Foundation; either
12 //  version 2.1 of the License, or (at your option) any later version.
13 //
14 //  This library is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //  Lesser General Public License for more details.
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20
21 #include "lzma_encoder_private.h"
22
23
24 uint8_t lzma_fastpos[1 << 11];
25
26 extern void
27 lzma_fastpos_init(void)
28 {
29         static const uint8_t fast_slots = 22;
30
31         int c = 2;
32         lzma_fastpos[0] = 0;
33         lzma_fastpos[1] = 1;
34
35         for (uint8_t slot_fast = 2; slot_fast < fast_slots; ++slot_fast) {
36                 const uint32_t k = (1 << ((slot_fast >> 1) - 1));
37
38                 for (uint32_t j = 0; j < k; ++j, ++c)
39                         lzma_fastpos[c] = slot_fast;
40         }
41
42         return;
43 }
44
45
46 /// \brief      Initializes the length encoder
47 static void
48 length_encoder_reset(lzma_length_encoder *lencoder,
49                 const uint32_t num_pos_states, const uint32_t table_size)
50 {
51         // NLength::CPriceTableEncoder::SetTableSize()
52         lencoder->table_size = table_size;
53
54         // NLength::CEncoder::Init()
55         bit_reset(lencoder->choice);
56         bit_reset(lencoder->choice2);
57
58         for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
59                 bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS);
60                 bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS);
61         }
62
63         bittree_reset(lencoder->high, LEN_HIGH_BITS);
64
65         // NLength::CPriceTableEncoder::UpdateTables()
66         for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state)
67                 lzma_length_encoder_update_table(lencoder, pos_state);
68
69         return;
70 }
71
72
73 static void
74 lzma_lzma_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
75 {
76         lzma_lz_encoder_end(&coder->lz, allocator);
77         lzma_literal_end(&coder->literal_coder, allocator);
78         lzma_free(coder, allocator);
79         return;
80 }
81
82
83 extern lzma_ret
84 lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
85                 const lzma_filter_info *filters)
86 {
87         if (next->coder == NULL) {
88                 next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
89                 if (next->coder == NULL)
90                         return LZMA_MEM_ERROR;
91
92                 next->coder->next = LZMA_NEXT_CODER_INIT;
93                 next->coder->lz = LZMA_LZ_ENCODER_INIT;
94                 next->coder->literal_coder = NULL;
95         }
96
97         // Validate options that aren't validated elsewhere.
98         const lzma_options_lzma *options = filters[0].options;
99         if (options->pos_bits > LZMA_POS_BITS_MAX
100                         || options->fast_bytes < LZMA_FAST_BYTES_MIN
101                         || options->fast_bytes > LZMA_FAST_BYTES_MAX) {
102                 lzma_lzma_encoder_end(next->coder, allocator);
103                 return LZMA_HEADER_ERROR;
104         }
105
106         // Set compression mode.
107         switch (options->mode) {
108                 case LZMA_MODE_FAST:
109                         next->coder->best_compression = false;
110                         break;
111
112                 case LZMA_MODE_BEST:
113                         next->coder->best_compression = true;
114                         break;
115
116                 default:
117                         lzma_lzma_encoder_end(next->coder, allocator);
118                         return LZMA_HEADER_ERROR;
119         }
120
121         // Initialize literal coder.
122         {
123                 const lzma_ret ret = lzma_literal_init(
124                                 &next->coder->literal_coder, allocator,
125                                 options->literal_context_bits,
126                                 options->literal_pos_bits);
127                 if (ret != LZMA_OK) {
128                         lzma_lzma_encoder_end(next->coder, allocator);
129                         return ret;
130                 }
131         }
132
133         // Initialize LZ encoder.
134         {
135                 const lzma_ret ret = lzma_lz_encoder_reset(
136                                 &next->coder->lz, allocator, &lzma_lzma_encode,
137                                 filters[0].uncompressed_size,
138                                 options->dictionary_size, OPTS,
139                                 options->fast_bytes, MATCH_MAX_LEN + 1 + OPTS,
140                                 options->match_finder,
141                                 options->match_finder_cycles,
142                                 options->preset_dictionary,
143                                 options->preset_dictionary_size);
144                 if (ret != LZMA_OK) {
145                         lzma_lzma_encoder_end(next->coder, allocator);
146                         return ret;
147                 }
148         }
149
150         // Set dist_table_size.
151         {
152                 // Round the dictionary size up to next 2^n.
153                 uint32_t log_size;
154                 for (log_size = 0; (UINT32_C(1) << log_size)
155                                 < options->dictionary_size; ++log_size) ;
156
157                 next->coder->dist_table_size = log_size * 2;
158         }
159
160         // Misc FIXME desc
161         next->coder->dictionary_size = options->dictionary_size;
162         next->coder->pos_mask = (1U << options->pos_bits) - 1;
163         next->coder->fast_bytes = options->fast_bytes;
164
165         // Range coder
166         rc_reset(next->coder->rc);
167
168         // State
169         next->coder->state = 0;
170         next->coder->previous_byte = 0;
171         for (size_t i = 0; i < REP_DISTANCES; ++i)
172                 next->coder->rep_distances[i] = 0;
173
174         // Bit encoders
175         for (size_t i = 0; i < STATES; ++i) {
176                 for (size_t j = 0; j <= next->coder->pos_mask; ++j) {
177                         bit_reset(next->coder->is_match[i][j]);
178                         bit_reset(next->coder->is_rep0_long[i][j]);
179                 }
180
181                 bit_reset(next->coder->is_rep[i]);
182                 bit_reset(next->coder->is_rep0[i]);
183                 bit_reset(next->coder->is_rep1[i]);
184                 bit_reset(next->coder->is_rep2[i]);
185         }
186
187         for (size_t i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
188                 bit_reset(next->coder->pos_encoders[i]);
189
190         // Bit tree encoders
191         for (size_t i = 0; i < LEN_TO_POS_STATES; ++i)
192                 bittree_reset(next->coder->pos_slot_encoder[i], POS_SLOT_BITS);
193
194         bittree_reset(next->coder->pos_align_encoder, ALIGN_BITS);
195
196         // Length encoders
197         length_encoder_reset(&next->coder->len_encoder, 1U << options->pos_bits,
198                         options->fast_bytes + 1 - MATCH_MIN_LEN);
199
200         length_encoder_reset(&next->coder->rep_match_len_encoder,
201                         1U << options->pos_bits,
202                         next->coder->fast_bytes + 1 - MATCH_MIN_LEN);
203
204         // Misc
205         next->coder->longest_match_was_found = false;
206         next->coder->optimum_end_index = 0;
207         next->coder->optimum_current_index = 0;
208         next->coder->additional_offset = 0;
209
210         next->coder->now_pos = 0;
211         next->coder->is_initialized = false;
212
213         // Initialize the next decoder in the chain, if any.
214         {
215                 const lzma_ret ret = lzma_next_filter_init(&next->coder->next,
216                                 allocator, filters + 1);
217                 if (ret != LZMA_OK) {
218                         lzma_lzma_encoder_end(next->coder, allocator);
219                         return ret;
220                 }
221         }
222
223         // Initialization successful. Set the function pointers.
224         next->code = &lzma_lz_encode;
225         next->end = &lzma_lzma_encoder_end;
226
227         return LZMA_OK;
228 }
229
230
231 extern bool
232 lzma_lzma_encode_properties(const lzma_options_lzma *options, uint8_t *byte)
233 {
234         if (options->literal_context_bits > LZMA_LITERAL_CONTEXT_BITS_MAX
235                         || options->literal_pos_bits
236                                 > LZMA_LITERAL_POS_BITS_MAX
237                         || options->pos_bits > LZMA_POS_BITS_MAX)
238                 return true;
239
240         *byte = (options->pos_bits * 5 + options->literal_pos_bits) * 9
241                         + options->literal_context_bits;
242         assert(*byte <= (4 * 5 + 4) * 9 + 8);
243
244         return false;
245 }