]> git.proxmox.com Git - ceph.git/blob - ceph/src/isa-l/igzip/igzip_base.c
49bf0b1574e8a91cb25d65d07351138132a009f0
[ceph.git] / ceph / src / isa-l / igzip / igzip_base.c
1 #include <stdint.h>
2 #include "igzip_lib.h"
3 #include "huffman.h"
4 #include "huff_codes.h"
5 #include "bitbuf2.h"
6
7 extern const struct isal_hufftables hufftables_default;
8
9 void isal_deflate_init_base(struct isal_zstream *stream)
10 {
11 struct isal_zstate *state = &stream->internal_state;
12 int i;
13
14 uint32_t *crc = state->crc;
15
16 stream->total_in = 0;
17 stream->total_out = 0;
18 stream->hufftables = (struct isal_hufftables *)&hufftables_default;
19 stream->flush = 0;
20 state->b_bytes_valid = 0;
21 state->b_bytes_processed = 0;
22 state->has_eob = 0;
23 state->has_eob_hdr = 0;
24 state->left_over = 0;
25 state->last_flush = 0;
26 state->has_gzip_hdr = 0;
27 state->state = ZSTATE_NEW_HDR;
28 state->count = 0;
29
30 state->tmp_out_start = 0;
31 state->tmp_out_end = 0;
32
33 state->file_start = state->buffer;
34
35 init(&state->bitbuf);
36
37 *crc = ~0;
38
39 for (i = 0; i < HASH_SIZE; i++)
40 state->head[i] = (uint16_t) - (IGZIP_D + 1);
41 return;
42 }
43
44 uint32_t get_crc_base(uint32_t * crc)
45 {
46 return ~*crc;
47 }
48
49 static inline void update_state(struct isal_zstream *stream, struct isal_zstate *state,
50 uint8_t * start_in)
51 {
52 uint32_t bytes_written;
53
54 stream->total_in += stream->next_in - start_in;
55
56 bytes_written = buffer_used(&state->bitbuf);
57 stream->total_out += bytes_written;
58 stream->next_out += bytes_written;
59 stream->avail_out -= bytes_written;
60
61 }
62
63 void isal_deflate_body_base(struct isal_zstream *stream)
64 {
65 uint32_t literal, hash;
66 uint8_t *start_in, *next_in, *end_in, *end, *next_hash;
67 uint16_t match_length;
68 uint32_t dist, bytes_to_buffer, offset;
69 uint64_t code, code_len, code2, code_len2;
70 struct isal_zstate *state = &stream->internal_state;
71 uint16_t *last_seen = state->head;
72 uint32_t *crc = state->crc;
73
74 if (stream->avail_in == 0) {
75 if (stream->end_of_stream || stream->flush != NO_FLUSH)
76 state->state = ZSTATE_FLUSH_READ_BUFFER;
77 return;
78 }
79
80 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
81 start_in = stream->next_in;
82
83 while (stream->avail_in != 0) {
84 bytes_to_buffer =
85 IGZIP_D + IGZIP_LA - (state->b_bytes_valid - state->b_bytes_processed);
86
87 if (bytes_to_buffer > IGZIP_D)
88 bytes_to_buffer = IGZIP_D;
89
90 if (stream->avail_in < IGZIP_D)
91 bytes_to_buffer = stream->avail_in;
92
93 if (bytes_to_buffer > BSIZE - state->b_bytes_valid) {
94 if (state->b_bytes_valid - state->b_bytes_processed > IGZIP_LA) {
95 /* There was an out buffer overflow last round,
96 * complete the processing of data */
97 bytes_to_buffer = 0;
98
99 } else {
100 /* Not enough room in the buffer, shift the
101 * buffer down to make space for the new data */
102 offset = state->b_bytes_processed - IGZIP_D; // state->b_bytes_valid - (IGZIP_D + IGZIP_LA);
103 memmove(state->buffer, state->buffer + offset,
104 IGZIP_D + IGZIP_LA);
105
106 state->b_bytes_processed -= offset;
107 state->b_bytes_valid -= offset;
108 state->file_start -= offset;
109
110 stream->avail_in -= bytes_to_buffer;
111 memcpy(state->buffer + state->b_bytes_valid, stream->next_in,
112 bytes_to_buffer);
113 update_crc(crc, stream->next_in, bytes_to_buffer);
114 stream->next_in += bytes_to_buffer;
115 }
116 } else {
117 /* There is enough space in the buffer, copy in the new data */
118 stream->avail_in -= bytes_to_buffer;
119 memcpy(state->buffer + state->b_bytes_valid, stream->next_in,
120 bytes_to_buffer);
121 update_crc(crc, stream->next_in, bytes_to_buffer);
122 stream->next_in += bytes_to_buffer;
123 }
124
125 state->b_bytes_valid += bytes_to_buffer;
126
127 end_in = state->buffer + state->b_bytes_valid - IGZIP_LA;
128
129 next_in = state->b_bytes_processed + state->buffer;
130
131 while (next_in < end_in) {
132
133 if (is_full(&state->bitbuf)) {
134 state->b_bytes_processed = next_in - state->buffer;
135 update_state(stream, state, start_in);
136 return;
137 }
138
139 literal = *(uint32_t *) next_in;
140 hash = compute_hash(literal) & HASH_MASK;
141 dist = (next_in - state->file_start - last_seen[hash]) & 0xFFFF;
142 last_seen[hash] = (uint64_t) (next_in - state->file_start);
143
144 if (dist - 1 < IGZIP_D - 1) { /* The -1 are to handle the case when dist = 0 */
145 assert(next_in - dist >= state->buffer);
146 assert(dist != 0);
147
148 match_length = compare258(next_in - dist, next_in, 258);
149
150 if (match_length >= SHORTEST_MATCH) {
151 next_hash = next_in;
152 #ifdef LIMIT_HASH_UPDATE
153 end = next_hash + 3;
154 #else
155 end = next_hash + match_length;
156 #endif
157 next_hash++;
158
159 for (; next_hash < end; next_hash++) {
160 literal = *(uint32_t *) next_hash;
161 hash = compute_hash(literal) & HASH_MASK;
162 last_seen[hash] =
163 (uint64_t) (next_hash - state->file_start);
164 }
165
166 get_len_code(stream->hufftables, match_length, &code,
167 &code_len);
168 get_dist_code(stream->hufftables, dist, &code2,
169 &code_len2);
170
171 code |= code2 << code_len;
172 code_len += code_len2;
173
174 write_bits(&state->bitbuf, code, code_len);
175
176 next_in += match_length;
177
178 continue;
179 }
180 }
181
182 get_lit_code(stream->hufftables, literal & 0xFF, &code, &code_len);
183 write_bits(&state->bitbuf, code, code_len);
184 next_in++;
185 }
186
187 state->b_bytes_processed = next_in - state->buffer;
188
189 }
190
191 update_state(stream, state, start_in);
192
193 if (stream->avail_in == 0) {
194 if (stream->end_of_stream || stream->flush != NO_FLUSH)
195 state->state = ZSTATE_FLUSH_READ_BUFFER;
196 return;
197 }
198
199 return;
200
201 }
202
203 void isal_deflate_finish_base(struct isal_zstream *stream)
204 {
205 uint32_t literal = 0, hash;
206 uint8_t *next_in, *end_in, *end, *next_hash;
207 uint16_t match_length;
208 uint32_t dist;
209 uint64_t code, code_len, code2, code_len2;
210 struct isal_zstate *state = &stream->internal_state;
211 uint16_t *last_seen = state->head;
212
213 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
214
215 end_in = state->b_bytes_valid + (uint8_t *) state->buffer;
216
217 next_in = state->b_bytes_processed + state->buffer;
218
219 while (next_in < end_in) {
220
221 if (is_full(&state->bitbuf)) {
222 state->b_bytes_processed = next_in - state->buffer;
223 update_state(stream, state, stream->next_in);
224 return;
225 }
226
227 literal = *(uint32_t *) next_in;
228 hash = compute_hash(literal) & HASH_MASK;
229 dist = (next_in - state->file_start - last_seen[hash]) & 0xFFFF;
230 last_seen[hash] = (uint64_t) (next_in - state->file_start);
231
232 if (dist - 1 < IGZIP_D - 1) { /* The -1 are to handle the case when dist = 0 */
233 assert(next_in - dist >= state->buffer);
234 match_length = compare258(next_in - dist, next_in, end_in - next_in);
235
236 if (match_length >= SHORTEST_MATCH) {
237 next_hash = next_in;
238 #ifdef LIMIT_HASH_UPDATE
239 end = next_hash + 3;
240 #else
241 end = next_hash + match_length;
242 #endif
243 next_hash++;
244
245 for (; next_hash < end; next_hash++) {
246 literal = *(uint32_t *) next_hash;
247 hash = compute_hash(literal) & HASH_MASK;
248 last_seen[hash] =
249 (uint64_t) (next_hash - state->file_start);
250 }
251
252 get_len_code(stream->hufftables, match_length, &code,
253 &code_len);
254 get_dist_code(stream->hufftables, dist, &code2, &code_len2);
255
256 code |= code2 << code_len;
257 code_len += code_len2;
258
259 write_bits(&state->bitbuf, code, code_len);
260
261 next_in += match_length;
262
263 continue;
264 }
265 }
266
267 get_lit_code(stream->hufftables, literal & 0xFF, &code, &code_len);
268 write_bits(&state->bitbuf, code, code_len);
269 next_in++;
270
271 }
272
273 state->b_bytes_processed = next_in - state->buffer;
274
275 if (is_full(&state->bitbuf) || state->left_over > 0) {
276 update_state(stream, state, stream->next_in);
277 return;
278 }
279
280 get_lit_code(stream->hufftables, 256, &code, &code_len);
281 write_bits(&state->bitbuf, code, code_len);
282 state->has_eob = 1;
283
284 update_state(stream, state, stream->next_in);
285
286 if (stream->end_of_stream == 1)
287 state->state = ZSTATE_TRL;
288 else
289 state->state = ZSTATE_SYNC_FLUSH;
290
291 return;
292 }