1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
///////////////////////////////////////////////////////////////////////////////
//
/// \file lzma_encoder_private.h
/// \brief Private definitions for LZMA encoder
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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_LZMA_ENCODER_PRIVATE_H
#define LZMA_LZMA_ENCODER_PRIVATE_H
#include "lzma_encoder.h"
#include "lzma_common.h"
#include "lz_encoder.h"
#include "range_encoder.h"
#define move_pos(num) \
do { \
assert((int32_t)(num) >= 0); \
if ((num) != 0) { \
coder->additional_offset += num; \
coder->lz.skip(&coder->lz, num); \
} \
} while (0)
typedef struct {
probability choice;
probability choice2;
probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
probability high[LEN_HIGH_SYMBOLS];
uint32_t prices[POS_STATES_MAX][LEN_SYMBOLS];
uint32_t table_size;
uint32_t counters[POS_STATES_MAX];
} lzma_length_encoder;
typedef struct {
lzma_lzma_state state;
bool prev_1_is_char;
bool prev_2;
uint32_t pos_prev_2;
uint32_t back_prev_2;
uint32_t price;
uint32_t pos_prev; // pos_next;
uint32_t back_prev;
uint32_t backs[REP_DISTANCES];
} lzma_optimal;
struct lzma_coder_s {
// Next coder in the chain
lzma_next_coder next;
// In window and match finder
lzma_lz_encoder lz;
// Range encoder
lzma_range_encoder rc;
// State
lzma_lzma_state state;
uint8_t previous_byte;
uint32_t reps[REP_DISTANCES];
// Misc
uint32_t match_distances[MATCH_MAX_LEN * 2 + 2 + 1];
uint32_t num_distance_pairs;
uint32_t additional_offset;
uint32_t now_pos; // Lowest 32 bits are enough here.
bool best_compression; ///< True when LZMA_MODE_BEST is used
bool is_initialized;
bool is_flushed;
bool write_eopm;
// Literal encoder
lzma_literal_coder literal_coder;
// Bit encoders
probability is_match[STATES][POS_STATES_MAX];
probability is_rep[STATES];
probability is_rep0[STATES];
probability is_rep1[STATES];
probability is_rep2[STATES];
probability is_rep0_long[STATES][POS_STATES_MAX];
probability pos_encoders[FULL_DISTANCES - END_POS_MODEL_INDEX];
// Bit Tree Encoders
probability pos_slot_encoder[LEN_TO_POS_STATES][1 << POS_SLOT_BITS];
probability pos_align_encoder[1 << ALIGN_BITS];
// Length encoders
lzma_length_encoder match_len_encoder;
lzma_length_encoder rep_len_encoder;
lzma_length_encoder *prev_len_encoder;
// Optimal
lzma_optimal optimum[OPTS];
uint32_t optimum_end_index;
uint32_t optimum_current_index;
uint32_t longest_match_length;
bool longest_match_was_found;
// Prices
uint32_t pos_slot_prices[LEN_TO_POS_STATES][DIST_TABLE_SIZE_MAX];
uint32_t distances_prices[LEN_TO_POS_STATES][FULL_DISTANCES];
uint32_t align_prices[ALIGN_TABLE_SIZE];
uint32_t align_price_count;
uint32_t dist_table_size;
uint32_t match_price_count;
// LZMA specific settings
uint32_t dictionary_size; ///< Size in bytes
uint32_t fast_bytes;
uint32_t pos_state_bits;
uint32_t pos_mask; ///< (1 << pos_state_bits) - 1
};
extern void lzma_length_encoder_update_table(lzma_length_encoder *lencoder,
const uint32_t pos_state);
extern bool lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size);
extern void lzma_get_optimum(lzma_coder *restrict coder,
uint32_t *restrict back_res, uint32_t *restrict len_res);
extern void lzma_get_optimum_fast(lzma_coder *restrict coder,
uint32_t *restrict back_res, uint32_t *restrict len_res);
// NOTE: Don't add 'restrict'.
static inline void
lzma_read_match_distances(lzma_coder *coder,
uint32_t *len_res, uint32_t *num_distance_pairs)
{
*len_res = 0;
coder->lz.get_matches(&coder->lz, coder->match_distances);
*num_distance_pairs = coder->match_distances[0];
if (*num_distance_pairs > 0) {
*len_res = coder->match_distances[*num_distance_pairs - 1];
assert(*len_res <= MATCH_MAX_LEN);
if (*len_res == coder->fast_bytes) {
uint32_t offset = *len_res - 1;
const uint32_t distance = coder->match_distances[
*num_distance_pairs] + 1;
uint32_t limit = MATCH_MAX_LEN - *len_res;
assert(offset + limit < coder->lz.keep_size_after);
assert(coder->lz.read_pos <= coder->lz.write_pos);
// If we are close to end of the stream, we may need
// to limit the length of the match.
if (coder->lz.write_pos - coder->lz.read_pos
< offset + limit)
limit = coder->lz.write_pos
- (coder->lz.read_pos + offset);
offset += coder->lz.read_pos;
uint32_t i = 0;
while (i < limit && coder->lz.buffer[offset + i]
== coder->lz.buffer[
offset + i - distance])
++i;
*len_res += i;
}
}
++coder->additional_offset;
return;
}
#endif
|