diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-04-21 11:09:56 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-04-21 11:09:56 +0200 |
| commit | 123144c93bfc77883c8fb517828b47bbe13b8671 (patch) | |
| tree | 762739afedb5f3f168051367515cb9b9a06ec68d /raylib/src/external/sinfl.h | |
| download | minesweeper-123144c93bfc77883c8fb517828b47bbe13b8671.tar.gz minesweeper-123144c93bfc77883c8fb517828b47bbe13b8671.zip | |
Diffstat (limited to 'raylib/src/external/sinfl.h')
| -rw-r--r-- | raylib/src/external/sinfl.h | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/raylib/src/external/sinfl.h b/raylib/src/external/sinfl.h new file mode 100644 index 0000000..3c71737 --- /dev/null +++ b/raylib/src/external/sinfl.h | |||
| @@ -0,0 +1,629 @@ | |||
| 1 | /* | ||
| 2 | # Small Deflate | ||
| 3 | `sdefl` is a small bare bone lossless compression library in ANSI C (ISO C90) | ||
| 4 | which implements the Deflate (RFC 1951) compressed data format specification standard. | ||
| 5 | It is mainly tuned to get as much speed and compression ratio from as little code | ||
| 6 | as needed to keep the implementation as concise as possible. | ||
| 7 | |||
| 8 | ## Features | ||
| 9 | - Portable single header and source file duo written in ANSI C (ISO C90) | ||
| 10 | - Dual license with either MIT or public domain | ||
| 11 | - Small implementation | ||
| 12 | - Deflate: 525 LoC | ||
| 13 | - Inflate: 500 LoC | ||
| 14 | - Webassembly: | ||
| 15 | - Deflate ~3.7 KB (~2.2KB compressed) | ||
| 16 | - Inflate ~3.6 KB (~2.2KB compressed) | ||
| 17 | |||
| 18 | ## Usage: | ||
| 19 | This file behaves differently depending on what symbols you define | ||
| 20 | before including it. | ||
| 21 | |||
| 22 | Header-File mode: | ||
| 23 | If you do not define `SINFL_IMPLEMENTATION` before including this file, it | ||
| 24 | will operate in header only mode. In this mode it declares all used structs | ||
| 25 | and the API of the library without including the implementation of the library. | ||
| 26 | |||
| 27 | Implementation mode: | ||
| 28 | If you define `SINFL_IMPLEMENTATION` before including this file, it will | ||
| 29 | compile the implementation. Make sure that you only include | ||
| 30 | this file implementation in *one* C or C++ file to prevent collisions. | ||
| 31 | |||
| 32 | ### Benchmark | ||
| 33 | |||
| 34 | | Compressor name | Compression| Decompress.| Compr. size | Ratio | | ||
| 35 | | ------------------------| -----------| -----------| ----------- | ----- | | ||
| 36 | | miniz 1.0 -1 | 122 MB/s | 208 MB/s | 48510028 | 48.51 | | ||
| 37 | | miniz 1.0 -6 | 27 MB/s | 260 MB/s | 36513697 | 36.51 | | ||
| 38 | | miniz 1.0 -9 | 23 MB/s | 261 MB/s | 36460101 | 36.46 | | ||
| 39 | | zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 | | ||
| 40 | | zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 | | ||
| 41 | | zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 | | ||
| 42 | | sdefl 1.0 -0 | 127 MB/s | 355 MB/s | 40004116 | 39.88 | | ||
| 43 | | sdefl 1.0 -1 | 111 MB/s | 413 MB/s | 38940674 | 38.82 | | ||
| 44 | | sdefl 1.0 -5 | 45 MB/s | 436 MB/s | 36577183 | 36.46 | | ||
| 45 | | sdefl 1.0 -7 | 38 MB/s | 432 MB/s | 36523781 | 36.41 | | ||
| 46 | | libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 | | ||
| 47 | | libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 | | ||
| 48 | | libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 | | ||
| 49 | | libdeflate 1.3 -12 | 8.13 MB/s | 670 MB/s | 35100568 | 35.10 | | ||
| 50 | |||
| 51 | ### Compression | ||
| 52 | Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia): | ||
| 53 | |||
| 54 | | File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` | | ||
| 55 | | --------| -----------| -------------| ---------- | ------------| | ||
| 56 | | dickens | 10.192.446 | 4,260,187 | 3,845,261 | 3,833,657 | | ||
| 57 | | mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 | | ||
| 58 | | mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 | | ||
| 59 | | nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 | | ||
| 60 | | ooffice | 6.152.192 | 3,320,063 | 3,186,373 | 3,183,815 | | ||
| 61 | | osdb | 10.085.684 | 3,919,646 | 3,649,510 | 3,649,477 | | ||
| 62 | | reymont | 6.627.202 | 2,263,378 | 1,857,588 | 1,827,237 | | ||
| 63 | | samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 | | ||
| 64 | | sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 | | ||
| 65 | | webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 | | ||
| 66 | | xml | 5.345.280 | 886,620 | 674,009 | 662,141 | | ||
| 67 | | x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 | | ||
| 68 | |||
| 69 | ## License | ||
| 70 | ``` | ||
| 71 | ------------------------------------------------------------------------------ | ||
| 72 | This software is available under 2 licenses -- choose whichever you prefer. | ||
| 73 | ------------------------------------------------------------------------------ | ||
| 74 | ALTERNATIVE A - MIT License | ||
| 75 | Copyright (c) 2020-2023 Micha Mettke | ||
| 76 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 77 | this software and associated documentation files (the "Software"), to deal in | ||
| 78 | the Software without restriction, including without limitation the rights to | ||
| 79 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
| 80 | of the Software, and to permit persons to whom the Software is furnished to do | ||
| 81 | so, subject to the following conditions: | ||
| 82 | The above copyright notice and this permission notice shall be included in all | ||
| 83 | copies or substantial portions of the Software. | ||
| 84 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 85 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 86 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 87 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 88 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 89 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 90 | SOFTWARE. | ||
| 91 | ------------------------------------------------------------------------------ | ||
| 92 | ALTERNATIVE B - Public Domain (www.unlicense.org) | ||
| 93 | This is free and unencumbered software released into the public domain. | ||
| 94 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this | ||
| 95 | software, either in source code form or as a compiled binary, for any purpose, | ||
| 96 | commercial or non-commercial, and by any means. | ||
| 97 | In jurisdictions that recognize copyright laws, the author or authors of this | ||
| 98 | software dedicate any and all copyright interest in the software to the public | ||
| 99 | domain. We make this dedication for the benefit of the public at large and to | ||
| 100 | the detriment of our heirs and successors. We intend this dedication to be an | ||
| 101 | overt act of relinquishment in perpetuity of all present and future rights to | ||
| 102 | this software under copyright law. | ||
| 103 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 104 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 105 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 106 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 107 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 108 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 109 | ------------------------------------------------------------------------------ | ||
| 110 | ``` | ||
| 111 | */ | ||
| 112 | #ifndef SINFL_H_INCLUDED | ||
| 113 | #define SINFL_H_INCLUDED | ||
| 114 | |||
| 115 | #ifdef __cplusplus | ||
| 116 | extern "C" { | ||
| 117 | #endif | ||
| 118 | |||
| 119 | #define SINFL_PRE_TBL_SIZE 128 | ||
| 120 | #define SINFL_LIT_TBL_SIZE 1334 | ||
| 121 | #define SINFL_OFF_TBL_SIZE 402 | ||
| 122 | |||
| 123 | struct sinfl { | ||
| 124 | const unsigned char *bitptr; | ||
| 125 | const unsigned char *bitend; // @raysan5: added | ||
| 126 | unsigned long long bitbuf; | ||
| 127 | int bitcnt; | ||
| 128 | |||
| 129 | unsigned lits[SINFL_LIT_TBL_SIZE]; | ||
| 130 | unsigned dsts[SINFL_OFF_TBL_SIZE]; | ||
| 131 | }; | ||
| 132 | extern int sinflate(void *out, int cap, const void *in, int size); | ||
| 133 | extern int zsinflate(void *out, int cap, const void *in, int size); | ||
| 134 | |||
| 135 | #ifdef __cplusplus | ||
| 136 | } | ||
| 137 | #endif | ||
| 138 | |||
| 139 | #endif /* SINFL_H_INCLUDED */ | ||
| 140 | |||
| 141 | #ifdef SINFL_IMPLEMENTATION | ||
| 142 | |||
| 143 | #include <string.h> /* memcpy, memset */ | ||
| 144 | #include <assert.h> /* assert */ | ||
| 145 | |||
| 146 | #if defined(__GNUC__) || defined(__clang__) | ||
| 147 | #define sinfl_likely(x) __builtin_expect((x),1) | ||
| 148 | #define sinfl_unlikely(x) __builtin_expect((x),0) | ||
| 149 | #else | ||
| 150 | #define sinfl_likely(x) (x) | ||
| 151 | #define sinfl_unlikely(x) (x) | ||
| 152 | #endif | ||
| 153 | |||
| 154 | #ifndef SINFL_NO_SIMD | ||
| 155 | #if defined(__x86_64__) || defined(_WIN32) || defined(_WIN64) | ||
| 156 | #include <emmintrin.h> | ||
| 157 | #define sinfl_char16 __m128i | ||
| 158 | #define sinfl_char16_ld(p) _mm_loadu_si128((const __m128i *)(void*)(p)) | ||
| 159 | #define sinfl_char16_str(d,v) _mm_storeu_si128((__m128i*)(void*)(d), v) | ||
| 160 | #define sinfl_char16_char(c) _mm_set1_epi8(c) | ||
| 161 | #elif defined(__arm__) || defined(__aarch64__) | ||
| 162 | #include <arm_neon.h> | ||
| 163 | #define sinfl_char16 uint8x16_t | ||
| 164 | #define sinfl_char16_ld(p) vld1q_u8((const unsigned char*)(p)) | ||
| 165 | #define sinfl_char16_str(d,v) vst1q_u8((unsigned char*)(d), v) | ||
| 166 | #define sinfl_char16_char(c) vdupq_n_u8(c) | ||
| 167 | #else | ||
| 168 | #define SINFL_NO_SIMD | ||
| 169 | #endif | ||
| 170 | #endif | ||
| 171 | |||
| 172 | static int | ||
| 173 | sinfl_bsr(unsigned n) { | ||
| 174 | #if defined(_MSC_VER) && !defined(__clang__) | ||
| 175 | _BitScanReverse(&n, n); | ||
| 176 | return n; | ||
| 177 | #elif defined(__GNUC__) || defined(__clang__) | ||
| 178 | return 31 - __builtin_clz(n); | ||
| 179 | #endif | ||
| 180 | } | ||
| 181 | static unsigned long long | ||
| 182 | sinfl_read64(const void *p) { | ||
| 183 | unsigned long long n; | ||
| 184 | memcpy(&n, p, 8); | ||
| 185 | return n; | ||
| 186 | } | ||
| 187 | static void | ||
| 188 | sinfl_copy64(unsigned char **dst, unsigned char **src) { | ||
| 189 | //unsigned long long n; | ||
| 190 | //memcpy(&n, *src, 8); | ||
| 191 | //memcpy(*dst, &n, 8); | ||
| 192 | memcpy(*dst, *src, 8); // @raysan5 | ||
| 193 | *dst += 8, *src += 8; | ||
| 194 | } | ||
| 195 | static unsigned char* | ||
| 196 | sinfl_write64(unsigned char *dst, unsigned long long w) { | ||
| 197 | memcpy(dst, &w, 8); | ||
| 198 | return dst + 8; | ||
| 199 | } | ||
| 200 | #ifndef SINFL_NO_SIMD | ||
| 201 | static unsigned char* | ||
| 202 | sinfl_write128(unsigned char *dst, sinfl_char16 w) { | ||
| 203 | sinfl_char16_str(dst, w); | ||
| 204 | return dst + 8; | ||
| 205 | } | ||
| 206 | static void | ||
| 207 | sinfl_copy128(unsigned char **dst, unsigned char **src) { | ||
| 208 | sinfl_char16 n = sinfl_char16_ld(*src); | ||
| 209 | sinfl_char16_str(*dst, n); | ||
| 210 | *dst += 16, *src += 16; | ||
| 211 | } | ||
| 212 | #endif | ||
| 213 | static void | ||
| 214 | sinfl_refill(struct sinfl *s) { | ||
| 215 | if (s->bitend - s->bitptr >= 8) { | ||
| 216 | // @raysan5: original code, only those 3 lines | ||
| 217 | s->bitbuf |= sinfl_read64(s->bitptr) << s->bitcnt; | ||
| 218 | s->bitptr += (63 - s->bitcnt) >> 3; | ||
| 219 | s->bitcnt |= 56; /* bitcount in range [56,63] */ | ||
| 220 | } else { | ||
| 221 | // @raysan5: added this case when bits remaining < 8 | ||
| 222 | int bitswant = 63 - s->bitcnt; | ||
| 223 | int byteswant = bitswant >> 3; | ||
| 224 | int bytesuse = s->bitend - s->bitptr <= byteswant ? (int)(s->bitend - s->bitptr) : byteswant; | ||
| 225 | unsigned long long n = 0; | ||
| 226 | memcpy(&n, s->bitptr, bytesuse); | ||
| 227 | s->bitbuf |= n << s->bitcnt; | ||
| 228 | s->bitptr += bytesuse; | ||
| 229 | s->bitcnt += bytesuse << 3; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | static int | ||
| 233 | sinfl_peek(struct sinfl *s, int cnt) { | ||
| 234 | //assert(cnt >= 0 && cnt <= 56); // @raysan5: commented to avoid crash on decompression | ||
| 235 | //assert(cnt <= s->bitcnt); | ||
| 236 | return s->bitbuf & ((1ull << cnt) - 1); | ||
| 237 | } | ||
| 238 | static void | ||
| 239 | sinfl_eat(struct sinfl *s, int cnt) { | ||
| 240 | //assert(cnt <= s->bitcnt); // @raysan5: commented | ||
| 241 | s->bitbuf >>= cnt; | ||
| 242 | s->bitcnt -= cnt; | ||
| 243 | } | ||
| 244 | static int | ||
| 245 | sinfl__get(struct sinfl *s, int cnt) { | ||
| 246 | int res = sinfl_peek(s, cnt); | ||
| 247 | sinfl_eat(s, cnt); | ||
| 248 | return res; | ||
| 249 | } | ||
| 250 | static int | ||
| 251 | sinfl_get(struct sinfl *s, int cnt) { | ||
| 252 | sinfl_refill(s); | ||
| 253 | return sinfl__get(s, cnt); | ||
| 254 | } | ||
| 255 | struct sinfl_gen { | ||
| 256 | int len; | ||
| 257 | int cnt; | ||
| 258 | int word; | ||
| 259 | short* sorted; | ||
| 260 | }; | ||
| 261 | static int | ||
| 262 | sinfl_build_tbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, | ||
| 263 | const int *cnt) { | ||
| 264 | int tbl_end = 0; | ||
| 265 | while (!(gen->cnt = cnt[gen->len])) { | ||
| 266 | ++gen->len; | ||
| 267 | } | ||
| 268 | tbl_end = 1 << gen->len; | ||
| 269 | while (gen->len <= tbl_bits) { | ||
| 270 | do {unsigned bit = 0; | ||
| 271 | tbl[gen->word] = (*gen->sorted++ << 16) | gen->len; | ||
| 272 | if (gen->word == tbl_end - 1) { | ||
| 273 | for (; gen->len < tbl_bits; gen->len++) { | ||
| 274 | memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0])); | ||
| 275 | tbl_end <<= 1; | ||
| 276 | } | ||
| 277 | return 1; | ||
| 278 | } | ||
| 279 | bit = 1 << sinfl_bsr((unsigned)(gen->word ^ (tbl_end - 1))); | ||
| 280 | gen->word &= bit - 1; | ||
| 281 | gen->word |= bit; | ||
| 282 | } while (--gen->cnt); | ||
| 283 | do { | ||
| 284 | if (++gen->len <= tbl_bits) { | ||
| 285 | memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0])); | ||
| 286 | tbl_end <<= 1; | ||
| 287 | } | ||
| 288 | } while (!(gen->cnt = cnt[gen->len])); | ||
| 289 | } | ||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | static void | ||
| 293 | sinfl_build_subtbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, | ||
| 294 | const int *cnt) { | ||
| 295 | int sub_bits = 0; | ||
| 296 | int sub_start = 0; | ||
| 297 | int sub_prefix = -1; | ||
| 298 | int tbl_end = 1 << tbl_bits; | ||
| 299 | while (1) { | ||
| 300 | unsigned entry; | ||
| 301 | int bit, stride, i; | ||
| 302 | /* start new sub-table */ | ||
| 303 | if ((gen->word & ((1 << tbl_bits)-1)) != sub_prefix) { | ||
| 304 | int used = 0; | ||
| 305 | sub_prefix = gen->word & ((1 << tbl_bits)-1); | ||
| 306 | sub_start = tbl_end; | ||
| 307 | sub_bits = gen->len - tbl_bits; | ||
| 308 | used = gen->cnt; | ||
| 309 | while (used < (1 << sub_bits)) { | ||
| 310 | sub_bits++; | ||
| 311 | used = (used << 1) + cnt[tbl_bits + sub_bits]; | ||
| 312 | } | ||
| 313 | tbl_end = sub_start + (1 << sub_bits); | ||
| 314 | tbl[sub_prefix] = (sub_start << 16) | 0x10 | (sub_bits & 0xf); | ||
| 315 | } | ||
| 316 | /* fill sub-table */ | ||
| 317 | entry = (*gen->sorted << 16) | ((gen->len - tbl_bits) & 0xf); | ||
| 318 | gen->sorted++; | ||
| 319 | i = sub_start + (gen->word >> tbl_bits); | ||
| 320 | stride = 1 << (gen->len - tbl_bits); | ||
| 321 | do { | ||
| 322 | tbl[i] = entry; | ||
| 323 | i += stride; | ||
| 324 | } while (i < tbl_end); | ||
| 325 | if (gen->word == (1 << gen->len)-1) { | ||
| 326 | return; | ||
| 327 | } | ||
| 328 | bit = 1 << sinfl_bsr(gen->word ^ ((1 << gen->len) - 1)); | ||
| 329 | gen->word &= bit - 1; | ||
| 330 | gen->word |= bit; | ||
| 331 | gen->cnt--; | ||
| 332 | while (!gen->cnt) { | ||
| 333 | gen->cnt = cnt[++gen->len]; | ||
| 334 | } | ||
| 335 | } | ||
| 336 | } | ||
| 337 | static void | ||
| 338 | sinfl_build(unsigned *tbl, unsigned char *lens, int tbl_bits, int maxlen, | ||
| 339 | int symcnt) { | ||
| 340 | int i, used = 0; | ||
| 341 | short sort[288]; | ||
| 342 | int cnt[16] = {0}, off[16]= {0}; | ||
| 343 | struct sinfl_gen gen = {0}; | ||
| 344 | gen.sorted = sort; | ||
| 345 | gen.len = 1; | ||
| 346 | |||
| 347 | for (i = 0; i < symcnt; ++i) | ||
| 348 | cnt[lens[i]]++; | ||
| 349 | off[1] = cnt[0]; | ||
| 350 | for (i = 1; i < maxlen; ++i) { | ||
| 351 | off[i + 1] = off[i] + cnt[i]; | ||
| 352 | used = (used << 1) + cnt[i]; | ||
| 353 | } | ||
| 354 | used = (used << 1) + cnt[i]; | ||
| 355 | for (i = 0; i < symcnt; ++i) | ||
| 356 | gen.sorted[off[lens[i]]++] = (short)i; | ||
| 357 | gen.sorted += off[0]; | ||
| 358 | |||
| 359 | if (used < (1 << maxlen)){ | ||
| 360 | for (i = 0; i < 1 << tbl_bits; ++i) | ||
| 361 | tbl[i] = (0 << 16u) | 1; | ||
| 362 | return; | ||
| 363 | } | ||
| 364 | if (!sinfl_build_tbl(&gen, tbl, tbl_bits, cnt)){ | ||
| 365 | sinfl_build_subtbl(&gen, tbl, tbl_bits, cnt); | ||
| 366 | } | ||
| 367 | } | ||
| 368 | static int | ||
| 369 | sinfl_decode(struct sinfl *s, const unsigned *tbl, int bit_len) { | ||
| 370 | int idx = sinfl_peek(s, bit_len); | ||
| 371 | unsigned key = tbl[idx]; | ||
| 372 | if (key & 0x10) { | ||
| 373 | /* sub-table lookup */ | ||
| 374 | int len = key & 0x0f; | ||
| 375 | sinfl_eat(s, bit_len); | ||
| 376 | idx = sinfl_peek(s, len); | ||
| 377 | key = tbl[((key >> 16) & 0xffff) + (unsigned)idx]; | ||
| 378 | } | ||
| 379 | sinfl_eat(s, key & 0x0f); | ||
| 380 | return (key >> 16) & 0x0fff; | ||
| 381 | } | ||
| 382 | static int | ||
| 383 | sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size) { | ||
| 384 | static const unsigned char order[] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; | ||
| 385 | static const short dbase[30+2] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, | ||
| 386 | 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; | ||
| 387 | static const unsigned char dbits[30+2] = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9, | ||
| 388 | 10,10,11,11,12,12,13,13,0,0}; | ||
| 389 | static const short lbase[29+2] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35, | ||
| 390 | 43,51,59,67,83,99,115,131,163,195,227,258,0,0}; | ||
| 391 | static const unsigned char lbits[29+2] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4, | ||
| 392 | 4,4,4,5,5,5,5,0,0,0}; | ||
| 393 | |||
| 394 | const unsigned char *oe = out + cap; | ||
| 395 | const unsigned char *e = in + size, *o = out; | ||
| 396 | enum sinfl_states {hdr,stored,fixed,dyn,blk}; | ||
| 397 | enum sinfl_states state = hdr; | ||
| 398 | struct sinfl s = {0}; | ||
| 399 | int last = 0; | ||
| 400 | |||
| 401 | s.bitptr = in; | ||
| 402 | s.bitend = e; // @raysan5: added | ||
| 403 | while (1) { | ||
| 404 | switch (state) { | ||
| 405 | case hdr: { | ||
| 406 | /* block header */ | ||
| 407 | int type = 0; | ||
| 408 | sinfl_refill(&s); | ||
| 409 | last = sinfl__get(&s,1); | ||
| 410 | type = sinfl__get(&s,2); | ||
| 411 | |||
| 412 | switch (type) {default: return (int)(out-o); | ||
| 413 | case 0x00: state = stored; break; | ||
| 414 | case 0x01: state = fixed; break; | ||
| 415 | case 0x02: state = dyn; break;} | ||
| 416 | } break; | ||
| 417 | case stored: { | ||
| 418 | /* uncompressed block */ | ||
| 419 | unsigned len, nlen; | ||
| 420 | sinfl__get(&s,s.bitcnt & 7); | ||
| 421 | len = (unsigned short)sinfl__get(&s,16); | ||
| 422 | nlen = (unsigned short)sinfl__get(&s,16); | ||
| 423 | s.bitptr -= s.bitcnt / 8; | ||
| 424 | s.bitbuf = s.bitcnt = 0; | ||
| 425 | |||
| 426 | if ((unsigned short)len != (unsigned short)~nlen) | ||
| 427 | return (int)(out-o); | ||
| 428 | if (len > (e - s.bitptr) || !len) | ||
| 429 | return (int)(out-o); | ||
| 430 | |||
| 431 | memcpy(out, s.bitptr, (size_t)len); | ||
| 432 | s.bitptr += len, out += len; | ||
| 433 | if (last) return (int)(out-o); | ||
| 434 | state = hdr; | ||
| 435 | } break; | ||
| 436 | case fixed: { | ||
| 437 | /* fixed huffman codes */ | ||
| 438 | int n; unsigned char lens[288+32]; | ||
| 439 | for (n = 0; n <= 143; n++) lens[n] = 8; | ||
| 440 | for (n = 144; n <= 255; n++) lens[n] = 9; | ||
| 441 | for (n = 256; n <= 279; n++) lens[n] = 7; | ||
| 442 | for (n = 280; n <= 287; n++) lens[n] = 8; | ||
| 443 | for (n = 0; n < 32; n++) lens[288+n] = 5; | ||
| 444 | |||
| 445 | /* build lit/dist tables */ | ||
| 446 | sinfl_build(s.lits, lens, 10, 15, 288); | ||
| 447 | sinfl_build(s.dsts, lens + 288, 8, 15, 32); | ||
| 448 | state = blk; | ||
| 449 | } break; | ||
| 450 | case dyn: { | ||
| 451 | /* dynamic huffman codes */ | ||
| 452 | int n, i; | ||
| 453 | unsigned hlens[SINFL_PRE_TBL_SIZE]; | ||
| 454 | unsigned char nlens[19] = {0}, lens[288+32]; | ||
| 455 | |||
| 456 | sinfl_refill(&s); | ||
| 457 | {int nlit = 257 + sinfl__get(&s,5); | ||
| 458 | int ndist = 1 + sinfl__get(&s,5); | ||
| 459 | int nlen = 4 + sinfl__get(&s,4); | ||
| 460 | for (n = 0; n < nlen; n++) | ||
| 461 | nlens[order[n]] = (unsigned char)sinfl_get(&s,3); | ||
| 462 | sinfl_build(hlens, nlens, 7, 7, 19); | ||
| 463 | |||
| 464 | /* decode code lengths */ | ||
| 465 | for (n = 0; n < nlit + ndist;) { | ||
| 466 | int sym = 0; | ||
| 467 | sinfl_refill(&s); | ||
| 468 | sym = sinfl_decode(&s, hlens, 7); | ||
| 469 | switch (sym) {default: lens[n++] = (unsigned char)sym; break; | ||
| 470 | case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break; | ||
| 471 | case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break; | ||
| 472 | case 18: for (i=11+sinfl_get(&s,7);i;i--,n++) lens[n]=0; break;} | ||
| 473 | } | ||
| 474 | /* build lit/dist tables */ | ||
| 475 | sinfl_build(s.lits, lens, 10, 15, nlit); | ||
| 476 | sinfl_build(s.dsts, lens + nlit, 8, 15, ndist); | ||
| 477 | state = blk;} | ||
| 478 | } break; | ||
| 479 | case blk: { | ||
| 480 | /* decompress block */ | ||
| 481 | while (1) { | ||
| 482 | int sym; | ||
| 483 | sinfl_refill(&s); | ||
| 484 | sym = sinfl_decode(&s, s.lits, 10); | ||
| 485 | if (sym < 256) { | ||
| 486 | /* literal */ | ||
| 487 | if (sinfl_unlikely(out >= oe)) { | ||
| 488 | return (int)(out-o); | ||
| 489 | } | ||
| 490 | *out++ = (unsigned char)sym; | ||
| 491 | sym = sinfl_decode(&s, s.lits, 10); | ||
| 492 | if (sym < 256) { | ||
| 493 | *out++ = (unsigned char)sym; | ||
| 494 | continue; | ||
| 495 | } | ||
| 496 | } | ||
| 497 | if (sinfl_unlikely(sym == 256)) { | ||
| 498 | /* end of block */ | ||
| 499 | if (last) return (int)(out-o); | ||
| 500 | state = hdr; | ||
| 501 | break; | ||
| 502 | } | ||
| 503 | /* match */ | ||
| 504 | if (sym >= 286) { | ||
| 505 | /* length codes 286 and 287 must not appear in compressed data */ | ||
| 506 | return (int)(out-o); | ||
| 507 | } | ||
| 508 | sym -= 257; | ||
| 509 | {int len = sinfl__get(&s, lbits[sym]) + lbase[sym]; | ||
| 510 | int dsym = sinfl_decode(&s, s.dsts, 8); | ||
| 511 | int offs = sinfl__get(&s, dbits[dsym]) + dbase[dsym]; | ||
| 512 | unsigned char *dst = out, *src = out - offs; | ||
| 513 | if (sinfl_unlikely(offs > (int)(out-o))) { | ||
| 514 | return (int)(out-o); | ||
| 515 | } | ||
| 516 | out = out + len; | ||
| 517 | |||
| 518 | #ifndef SINFL_NO_SIMD | ||
| 519 | if (sinfl_likely(oe - out >= 16 * 3)) { | ||
| 520 | if (offs >= 16) { | ||
| 521 | /* simd copy match */ | ||
| 522 | sinfl_copy128(&dst, &src); | ||
| 523 | sinfl_copy128(&dst, &src); | ||
| 524 | do sinfl_copy128(&dst, &src); | ||
| 525 | while (dst < out); | ||
| 526 | } else if (offs >= 8) { | ||
| 527 | /* word copy match */ | ||
| 528 | sinfl_copy64(&dst, &src); | ||
| 529 | sinfl_copy64(&dst, &src); | ||
| 530 | do sinfl_copy64(&dst, &src); | ||
| 531 | while (dst < out); | ||
| 532 | } else if (offs == 1) { | ||
| 533 | /* rle match copying */ | ||
| 534 | sinfl_char16 w = sinfl_char16_char(src[0]); | ||
| 535 | dst = sinfl_write128(dst, w); | ||
| 536 | dst = sinfl_write128(dst, w); | ||
| 537 | do dst = sinfl_write128(dst, w); | ||
| 538 | while (dst < out); | ||
| 539 | } else { | ||
| 540 | /* byte copy match */ | ||
| 541 | *dst++ = *src++; | ||
| 542 | *dst++ = *src++; | ||
| 543 | do *dst++ = *src++; | ||
| 544 | while (dst < out); | ||
| 545 | } | ||
| 546 | } | ||
| 547 | #else | ||
| 548 | if (sinfl_likely(oe - out >= 3 * 8 - 3)) { | ||
| 549 | if (offs >= 8) { | ||
| 550 | /* word copy match */ | ||
| 551 | sinfl_copy64(&dst, &src); | ||
| 552 | sinfl_copy64(&dst, &src); | ||
| 553 | do sinfl_copy64(&dst, &src); | ||
| 554 | while (dst < out); | ||
| 555 | } else if (offs == 1) { | ||
| 556 | /* rle match copying */ | ||
| 557 | unsigned int c = src[0]; | ||
| 558 | unsigned int hw = (c << 24u) | (c << 16u) | (c << 8u) | (unsigned)c; | ||
| 559 | unsigned long long w = (unsigned long long)hw << 32llu | hw; | ||
| 560 | dst = sinfl_write64(dst, w); | ||
| 561 | dst = sinfl_write64(dst, w); | ||
| 562 | do dst = sinfl_write64(dst, w); | ||
| 563 | while (dst < out); | ||
| 564 | } else { | ||
| 565 | /* byte copy match */ | ||
| 566 | *dst++ = *src++; | ||
| 567 | *dst++ = *src++; | ||
| 568 | do *dst++ = *src++; | ||
| 569 | while (dst < out); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | #endif | ||
| 573 | else { | ||
| 574 | *dst++ = *src++; | ||
| 575 | *dst++ = *src++; | ||
| 576 | do *dst++ = *src++; | ||
| 577 | while (dst < out); | ||
| 578 | }} | ||
| 579 | } | ||
| 580 | } break;} | ||
| 581 | } | ||
| 582 | return (int)(out-o); | ||
| 583 | } | ||
| 584 | extern int | ||
| 585 | sinflate(void *out, int cap, const void *in, int size) { | ||
| 586 | return sinfl_decompress((unsigned char*)out, cap, (const unsigned char*)in, size); | ||
| 587 | } | ||
| 588 | static unsigned | ||
| 589 | sinfl_adler32(unsigned adler32, const unsigned char *in, int in_len) { | ||
| 590 | const unsigned ADLER_MOD = 65521; | ||
| 591 | unsigned s1 = adler32 & 0xffff; | ||
| 592 | unsigned s2 = adler32 >> 16; | ||
| 593 | unsigned blk_len, i; | ||
| 594 | |||
| 595 | blk_len = in_len % 5552; | ||
| 596 | while (in_len) { | ||
| 597 | for (i=0; i + 7 < blk_len; i += 8) { | ||
| 598 | s1 += in[0]; s2 += s1; | ||
| 599 | s1 += in[1]; s2 += s1; | ||
| 600 | s1 += in[2]; s2 += s1; | ||
| 601 | s1 += in[3]; s2 += s1; | ||
| 602 | s1 += in[4]; s2 += s1; | ||
| 603 | s1 += in[5]; s2 += s1; | ||
| 604 | s1 += in[6]; s2 += s1; | ||
| 605 | s1 += in[7]; s2 += s1; | ||
| 606 | in += 8; | ||
| 607 | } | ||
| 608 | for (; i < blk_len; ++i) | ||
| 609 | s1 += *in++, s2 += s1; | ||
| 610 | s1 %= ADLER_MOD; s2 %= ADLER_MOD; | ||
| 611 | in_len -= blk_len; | ||
| 612 | blk_len = 5552; | ||
| 613 | } return (unsigned)(s2 << 16) + (unsigned)s1; | ||
| 614 | } | ||
| 615 | extern int | ||
| 616 | zsinflate(void *out, int cap, const void *mem, int size) { | ||
| 617 | const unsigned char *in = (const unsigned char*)mem; | ||
| 618 | if (size >= 6) { | ||
| 619 | const unsigned char *eob = in + size - 4; | ||
| 620 | int n = sinfl_decompress((unsigned char*)out, cap, in + 2u, size); | ||
| 621 | unsigned a = sinfl_adler32(1u, (unsigned char*)out, n); | ||
| 622 | unsigned h = eob[0] << 24 | eob[1] << 16 | eob[2] << 8 | eob[3] << 0; | ||
| 623 | return a == h ? n : -1; | ||
| 624 | } else { | ||
| 625 | return -1; | ||
| 626 | } | ||
| 627 | } | ||
| 628 | #endif | ||
| 629 | |||
