github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/sinfl.h (about)

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