]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
224ce89b WB |
9 | static inline void update_state(struct isal_zstream *stream, uint8_t * start_in, |
10 | uint8_t * next_in, uint8_t * end_in) | |
7c673cae FG |
11 | { |
12 | struct isal_zstate *state = &stream->internal_state; | |
7c673cae FG |
13 | uint32_t bytes_written; |
14 | ||
224ce89b WB |
15 | stream->next_in = next_in; |
16 | stream->total_in += next_in - start_in; | |
17 | stream->avail_in = end_in - next_in; | |
7c673cae FG |
18 | |
19 | bytes_written = buffer_used(&state->bitbuf); | |
20 | stream->total_out += bytes_written; | |
21 | stream->next_out += bytes_written; | |
22 | stream->avail_out -= bytes_written; | |
23 | ||
24 | } | |
25 | ||
26 | void isal_deflate_body_base(struct isal_zstream *stream) | |
27 | { | |
28 | uint32_t literal, hash; | |
29 | uint8_t *start_in, *next_in, *end_in, *end, *next_hash; | |
30 | uint16_t match_length; | |
224ce89b | 31 | uint32_t dist; |
7c673cae FG |
32 | uint64_t code, code_len, code2, code_len2; |
33 | struct isal_zstate *state = &stream->internal_state; | |
34 | uint16_t *last_seen = state->head; | |
7c673cae FG |
35 | |
36 | if (stream->avail_in == 0) { | |
37 | if (stream->end_of_stream || stream->flush != NO_FLUSH) | |
38 | state->state = ZSTATE_FLUSH_READ_BUFFER; | |
39 | return; | |
40 | } | |
41 | ||
42 | set_buf(&state->bitbuf, stream->next_out, stream->avail_out); | |
224ce89b | 43 | |
7c673cae | 44 | start_in = stream->next_in; |
224ce89b WB |
45 | end_in = start_in + stream->avail_in; |
46 | next_in = start_in; | |
47 | ||
48 | while (next_in + ISAL_LOOK_AHEAD < end_in) { | |
49 | ||
50 | if (is_full(&state->bitbuf)) { | |
51 | update_state(stream, start_in, next_in, end_in); | |
52 | return; | |
53 | } | |
54 | ||
55 | literal = *(uint32_t *) next_in; | |
56 | hash = compute_hash(literal) & HASH_MASK; | |
57 | dist = (next_in - state->file_start - last_seen[hash]) & 0xFFFF; | |
58 | last_seen[hash] = (uint64_t) (next_in - state->file_start); | |
59 | ||
60 | /* The -1 are to handle the case when dist = 0 */ | |
61 | if (dist - 1 < IGZIP_HIST_SIZE - 1) { | |
62 | assert(dist != 0); | |
63 | ||
64 | match_length = compare258(next_in - dist, next_in, 258); | |
65 | ||
66 | if (match_length >= SHORTEST_MATCH) { | |
67 | next_hash = next_in; | |
68 | #ifdef ISAL_LIMIT_HASH_UPDATE | |
69 | end = next_hash + 3; | |
70 | #else | |
71 | end = next_hash + match_length; | |
72 | #endif | |
73 | next_hash++; | |
7c673cae | 74 | |
224ce89b WB |
75 | for (; next_hash < end; next_hash++) { |
76 | literal = *(uint32_t *) next_hash; | |
77 | hash = compute_hash(literal) & HASH_MASK; | |
78 | last_seen[hash] = | |
79 | (uint64_t) (next_hash - state->file_start); | |
80 | } | |
81 | ||
82 | get_len_code(stream->hufftables, match_length, &code, | |
83 | &code_len); | |
84 | get_dist_code(stream->hufftables, dist, &code2, &code_len2); | |
85 | ||
86 | code |= code2 << code_len; | |
87 | code_len += code_len2; | |
88 | ||
89 | write_bits(&state->bitbuf, code, code_len); | |
90 | ||
91 | next_in += match_length; | |
92 | ||
93 | continue; | |
7c673cae | 94 | } |
7c673cae FG |
95 | } |
96 | ||
224ce89b WB |
97 | get_lit_code(stream->hufftables, literal & 0xFF, &code, &code_len); |
98 | write_bits(&state->bitbuf, code, code_len); | |
99 | next_in++; | |
100 | } | |
7c673cae | 101 | |
224ce89b | 102 | update_state(stream, start_in, next_in, end_in); |
7c673cae | 103 | |
224ce89b WB |
104 | assert(stream->avail_in <= ISAL_LOOK_AHEAD); |
105 | if (stream->end_of_stream || stream->flush != NO_FLUSH) | |
106 | state->state = ZSTATE_FLUSH_READ_BUFFER; | |
7c673cae | 107 | |
224ce89b WB |
108 | return; |
109 | ||
110 | } | |
7c673cae | 111 | |
224ce89b WB |
112 | void isal_deflate_finish_base(struct isal_zstream *stream) |
113 | { | |
114 | uint32_t literal = 0, hash; | |
115 | uint8_t *start_in, *next_in, *end_in, *end, *next_hash; | |
116 | uint16_t match_length; | |
117 | uint32_t dist; | |
118 | uint64_t code, code_len, code2, code_len2; | |
119 | struct isal_zstate *state = &stream->internal_state; | |
120 | uint16_t *last_seen = state->head; | |
121 | ||
122 | set_buf(&state->bitbuf, stream->next_out, stream->avail_out); | |
123 | ||
124 | start_in = stream->next_in; | |
125 | end_in = start_in + stream->avail_in; | |
126 | next_in = start_in; | |
127 | ||
128 | if (stream->avail_in != 0) { | |
129 | while (next_in + 3 < end_in) { | |
7c673cae | 130 | if (is_full(&state->bitbuf)) { |
224ce89b | 131 | update_state(stream, start_in, next_in, end_in); |
7c673cae FG |
132 | return; |
133 | } | |
134 | ||
135 | literal = *(uint32_t *) next_in; | |
136 | hash = compute_hash(literal) & HASH_MASK; | |
137 | dist = (next_in - state->file_start - last_seen[hash]) & 0xFFFF; | |
138 | last_seen[hash] = (uint64_t) (next_in - state->file_start); | |
139 | ||
224ce89b WB |
140 | if (dist - 1 < IGZIP_HIST_SIZE - 1) { /* The -1 are to handle the case when dist = 0 */ |
141 | match_length = | |
142 | compare258(next_in - dist, next_in, end_in - next_in); | |
7c673cae FG |
143 | |
144 | if (match_length >= SHORTEST_MATCH) { | |
145 | next_hash = next_in; | |
224ce89b | 146 | #ifdef ISAL_LIMIT_HASH_UPDATE |
7c673cae FG |
147 | end = next_hash + 3; |
148 | #else | |
149 | end = next_hash + match_length; | |
150 | #endif | |
151 | next_hash++; | |
152 | ||
224ce89b | 153 | for (; next_hash < end - 3; next_hash++) { |
7c673cae FG |
154 | literal = *(uint32_t *) next_hash; |
155 | hash = compute_hash(literal) & HASH_MASK; | |
156 | last_seen[hash] = | |
157 | (uint64_t) (next_hash - state->file_start); | |
158 | } | |
159 | ||
160 | get_len_code(stream->hufftables, match_length, &code, | |
161 | &code_len); | |
162 | get_dist_code(stream->hufftables, dist, &code2, | |
163 | &code_len2); | |
164 | ||
165 | code |= code2 << code_len; | |
166 | code_len += code_len2; | |
167 | ||
168 | write_bits(&state->bitbuf, code, code_len); | |
169 | ||
170 | next_in += match_length; | |
171 | ||
172 | continue; | |
173 | } | |
174 | } | |
175 | ||
176 | get_lit_code(stream->hufftables, literal & 0xFF, &code, &code_len); | |
177 | write_bits(&state->bitbuf, code, code_len); | |
178 | next_in++; | |
7c673cae | 179 | |
7c673cae FG |
180 | } |
181 | ||
224ce89b WB |
182 | while (next_in < end_in) { |
183 | if (is_full(&state->bitbuf)) { | |
184 | update_state(stream, start_in, next_in, end_in); | |
185 | return; | |
7c673cae | 186 | } |
7c673cae | 187 | |
224ce89b WB |
188 | literal = *next_in; |
189 | get_lit_code(stream->hufftables, literal & 0xFF, &code, &code_len); | |
190 | write_bits(&state->bitbuf, code, code_len); | |
191 | next_in++; | |
7c673cae | 192 | |
224ce89b | 193 | } |
7c673cae FG |
194 | } |
195 | ||
224ce89b WB |
196 | if (!is_full(&state->bitbuf)) { |
197 | get_lit_code(stream->hufftables, 256, &code, &code_len); | |
198 | write_bits(&state->bitbuf, code, code_len); | |
199 | state->has_eob = 1; | |
7c673cae | 200 | |
224ce89b WB |
201 | if (stream->end_of_stream == 1) |
202 | state->state = ZSTATE_TRL; | |
203 | else | |
204 | state->state = ZSTATE_SYNC_FLUSH; | |
7c673cae FG |
205 | } |
206 | ||
224ce89b | 207 | update_state(stream, start_in, next_in, end_in); |
7c673cae FG |
208 | |
209 | return; | |
210 | } |