]> git.proxmox.com Git - ceph.git/blob - ceph/src/isa-l/igzip/igzip.c
94b0c3a0f22b3e7df5191802ca3e914f69ee0c31
[ceph.git] / ceph / src / isa-l / igzip / igzip.c
1 /**********************************************************************
2 Copyright(c) 2011-2016 Intel Corporation All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #define ASM
31
32 #include <assert.h>
33 #include <string.h>
34 #ifdef _WIN32
35 # include <intrin.h>
36 #endif
37
38 #ifndef IGZIP_USE_GZIP_FORMAT
39 # define DEFLATE 1
40 #endif
41
42 #define MAX_WRITE_BITS_SIZE 8
43 #define FORCE_FLUSH 64
44 #define MIN_OBUF_SIZE 224
45 #define NON_EMPTY_BLOCK_SIZE 6
46 #define MAX_SYNC_FLUSH_SIZE NON_EMPTY_BLOCK_SIZE + MAX_WRITE_BITS_SIZE
47
48 #include "huffman.h"
49 #include "bitbuf2.h"
50 #include "igzip_lib.h"
51 #include "repeated_char_result.h"
52
53 extern const uint8_t gzip_hdr[];
54 extern const uint32_t gzip_hdr_bytes;
55 extern const uint32_t gzip_trl_bytes;
56 extern const struct isal_hufftables hufftables_default;
57
58 extern uint32_t crc32_gzip(uint32_t init_crc, const unsigned char *buf, uint64_t len);
59
60 static int write_stored_block_stateless(struct isal_zstream *stream, uint32_t stored_len,
61 uint32_t crc32);
62 #ifndef DEFLATE
63 static int write_gzip_header_stateless(struct isal_zstream *stream);
64 #endif
65 static int write_deflate_header_stateless(struct isal_zstream *stream);
66 static int write_deflate_header_unaligned_stateless(struct isal_zstream *stream);
67 static int write_trailer_stateless(struct isal_zstream *stream, uint32_t avail_in,
68 uint32_t crc32);
69
70 void isal_deflate_body_stateless(struct isal_zstream *stream);
71
72 unsigned int detect_repeated_char(uint8_t * buf, uint32_t size);
73
74 #define STORED_BLK_HDR_BZ 5
75 #define STORED_BLK_MAX_BZ 65535
76
77 void isal_deflate_body(struct isal_zstream *stream);
78 void isal_deflate_finish(struct isal_zstream *stream);
79 uint32_t crc_512to32_01(uint32_t * crc);
80 uint32_t get_crc(uint32_t * crc);
81
82 /*****************************************************************/
83
84 /* Forward declarations */
85 static inline void reset_match_history(struct isal_zstream *stream);
86 void write_header(struct isal_zstream *stream);
87 void write_deflate_header(struct isal_zstream *stream);
88 void write_trailer(struct isal_zstream *stream);
89
90 struct slver {
91 uint16_t snum;
92 uint8_t ver;
93 uint8_t core;
94 };
95
96 /* Version info */
97 struct slver isal_deflate_init_slver_01030081;
98 struct slver isal_deflate_init_slver = { 0x0081, 0x03, 0x01 };
99
100 struct slver isal_deflate_slver_01030082;
101 struct slver isal_deflate_slver = { 0x0082, 0x03, 0x01 };
102
103 struct slver isal_deflate_stateless_slver_01010083;
104 struct slver isal_deflate_stateless_slver = { 0x0083, 0x01, 0x01 };
105
106 /*****************************************************************/
107
108 uint32_t file_size(struct isal_zstate *state)
109 {
110 return state->b_bytes_valid + (uint32_t) (state->buffer - state->file_start);
111 }
112
113 static
114 void sync_flush(struct isal_zstream *stream)
115 {
116 struct isal_zstate *state = &stream->internal_state;
117 uint64_t bits_to_write = 0xFFFF0000, bits_len;
118 uint64_t code = 0, len = 0, bytes;
119 int flush_size;
120
121 if (stream->avail_out >= 8) {
122 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
123
124 if (!state->has_eob)
125 get_lit_code(stream->hufftables, 256, &code, &len);
126
127 flush_size = (-(state->bitbuf.m_bit_count + len + 3)) % 8;
128
129 bits_to_write <<= flush_size + 3;
130 bits_len = 32 + len + flush_size + 3;
131
132 #ifdef USE_BITBUFB /* Write Bits Always */
133 state->state = ZSTATE_NEW_HDR;
134 #else /* Not Write Bits Always */
135 state->state = ZSTATE_FLUSH_WRITE_BUFFER;
136 #endif
137 state->has_eob = 0;
138
139 if (len > 0)
140 bits_to_write = (bits_to_write << len) | code;
141
142 write_bits(&state->bitbuf, bits_to_write, bits_len);
143
144 bytes = buffer_used(&state->bitbuf);
145 stream->next_out = buffer_ptr(&state->bitbuf);
146 stream->avail_out -= bytes;
147 stream->total_out += bytes;
148
149 if (stream->flush == FULL_FLUSH) {
150 /* Clear match history so there are no cross
151 * block length distance pairs */
152 reset_match_history(stream);
153 }
154 }
155 }
156
157 static void flush_write_buffer(struct isal_zstream *stream)
158 {
159 struct isal_zstate *state = &stream->internal_state;
160 int bytes = 0;
161 if (stream->avail_out >= 8) {
162 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
163 flush(&state->bitbuf);
164 stream->next_out = buffer_ptr(&state->bitbuf);
165 bytes = buffer_used(&state->bitbuf);
166 stream->avail_out -= bytes;
167 stream->total_out += bytes;
168 state->state = ZSTATE_NEW_HDR;
169 }
170 }
171
172 static void isal_deflate_int(struct isal_zstream *stream)
173 {
174 struct isal_zstate *state = &stream->internal_state;
175 if (state->state == ZSTATE_NEW_HDR || state->state == ZSTATE_HDR)
176 write_header(stream);
177
178 if (state->state == ZSTATE_BODY)
179 isal_deflate_body(stream);
180
181 if (state->state == ZSTATE_FLUSH_READ_BUFFER)
182 isal_deflate_finish(stream);
183
184 if (state->state == ZSTATE_SYNC_FLUSH)
185 sync_flush(stream);
186
187 if (state->state == ZSTATE_FLUSH_WRITE_BUFFER)
188 flush_write_buffer(stream);
189
190 if (state->state == ZSTATE_TRL)
191 write_trailer(stream);
192 }
193
194 static uint32_t write_constant_compressed_stateless(struct isal_zstream *stream,
195 uint32_t repeated_char,
196 uint32_t repeated_length,
197 uint32_t end_of_stream)
198 {
199 /* Assumes repeated_length is at least 1.
200 * Assumes the input end_of_stream is either 0 or 1. */
201 struct isal_zstate *state = &stream->internal_state;
202 uint32_t rep_bits = ((repeated_length - 1) / 258) * 2;
203 uint32_t rep_bytes = rep_bits / 8;
204 uint32_t rep_extra = (repeated_length - 1) % 258;
205 uint32_t bytes;
206
207 /* Guarantee there is enough space for the header even in the worst case */
208 if (stream->avail_out < HEADER_LENGTH + MAX_FIXUP_CODE_LENGTH + rep_bytes + 8)
209 return STATELESS_OVERFLOW;
210
211 /* Assumes the repeated char is either 0 or 0xFF. */
212 memcpy(stream->next_out, repeated_char_header[repeated_char & 1], HEADER_LENGTH);
213
214 if (end_of_stream > 0)
215 stream->next_out[0] |= 1;
216
217 memset(stream->next_out + HEADER_LENGTH, 0, rep_bytes);
218 stream->avail_out -= HEADER_LENGTH + rep_bytes;
219 stream->next_out += HEADER_LENGTH + rep_bytes;
220 stream->total_out += HEADER_LENGTH + rep_bytes;
221
222 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
223
224 /* These two lines are basically a modified version of init. */
225 state->bitbuf.m_bits = 0;
226 state->bitbuf.m_bit_count = rep_bits % 8;
227
228 /* Add smaller repeat codes as necessary. Code280 can describe repeat
229 * lengths of 115-130 bits. Code10 can describe repeat lengths of 10
230 * bits. If more than 230 bits, fill code with two code280s. Else if
231 * more than 115 repeates, fill with code10s until one code280 can
232 * finish the rest of the repeats. Else, fill with code10s and
233 * literals */
234 if (rep_extra > 115) {
235 while (rep_extra > 130 && rep_extra < 230) {
236 write_bits(&state->bitbuf, CODE_10, CODE_10_LENGTH);
237 rep_extra -= 10;
238 }
239
240 if (rep_extra >= 230) {
241 write_bits(&state->bitbuf,
242 CODE_280 | ((rep_extra / 2 - 115) << CODE_280_LENGTH),
243 CODE_280_TOTAL_LENGTH);
244 rep_extra -= rep_extra / 2;
245 }
246
247 write_bits(&state->bitbuf,
248 CODE_280 | ((rep_extra - 115) << CODE_280_LENGTH),
249 CODE_280_TOTAL_LENGTH);
250
251 } else {
252 while (rep_extra >= 10) {
253
254 write_bits(&state->bitbuf, CODE_10, CODE_10_LENGTH);
255 rep_extra -= 10;
256 }
257
258 for (; rep_extra > 0; rep_extra--)
259 write_bits(&state->bitbuf, CODE_LIT, CODE_LIT_LENGTH);
260 }
261
262 write_bits(&state->bitbuf, END_OF_BLOCK, END_OF_BLOCK_LEN);
263
264 stream->next_in += repeated_length;
265 stream->avail_in -= repeated_length;
266 stream->total_in += repeated_length;
267
268 bytes = buffer_used(&state->bitbuf);
269 stream->next_out = buffer_ptr(&state->bitbuf);
270 stream->avail_out -= bytes;
271 stream->total_out += bytes;
272
273 return COMP_OK;
274 }
275
276 int detect_repeated_char_length(uint8_t * in, uint32_t length)
277 {
278 /* This currently assumes the first 8 bytes are the same character.
279 * This won't work effectively if the input stream isn't aligned well. */
280 uint8_t *p_8, *end = in + length;
281 uint64_t *p_64 = (uint64_t *) in;
282 uint64_t w = *p_64;
283 uint8_t c = (uint8_t) w;
284
285 for (; (p_64 <= (uint64_t *) (end - 8)) && (w == *p_64); p_64++) ;
286
287 p_8 = (uint8_t *) p_64;
288
289 for (; (p_8 < end) && (c == *p_8); p_8++) ;
290
291 return p_8 - in;
292 }
293
294 static int isal_deflate_int_stateless(struct isal_zstream *stream, uint8_t * next_in,
295 const uint32_t avail_in)
296 {
297 uint32_t crc32 = 0;
298 uint32_t repeated_char_length;
299
300 #ifndef DEFLATE
301 if (write_gzip_header_stateless(stream))
302 return STATELESS_OVERFLOW;
303 #endif
304
305 if (avail_in >= 8
306 && (*(uint64_t *) stream->next_in == 0
307 || *(uint64_t *) stream->next_in == ~(uint64_t) 0))
308 repeated_char_length =
309 detect_repeated_char_length(stream->next_in, stream->avail_in);
310 else
311 repeated_char_length = 0;
312
313 if (stream->avail_in == repeated_char_length) {
314 if (write_constant_compressed_stateless(stream,
315 stream->next_in[0],
316 repeated_char_length, 1) != COMP_OK)
317 return STATELESS_OVERFLOW;
318
319 #ifndef DEFLATE
320 crc32 = crc32_gzip(0x0, next_in, avail_in);
321 #endif
322
323 /* write_trailer_stateless is required because if flushes out the last of the output */
324 if (write_trailer_stateless(stream, avail_in, crc32) != COMP_OK)
325 return STATELESS_OVERFLOW;
326 return COMP_OK;
327
328 } else if (repeated_char_length >= MIN_REPEAT_LEN) {
329 if (write_constant_compressed_stateless
330 (stream, stream->next_in[0], repeated_char_length, 0) != COMP_OK)
331 return STATELESS_OVERFLOW;
332 }
333
334 if (write_deflate_header_unaligned_stateless(stream) != COMP_OK)
335 return STATELESS_OVERFLOW;
336 if (stream->avail_out < 8)
337 return STATELESS_OVERFLOW;
338
339 isal_deflate_body_stateless(stream);
340
341 if (!stream->internal_state.has_eob)
342 return STATELESS_OVERFLOW;
343
344 #ifndef DEFLATE
345 crc32 = crc32_gzip(0x0, next_in, avail_in);
346 #endif
347
348 if (write_trailer_stateless(stream, avail_in, crc32) != COMP_OK)
349 return STATELESS_OVERFLOW;
350
351 return COMP_OK;
352 }
353
354 static int write_stored_block_stateless(struct isal_zstream *stream,
355 uint32_t stored_len, uint32_t crc32)
356 {
357 uint64_t stored_blk_hdr;
358 uint32_t copy_size;
359 uint32_t avail_in;
360
361 #ifndef DEFLATE
362 uint64_t gzip_trl;
363 #endif
364
365 if (stream->avail_out < stored_len)
366 return STATELESS_OVERFLOW;
367
368 stream->avail_out -= stored_len;
369 stream->total_out += stored_len;
370 avail_in = stream->avail_in;
371
372 #ifndef DEFLATE
373 memcpy(stream->next_out, gzip_hdr, gzip_hdr_bytes);
374 stream->next_out += gzip_hdr_bytes;
375 #endif
376
377 do {
378 if (avail_in >= STORED_BLK_MAX_BZ) {
379 stored_blk_hdr = 0xFFFF00;
380 copy_size = STORED_BLK_MAX_BZ;
381 } else {
382 stored_blk_hdr = ~avail_in;
383 stored_blk_hdr <<= 24;
384 stored_blk_hdr |= (avail_in & 0xFFFF) << 8;
385 copy_size = avail_in;
386 }
387
388 avail_in -= copy_size;
389
390 /* Handle BFINAL bit */
391 if (avail_in == 0)
392 stored_blk_hdr |= 0x1;
393
394 memcpy(stream->next_out, &stored_blk_hdr, STORED_BLK_HDR_BZ);
395 stream->next_out += STORED_BLK_HDR_BZ;
396
397 memcpy(stream->next_out, stream->next_in, copy_size);
398 stream->next_out += copy_size;
399 stream->next_in += copy_size;
400 stream->total_in += copy_size;
401 } while (avail_in != 0);
402
403 #ifndef DEFLATE
404 gzip_trl = stream->avail_in;
405 gzip_trl <<= 32;
406 gzip_trl |= crc32 & 0xFFFFFFFF;
407 memcpy(stream->next_out, &gzip_trl, gzip_trl_bytes);
408 stream->next_out += gzip_trl_bytes;
409 #endif
410
411 stream->avail_in = 0;
412 return COMP_OK;
413 }
414
415 static inline void reset_match_history(struct isal_zstream *stream)
416 {
417 struct isal_zstate *state = &stream->internal_state;
418 uint16_t *head = stream->internal_state.head;
419 int i = 0;
420
421 for (i = 0; i < sizeof(state->head) / 2; i++)
422 head[i] =
423 (uint16_t) (state->b_bytes_processed + state->buffer - state->file_start -
424 (IGZIP_D + 1));
425 }
426
427 void isal_deflate_init_01(struct isal_zstream *stream)
428 {
429 struct isal_zstate *state = &stream->internal_state;
430
431 stream->total_in = 0;
432 stream->total_out = 0;
433 stream->hufftables = (struct isal_hufftables *)&hufftables_default;
434 stream->flush = 0;
435
436 state->b_bytes_valid = 0;
437 state->b_bytes_processed = 0;
438 state->has_eob = 0;
439 state->has_eob_hdr = 0;
440 state->left_over = 0;
441 state->last_flush = 0;
442 state->has_gzip_hdr = 0;
443 state->state = ZSTATE_NEW_HDR;
444 state->count = 0;
445
446 state->tmp_out_start = 0;
447 state->tmp_out_end = 0;
448
449 state->file_start = state->buffer;
450
451 init(&state->bitbuf);
452
453 memset(state->crc, 0, sizeof(state->crc));
454 *state->crc = 0x9db42487;
455
456 reset_match_history(stream);
457
458 return;
459 }
460
461 int isal_deflate_stateless(struct isal_zstream *stream)
462 {
463 uint8_t *next_in = stream->next_in;
464 const uint32_t avail_in = stream->avail_in;
465
466 uint8_t *next_out = stream->next_out;
467 const uint32_t avail_out = stream->avail_out;
468
469 uint32_t crc32 = 0;
470 uint32_t stored_len;
471 uint32_t dyn_min_len;
472 uint32_t min_len;
473 uint32_t select_stored_blk = 0;
474
475 if (avail_in == 0)
476 stored_len = STORED_BLK_HDR_BZ;
477 else
478 stored_len =
479 STORED_BLK_HDR_BZ * ((avail_in + STORED_BLK_MAX_BZ - 1) /
480 STORED_BLK_MAX_BZ) + avail_in;
481
482 /*
483 at least 1 byte compressed data in the case of empty dynamic block which only
484 contains the EOB
485 */
486
487 dyn_min_len = stream->hufftables->deflate_hdr_count + 1;
488 #ifndef DEFLATE
489 dyn_min_len += gzip_hdr_bytes + gzip_trl_bytes + 1;
490 stored_len += gzip_hdr_bytes + gzip_trl_bytes;
491 #endif
492
493 min_len = dyn_min_len;
494
495 if (stored_len < dyn_min_len) {
496 min_len = stored_len;
497 select_stored_blk = 1;
498 }
499
500 /*
501 the output buffer should be no less than 8 bytes
502 while empty stored deflate block is 5 bytes only
503 */
504 if (avail_out < min_len || stream->avail_out < 8)
505 return STATELESS_OVERFLOW;
506
507 if (!select_stored_blk) {
508 if (isal_deflate_int_stateless(stream, next_in, avail_in) == COMP_OK)
509 return COMP_OK;
510 }
511 if (avail_out < stored_len)
512 return STATELESS_OVERFLOW;
513
514 isal_deflate_init(stream);
515
516 stream->next_in = next_in;
517 stream->avail_in = avail_in;
518 stream->total_in = 0;
519
520 stream->next_out = next_out;
521 stream->avail_out = avail_out;
522 stream->total_out = 0;
523
524 #ifndef DEFLATE
525 crc32 = crc32_gzip(0x0, next_in, avail_in);
526 #endif
527 return write_stored_block_stateless(stream, stored_len, crc32);
528 }
529
530 int isal_deflate(struct isal_zstream *stream)
531 {
532 struct isal_zstate *state = &stream->internal_state;
533 uint32_t size;
534 int ret = COMP_OK;
535
536 if (stream->flush < 3) {
537
538 state->last_flush = stream->flush;
539
540 if (state->state >= TMP_OFFSET_SIZE) {
541 size = state->tmp_out_end - state->tmp_out_start;
542 if (size > stream->avail_out)
543 size = stream->avail_out;
544 memcpy(stream->next_out, state->tmp_out_buff + state->tmp_out_start,
545 size);
546 stream->next_out += size;
547 stream->avail_out -= size;
548 stream->total_out += size;
549 state->tmp_out_start += size;
550
551 if (state->tmp_out_start == state->tmp_out_end)
552 state->state -= TMP_OFFSET_SIZE;
553
554 if (stream->avail_out == 0 || state->state == ZSTATE_END)
555 return ret;
556 }
557 assert(state->tmp_out_start == state->tmp_out_end);
558
559 isal_deflate_int(stream);
560
561 if (stream->avail_out == 0)
562 return ret;
563
564 else if (stream->avail_out < 8) {
565 uint8_t *next_out;
566 uint32_t avail_out;
567 uint32_t total_out;
568
569 next_out = stream->next_out;
570 avail_out = stream->avail_out;
571 total_out = stream->total_out;
572
573 stream->next_out = state->tmp_out_buff;
574 stream->avail_out = sizeof(state->tmp_out_buff);
575 stream->total_out = 0;
576
577 isal_deflate_int(stream);
578
579 state->tmp_out_start = 0;
580 state->tmp_out_end = stream->total_out;
581
582 stream->next_out = next_out;
583 stream->avail_out = avail_out;
584 stream->total_out = total_out;
585 if (state->tmp_out_end) {
586 size = state->tmp_out_end;
587 if (size > stream->avail_out)
588 size = stream->avail_out;
589 memcpy(stream->next_out, state->tmp_out_buff, size);
590 stream->next_out += size;
591 stream->avail_out -= size;
592 stream->total_out += size;
593 state->tmp_out_start += size;
594 if (state->tmp_out_start != state->tmp_out_end)
595 state->state += TMP_OFFSET_SIZE;
596
597 }
598 }
599 } else
600 ret = INVALID_FLUSH;
601
602 return ret;
603 }
604
605 #ifndef DEFLATE
606 static int write_gzip_header_stateless(struct isal_zstream *stream)
607 {
608 if (gzip_hdr_bytes >= stream->avail_out)
609 return STATELESS_OVERFLOW;
610
611 stream->avail_out -= gzip_hdr_bytes;
612 stream->total_out += gzip_hdr_bytes;
613
614 memcpy(stream->next_out, gzip_hdr, gzip_hdr_bytes);
615
616 stream->next_out += gzip_hdr_bytes;
617
618 return COMP_OK;
619 }
620
621 static void write_gzip_header(struct isal_zstream *stream)
622 {
623 struct isal_zstate *state = &stream->internal_state;
624 int bytes_to_write = gzip_hdr_bytes;
625
626 bytes_to_write -= state->count;
627
628 if (bytes_to_write > stream->avail_out)
629 bytes_to_write = stream->avail_out;
630
631 memcpy(stream->next_out, gzip_hdr + state->count, bytes_to_write);
632 state->count += bytes_to_write;
633
634 if (state->count == gzip_hdr_bytes) {
635 state->count = 0;
636 state->has_gzip_hdr = 1;
637 }
638
639 stream->avail_out -= bytes_to_write;
640 stream->total_out += bytes_to_write;
641 stream->next_out += bytes_to_write;
642
643 }
644 #endif
645
646 static int write_deflate_header_stateless(struct isal_zstream *stream)
647 {
648 struct isal_zstate *state = &stream->internal_state;
649 struct isal_hufftables *hufftables = stream->hufftables;
650 uint32_t count;
651
652 if (hufftables->deflate_hdr_count + 8 >= stream->avail_out)
653 return STATELESS_OVERFLOW;
654
655 memcpy(stream->next_out, hufftables->deflate_hdr, hufftables->deflate_hdr_count);
656
657 stream->avail_out -= hufftables->deflate_hdr_count;
658 stream->total_out += hufftables->deflate_hdr_count;
659 stream->next_out += hufftables->deflate_hdr_count;
660
661 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
662
663 write_bits(&state->bitbuf, hufftables->deflate_hdr[hufftables->deflate_hdr_count],
664 hufftables->deflate_hdr_extra_bits);
665
666 count = buffer_used(&state->bitbuf);
667 stream->next_out = buffer_ptr(&state->bitbuf);
668 stream->avail_out -= count;
669 stream->total_out += count;
670
671 return COMP_OK;
672 }
673
674 static int write_deflate_header_unaligned_stateless(struct isal_zstream *stream)
675 {
676 struct isal_zstate *state = &stream->internal_state;
677 struct isal_hufftables *hufftables = stream->hufftables;
678 unsigned int count;
679 uint64_t bit_count;
680 uint64_t *header_next;
681 uint64_t *header_end;
682 uint64_t header_bits;
683
684 if (state->bitbuf.m_bit_count == 0)
685 return write_deflate_header_stateless(stream);
686
687 if (hufftables->deflate_hdr_count + 16 >= stream->avail_out)
688 return STATELESS_OVERFLOW;
689
690 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
691
692 header_next = (uint64_t *) hufftables->deflate_hdr;
693 header_end = header_next + hufftables->deflate_hdr_count / 8;
694
695 /* Write out Complete Header bits */
696 for (; header_next < header_end; header_next++) {
697 header_bits = *header_next;
698 write_bits(&state->bitbuf, header_bits, 32);
699 header_bits >>= 32;
700 write_bits(&state->bitbuf, header_bits, 32);
701 }
702
703 header_bits = *header_next;
704 bit_count =
705 (hufftables->deflate_hdr_count & 0x7) * 8 + hufftables->deflate_hdr_extra_bits;
706
707 if (bit_count > MAX_BITBUF_BIT_WRITE) {
708 write_bits(&state->bitbuf, header_bits, MAX_BITBUF_BIT_WRITE);
709 header_bits >>= MAX_BITBUF_BIT_WRITE;
710 bit_count -= MAX_BITBUF_BIT_WRITE;
711
712 }
713
714 write_bits(&state->bitbuf, header_bits, bit_count);
715
716 /* check_space flushes extra bytes in bitbuf. Required because
717 * write_bits_always fails when the next commit makes the buffer
718 * length exceed 64 bits */
719 check_space(&state->bitbuf, FORCE_FLUSH);
720
721 count = buffer_used(&state->bitbuf);
722 stream->next_out = buffer_ptr(&state->bitbuf);
723 stream->avail_out -= count;
724 stream->total_out += count;
725
726 return COMP_OK;
727 }
728
729 void write_header(struct isal_zstream *stream)
730 {
731 struct isal_zstate *state = &stream->internal_state;
732 struct isal_hufftables *hufftables = stream->hufftables;
733 uint32_t count;
734
735 state->state = ZSTATE_HDR;
736
737 if (state->bitbuf.m_bit_count != 0) {
738 if (stream->avail_out < 8)
739 return;
740 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
741 flush(&state->bitbuf);
742 count = buffer_used(&state->bitbuf);
743 stream->next_out = buffer_ptr(&state->bitbuf);
744 stream->avail_out -= count;
745 stream->total_out += count;
746 }
747 #ifndef DEFLATE
748 if (!state->has_gzip_hdr)
749 write_gzip_header(stream);
750 #endif
751
752 count = hufftables->deflate_hdr_count - state->count;
753
754 if (count != 0) {
755 if (count > stream->avail_out)
756 count = stream->avail_out;
757
758 memcpy(stream->next_out, hufftables->deflate_hdr + state->count, count);
759
760 if (state->count == 0 && count > 0) {
761 if (!stream->end_of_stream)
762 *stream->next_out &= 0xfe;
763 else
764 state->has_eob_hdr = 1;
765 }
766
767 stream->next_out += count;
768 stream->avail_out -= count;
769 stream->total_out += count;
770 state->count += count;
771
772 count = hufftables->deflate_hdr_count - state->count;
773 }
774
775 if ((count == 0) && (stream->avail_out >= 8)) {
776
777 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
778
779 write_bits(&state->bitbuf,
780 hufftables->deflate_hdr[hufftables->deflate_hdr_count],
781 hufftables->deflate_hdr_extra_bits);
782
783 state->state = ZSTATE_BODY;
784 state->count = 0;
785
786 count = buffer_used(&state->bitbuf);
787 stream->next_out = buffer_ptr(&state->bitbuf);
788 stream->avail_out -= count;
789 stream->total_out += count;
790 }
791
792 }
793
794 uint32_t get_crc_01(uint32_t * crc)
795 {
796 return crc_512to32_01(crc);
797 }
798
799 void write_trailer(struct isal_zstream *stream)
800 {
801 struct isal_zstate *state = &stream->internal_state;
802 unsigned int bytes;
803
804 if (stream->avail_out >= 8) {
805 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
806
807 /* the flush() will pad to the next byte and write up to 8 bytes
808 * to the output stream/buffer.
809 */
810 if (!state->has_eob_hdr) {
811 /* If the final header has not been written, write a
812 * final block. This block is a static huffman block
813 * which only contains the end of block symbol. The code
814 * that happens to do this is the fist 10 bits of
815 * 0x003 */
816 state->has_eob_hdr = 1;
817 write_bits(&state->bitbuf, 0x003, 10);
818 if (is_full(&state->bitbuf)) {
819 stream->next_out = buffer_ptr(&state->bitbuf);
820 bytes = buffer_used(&state->bitbuf);
821 stream->avail_out -= bytes;
822 stream->total_out += bytes;
823 return;
824 }
825 }
826
827 flush(&state->bitbuf);
828 stream->next_out = buffer_ptr(&state->bitbuf);
829 bytes = buffer_used(&state->bitbuf);
830
831 #ifndef DEFLATE
832 uint32_t *crc = state->crc;
833
834 if (!is_full(&state->bitbuf)) {
835 *(uint64_t *) stream->next_out =
836 ((uint64_t) file_size(state) << 32) | get_crc(crc);
837 stream->next_out += 8;
838 bytes += 8;
839 state->state = ZSTATE_END;
840 }
841 #else
842 state->state = ZSTATE_END;
843 #endif
844
845 stream->avail_out -= bytes;
846 stream->total_out += bytes;
847 }
848 }
849
850 static int write_trailer_stateless(struct isal_zstream *stream, uint32_t avail_in,
851 uint32_t crc32)
852 {
853 int ret = COMP_OK;
854 struct isal_zstate *state = &stream->internal_state;
855 unsigned int bytes;
856
857 if (stream->avail_out < 8) {
858 ret = STATELESS_OVERFLOW;
859 } else {
860 set_buf(&state->bitbuf, stream->next_out, stream->avail_out);
861
862 /* the flush() will pad to the next byte and write up to 8 bytes
863 * to the output stream/buffer.
864 */
865 flush(&state->bitbuf);
866 stream->next_out = buffer_ptr(&state->bitbuf);
867 bytes = buffer_used(&state->bitbuf);
868 #ifndef DEFLATE
869 if (is_full(&state->bitbuf)) {
870 ret = STATELESS_OVERFLOW;
871 } else {
872 *(uint64_t *) stream->next_out = ((uint64_t) avail_in << 32) | crc32;
873 stream->next_out += 8;
874 bytes += 8;
875 }
876 #endif
877 stream->avail_out -= bytes;
878 stream->total_out += bytes;
879 }
880
881 return ret;
882 }