diff options
Diffstat (limited to 'raylib/src/external/sdefl.h')
| -rw-r--r-- | raylib/src/external/sdefl.h | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/raylib/src/external/sdefl.h b/raylib/src/external/sdefl.h new file mode 100644 index 0000000..36015b9 --- /dev/null +++ b/raylib/src/external/sdefl.h | |||
| @@ -0,0 +1,790 @@ | |||
| 1 | /*# Small Deflate | ||
| 2 | `sdefl` is a small bare bone lossless compression library in ANSI C (ISO C90) | ||
| 3 | which implements the Deflate (RFC 1951) compressed data format specification standard. | ||
| 4 | It is mainly tuned to get as much speed and compression ratio from as little code | ||
| 5 | as needed to keep the implementation as concise as possible. | ||
| 6 | |||
| 7 | ## Features | ||
| 8 | - Portable single header and source file duo written in ANSI C (ISO C90) | ||
| 9 | - Dual license with either MIT or public domain | ||
| 10 | - Small implementation | ||
| 11 | - Deflate: 525 LoC | ||
| 12 | - Inflate: 320 LoC | ||
| 13 | - Webassembly: | ||
| 14 | - Deflate ~3.7 KB (~2.2KB compressed) | ||
| 15 | - Inflate ~3.6 KB (~2.2KB compressed) | ||
| 16 | |||
| 17 | ## Usage: | ||
| 18 | This file behaves differently depending on what symbols you define | ||
| 19 | before including it. | ||
| 20 | |||
| 21 | Header-File mode: | ||
| 22 | If you do not define `SDEFL_IMPLEMENTATION` before including this file, it | ||
| 23 | will operate in header only mode. In this mode it declares all used structs | ||
| 24 | and the API of the library without including the implementation of the library. | ||
| 25 | |||
| 26 | Implementation mode: | ||
| 27 | If you define `SDEFL_IMPLEMENTATION` before including this file, it will | ||
| 28 | compile the implementation . Make sure that you only include | ||
| 29 | this file implementation in *one* C or C++ file to prevent collisions. | ||
| 30 | |||
| 31 | ### Benchmark | ||
| 32 | |||
| 33 | | Compressor name | Compression| Decompress.| Compr. size | Ratio | | ||
| 34 | | ------------------------| -----------| -----------| ----------- | ----- | | ||
| 35 | | miniz 1.0 -1 | 122 MB/s | 208 MB/s | 48510028 | 48.51 | | ||
| 36 | | miniz 1.0 -6 | 27 MB/s | 260 MB/s | 36513697 | 36.51 | | ||
| 37 | | miniz 1.0 -9 | 23 MB/s | 261 MB/s | 36460101 | 36.46 | | ||
| 38 | | zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 | | ||
| 39 | | zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 | | ||
| 40 | | zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 | | ||
| 41 | | sdefl 1.0 -0 | 127 MB/s | 355 MB/s | 40004116 | 39.88 | | ||
| 42 | | sdefl 1.0 -1 | 111 MB/s | 413 MB/s | 38940674 | 38.82 | | ||
| 43 | | sdefl 1.0 -5 | 45 MB/s | 436 MB/s | 36577183 | 36.46 | | ||
| 44 | | sdefl 1.0 -7 | 38 MB/s | 432 MB/s | 36523781 | 36.41 | | ||
| 45 | | libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 | | ||
| 46 | | libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 | | ||
| 47 | | libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 | | ||
| 48 | | libdeflate 1.3 -12 | 8.13 MB/s | 670 MB/s | 35100568 | 35.10 | | ||
| 49 | |||
| 50 | ### Compression | ||
| 51 | Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia): | ||
| 52 | |||
| 53 | | File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` | | ||
| 54 | | --------| -----------| -------------| ---------- | ------------| | ||
| 55 | | dickens | 10.192.446 | 4,260,187 | 3,845,261 | 3,833,657 | | ||
| 56 | | mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 | | ||
| 57 | | mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 | | ||
| 58 | | nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 | | ||
| 59 | | ooffice | 6.152.192 | 3,320,063 | 3,186,373 | 3,183,815 | | ||
| 60 | | osdb | 10.085.684 | 3,919,646 | 3,649,510 | 3,649,477 | | ||
| 61 | | reymont | 6.627.202 | 2,263,378 | 1,857,588 | 1,827,237 | | ||
| 62 | | samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 | | ||
| 63 | | sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 | | ||
| 64 | | webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 | | ||
| 65 | | xml | 5.345.280 | 886,620 | 674,009 | 662,141 | | ||
| 66 | | x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 | | ||
| 67 | |||
| 68 | ## License | ||
| 69 | ``` | ||
| 70 | ------------------------------------------------------------------------------ | ||
| 71 | This software is available under 2 licenses -- choose whichever you prefer. | ||
| 72 | ------------------------------------------------------------------------------ | ||
| 73 | ALTERNATIVE A - MIT License | ||
| 74 | Copyright (c) 2020-2023 Micha Mettke | ||
| 75 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 76 | this software and associated documentation files (the "Software"), to deal in | ||
| 77 | the Software without restriction, including without limitation the rights to | ||
| 78 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
| 79 | of the Software, and to permit persons to whom the Software is furnished to do | ||
| 80 | so, subject to the following conditions: | ||
| 81 | The above copyright notice and this permission notice shall be included in all | ||
| 82 | copies or substantial portions of the Software. | ||
| 83 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 84 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 85 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 86 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 87 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 88 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 89 | SOFTWARE. | ||
| 90 | ------------------------------------------------------------------------------ | ||
| 91 | ALTERNATIVE B - Public Domain (www.unlicense.org) | ||
| 92 | This is free and unencumbered software released into the public domain. | ||
| 93 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this | ||
| 94 | software, either in source code form or as a compiled binary, for any purpose, | ||
| 95 | commercial or non-commercial, and by any means. | ||
| 96 | In jurisdictions that recognize copyright laws, the author or authors of this | ||
| 97 | software dedicate any and all copyright interest in the software to the public | ||
| 98 | domain. We make this dedication for the benefit of the public at large and to | ||
| 99 | the detriment of our heirs and successors. We intend this dedication to be an | ||
| 100 | overt act of relinquishment in perpetuity of all present and future rights to | ||
| 101 | this software under copyright law. | ||
| 102 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 103 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 104 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 105 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 106 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 107 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 108 | ------------------------------------------------------------------------------ | ||
| 109 | ``` | ||
| 110 | */ | ||
| 111 | #ifndef SDEFL_H_INCLUDED | ||
| 112 | #define SDEFL_H_INCLUDED | ||
| 113 | |||
| 114 | #ifdef __cplusplus | ||
| 115 | extern "C" { | ||
| 116 | #endif | ||
| 117 | |||
| 118 | #define SDEFL_MAX_OFF (1 << 15) | ||
| 119 | #define SDEFL_WIN_SIZ SDEFL_MAX_OFF | ||
| 120 | #define SDEFL_WIN_MSK (SDEFL_WIN_SIZ-1) | ||
| 121 | |||
| 122 | #define SDEFL_HASH_BITS 15 | ||
| 123 | #define SDEFL_HASH_SIZ (1 << SDEFL_HASH_BITS) | ||
| 124 | #define SDEFL_HASH_MSK (SDEFL_HASH_SIZ-1) | ||
| 125 | |||
| 126 | #define SDEFL_MIN_MATCH 4 | ||
| 127 | #define SDEFL_BLK_MAX (256*1024) | ||
| 128 | #define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX+2)/3) | ||
| 129 | |||
| 130 | #define SDEFL_SYM_MAX (288) | ||
| 131 | #define SDEFL_OFF_MAX (32) | ||
| 132 | #define SDEFL_PRE_MAX (19) | ||
| 133 | |||
| 134 | #define SDEFL_LVL_MIN 0 | ||
| 135 | #define SDEFL_LVL_DEF 5 | ||
| 136 | #define SDEFL_LVL_MAX 8 | ||
| 137 | |||
| 138 | struct sdefl_freq { | ||
| 139 | unsigned lit[SDEFL_SYM_MAX]; | ||
| 140 | unsigned off[SDEFL_OFF_MAX]; | ||
| 141 | }; | ||
| 142 | struct sdefl_code_words { | ||
| 143 | unsigned lit[SDEFL_SYM_MAX]; | ||
| 144 | unsigned off[SDEFL_OFF_MAX]; | ||
| 145 | }; | ||
| 146 | struct sdefl_lens { | ||
| 147 | unsigned char lit[SDEFL_SYM_MAX]; | ||
| 148 | unsigned char off[SDEFL_OFF_MAX]; | ||
| 149 | }; | ||
| 150 | struct sdefl_codes { | ||
| 151 | struct sdefl_code_words word; | ||
| 152 | struct sdefl_lens len; | ||
| 153 | }; | ||
| 154 | struct sdefl_seqt { | ||
| 155 | int off, len; | ||
| 156 | }; | ||
| 157 | struct sdefl { | ||
| 158 | int bits, bitcnt; | ||
| 159 | int tbl[SDEFL_HASH_SIZ]; | ||
| 160 | int prv[SDEFL_WIN_SIZ]; | ||
| 161 | |||
| 162 | int seq_cnt; | ||
| 163 | struct sdefl_seqt seq[SDEFL_SEQ_SIZ]; | ||
| 164 | struct sdefl_freq freq; | ||
| 165 | struct sdefl_codes cod; | ||
| 166 | }; | ||
| 167 | extern int sdefl_bound(int in_len); | ||
| 168 | extern int sdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl); | ||
| 169 | extern int zsdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl); | ||
| 170 | |||
| 171 | #ifdef __cplusplus | ||
| 172 | } | ||
| 173 | #endif | ||
| 174 | |||
| 175 | #endif /* SDEFL_H_INCLUDED */ | ||
| 176 | |||
| 177 | #ifdef SDEFL_IMPLEMENTATION | ||
| 178 | |||
| 179 | #include <assert.h> /* assert */ | ||
| 180 | #include <string.h> /* memcpy */ | ||
| 181 | #include <limits.h> /* CHAR_BIT */ | ||
| 182 | |||
| 183 | #define SDEFL_NIL (-1) | ||
| 184 | #define SDEFL_MAX_MATCH 258 | ||
| 185 | #define SDEFL_MAX_CODE_LEN (15) | ||
| 186 | #define SDEFL_SYM_BITS (10u) | ||
| 187 | #define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u) | ||
| 188 | #define SDEFL_RAW_BLK_SIZE (65535) | ||
| 189 | #define SDEFL_LIT_LEN_CODES (14) | ||
| 190 | #define SDEFL_OFF_CODES (15) | ||
| 191 | #define SDEFL_PRE_CODES (7) | ||
| 192 | #define SDEFL_CNT_NUM(n) ((((n)+3u/4u)+3u)&~3u) | ||
| 193 | #define SDEFL_EOB (256) | ||
| 194 | |||
| 195 | #define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1)) | ||
| 196 | #define sdefl_div_round_up(n,d) (((n)+((d)-1))/(d)) | ||
| 197 | |||
| 198 | static int | ||
| 199 | sdefl_ilog2(int n) { | ||
| 200 | if (!n) return 0; | ||
| 201 | #ifdef _MSC_VER | ||
| 202 | unsigned long msbp = 0; | ||
| 203 | _BitScanReverse(&msbp, (unsigned long)n); | ||
| 204 | return (int)msbp; | ||
| 205 | #elif defined(__GNUC__) || defined(__clang__) | ||
| 206 | return (int)sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl((unsigned long)n); | ||
| 207 | #else | ||
| 208 | #define lt(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n | ||
| 209 | static const char tbl[256] = { | ||
| 210 | 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,lt(4), lt(5), lt(5), lt(6), lt(6), lt(6), lt(6), | ||
| 211 | lt(7), lt(7), lt(7), lt(7), lt(7), lt(7), lt(7), lt(7)}; | ||
| 212 | int tt, t; | ||
| 213 | if ((tt = (n >> 16))) { | ||
| 214 | return (t = (tt >> 8)) ? 24 + tbl[t] : 16 + tbl[tt]; | ||
| 215 | } else { | ||
| 216 | return (t = (n >> 8)) ? 8 + tbl[t] : tbl[n]; | ||
| 217 | } | ||
| 218 | #undef lt | ||
| 219 | #endif | ||
| 220 | } | ||
| 221 | static unsigned | ||
| 222 | sdefl_uload32(const void *p) { | ||
| 223 | /* hopefully will be optimized to an unaligned read */ | ||
| 224 | unsigned n = 0; | ||
| 225 | memcpy(&n, p, sizeof(n)); | ||
| 226 | return n; | ||
| 227 | } | ||
| 228 | static unsigned | ||
| 229 | sdefl_hash32(const void *p) { | ||
| 230 | unsigned n = sdefl_uload32(p); | ||
| 231 | return (n * 0x9E377989) >> (32 - SDEFL_HASH_BITS); | ||
| 232 | } | ||
| 233 | static void | ||
| 234 | sdefl_put(unsigned char **dst, struct sdefl *s, int code, int bitcnt) { | ||
| 235 | s->bits |= (code << s->bitcnt); | ||
| 236 | s->bitcnt += bitcnt; | ||
| 237 | while (s->bitcnt >= 8) { | ||
| 238 | unsigned char *tar = *dst; | ||
| 239 | *tar = (unsigned char)(s->bits & 0xFF); | ||
| 240 | s->bits >>= 8; | ||
| 241 | s->bitcnt -= 8; | ||
| 242 | *dst = *dst + 1; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | static void | ||
| 246 | sdefl_heap_sub(unsigned A[], unsigned len, unsigned sub) { | ||
| 247 | unsigned c, p = sub; | ||
| 248 | unsigned v = A[sub]; | ||
| 249 | while ((c = p << 1) <= len) { | ||
| 250 | if (c < len && A[c + 1] > A[c]) c++; | ||
| 251 | if (v >= A[c]) break; | ||
| 252 | A[p] = A[c], p = c; | ||
| 253 | } | ||
| 254 | A[p] = v; | ||
| 255 | } | ||
| 256 | static void | ||
| 257 | sdefl_heap_array(unsigned *A, unsigned len) { | ||
| 258 | unsigned sub; | ||
| 259 | for (sub = len >> 1; sub >= 1; sub--) | ||
| 260 | sdefl_heap_sub(A, len, sub); | ||
| 261 | } | ||
| 262 | static void | ||
| 263 | sdefl_heap_sort(unsigned *A, unsigned n) { | ||
| 264 | A--; | ||
| 265 | sdefl_heap_array(A, n); | ||
| 266 | while (n >= 2) { | ||
| 267 | unsigned tmp = A[n]; | ||
| 268 | A[n--] = A[1]; | ||
| 269 | A[1] = tmp; | ||
| 270 | sdefl_heap_sub(A, n, 1); | ||
| 271 | } | ||
| 272 | } | ||
| 273 | static unsigned | ||
| 274 | sdefl_sort_sym(unsigned sym_cnt, unsigned *freqs, | ||
| 275 | unsigned char *lens, unsigned *sym_out) { | ||
| 276 | unsigned cnts[SDEFL_CNT_NUM(SDEFL_SYM_MAX)] = {0}; | ||
| 277 | unsigned cnt_num = SDEFL_CNT_NUM(sym_cnt); | ||
| 278 | unsigned used_sym = 0; | ||
| 279 | unsigned sym, i; | ||
| 280 | for (sym = 0; sym < sym_cnt; sym++) | ||
| 281 | cnts[freqs[sym] < cnt_num-1 ? freqs[sym]: cnt_num-1]++; | ||
| 282 | for (i = 1; i < cnt_num; i++) { | ||
| 283 | unsigned cnt = cnts[i]; | ||
| 284 | cnts[i] = used_sym; | ||
| 285 | used_sym += cnt; | ||
| 286 | } | ||
| 287 | for (sym = 0; sym < sym_cnt; sym++) { | ||
| 288 | unsigned freq = freqs[sym]; | ||
| 289 | if (freq) { | ||
| 290 | unsigned idx = freq < cnt_num-1 ? freq : cnt_num-1; | ||
| 291 | sym_out[cnts[idx]++] = sym | (freq << SDEFL_SYM_BITS); | ||
| 292 | } else lens[sym] = 0; | ||
| 293 | } | ||
| 294 | sdefl_heap_sort(sym_out + cnts[cnt_num-2], cnts[cnt_num-1] - cnts[cnt_num-2]); | ||
| 295 | return used_sym; | ||
| 296 | } | ||
| 297 | static void | ||
| 298 | sdefl_build_tree(unsigned *A, unsigned sym_cnt) { | ||
| 299 | unsigned i = 0, b = 0, e = 0; | ||
| 300 | do { | ||
| 301 | unsigned m, n, freq_shift; | ||
| 302 | if (i != sym_cnt && (b == e || (A[i] >> SDEFL_SYM_BITS) <= (A[b] >> SDEFL_SYM_BITS))) | ||
| 303 | m = i++; | ||
| 304 | else m = b++; | ||
| 305 | if (i != sym_cnt && (b == e || (A[i] >> SDEFL_SYM_BITS) <= (A[b] >> SDEFL_SYM_BITS))) | ||
| 306 | n = i++; | ||
| 307 | else n = b++; | ||
| 308 | |||
| 309 | freq_shift = (A[m] & ~SDEFL_SYM_MSK) + (A[n] & ~SDEFL_SYM_MSK); | ||
| 310 | A[m] = (A[m] & SDEFL_SYM_MSK) | (e << SDEFL_SYM_BITS); | ||
| 311 | A[n] = (A[n] & SDEFL_SYM_MSK) | (e << SDEFL_SYM_BITS); | ||
| 312 | A[e] = (A[e] & SDEFL_SYM_MSK) | freq_shift; | ||
| 313 | } while (sym_cnt - ++e > 1); | ||
| 314 | } | ||
| 315 | static void | ||
| 316 | sdefl_gen_len_cnt(unsigned *A, unsigned root, unsigned *len_cnt, | ||
| 317 | unsigned max_code_len) { | ||
| 318 | int n; | ||
| 319 | unsigned i; | ||
| 320 | for (i = 0; i <= max_code_len; i++) | ||
| 321 | len_cnt[i] = 0; | ||
| 322 | len_cnt[1] = 2; | ||
| 323 | |||
| 324 | A[root] &= SDEFL_SYM_MSK; | ||
| 325 | for (n = (int)root - 1; n >= 0; n--) { | ||
| 326 | unsigned p = A[n] >> SDEFL_SYM_BITS; | ||
| 327 | unsigned pdepth = A[p] >> SDEFL_SYM_BITS; | ||
| 328 | unsigned depth = pdepth + 1; | ||
| 329 | unsigned len = depth; | ||
| 330 | |||
| 331 | A[n] = (A[n] & SDEFL_SYM_MSK) | (depth << SDEFL_SYM_BITS); | ||
| 332 | if (len >= max_code_len) { | ||
| 333 | len = max_code_len; | ||
| 334 | do len--; while (!len_cnt[len]); | ||
| 335 | } | ||
| 336 | len_cnt[len]--; | ||
| 337 | len_cnt[len+1] += 2; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | static void | ||
| 341 | sdefl_gen_codes(unsigned *A, unsigned char *lens, const unsigned *len_cnt, | ||
| 342 | unsigned max_code_word_len, unsigned sym_cnt) { | ||
| 343 | unsigned i, sym, len, nxt[SDEFL_MAX_CODE_LEN + 1]; | ||
| 344 | for (i = 0, len = max_code_word_len; len >= 1; len--) { | ||
| 345 | unsigned cnt = len_cnt[len]; | ||
| 346 | while (cnt--) lens[A[i++] & SDEFL_SYM_MSK] = (unsigned char)len; | ||
| 347 | } | ||
| 348 | nxt[0] = nxt[1] = 0; | ||
| 349 | for (len = 2; len <= max_code_word_len; len++) | ||
| 350 | nxt[len] = (nxt[len-1] + len_cnt[len-1]) << 1; | ||
| 351 | for (sym = 0; sym < sym_cnt; sym++) | ||
| 352 | A[sym] = nxt[lens[sym]]++; | ||
| 353 | } | ||
| 354 | static unsigned | ||
| 355 | sdefl_rev(unsigned c, unsigned char n) { | ||
| 356 | c = ((c & 0x5555) << 1) | ((c & 0xAAAA) >> 1); | ||
| 357 | c = ((c & 0x3333) << 2) | ((c & 0xCCCC) >> 2); | ||
| 358 | c = ((c & 0x0F0F) << 4) | ((c & 0xF0F0) >> 4); | ||
| 359 | c = ((c & 0x00FF) << 8) | ((c & 0xFF00) >> 8); | ||
| 360 | return c >> (16-n); | ||
| 361 | } | ||
| 362 | static void | ||
| 363 | sdefl_huff(unsigned char *lens, unsigned *codes, unsigned *freqs, | ||
| 364 | unsigned num_syms, unsigned max_code_len) { | ||
| 365 | unsigned c, *A = codes; | ||
| 366 | unsigned len_cnt[SDEFL_MAX_CODE_LEN + 1]; | ||
| 367 | unsigned used_syms = sdefl_sort_sym(num_syms, freqs, lens, A); | ||
| 368 | if (!used_syms) return; | ||
| 369 | if (used_syms == 1) { | ||
| 370 | unsigned s = A[0] & SDEFL_SYM_MSK; | ||
| 371 | unsigned i = s ? s : 1; | ||
| 372 | codes[0] = 0, lens[0] = 1; | ||
| 373 | codes[i] = 1, lens[i] = 1; | ||
| 374 | return; | ||
| 375 | } | ||
| 376 | sdefl_build_tree(A, used_syms); | ||
| 377 | sdefl_gen_len_cnt(A, used_syms-2, len_cnt, max_code_len); | ||
| 378 | sdefl_gen_codes(A, lens, len_cnt, max_code_len, num_syms); | ||
| 379 | for (c = 0; c < num_syms; c++) { | ||
| 380 | codes[c] = sdefl_rev(codes[c], lens[c]); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | struct sdefl_symcnt { | ||
| 384 | int items; | ||
| 385 | int lit; | ||
| 386 | int off; | ||
| 387 | }; | ||
| 388 | static void | ||
| 389 | sdefl_precode(struct sdefl_symcnt *cnt, unsigned *freqs, unsigned *items, | ||
| 390 | const unsigned char *litlen, const unsigned char *offlen) { | ||
| 391 | unsigned *at = items; | ||
| 392 | unsigned run_start = 0; | ||
| 393 | |||
| 394 | unsigned total = 0; | ||
| 395 | unsigned char lens[SDEFL_SYM_MAX + SDEFL_OFF_MAX]; | ||
| 396 | for (cnt->lit = SDEFL_SYM_MAX; cnt->lit > 257; cnt->lit--) | ||
| 397 | if (litlen[cnt->lit - 1]) break; | ||
| 398 | for (cnt->off = SDEFL_OFF_MAX; cnt->off > 1; cnt->off--) | ||
| 399 | if (offlen[cnt->off - 1]) break; | ||
| 400 | |||
| 401 | total = (unsigned)(cnt->lit + cnt->off); | ||
| 402 | memcpy(lens, litlen, sizeof(unsigned char) * (size_t)cnt->lit); | ||
| 403 | memcpy(lens + cnt->lit, offlen, sizeof(unsigned char) * (size_t)cnt->off); | ||
| 404 | do { | ||
| 405 | unsigned len = lens[run_start]; | ||
| 406 | unsigned run_end = run_start; | ||
| 407 | do run_end++; while (run_end != total && len == lens[run_end]); | ||
| 408 | if (!len) { | ||
| 409 | while ((run_end - run_start) >= 11) { | ||
| 410 | unsigned n = (run_end - run_start) - 11; | ||
| 411 | unsigned xbits = n < 0x7f ? n : 0x7f; | ||
| 412 | freqs[18]++; | ||
| 413 | *at++ = 18u | (xbits << 5u); | ||
| 414 | run_start += 11 + xbits; | ||
| 415 | } | ||
| 416 | if ((run_end - run_start) >= 3) { | ||
| 417 | unsigned n = (run_end - run_start) - 3; | ||
| 418 | unsigned xbits = n < 0x7 ? n : 0x7; | ||
| 419 | freqs[17]++; | ||
| 420 | *at++ = 17u | (xbits << 5u); | ||
| 421 | run_start += 3 + xbits; | ||
| 422 | } | ||
| 423 | } else if ((run_end - run_start) >= 4) { | ||
| 424 | freqs[len]++; | ||
| 425 | *at++ = len; | ||
| 426 | run_start++; | ||
| 427 | do { | ||
| 428 | unsigned xbits = (run_end - run_start) - 3; | ||
| 429 | xbits = xbits < 0x03 ? xbits : 0x03; | ||
| 430 | *at++ = 16 | (xbits << 5); | ||
| 431 | run_start += 3 + xbits; | ||
| 432 | freqs[16]++; | ||
| 433 | } while ((run_end - run_start) >= 3); | ||
| 434 | } | ||
| 435 | while (run_start != run_end) { | ||
| 436 | freqs[len]++; | ||
| 437 | *at++ = len; | ||
| 438 | run_start++; | ||
| 439 | } | ||
| 440 | } while (run_start != total); | ||
| 441 | cnt->items = (int)(at - items); | ||
| 442 | } | ||
| 443 | struct sdefl_match_codest { | ||
| 444 | int ls, lc; | ||
| 445 | int dc, dx; | ||
| 446 | }; | ||
| 447 | static void | ||
| 448 | sdefl_match_codes(struct sdefl_match_codest *cod, int dist, int len) { | ||
| 449 | static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576}; | ||
| 450 | static const unsigned char lslot[258+1] = { | ||
| 451 | 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, | ||
| 452 | 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, | ||
| 453 | 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, | ||
| 454 | 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, | ||
| 455 | 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, | ||
| 456 | 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, | ||
| 457 | 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, | ||
| 458 | 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, | ||
| 459 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, | ||
| 460 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, | ||
| 461 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, | ||
| 462 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, | ||
| 463 | 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | ||
| 464 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | ||
| 465 | 27, 27, 28 | ||
| 466 | }; | ||
| 467 | assert(len <= 258); | ||
| 468 | assert(dist <= 32768); | ||
| 469 | cod->ls = lslot[len]; | ||
| 470 | cod->lc = 257 + cod->ls; | ||
| 471 | assert(cod->lc <= 285); | ||
| 472 | |||
| 473 | cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2); | ||
| 474 | cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1; | ||
| 475 | } | ||
| 476 | enum sdefl_blk_type { | ||
| 477 | SDEFL_BLK_UCOMPR, | ||
| 478 | SDEFL_BLK_DYN | ||
| 479 | }; | ||
| 480 | static enum sdefl_blk_type | ||
| 481 | sdefl_blk_type(const struct sdefl *s, int blk_len, int pre_item_len, | ||
| 482 | const unsigned *pre_freq, const unsigned char *pre_len) { | ||
| 483 | static const unsigned char x_pre_bits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; | ||
| 484 | static const unsigned char x_len_bits[] = {0,0,0,0,0,0,0,0, 1,1,1,1,2,2,2,2, | ||
| 485 | 3,3,3,3,4,4,4,4, 5,5,5,5,0}; | ||
| 486 | static const unsigned char x_off_bits[] = {0,0,0,0,1,1,2,2, 3,3,4,4,5,5,6,6, | ||
| 487 | 7,7,8,8,9,9,10,10, 11,11,12,12,13,13}; | ||
| 488 | |||
| 489 | int dyn_cost = 0; | ||
| 490 | int fix_cost = 0; | ||
| 491 | int sym = 0; | ||
| 492 | |||
| 493 | dyn_cost += 5 + 5 + 4 + (3 * pre_item_len); | ||
| 494 | for (sym = 0; sym < SDEFL_PRE_MAX; sym++) | ||
| 495 | dyn_cost += pre_freq[sym] * (x_pre_bits[sym] + pre_len[sym]); | ||
| 496 | for (sym = 0; sym < 256; sym++) | ||
| 497 | dyn_cost += s->freq.lit[sym] * s->cod.len.lit[sym]; | ||
| 498 | dyn_cost += s->cod.len.lit[SDEFL_EOB]; | ||
| 499 | for (sym = 257; sym < 286; sym++) | ||
| 500 | dyn_cost += s->freq.lit[sym] * (x_len_bits[sym - 257] + s->cod.len.lit[sym]); | ||
| 501 | for (sym = 0; sym < 30; sym++) | ||
| 502 | dyn_cost += s->freq.off[sym] * (x_off_bits[sym] + s->cod.len.off[sym]); | ||
| 503 | |||
| 504 | fix_cost += 8*(5 * sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE) + blk_len + 1 + 2); | ||
| 505 | return (dyn_cost < fix_cost) ? SDEFL_BLK_DYN : SDEFL_BLK_UCOMPR; | ||
| 506 | } | ||
| 507 | static void | ||
| 508 | sdefl_put16(unsigned char **dst, unsigned short x) { | ||
| 509 | unsigned char *val = *dst; | ||
| 510 | val[0] = (unsigned char)(x & 0xff); | ||
| 511 | val[1] = (unsigned char)(x >> 8); | ||
| 512 | *dst = val + 2; | ||
| 513 | } | ||
| 514 | static void | ||
| 515 | sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) { | ||
| 516 | static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; | ||
| 517 | static const short lmin[] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43, | ||
| 518 | 51,59,67,83,99,115,131,163,195,227,258}; | ||
| 519 | static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257, | ||
| 520 | 385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; | ||
| 521 | |||
| 522 | struct sdefl_match_codest cod; | ||
| 523 | sdefl_match_codes(&cod, dist, len); | ||
| 524 | sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]); | ||
| 525 | sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]); | ||
| 526 | sdefl_put(dst, s, (int)s->cod.word.off[cod.dc], s->cod.len.off[cod.dc]); | ||
| 527 | sdefl_put(dst, s, dist - dmin[cod.dc], cod.dx); | ||
| 528 | } | ||
| 529 | static void | ||
| 530 | sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last, | ||
| 531 | const unsigned char *in, int blk_begin, int blk_end) { | ||
| 532 | int blk_len = blk_end - blk_begin; | ||
| 533 | int j, i = 0, item_cnt = 0; | ||
| 534 | struct sdefl_symcnt symcnt = {0}; | ||
| 535 | unsigned codes[SDEFL_PRE_MAX]; | ||
| 536 | unsigned char lens[SDEFL_PRE_MAX]; | ||
| 537 | unsigned freqs[SDEFL_PRE_MAX] = {0}; | ||
| 538 | unsigned items[SDEFL_SYM_MAX + SDEFL_OFF_MAX]; | ||
| 539 | static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11, | ||
| 540 | 4,12,3,13,2,14,1,15}; | ||
| 541 | |||
| 542 | /* calculate huffman codes */ | ||
| 543 | s->freq.lit[SDEFL_EOB]++; | ||
| 544 | sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES); | ||
| 545 | sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES); | ||
| 546 | sdefl_precode(&symcnt, freqs, items, s->cod.len.lit, s->cod.len.off); | ||
| 547 | sdefl_huff(lens, codes, freqs, SDEFL_PRE_MAX, SDEFL_PRE_CODES); | ||
| 548 | for (item_cnt = SDEFL_PRE_MAX; item_cnt > 4; item_cnt--) { | ||
| 549 | if (lens[perm[item_cnt - 1]]){ | ||
| 550 | break; | ||
| 551 | } | ||
| 552 | } | ||
| 553 | /* write block */ | ||
| 554 | switch (sdefl_blk_type(s, blk_len, item_cnt, freqs, lens)) { | ||
| 555 | case SDEFL_BLK_UCOMPR: { | ||
| 556 | /* uncompressed blocks */ | ||
| 557 | int n = sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE); | ||
| 558 | for (i = 0; i < n; ++i) { | ||
| 559 | int fin = is_last && (i + 1 == n); | ||
| 560 | int amount = blk_len < SDEFL_RAW_BLK_SIZE ? blk_len : SDEFL_RAW_BLK_SIZE; | ||
| 561 | sdefl_put(dst, s, !!fin, 1); /* block */ | ||
| 562 | sdefl_put(dst, s, 0x00, 2); /* stored block */ | ||
| 563 | if (s->bitcnt) { | ||
| 564 | sdefl_put(dst, s, 0x00, 8 - s->bitcnt); | ||
| 565 | } | ||
| 566 | assert(s->bitcnt == 0); | ||
| 567 | sdefl_put16(dst, (unsigned short)amount); | ||
| 568 | sdefl_put16(dst, ~(unsigned short)amount); | ||
| 569 | memcpy(*dst, in + blk_begin + i * SDEFL_RAW_BLK_SIZE, amount); | ||
| 570 | *dst = *dst + amount; | ||
| 571 | blk_len -= amount; | ||
| 572 | } | ||
| 573 | } break; | ||
| 574 | case SDEFL_BLK_DYN: { | ||
| 575 | /* dynamic huffman block */ | ||
| 576 | sdefl_put(dst, s, !!is_last, 1); /* block */ | ||
| 577 | sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */ | ||
| 578 | sdefl_put(dst, s, symcnt.lit - 257, 5); | ||
| 579 | sdefl_put(dst, s, symcnt.off - 1, 5); | ||
| 580 | sdefl_put(dst, s, item_cnt - 4, 4); | ||
| 581 | for (i = 0; i < item_cnt; ++i) { | ||
| 582 | sdefl_put(dst, s, lens[perm[i]], 3); | ||
| 583 | } | ||
| 584 | for (i = 0; i < symcnt.items; ++i) { | ||
| 585 | unsigned sym = items[i] & 0x1F; | ||
| 586 | sdefl_put(dst, s, (int)codes[sym], lens[sym]); | ||
| 587 | if (sym < 16) continue; | ||
| 588 | if (sym == 16) sdefl_put(dst, s, items[i] >> 5, 2); | ||
| 589 | else if(sym == 17) sdefl_put(dst, s, items[i] >> 5, 3); | ||
| 590 | else sdefl_put(dst, s, items[i] >> 5, 7); | ||
| 591 | } | ||
| 592 | /* block sequences */ | ||
| 593 | for (i = 0; i < s->seq_cnt; ++i) { | ||
| 594 | if (s->seq[i].off >= 0) { | ||
| 595 | for (j = 0; j < s->seq[i].len; ++j) { | ||
| 596 | int c = in[s->seq[i].off + j]; | ||
| 597 | sdefl_put(dst, s, (int)s->cod.word.lit[c], s->cod.len.lit[c]); | ||
| 598 | } | ||
| 599 | } else { | ||
| 600 | sdefl_match(dst, s, -s->seq[i].off, s->seq[i].len); | ||
| 601 | } | ||
| 602 | } | ||
| 603 | sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]); | ||
| 604 | } break;} | ||
| 605 | memset(&s->freq, 0, sizeof(s->freq)); | ||
| 606 | s->seq_cnt = 0; | ||
| 607 | } | ||
| 608 | static void | ||
| 609 | sdefl_seq(struct sdefl *s, int off, int len) { | ||
| 610 | assert(s->seq_cnt + 2 < SDEFL_SEQ_SIZ); | ||
| 611 | s->seq[s->seq_cnt].off = off; | ||
| 612 | s->seq[s->seq_cnt].len = len; | ||
| 613 | s->seq_cnt++; | ||
| 614 | } | ||
| 615 | static void | ||
| 616 | sdefl_reg_match(struct sdefl *s, int off, int len) { | ||
| 617 | struct sdefl_match_codest cod; | ||
| 618 | sdefl_match_codes(&cod, off, len); | ||
| 619 | |||
| 620 | assert(cod.lc < SDEFL_SYM_MAX); | ||
| 621 | assert(cod.dc < SDEFL_OFF_MAX); | ||
| 622 | |||
| 623 | s->freq.lit[cod.lc]++; | ||
| 624 | s->freq.off[cod.dc]++; | ||
| 625 | } | ||
| 626 | struct sdefl_match { | ||
| 627 | int off; | ||
| 628 | int len; | ||
| 629 | }; | ||
| 630 | static void | ||
| 631 | sdefl_fnd(struct sdefl_match *m, const struct sdefl *s, int chain_len, | ||
| 632 | int max_match, const unsigned char *in, int p, int e) { | ||
| 633 | int i = s->tbl[sdefl_hash32(in + p)]; | ||
| 634 | int limit = ((p - SDEFL_WIN_SIZ) < SDEFL_NIL) ? SDEFL_NIL : (p-SDEFL_WIN_SIZ); | ||
| 635 | |||
| 636 | assert(p < e); | ||
| 637 | assert(p + max_match <= e); | ||
| 638 | while (i > limit) { | ||
| 639 | assert(i + m->len < e); | ||
| 640 | assert(p + m->len < e); | ||
| 641 | assert(i + SDEFL_MIN_MATCH < e); | ||
| 642 | assert(p + SDEFL_MIN_MATCH < e); | ||
| 643 | |||
| 644 | if (in[i + m->len] == in[p + m->len] && | ||
| 645 | (sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))) { | ||
| 646 | int n = SDEFL_MIN_MATCH; | ||
| 647 | while (n < max_match && in[i + n] == in[p + n]) { | ||
| 648 | assert(i + n < e); | ||
| 649 | assert(p + n < e); | ||
| 650 | n++; | ||
| 651 | } | ||
| 652 | if (n > m->len) { | ||
| 653 | m->len = n, m->off = p - i; | ||
| 654 | if (n == max_match) | ||
| 655 | break; | ||
| 656 | } | ||
| 657 | } | ||
| 658 | if (!(--chain_len)) break; | ||
| 659 | i = s->prv[i & SDEFL_WIN_MSK]; | ||
| 660 | } | ||
| 661 | } | ||
| 662 | static int | ||
| 663 | sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in, | ||
| 664 | int in_len, int lvl) { | ||
| 665 | unsigned char *q = out; | ||
| 666 | static const unsigned char pref[] = {8,10,14,24,30,48,65,96,130}; | ||
| 667 | int max_chain = (lvl < 8) ? (1 << (lvl + 1)): (1 << 13); | ||
| 668 | int n, i = 0, litlen = 0; | ||
| 669 | for (n = 0; n < SDEFL_HASH_SIZ; ++n) { | ||
| 670 | s->tbl[n] = SDEFL_NIL; | ||
| 671 | } | ||
| 672 | do {int blk_begin = i; | ||
| 673 | int blk_end = ((i + SDEFL_BLK_MAX) < in_len) ? (i + SDEFL_BLK_MAX) : in_len; | ||
| 674 | while (i < blk_end) { | ||
| 675 | struct sdefl_match m = {0}; | ||
| 676 | int left = blk_end - i; | ||
| 677 | int max_match = (left > SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH : left; | ||
| 678 | int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match; | ||
| 679 | int run = 1, inc = 1, run_inc = 0; | ||
| 680 | if (max_match > SDEFL_MIN_MATCH) { | ||
| 681 | sdefl_fnd(&m, s, max_chain, max_match, in, i, in_len); | ||
| 682 | } | ||
| 683 | if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len + 1 < nice_match){ | ||
| 684 | struct sdefl_match m2 = {0}; | ||
| 685 | sdefl_fnd(&m2, s, max_chain, m.len + 1, in, i + 1, in_len); | ||
| 686 | m.len = (m2.len > m.len) ? 0 : m.len; | ||
| 687 | } | ||
| 688 | if (m.len >= SDEFL_MIN_MATCH) { | ||
| 689 | if (litlen) { | ||
| 690 | sdefl_seq(s, i - litlen, litlen); | ||
| 691 | litlen = 0; | ||
| 692 | } | ||
| 693 | sdefl_seq(s, -m.off, m.len); | ||
| 694 | sdefl_reg_match(s, m.off, m.len); | ||
| 695 | if (lvl < 2 && m.len >= nice_match) { | ||
| 696 | inc = m.len; | ||
| 697 | } else { | ||
| 698 | run = m.len; | ||
| 699 | } | ||
| 700 | } else { | ||
| 701 | s->freq.lit[in[i]]++; | ||
| 702 | litlen++; | ||
| 703 | } | ||
| 704 | run_inc = run * inc; | ||
| 705 | if (in_len - (i + run_inc) > SDEFL_MIN_MATCH) { | ||
| 706 | while (run-- > 0) { | ||
| 707 | unsigned h = sdefl_hash32(&in[i]); | ||
| 708 | s->prv[i&SDEFL_WIN_MSK] = s->tbl[h]; | ||
| 709 | s->tbl[h] = i, i += inc; | ||
| 710 | assert(i <= blk_end); | ||
| 711 | } | ||
| 712 | } else { | ||
| 713 | i += run_inc; | ||
| 714 | assert(i <= blk_end); | ||
| 715 | } | ||
| 716 | } | ||
| 717 | if (litlen) { | ||
| 718 | sdefl_seq(s, i - litlen, litlen); | ||
| 719 | litlen = 0; | ||
| 720 | } | ||
| 721 | sdefl_flush(&q, s, blk_end == in_len, in, blk_begin, blk_end); | ||
| 722 | } while (i < in_len); | ||
| 723 | if (s->bitcnt) { | ||
| 724 | sdefl_put(&q, s, 0x00, 8 - s->bitcnt); | ||
| 725 | } | ||
| 726 | assert(s->bitcnt == 0); | ||
| 727 | return (int)(q - out); | ||
| 728 | } | ||
| 729 | extern int | ||
| 730 | sdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) { | ||
| 731 | s->bits = s->bitcnt = 0; | ||
| 732 | return sdefl_compr(s, (unsigned char*)out, (const unsigned char*)in, n, lvl); | ||
| 733 | } | ||
| 734 | static unsigned | ||
| 735 | sdefl_adler32(unsigned adler32, const unsigned char *in, int in_len) { | ||
| 736 | #define SDEFL_ADLER_INIT (1) | ||
| 737 | const unsigned ADLER_MOD = 65521; | ||
| 738 | unsigned s1 = adler32 & 0xffff; | ||
| 739 | unsigned s2 = adler32 >> 16; | ||
| 740 | unsigned blk_len, i; | ||
| 741 | |||
| 742 | blk_len = in_len % 5552; | ||
| 743 | while (in_len) { | ||
| 744 | for (i = 0; i + 7 < blk_len; i += 8) { | ||
| 745 | s1 += in[0]; s2 += s1; | ||
| 746 | s1 += in[1]; s2 += s1; | ||
| 747 | s1 += in[2]; s2 += s1; | ||
| 748 | s1 += in[3]; s2 += s1; | ||
| 749 | s1 += in[4]; s2 += s1; | ||
| 750 | s1 += in[5]; s2 += s1; | ||
| 751 | s1 += in[6]; s2 += s1; | ||
| 752 | s1 += in[7]; s2 += s1; | ||
| 753 | in += 8; | ||
| 754 | } | ||
| 755 | for (; i < blk_len; ++i) { | ||
| 756 | s1 += *in++, s2 += s1; | ||
| 757 | } | ||
| 758 | s1 %= ADLER_MOD; | ||
| 759 | s2 %= ADLER_MOD; | ||
| 760 | in_len -= blk_len; | ||
| 761 | blk_len = 5552; | ||
| 762 | } | ||
| 763 | return (unsigned)(s2 << 16) + (unsigned)s1; | ||
| 764 | } | ||
| 765 | extern int | ||
| 766 | zsdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) { | ||
| 767 | int p = 0; | ||
| 768 | unsigned a = 0; | ||
| 769 | unsigned char *q = (unsigned char*)out; | ||
| 770 | |||
| 771 | s->bits = s->bitcnt = 0; | ||
| 772 | sdefl_put(&q, s, 0x78, 8); /* deflate, 32k window */ | ||
| 773 | sdefl_put(&q, s, 0x01, 8); /* fast compression */ | ||
| 774 | q += sdefl_compr(s, q, (const unsigned char*)in, n, lvl); | ||
| 775 | |||
| 776 | /* append adler checksum */ | ||
| 777 | a = sdefl_adler32(SDEFL_ADLER_INIT, (const unsigned char*)in, n); | ||
| 778 | for (p = 0; p < 4; ++p) { | ||
| 779 | sdefl_put(&q, s, (a >> 24) & 0xFF, 8); | ||
| 780 | a <<= 8; | ||
| 781 | } | ||
| 782 | return (int)(q - (unsigned char*)out); | ||
| 783 | } | ||
| 784 | extern int | ||
| 785 | sdefl_bound(int len) { | ||
| 786 | int max_blocks = 1 + sdefl_div_round_up(len, SDEFL_RAW_BLK_SIZE); | ||
| 787 | int bound = 5 * max_blocks + len + 1 + 4 + 8; | ||
| 788 | return bound; | ||
| 789 | } | ||
| 790 | #endif /* SDEFL_IMPLEMENTATION */ | ||
