| Line | Branch | Exec | Source | 
    
      | 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 |  |  | unsigned long long bitbuf; | 
    
      | 126 |  |  | int bitcnt; | 
    
      | 127 |  |  |  | 
    
      | 128 |  |  | unsigned lits[SINFL_LIT_TBL_SIZE]; | 
    
      | 129 |  |  | unsigned dsts[SINFL_OFF_TBL_SIZE]; | 
    
      | 130 |  |  | }; | 
    
      | 131 |  |  | extern int sinflate(void *out, int cap, const void *in, int size); | 
    
      | 132 |  |  | extern int zsinflate(void *out, int cap, const void *in, int size); | 
    
      | 133 |  |  |  | 
    
      | 134 |  |  | #ifdef __cplusplus | 
    
      | 135 |  |  | } | 
    
      | 136 |  |  | #endif | 
    
      | 137 |  |  |  | 
    
      | 138 |  |  | #endif /* SINFL_H_INCLUDED */ | 
    
      | 139 |  |  |  | 
    
      | 140 |  |  | #ifdef SINFL_IMPLEMENTATION | 
    
      | 141 |  |  |  | 
    
      | 142 |  |  | #include <string.h> /* memcpy, memset */ | 
    
      | 143 |  |  | #include <assert.h> /* assert */ | 
    
      | 144 |  |  |  | 
    
      | 145 |  |  | #if defined(__GNUC__) || defined(__clang__) | 
    
      | 146 |  |  | #define sinfl_likely(x)       __builtin_expect((x),1) | 
    
      | 147 |  |  | #define sinfl_unlikely(x)     __builtin_expect((x),0) | 
    
      | 148 |  |  | #else | 
    
      | 149 |  |  | #define sinfl_likely(x)       (x) | 
    
      | 150 |  |  | #define sinfl_unlikely(x)     (x) | 
    
      | 151 |  |  | #endif | 
    
      | 152 |  |  |  | 
    
      | 153 |  |  | #ifndef SINFL_NO_SIMD | 
    
      | 154 |  |  | #if defined(__x86_64__) || defined(_WIN32) || defined(_WIN64) | 
    
      | 155 |  |  | #include <emmintrin.h> | 
    
      | 156 |  |  | #define sinfl_char16 __m128i | 
    
      | 157 |  |  | #define sinfl_char16_ld(p) _mm_loadu_si128((const __m128i *)(void*)(p)) | 
    
      | 158 |  |  | #define sinfl_char16_str(d,v)  _mm_storeu_si128((__m128i*)(void*)(d), v) | 
    
      | 159 |  |  | #define sinfl_char16_char(c) _mm_set1_epi8(c) | 
    
      | 160 |  |  | #elif defined(__arm__) || defined(__aarch64__) | 
    
      | 161 |  |  | #include <arm_neon.h> | 
    
      | 162 |  |  | #define sinfl_char16 uint8x16_t | 
    
      | 163 |  |  | #define sinfl_char16_ld(p) vld1q_u8((const unsigned char*)(p)) | 
    
      | 164 |  |  | #define sinfl_char16_str(d,v) vst1q_u8((unsigned char*)(d), v) | 
    
      | 165 |  |  | #define sinfl_char16_char(c) vdupq_n_u8(c) | 
    
      | 166 |  |  | #else | 
    
      | 167 |  |  | #define SINFL_NO_SIMD | 
    
      | 168 |  |  | #endif | 
    
      | 169 |  |  | #endif | 
    
      | 170 |  |  |  | 
    
      | 171 |  |  | static int | 
    
      | 172 |  |  | sinfl_bsr(unsigned n) { | 
    
      | 173 |  |  | #ifdef _MSC_VER | 
    
      | 174 |  |  | _BitScanReverse(&n, n); | 
    
      | 175 |  |  | return n; | 
    
      | 176 |  |  | #elif defined(__GNUC__) || defined(__clang__) | 
    
      | 177 |  | ✗ | return 31 - __builtin_clz(n); | 
    
      | 178 |  |  | #endif | 
    
      | 179 |  |  | } | 
    
      | 180 |  |  | static unsigned long long | 
    
      | 181 |  |  | sinfl_read64(const void *p) { | 
    
      | 182 |  |  | unsigned long long n; | 
    
      | 183 |  |  | memcpy(&n, p, 8); | 
    
      | 184 |  |  | return n; | 
    
      | 185 |  |  | } | 
    
      | 186 |  |  | static void | 
    
      | 187 |  | ✗ | sinfl_copy64(unsigned char **dst, unsigned char **src) { | 
    
      | 188 |  |  | unsigned long long n; | 
    
      | 189 |  | ✗ | memcpy(&n, *src, 8); | 
    
      | 190 |  | ✗ | memcpy(*dst, &n, 8); | 
    
      | 191 |  | ✗ | *dst += 8, *src += 8; | 
    
      | 192 |  |  | } | 
    
      | 193 |  |  | static unsigned char* | 
    
      | 194 |  |  | sinfl_write64(unsigned char *dst, unsigned long long w) { | 
    
      | 195 |  |  | memcpy(dst, &w, 8); | 
    
      | 196 |  | ✗ | return dst + 8; | 
    
      | 197 |  |  | } | 
    
      | 198 |  |  | #ifndef SINFL_NO_SIMD | 
    
      | 199 |  |  | static unsigned char* | 
    
      | 200 |  |  | sinfl_write128(unsigned char *dst, sinfl_char16 w) { | 
    
      | 201 |  |  | sinfl_char16_str(dst, w); | 
    
      | 202 |  |  | return dst + 8; | 
    
      | 203 |  |  | } | 
    
      | 204 |  |  | static void | 
    
      | 205 |  |  | sinfl_copy128(unsigned char **dst, unsigned char **src) { | 
    
      | 206 |  |  | sinfl_char16 n = sinfl_char16_ld(*src); | 
    
      | 207 |  |  | sinfl_char16_str(*dst, n); | 
    
      | 208 |  |  | *dst += 16, *src += 16; | 
    
      | 209 |  |  | } | 
    
      | 210 |  |  | #endif | 
    
      | 211 |  |  | static void | 
    
      | 212 |  |  | sinfl_refill(struct sinfl *s) { | 
    
      | 213 |  | ✗ | s->bitbuf |= sinfl_read64(s->bitptr) << s->bitcnt; | 
    
      | 214 |  | ✗ | s->bitptr += (63 - s->bitcnt) >> 3; | 
    
      | 215 |  | ✗ | s->bitcnt |= 56; /* bitcount in range [56,63] */ | 
    
      | 216 |  |  | } | 
    
      | 217 |  |  | static int | 
    
      | 218 |  |  | sinfl_peek(struct sinfl *s, int cnt) { | 
    
      | 219 |  |  | assert(cnt >= 0 && cnt <= 56); | 
    
      | 220 |  |  | assert(cnt <= s->bitcnt); | 
    
      | 221 |  | ✗ | return s->bitbuf & ((1ull << cnt) - 1); | 
    
      | 222 |  |  | } | 
    
      | 223 |  |  | static void | 
    
      | 224 |  |  | sinfl_eat(struct sinfl *s, int cnt) { | 
    
      | 225 |  |  | assert(cnt <= s->bitcnt); | 
    
      | 226 |  | ✗ | s->bitbuf >>= cnt; | 
    
      | 227 |  | ✗ | s->bitcnt -= cnt; | 
    
      | 228 |  |  | } | 
    
      | 229 |  |  | static int | 
    
      | 230 |  |  | sinfl__get(struct sinfl *s, int cnt) { | 
    
      | 231 |  |  | int res = sinfl_peek(s, cnt); | 
    
      | 232 |  |  | sinfl_eat(s, cnt); | 
    
      | 233 |  |  | return res; | 
    
      | 234 |  |  | } | 
    
      | 235 |  |  | static int | 
    
      | 236 |  |  | sinfl_get(struct sinfl *s, int cnt) { | 
    
      | 237 |  |  | sinfl_refill(s); | 
    
      | 238 |  |  | return sinfl__get(s, cnt); | 
    
      | 239 |  |  | } | 
    
      | 240 |  |  | struct sinfl_gen { | 
    
      | 241 |  |  | int len; | 
    
      | 242 |  |  | int cnt; | 
    
      | 243 |  |  | int word; | 
    
      | 244 |  |  | short* sorted; | 
    
      | 245 |  |  | }; | 
    
      | 246 |  |  | static int | 
    
      | 247 |  | ✗ | sinfl_build_tbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, | 
    
      | 248 |  |  | const int *cnt) { | 
    
      | 249 |  |  | int tbl_end = 0; | 
    
      | 250 |  | ✗ | while (!(gen->cnt = cnt[gen->len])) { | 
    
      | 251 |  | ✗ | ++gen->len; | 
    
      | 252 |  |  | } | 
    
      | 253 |  | ✗ | tbl_end = 1 << gen->len; | 
    
      | 254 |  | ✗ | while (gen->len <= tbl_bits) { | 
    
      | 255 |  |  | do {unsigned bit = 0; | 
    
      | 256 |  | ✗ | tbl[gen->word] = (*gen->sorted++ << 16) | gen->len; | 
    
      | 257 |  | ✗ | if (gen->word == tbl_end - 1) { | 
    
      | 258 |  | ✗ | for (; gen->len < tbl_bits; gen->len++) { | 
    
      | 259 |  | ✗ | memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0])); | 
    
      | 260 |  | ✗ | tbl_end <<= 1; | 
    
      | 261 |  |  | } | 
    
      | 262 |  |  | return 1; | 
    
      | 263 |  |  | } | 
    
      | 264 |  | ✗ | bit = 1 << sinfl_bsr((unsigned)(gen->word ^ (tbl_end - 1))); | 
    
      | 265 |  | ✗ | gen->word &= bit - 1; | 
    
      | 266 |  | ✗ | gen->word |= bit; | 
    
      | 267 |  | ✗ | } while (--gen->cnt); | 
    
      | 268 |  |  | do { | 
    
      | 269 |  | ✗ | if (++gen->len <= tbl_bits) { | 
    
      | 270 |  | ✗ | memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0])); | 
    
      | 271 |  | ✗ | tbl_end <<= 1; | 
    
      | 272 |  |  | } | 
    
      | 273 |  | ✗ | } while (!(gen->cnt = cnt[gen->len])); | 
    
      | 274 |  |  | } | 
    
      | 275 |  |  | return 0; | 
    
      | 276 |  |  | } | 
    
      | 277 |  |  | static void | 
    
      | 278 |  | ✗ | sinfl_build_subtbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, | 
    
      | 279 |  |  | const int *cnt) { | 
    
      | 280 |  |  | int sub_bits = 0; | 
    
      | 281 |  |  | int sub_start = 0; | 
    
      | 282 |  |  | int sub_prefix = -1; | 
    
      | 283 |  | ✗ | int tbl_end = 1 << tbl_bits; | 
    
      | 284 |  |  | while (1) { | 
    
      | 285 |  |  | unsigned entry; | 
    
      | 286 |  |  | int bit, stride, i; | 
    
      | 287 |  |  | /* start new sub-table */ | 
    
      | 288 |  | ✗ | if ((gen->word & ((1 << tbl_bits)-1)) != sub_prefix) { | 
    
      | 289 |  |  | int used = 0; | 
    
      | 290 |  |  | sub_prefix = gen->word & ((1 << tbl_bits)-1); | 
    
      | 291 |  |  | sub_start = tbl_end; | 
    
      | 292 |  | ✗ | sub_bits = gen->len - tbl_bits; | 
    
      | 293 |  | ✗ | used = gen->cnt; | 
    
      | 294 |  | ✗ | while (used < (1 << sub_bits)) { | 
    
      | 295 |  | ✗ | sub_bits++; | 
    
      | 296 |  | ✗ | used = (used << 1) + cnt[tbl_bits + sub_bits]; | 
    
      | 297 |  |  | } | 
    
      | 298 |  | ✗ | tbl_end = sub_start + (1 << sub_bits); | 
    
      | 299 |  | ✗ | tbl[sub_prefix] = (sub_start << 16) | 0x10 | (sub_bits & 0xf); | 
    
      | 300 |  |  | } | 
    
      | 301 |  |  | /* fill sub-table */ | 
    
      | 302 |  | ✗ | entry = (*gen->sorted << 16) | ((gen->len - tbl_bits) & 0xf); | 
    
      | 303 |  | ✗ | gen->sorted++; | 
    
      | 304 |  | ✗ | i = sub_start + (gen->word >> tbl_bits); | 
    
      | 305 |  | ✗ | stride = 1 << (gen->len - tbl_bits); | 
    
      | 306 |  |  | do { | 
    
      | 307 |  | ✗ | tbl[i] = entry; | 
    
      | 308 |  | ✗ | i += stride; | 
    
      | 309 |  | ✗ | } while (i < tbl_end); | 
    
      | 310 |  | ✗ | if (gen->word == (1 << gen->len)-1) { | 
    
      | 311 |  | ✗ | return; | 
    
      | 312 |  |  | } | 
    
      | 313 |  | ✗ | bit = 1 << sinfl_bsr(gen->word ^ ((1 << gen->len) - 1)); | 
    
      | 314 |  | ✗ | gen->word &= bit - 1; | 
    
      | 315 |  | ✗ | gen->word |= bit; | 
    
      | 316 |  | ✗ | gen->cnt--; | 
    
      | 317 |  | ✗ | while (!gen->cnt) { | 
    
      | 318 |  | ✗ | gen->cnt = cnt[++gen->len]; | 
    
      | 319 |  |  | } | 
    
      | 320 |  |  | } | 
    
      | 321 |  |  | } | 
    
      | 322 |  |  | static void | 
    
      | 323 |  | ✗ | sinfl_build(unsigned *tbl, unsigned char *lens, int tbl_bits, int maxlen, | 
    
      | 324 |  |  | int symcnt) { | 
    
      | 325 |  |  | int i, used = 0; | 
    
      | 326 |  |  | short sort[288]; | 
    
      | 327 |  | ✗ | int cnt[16] = {0}, off[16]= {0}; | 
    
      | 328 |  | ✗ | struct sinfl_gen gen = {0}; | 
    
      | 329 |  |  | gen.sorted = sort; | 
    
      | 330 |  | ✗ | gen.len = 1; | 
    
      | 331 |  |  |  | 
    
      | 332 |  | ✗ | for (i = 0; i < symcnt; ++i) | 
    
      | 333 |  | ✗ | cnt[lens[i]]++; | 
    
      | 334 |  | ✗ | off[1] = cnt[0]; | 
    
      | 335 |  | ✗ | for (i = 1; i < maxlen; ++i) { | 
    
      | 336 |  | ✗ | off[i + 1] = off[i] + cnt[i]; | 
    
      | 337 |  | ✗ | used = (used << 1) + cnt[i]; | 
    
      | 338 |  |  | } | 
    
      | 339 |  | ✗ | used = (used << 1) + cnt[i]; | 
    
      | 340 |  | ✗ | for (i = 0; i < symcnt; ++i) | 
    
      | 341 |  | ✗ | gen.sorted[off[lens[i]]++] = (short)i; | 
    
      | 342 |  | ✗ | gen.sorted += off[0]; | 
    
      | 343 |  |  |  | 
    
      | 344 |  | ✗ | if (used < (1 << maxlen)){ | 
    
      | 345 |  | ✗ | for (i = 0; i < 1 << tbl_bits; ++i) | 
    
      | 346 |  | ✗ | tbl[i] = (0 << 16u) | 1; | 
    
      | 347 |  | ✗ | return; | 
    
      | 348 |  |  | } | 
    
      | 349 |  | ✗ | if (!sinfl_build_tbl(&gen, tbl, tbl_bits, cnt)){ | 
    
      | 350 |  | ✗ | sinfl_build_subtbl(&gen, tbl, tbl_bits, cnt); | 
    
      | 351 |  |  | } | 
    
      | 352 |  |  | } | 
    
      | 353 |  |  | static int | 
    
      | 354 |  | ✗ | sinfl_decode(struct sinfl *s, const unsigned *tbl, int bit_len) { | 
    
      | 355 |  |  | int idx = sinfl_peek(s, bit_len); | 
    
      | 356 |  | ✗ | unsigned key = tbl[idx]; | 
    
      | 357 |  | ✗ | if (key & 0x10) { | 
    
      | 358 |  |  | /* sub-table lookup */ | 
    
      | 359 |  | ✗ | int len = key & 0x0f; | 
    
      | 360 |  |  | sinfl_eat(s, bit_len); | 
    
      | 361 |  |  | idx = sinfl_peek(s, len); | 
    
      | 362 |  | ✗ | key = tbl[((key >> 16) & 0xffff) + (unsigned)idx]; | 
    
      | 363 |  |  | } | 
    
      | 364 |  | ✗ | sinfl_eat(s, key & 0x0f); | 
    
      | 365 |  | ✗ | return (key >> 16) & 0x0fff; | 
    
      | 366 |  |  | } | 
    
      | 367 |  |  | static int | 
    
      | 368 |  | ✗ | sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size) { | 
    
      | 369 |  |  | static const unsigned char order[] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; | 
    
      | 370 |  |  | static const short dbase[30+2] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, | 
    
      | 371 |  |  | 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; | 
    
      | 372 |  |  | 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, | 
    
      | 373 |  |  | 10,10,11,11,12,12,13,13,0,0}; | 
    
      | 374 |  |  | static const short lbase[29+2] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35, | 
    
      | 375 |  |  | 43,51,59,67,83,99,115,131,163,195,227,258,0,0}; | 
    
      | 376 |  |  | 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, | 
    
      | 377 |  |  | 4,4,4,5,5,5,5,0,0,0}; | 
    
      | 378 |  |  |  | 
    
      | 379 |  | ✗ | const unsigned char *oe = out + cap; | 
    
      | 380 |  | ✗ | const unsigned char *e = in + size, *o = out; | 
    
      | 381 |  |  | enum sinfl_states {hdr,stored,fixed,dyn,blk}; | 
    
      | 382 |  |  | enum sinfl_states state = hdr; | 
    
      | 383 |  | ✗ | struct sinfl s = {0}; | 
    
      | 384 |  |  | int last = 0; | 
    
      | 385 |  |  |  | 
    
      | 386 |  | ✗ | s.bitptr = in; | 
    
      | 387 |  |  | while (1) { | 
    
      | 388 |  | ✗ | switch (state) { | 
    
      | 389 |  | ✗ | case hdr: { | 
    
      | 390 |  |  | /* block header */ | 
    
      | 391 |  |  | int type = 0; | 
    
      | 392 |  |  | sinfl_refill(&s); | 
    
      | 393 |  |  | last = sinfl__get(&s,1); | 
    
      | 394 |  |  | type = sinfl__get(&s,2); | 
    
      | 395 |  |  |  | 
    
      | 396 |  | ✗ | switch (type) {default: return (int)(out-o); | 
    
      | 397 |  |  | case 0x00: state = stored; break; | 
    
      | 398 |  | ✗ | case 0x01: state = fixed; break; | 
    
      | 399 |  | ✗ | case 0x02: state = dyn; break;} | 
    
      | 400 |  |  | } break; | 
    
      | 401 |  | ✗ | case stored: { | 
    
      | 402 |  |  | /* uncompressed block */ | 
    
      | 403 |  |  | unsigned len, nlen; | 
    
      | 404 |  | ✗ | sinfl__get(&s,s.bitcnt & 7); | 
    
      | 405 |  | ✗ | len = (unsigned short)sinfl__get(&s,16); | 
    
      | 406 |  | ✗ | nlen = (unsigned short)sinfl__get(&s,16); | 
    
      | 407 |  | ✗ | s.bitptr -= s.bitcnt / 8; | 
    
      | 408 |  | ✗ | s.bitbuf = s.bitcnt = 0; | 
    
      | 409 |  |  |  | 
    
      | 410 |  | ✗ | if ((unsigned short)len != (unsigned short)~nlen) | 
    
      | 411 |  | ✗ | return (int)(out-o); | 
    
      | 412 |  | ✗ | if (len > (e - s.bitptr) || !len) | 
    
      | 413 |  | ✗ | return (int)(out-o); | 
    
      | 414 |  |  |  | 
    
      | 415 |  |  | memcpy(out, s.bitptr, (size_t)len); | 
    
      | 416 |  | ✗ | s.bitptr += len, out += len; | 
    
      | 417 |  | ✗ | if (last) return (int)(out-o); | 
    
      | 418 |  |  | state = hdr; | 
    
      | 419 |  |  | } break; | 
    
      | 420 |  |  | case fixed: { | 
    
      | 421 |  |  | /* fixed huffman codes */ | 
    
      | 422 |  |  | int n; unsigned char lens[288+32]; | 
    
      | 423 |  | ✗ | for (n = 0; n <= 143; n++) lens[n] = 8; | 
    
      | 424 |  | ✗ | for (n = 144; n <= 255; n++) lens[n] = 9; | 
    
      | 425 |  | ✗ | for (n = 256; n <= 279; n++) lens[n] = 7; | 
    
      | 426 |  | ✗ | for (n = 280; n <= 287; n++) lens[n] = 8; | 
    
      | 427 |  | ✗ | for (n = 0; n < 32; n++) lens[288+n] = 5; | 
    
      | 428 |  |  |  | 
    
      | 429 |  |  | /* build lit/dist tables */ | 
    
      | 430 |  | ✗ | sinfl_build(s.lits, lens, 10, 15, 288); | 
    
      | 431 |  | ✗ | sinfl_build(s.dsts, lens + 288, 8, 15, 32); | 
    
      | 432 |  |  | state = blk; | 
    
      | 433 |  | ✗ | } break; | 
    
      | 434 |  | ✗ | case dyn: { | 
    
      | 435 |  |  | /* dynamic huffman codes */ | 
    
      | 436 |  |  | int n, i; | 
    
      | 437 |  |  | unsigned hlens[SINFL_PRE_TBL_SIZE]; | 
    
      | 438 |  | ✗ | unsigned char nlens[19] = {0}, lens[288+32]; | 
    
      | 439 |  |  |  | 
    
      | 440 |  |  | sinfl_refill(&s); | 
    
      | 441 |  | ✗ | {int nlit = 257 + sinfl__get(&s,5); | 
    
      | 442 |  | ✗ | int ndist = 1 + sinfl__get(&s,5); | 
    
      | 443 |  | ✗ | int nlen = 4 + sinfl__get(&s,4); | 
    
      | 444 |  | ✗ | for (n = 0; n < nlen; n++) | 
    
      | 445 |  | ✗ | nlens[order[n]] = (unsigned char)sinfl_get(&s,3); | 
    
      | 446 |  | ✗ | sinfl_build(hlens, nlens, 7, 7, 19); | 
    
      | 447 |  |  |  | 
    
      | 448 |  |  | /* decode code lengths */ | 
    
      | 449 |  | ✗ | for (n = 0; n < nlit + ndist;) { | 
    
      | 450 |  |  | int sym = 0; | 
    
      | 451 |  |  | sinfl_refill(&s); | 
    
      | 452 |  | ✗ | sym = sinfl_decode(&s, hlens, 7); | 
    
      | 453 |  | ✗ | switch (sym) {default: lens[n++] = (unsigned char)sym; break; | 
    
      | 454 |  | ✗ | case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break; | 
    
      | 455 |  | ✗ | case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break; | 
    
      | 456 |  | ✗ | case 18: for (i=11+sinfl_get(&s,7);i;i--,n++) lens[n]=0; break;} | 
    
      | 457 |  |  | } | 
    
      | 458 |  |  | /* build lit/dist tables */ | 
    
      | 459 |  | ✗ | sinfl_build(s.lits, lens, 10, 15, nlit); | 
    
      | 460 |  | ✗ | sinfl_build(s.dsts, lens + nlit, 8, 15, ndist); | 
    
      | 461 |  |  | state = blk;} | 
    
      | 462 |  | ✗ | } break; | 
    
      | 463 |  |  | case blk: { | 
    
      | 464 |  |  | /* decompress block */ | 
    
      | 465 |  |  | while (1) { | 
    
      | 466 |  |  | int sym; | 
    
      | 467 |  |  | sinfl_refill(&s); | 
    
      | 468 |  | ✗ | sym = sinfl_decode(&s, s.lits, 10); | 
    
      | 469 |  | ✗ | if (sym < 256) { | 
    
      | 470 |  |  | /* literal */ | 
    
      | 471 |  | ✗ | if (sinfl_unlikely(out >= oe)) { | 
    
      | 472 |  | ✗ | return (int)(out-o); | 
    
      | 473 |  |  | } | 
    
      | 474 |  | ✗ | *out++ = (unsigned char)sym; | 
    
      | 475 |  | ✗ | sym = sinfl_decode(&s, s.lits, 10); | 
    
      | 476 |  | ✗ | if (sym < 256) { | 
    
      | 477 |  | ✗ | *out++ = (unsigned char)sym; | 
    
      | 478 |  | ✗ | continue; | 
    
      | 479 |  |  | } | 
    
      | 480 |  |  | } | 
    
      | 481 |  | ✗ | if (sinfl_unlikely(sym == 256)) { | 
    
      | 482 |  |  | /* end of block */ | 
    
      | 483 |  | ✗ | if (last) return (int)(out-o); | 
    
      | 484 |  |  | state = hdr; | 
    
      | 485 |  |  | break; | 
    
      | 486 |  |  | } | 
    
      | 487 |  |  | /* match */ | 
    
      | 488 |  | ✗ | if (sym >= 286) { | 
    
      | 489 |  |  | /* length codes 286 and 287 must not appear in compressed data */ | 
    
      | 490 |  | ✗ | return (int)(out-o); | 
    
      | 491 |  |  | } | 
    
      | 492 |  | ✗ | sym -= 257; | 
    
      | 493 |  | ✗ | {int len = sinfl__get(&s, lbits[sym]) + lbase[sym]; | 
    
      | 494 |  | ✗ | int dsym = sinfl_decode(&s, s.dsts, 8); | 
    
      | 495 |  | ✗ | int offs = sinfl__get(&s, dbits[dsym]) + dbase[dsym]; | 
    
      | 496 |  | ✗ | unsigned char *dst = out, *src = out - offs; | 
    
      | 497 |  | ✗ | if (sinfl_unlikely(offs > (int)(out-o))) { | 
    
      | 498 |  | ✗ | return (int)(out-o); | 
    
      | 499 |  |  | } | 
    
      | 500 |  | ✗ | out = out + len; | 
    
      | 501 |  |  |  | 
    
      | 502 |  |  | #ifndef SINFL_NO_SIMD | 
    
      | 503 |  |  | if (sinfl_likely(oe - out >= 16 * 3)) { | 
    
      | 504 |  |  | if (offs >= 16) { | 
    
      | 505 |  |  | /* simd copy match */ | 
    
      | 506 |  |  | sinfl_copy128(&dst, &src); | 
    
      | 507 |  |  | sinfl_copy128(&dst, &src); | 
    
      | 508 |  |  | do sinfl_copy128(&dst, &src); | 
    
      | 509 |  |  | while (dst < out); | 
    
      | 510 |  |  | } else if (offs >= 8) { | 
    
      | 511 |  |  | /* word copy match */ | 
    
      | 512 |  |  | sinfl_copy64(&dst, &src); | 
    
      | 513 |  |  | sinfl_copy64(&dst, &src); | 
    
      | 514 |  |  | do sinfl_copy64(&dst, &src); | 
    
      | 515 |  |  | while (dst < out); | 
    
      | 516 |  |  | } else if (offs == 1) { | 
    
      | 517 |  |  | /* rle match copying */ | 
    
      | 518 |  |  | sinfl_char16 w = sinfl_char16_char(src[0]); | 
    
      | 519 |  |  | dst = sinfl_write128(dst, w); | 
    
      | 520 |  |  | dst = sinfl_write128(dst, w); | 
    
      | 521 |  |  | do dst = sinfl_write128(dst, w); | 
    
      | 522 |  |  | while (dst < out); | 
    
      | 523 |  |  | } else { | 
    
      | 524 |  |  | /* byte copy match */ | 
    
      | 525 |  |  | *dst++ = *src++; | 
    
      | 526 |  |  | *dst++ = *src++; | 
    
      | 527 |  |  | do *dst++ = *src++; | 
    
      | 528 |  |  | while (dst < out); | 
    
      | 529 |  |  | } | 
    
      | 530 |  |  | } | 
    
      | 531 |  |  | #else | 
    
      | 532 |  | ✗ | if (sinfl_likely(oe - out >= 3 * 8 - 3)) { | 
    
      | 533 |  | ✗ | if (offs >= 8) { | 
    
      | 534 |  |  | /* word copy match */ | 
    
      | 535 |  | ✗ | sinfl_copy64(&dst, &src); | 
    
      | 536 |  | ✗ | sinfl_copy64(&dst, &src); | 
    
      | 537 |  | ✗ | do sinfl_copy64(&dst, &src); | 
    
      | 538 |  | ✗ | while (dst < out); | 
    
      | 539 |  | ✗ | } else if (offs == 1) { | 
    
      | 540 |  |  | /* rle match copying */ | 
    
      | 541 |  | ✗ | unsigned int c = src[0]; | 
    
      | 542 |  | ✗ | unsigned int hw = (c << 24u) | (c << 16u) | (c << 8u) | (unsigned)c; | 
    
      | 543 |  | ✗ | unsigned long long w = (unsigned long long)hw << 32llu | hw; | 
    
      | 544 |  | ✗ | dst = sinfl_write64(dst, w); | 
    
      | 545 |  | ✗ | dst = sinfl_write64(dst, w); | 
    
      | 546 |  | ✗ | do dst = sinfl_write64(dst, w); | 
    
      | 547 |  | ✗ | while (dst < out); | 
    
      | 548 |  |  | } else { | 
    
      | 549 |  |  | /* byte copy match */ | 
    
      | 550 |  | ✗ | *dst++ = *src++; | 
    
      | 551 |  | ✗ | *dst++ = *src++; | 
    
      | 552 |  | ✗ | do *dst++ = *src++; | 
    
      | 553 |  | ✗ | while (dst < out); | 
    
      | 554 |  |  | } | 
    
      | 555 |  |  | } | 
    
      | 556 |  |  | #endif | 
    
      | 557 |  |  | else { | 
    
      | 558 |  | ✗ | *dst++ = *src++; | 
    
      | 559 |  | ✗ | *dst++ = *src++; | 
    
      | 560 |  | ✗ | do *dst++ = *src++; | 
    
      | 561 |  | ✗ | while (dst < out); | 
    
      | 562 |  |  | }} | 
    
      | 563 |  |  | } | 
    
      | 564 |  |  | } break;} | 
    
      | 565 |  |  | } | 
    
      | 566 |  |  | return (int)(out-o); | 
    
      | 567 |  |  | } | 
    
      | 568 |  |  | extern int | 
    
      | 569 |  | ✗ | sinflate(void *out, int cap, const void *in, int size) { | 
    
      | 570 |  | ✗ | return sinfl_decompress((unsigned char*)out, cap, (const unsigned char*)in, size); | 
    
      | 571 |  |  | } | 
    
      | 572 |  |  | static unsigned | 
    
      | 573 |  | ✗ | sinfl_adler32(unsigned adler32, const unsigned char *in, int in_len) { | 
    
      | 574 |  |  | const unsigned ADLER_MOD = 65521; | 
    
      | 575 |  | ✗ | unsigned s1 = adler32 & 0xffff; | 
    
      | 576 |  | ✗ | unsigned s2 = adler32 >> 16; | 
    
      | 577 |  |  | unsigned blk_len, i; | 
    
      | 578 |  |  |  | 
    
      | 579 |  | ✗ | blk_len = in_len % 5552; | 
    
      | 580 |  | ✗ | while (in_len) { | 
    
      | 581 |  | ✗ | for (i=0; i + 7 < blk_len; i += 8) { | 
    
      | 582 |  | ✗ | s1 += in[0]; s2 += s1; | 
    
      | 583 |  | ✗ | s1 += in[1]; s2 += s1; | 
    
      | 584 |  | ✗ | s1 += in[2]; s2 += s1; | 
    
      | 585 |  | ✗ | s1 += in[3]; s2 += s1; | 
    
      | 586 |  | ✗ | s1 += in[4]; s2 += s1; | 
    
      | 587 |  | ✗ | s1 += in[5]; s2 += s1; | 
    
      | 588 |  | ✗ | s1 += in[6]; s2 += s1; | 
    
      | 589 |  | ✗ | s1 += in[7]; s2 += s1; | 
    
      | 590 |  | ✗ | in += 8; | 
    
      | 591 |  |  | } | 
    
      | 592 |  | ✗ | for (; i < blk_len; ++i) | 
    
      | 593 |  | ✗ | s1 += *in++, s2 += s1; | 
    
      | 594 |  | ✗ | s1 %= ADLER_MOD; s2 %= ADLER_MOD; | 
    
      | 595 |  | ✗ | in_len -= blk_len; | 
    
      | 596 |  |  | blk_len = 5552; | 
    
      | 597 |  | ✗ | } return (unsigned)(s2 << 16) + (unsigned)s1; | 
    
      | 598 |  |  | } | 
    
      | 599 |  |  | extern int | 
    
      | 600 |  | ✗ | zsinflate(void *out, int cap, const void *mem, int size) { | 
    
      | 601 |  |  | const unsigned char *in = (const unsigned char*)mem; | 
    
      | 602 |  | ✗ | if (size >= 6) { | 
    
      | 603 |  | ✗ | const unsigned char *eob = in + size - 4; | 
    
      | 604 |  | ✗ | int n = sinfl_decompress((unsigned char*)out, cap, in + 2u, size); | 
    
      | 605 |  | ✗ | unsigned a = sinfl_adler32(1u, (unsigned char*)out, n); | 
    
      | 606 |  | ✗ | unsigned h = eob[0] << 24 | eob[1] << 16 | eob[2] << 8 | eob[3] << 0; | 
    
      | 607 |  | ✗ | return a == h ? n : -1; | 
    
      | 608 |  |  | } else { | 
    
      | 609 |  |  | return -1; | 
    
      | 610 |  |  | } | 
    
      | 611 |  |  | } | 
    
      | 612 |  |  | #endif | 
    
      | 613 |  |  |  | 
    
      | 614 |  |  |  |