|
10 | 10 | #include "mzip.h" /* for read/write little-endian helpers */ |
11 | 11 |
|
12 | 12 | typedef struct { |
13 | | - int quality; |
14 | | - int window_bits; |
15 | | - uint32_t crc32; |
| 13 | + int quality; |
| 14 | + int window_bits; |
| 15 | + uint32_t crc32; |
16 | 16 | } brotli_encoder_state; |
17 | 17 |
|
18 | 18 | typedef struct { |
19 | | - uint32_t crc32; |
| 19 | + uint32_t crc32; |
20 | 20 | } brotli_decoder_state; |
21 | 21 |
|
22 | 22 | static int clamp_quality(int lvl) { |
23 | | - if (lvl < 0) return 5; |
24 | | - if (lvl > 11) return 11; |
25 | | - return lvl; |
| 23 | + if (lvl < 0) { |
| 24 | + return 5; |
| 25 | + } |
| 26 | + if (lvl > 11) { |
| 27 | + return 11; |
| 28 | + } |
| 29 | + return lvl; |
26 | 30 | } |
27 | 31 |
|
28 | 32 | static uint32_t my_crc32(const uint8_t *data, size_t len, uint32_t crc) { |
29 | | - extern const uint32_t crc32_table[256]; |
30 | | - crc = ~crc; |
31 | | - for (size_t i = 0; i < len; i++) { |
32 | | - crc = crc32_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8); |
33 | | - } |
34 | | - return ~crc; |
| 33 | + extern const uint32_t crc32_table[256]; |
| 34 | + crc = ~crc; |
| 35 | + for (size_t i = 0; i < len; i++) { |
| 36 | + crc = crc32_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8); |
| 37 | + } |
| 38 | + return ~crc; |
35 | 39 | } |
36 | 40 |
|
37 | 41 | static size_t simple_compress(const uint8_t *input, size_t input_len, |
38 | | - uint8_t *output, size_t output_len) { |
39 | | - if (output_len < input_len + 8) return 0; |
40 | | - memcpy(output, "BROT", 4); |
41 | | - output[4] = 1; |
42 | | - /* Store length/checksum in little-endian fixed widths to be portable |
43 | | - * across architectures (avoid writing host-endian `size_t`). */ |
44 | | - mzip_write_le64(output + 5, (uint64_t)input_len); |
45 | | - uint32_t checksum = my_crc32(input, input_len, 0); |
46 | | - mzip_write_le32(output + 5 + 8, checksum); |
47 | | - memcpy(output + 5 + 8 + 4, input, input_len); |
48 | | - return (size_t)(5 + 8 + 4 + input_len); |
| 42 | + uint8_t *output, size_t output_len) { |
| 43 | + if (output_len < input_len + 8) { |
| 44 | + return 0; |
| 45 | + } |
| 46 | + memcpy (output, "BROT", 4); |
| 47 | + output[4] = 1; |
| 48 | + /* Store length/checksum in little-endian fixed widths to be portable |
| 49 | + * across architectures (avoid writing host-endian `size_t`). */ |
| 50 | + mzip_write_le64 (output + 5, (uint64_t)input_len); |
| 51 | + uint32_t checksum = my_crc32 (input, input_len, 0); |
| 52 | + mzip_write_le32 (output + 5 + 8, checksum); |
| 53 | + memcpy (output + 5 + 8 + 4, input, input_len); |
| 54 | + return (size_t) (5 + 8 + 4 + input_len); |
49 | 55 | } |
50 | 56 |
|
51 | 57 | static size_t simple_decompress(const uint8_t *input, size_t input_len, |
52 | | - uint8_t *output, size_t output_len) { |
53 | | - if (input_len < 5 + sizeof(size_t) + sizeof(uint32_t)) return 0; |
54 | | - if (memcmp(input, "BROT", 4) != 0) return 0; |
55 | | - /* Read fixed-width little-endian length and checksum */ |
56 | | - uint64_t stored_len = mzip_read_le64(input + 5); |
57 | | - if (stored_len > output_len) return 0; |
58 | | - if (input_len < 5 + 8 + 4 + stored_len) return 0; |
59 | | - uint32_t stored_crc = mzip_read_le32(input + 5 + 8); |
60 | | - const uint8_t *data = input + 5 + sizeof(size_t) + sizeof(uint32_t); |
61 | | - uint32_t computed_crc = my_crc32(data, stored_len, 0); |
62 | | - if (stored_crc != computed_crc) return 0; |
63 | | - memcpy(output, data, stored_len); |
64 | | - return stored_len; |
| 58 | + uint8_t *output, size_t output_len) { |
| 59 | + if (input_len < 5 + sizeof (size_t) + sizeof (uint32_t)) { |
| 60 | + return 0; |
| 61 | + } |
| 62 | + if (memcmp (input, "BROT", 4) != 0) { |
| 63 | + return 0; |
| 64 | + } |
| 65 | + /* Read fixed-width little-endian length and checksum */ |
| 66 | + uint64_t stored_len = mzip_read_le64 (input + 5); |
| 67 | + if (stored_len > output_len) { |
| 68 | + return 0; |
| 69 | + } |
| 70 | + if (input_len < 5 + 8 + 4 + stored_len) { |
| 71 | + return 0; |
| 72 | + } |
| 73 | + uint32_t stored_crc = mzip_read_le32 (input + 5 + 8); |
| 74 | + const uint8_t *data = input + 5 + sizeof (size_t) + sizeof (uint32_t); |
| 75 | + uint32_t computed_crc = my_crc32 (data, stored_len, 0); |
| 76 | + if (stored_crc != computed_crc) { |
| 77 | + return 0; |
| 78 | + } |
| 79 | + memcpy (output, data, stored_len); |
| 80 | + return stored_len; |
65 | 81 | } |
66 | 82 |
|
67 | 83 | int brotliInit(z_stream *strm, int level) { |
68 | | - if (!strm) return Z_STREAM_ERROR; |
69 | | - brotli_encoder_state *state = (brotli_encoder_state *)malloc(sizeof(brotli_encoder_state)); |
70 | | - if (!state) return Z_MEM_ERROR; |
71 | | - state->quality = clamp_quality(level); |
72 | | - state->window_bits = 22; |
73 | | - state->crc32 = 0; |
74 | | - strm->state = (struct internal_state *)state; |
75 | | - strm->total_in = 0; |
76 | | - strm->total_out = 0; |
77 | | - return Z_OK; |
| 84 | + if (!strm) { |
| 85 | + return Z_STREAM_ERROR; |
| 86 | + } |
| 87 | + brotli_encoder_state *state = (brotli_encoder_state *)malloc (sizeof (brotli_encoder_state)); |
| 88 | + if (!state) { |
| 89 | + return Z_MEM_ERROR; |
| 90 | + } |
| 91 | + state->quality = clamp_quality (level); |
| 92 | + state->window_bits = 22; |
| 93 | + state->crc32 = 0; |
| 94 | + strm->state = (struct internal_state *)state; |
| 95 | + strm->total_in = 0; |
| 96 | + strm->total_out = 0; |
| 97 | + return Z_OK; |
78 | 98 | } |
79 | 99 |
|
80 | 100 | int brotliCompress(z_stream *strm, int flush) { |
81 | | - if (!strm || !strm->state) return Z_STREAM_ERROR; |
82 | | - if (flush == Z_FINISH) { |
83 | | - size_t compressed_size = simple_compress( |
84 | | - strm->next_in, strm->avail_in, |
85 | | - strm->next_out, strm->avail_out); |
86 | | - if (compressed_size == 0) return Z_BUF_ERROR; |
87 | | - strm->next_in += strm->avail_in; |
88 | | - strm->total_in += strm->avail_in; |
89 | | - strm->avail_in = 0; |
90 | | - strm->next_out += compressed_size; |
91 | | - strm->total_out += compressed_size; |
92 | | - strm->avail_out -= compressed_size; |
93 | | - return Z_STREAM_END; |
94 | | - } |
95 | | - size_t copy_size = strm->avail_in < strm->avail_out ? strm->avail_in : strm->avail_out; |
96 | | - if (copy_size > 0) { |
97 | | - memcpy(strm->next_out, strm->next_in, copy_size); |
98 | | - strm->next_in += copy_size; |
99 | | - strm->next_out += copy_size; |
100 | | - strm->avail_in -= copy_size; |
101 | | - strm->avail_out -= copy_size; |
102 | | - strm->total_in += copy_size; |
103 | | - strm->total_out += copy_size; |
104 | | - } |
105 | | - return Z_OK; |
| 101 | + if (!strm || !strm->state) { |
| 102 | + return Z_STREAM_ERROR; |
| 103 | + } |
| 104 | + if (flush == Z_FINISH) { |
| 105 | + size_t compressed_size = simple_compress ( |
| 106 | + strm->next_in, strm->avail_in, |
| 107 | + strm->next_out, strm->avail_out); |
| 108 | + if (compressed_size == 0) { |
| 109 | + return Z_BUF_ERROR; |
| 110 | + } |
| 111 | + strm->next_in += strm->avail_in; |
| 112 | + strm->total_in += strm->avail_in; |
| 113 | + strm->avail_in = 0; |
| 114 | + strm->next_out += compressed_size; |
| 115 | + strm->total_out += compressed_size; |
| 116 | + strm->avail_out -= compressed_size; |
| 117 | + return Z_STREAM_END; |
| 118 | + } |
| 119 | + size_t copy_size = strm->avail_in < strm->avail_out? strm->avail_in: strm->avail_out; |
| 120 | + if (copy_size > 0) { |
| 121 | + memcpy (strm->next_out, strm->next_in, copy_size); |
| 122 | + strm->next_in += copy_size; |
| 123 | + strm->next_out += copy_size; |
| 124 | + strm->avail_in -= copy_size; |
| 125 | + strm->avail_out -= copy_size; |
| 126 | + strm->total_in += copy_size; |
| 127 | + strm->total_out += copy_size; |
| 128 | + } |
| 129 | + return Z_OK; |
106 | 130 | } |
107 | 131 |
|
108 | 132 | int brotliEnd(z_stream *strm) { |
109 | | - if (!strm || !strm->state) return Z_STREAM_ERROR; |
110 | | - free(strm->state); |
111 | | - strm->state = NULL; |
112 | | - return Z_OK; |
| 133 | + if (!strm || !strm->state) { |
| 134 | + return Z_STREAM_ERROR; |
| 135 | + } |
| 136 | + free (strm->state); |
| 137 | + strm->state = NULL; |
| 138 | + return Z_OK; |
113 | 139 | } |
114 | 140 |
|
115 | 141 | int brotliDecompressInit(z_stream *strm) { |
116 | | - if (!strm) return Z_STREAM_ERROR; |
117 | | - brotli_decoder_state *state = (brotli_decoder_state *)malloc(sizeof(brotli_decoder_state)); |
118 | | - if (!state) return Z_MEM_ERROR; |
119 | | - state->crc32 = 0; |
120 | | - strm->state = (struct internal_state *)state; |
121 | | - strm->total_in = 0; |
122 | | - strm->total_out = 0; |
123 | | - return Z_OK; |
| 142 | + if (!strm) { |
| 143 | + return Z_STREAM_ERROR; |
| 144 | + } |
| 145 | + brotli_decoder_state *state = (brotli_decoder_state *)malloc (sizeof (brotli_decoder_state)); |
| 146 | + if (!state) { |
| 147 | + return Z_MEM_ERROR; |
| 148 | + } |
| 149 | + state->crc32 = 0; |
| 150 | + strm->state = (struct internal_state *)state; |
| 151 | + strm->total_in = 0; |
| 152 | + strm->total_out = 0; |
| 153 | + return Z_OK; |
124 | 154 | } |
125 | 155 |
|
126 | 156 | int brotliDecompress(z_stream *strm, int flush) { |
127 | | - (void)flush; |
128 | | - if (!strm || !strm->state) return Z_STREAM_ERROR; |
129 | | - size_t decompressed_size = simple_decompress( |
130 | | - strm->next_in, strm->avail_in, |
131 | | - strm->next_out, strm->avail_out); |
132 | | - if (decompressed_size == 0) { |
133 | | - if (strm->avail_in >= 5 + 8) { |
134 | | - uint64_t stored_len_tmp = mzip_read_le64(strm->next_in + 5); |
135 | | - if (stored_len_tmp == 0) { |
136 | | - strm->next_in += strm->avail_in; |
137 | | - strm->total_in += strm->avail_in; |
138 | | - strm->avail_in = 0; |
139 | | - return Z_STREAM_END; |
140 | | - } |
141 | | - } |
142 | | - return Z_DATA_ERROR; |
143 | | - } |
144 | | - strm->next_in += strm->avail_in; |
145 | | - strm->total_in += strm->avail_in; |
146 | | - strm->avail_in = 0; |
147 | | - strm->next_out += decompressed_size; |
148 | | - strm->total_out += decompressed_size; |
149 | | - strm->avail_out -= decompressed_size; |
150 | | - return Z_STREAM_END; |
| 157 | + (void)flush; |
| 158 | + if (!strm || !strm->state) { |
| 159 | + return Z_STREAM_ERROR; |
| 160 | + } |
| 161 | + size_t decompressed_size = simple_decompress ( |
| 162 | + strm->next_in, strm->avail_in, |
| 163 | + strm->next_out, strm->avail_out); |
| 164 | + if (decompressed_size == 0) { |
| 165 | + if (strm->avail_in >= 5 + 8) { |
| 166 | + uint64_t stored_len_tmp = mzip_read_le64 (strm->next_in + 5); |
| 167 | + if (stored_len_tmp == 0) { |
| 168 | + strm->next_in += strm->avail_in; |
| 169 | + strm->total_in += strm->avail_in; |
| 170 | + strm->avail_in = 0; |
| 171 | + return Z_STREAM_END; |
| 172 | + } |
| 173 | + } |
| 174 | + return Z_DATA_ERROR; |
| 175 | + } |
| 176 | + strm->next_in += strm->avail_in; |
| 177 | + strm->total_in += strm->avail_in; |
| 178 | + strm->avail_in = 0; |
| 179 | + strm->next_out += decompressed_size; |
| 180 | + strm->total_out += decompressed_size; |
| 181 | + strm->avail_out -= decompressed_size; |
| 182 | + return Z_STREAM_END; |
151 | 183 | } |
152 | 184 |
|
153 | 185 | int brotliDecompressEnd(z_stream *strm) { |
154 | | - if (!strm || !strm->state) return Z_STREAM_ERROR; |
155 | | - free(strm->state); |
156 | | - strm->state = NULL; |
157 | | - return Z_OK; |
| 186 | + if (!strm || !strm->state) { |
| 187 | + return Z_STREAM_ERROR; |
| 188 | + } |
| 189 | + free (strm->state); |
| 190 | + strm->state = NULL; |
| 191 | + return Z_OK; |
158 | 192 | } |
159 | 193 |
|
160 | 194 | int brotliCompressInit2(z_stream *strm, int level, int windowBits, int memLevel, int strategy) { |
161 | | - (void)windowBits; (void)memLevel; (void)strategy; |
162 | | - return brotliInit(strm, level); |
| 195 | + (void)windowBits; |
| 196 | + (void)memLevel; |
| 197 | + (void)strategy; |
| 198 | + return brotliInit (strm, level); |
163 | 199 | } |
164 | 200 |
|
165 | 201 | int brotliCompressInit2_(z_stream *strm, int level, int windowBits, int memLevel, int strategy, const char *version, int stream_size) { |
166 | | - (void)version; (void)stream_size; |
167 | | - return brotliCompressInit2(strm, level, windowBits, memLevel, strategy); |
| 202 | + (void)version; |
| 203 | + (void)stream_size; |
| 204 | + return brotliCompressInit2 (strm, level, windowBits, memLevel, strategy); |
168 | 205 | } |
169 | 206 |
|
170 | 207 | int brotliDecompressInit2(z_stream *strm, int windowBits) { |
171 | | - (void)windowBits; |
172 | | - return brotliDecompressInit(strm); |
| 208 | + (void)windowBits; |
| 209 | + return brotliDecompressInit (strm); |
173 | 210 | } |
174 | 211 |
|
175 | 212 | int brotliDecompressInit2_(z_stream *strm, int windowBits, const char *version, int stream_size) { |
176 | | - (void)windowBits; (void)version; (void)stream_size; |
177 | | - return brotliDecompressInit(strm); |
| 213 | + (void)windowBits; |
| 214 | + (void)version; |
| 215 | + (void)stream_size; |
| 216 | + return brotliDecompressInit (strm); |
178 | 217 | } |
179 | 218 |
|
180 | 219 | #endif /* MZIP_ENABLE_BROTLI */ |
|
0 commit comments