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