minesweeper

A minewseeper implementation to play around with Hare and Raylib
git clone https://git.tronto.net/minesweeper
Download | Log | Files | Refs | README | LICENSE

sinfl.h (21581B)


      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