1 /* 2 * tinflate - tiny inflate 3 * 4 * Copyright (c) 2003 by Joergen Ibsen / Jibz 5 * All Rights Reserved 6 * 7 * http://www.ibsensoftware.com/ 8 * 9 * This software is provided 'as-is', without any express 10 * or implied warranty. In no event will the authors be 11 * held liable for any damages arising from the use of 12 * this software. 13 * 14 * Permission is granted to anyone to use this software 15 * for any purpose, including commercial applications, 16 * and to alter it and redistribute it freely, subject to 17 * the following restrictions: 18 * 19 * 1. The origin of this software must not be 20 * misrepresented; you must not claim that you 21 * wrote the original software. If you use this 22 * software in a product, an acknowledgment in 23 * the product documentation would be appreciated 24 * but is not required. 25 * 26 * 2. Altered source versions must be plainly marked 27 * as such, and must not be misrepresented as 28 * being the original software. 29 * 30 * 3. This notice may not be removed or altered from 31 * any source distribution. 32 */ 33 module npp_mimetools.tinflate; 34 35 36 //#ifdef __WATCOMC__ 37 // enum TINFCC = __cdecl; 38 //#else 39 // #define TINFCC 40 //#endif 41 42 extern(C): 43 44 enum TINF_OK = 0; 45 enum TINF_DATA_ERROR = -3; 46 47 /* ------------------------------ * 48 * -- internal data structures -- * 49 * ------------------------------ */ 50 51 struct TINF_TREE 52 { 53 /** 54 * table of code length counts 55 */ 56 ushort[16] table; 57 58 /** 59 * code -> symbol translation table 60 */ 61 ushort[288] trans; 62 } 63 64 struct TINF_DATA 65 { 66 const (ubyte)* source; 67 uint tag; 68 uint bitcount; 69 70 ubyte* dest; 71 uint destLen; 72 73 /** 74 * dynamic length/symbol tree 75 */ 76 .TINF_TREE ltree; 77 78 /** 79 * dynamic distance tree 80 */ 81 .TINF_TREE dtree; 82 } 83 84 /* --------------------------------------------------- * 85 * -- uninitialized global data (static structures) -- * 86 * --------------------------------------------------- */ 87 88 /** 89 * fixed length/symbol tree 90 */ 91 .TINF_TREE sltree; 92 93 /** 94 * fixed distance tree 95 */ 96 .TINF_TREE sdtree; 97 98 /* extra bits and base tables for length codes */ 99 ubyte[30] length_bits; 100 ushort[30] length_base; 101 102 /* extra bits and base tables for distance codes */ 103 ubyte[30] dist_bits; 104 ushort[30] dist_base; 105 106 /** 107 * special ordering of code length codes 108 */ 109 private static immutable ubyte[] clcidx = 110 [ 111 16, 17, 18, 0, 8, 7, 9, 6, 112 10, 5, 11, 4, 12, 3, 13, 2, 113 14, 1, 15, 114 ]; 115 116 /* ----------------------- * 117 * -- utility functions -- * 118 * ----------------------- */ 119 120 /** 121 * build extra bits and base tables 122 */ 123 pure nothrow @safe @nogc 124 private void tinf_build_bits_base(ref ubyte[30] bits, ref ushort[30] base, int delta, int first) 125 126 do 127 { 128 size_t i; 129 int sum; 130 131 /* build bits table */ 132 for (i = 0; i < delta; ++i) { 133 bits[i] = 0; 134 } 135 136 for (i = 0; i < 30 - delta; ++i) { 137 bits[i + delta] = cast(char)(cast(int)(i) / delta); 138 } 139 140 /* build base table */ 141 for (sum = first, i = 0; i < 30; ++i) { 142 base[i] = cast(char)(sum); 143 sum += 1 << bits[i]; 144 } 145 } 146 147 /** 148 * build the fixed huffman trees 149 */ 150 pure nothrow @safe @nogc 151 private void tinf_build_fixed_trees(ref .TINF_TREE lt, ref .TINF_TREE dt) 152 153 do 154 { 155 size_t i; 156 157 /* build fixed length tree */ 158 for (i = 0; i < 7; ++i) { 159 lt.table[i] = 0; 160 } 161 162 lt.table[7] = 24; 163 lt.table[8] = 152; 164 lt.table[9] = 112; 165 166 for (i = 0; i < 24; ++i) { 167 lt.trans[i] = cast(ushort)(256 + i); 168 } 169 170 for (i = 0; i < 144; ++i) { 171 lt.trans[24 + i] = cast(ushort)(i); 172 } 173 174 for (i = 0; i < 8; ++i) { 175 lt.trans[24 + 144 + i] = cast(ushort)(280 + i); 176 } 177 178 for (i = 0; i < 112; ++i) { 179 lt.trans[24 + 144 + 8 + i] = cast(ushort)(144 + i); 180 } 181 182 /* build fixed distance tree */ 183 for (i = 0; i < 5; ++i) { 184 dt.table[i] = 0; 185 } 186 187 dt.table[5] = 32; 188 189 for (i = 0; i < 32; ++i) { 190 dt.trans[i] = cast(ushort)(i); 191 } 192 } 193 194 /** 195 * given an array of code lengths, build a tree 196 */ 197 pure nothrow @safe @nogc 198 private void tinf_build_tree(ref .TINF_TREE t, const ubyte[] lengths, uint num) 199 200 do 201 { 202 ushort[16] offs; 203 size_t i; 204 uint sum; 205 206 /* clear code length count table */ 207 for (i = 0; i < 16; ++i) { 208 t.table[i] = 0; 209 } 210 211 /* scan symbol lengths, and sum code length counts */ 212 for (i = 0; i < num; ++i) { 213 t.table[lengths[i]]++; 214 } 215 216 t.table[0] = 0; 217 218 /* compute offset table for distribution sort */ 219 for (sum = 0, i = 0; i < 16; ++i) { 220 offs[i] = cast(ushort)(sum); 221 sum += t.table[i]; 222 } 223 224 /* create code->symbol translation table (symbols sorted by code) */ 225 for (i = 0; i < num; ++i) { 226 if (lengths[i]) { 227 t.trans[offs[lengths[i]]++] = cast(ushort)(i); 228 } 229 } 230 } 231 232 /* ---------------------- * 233 * -- decode functions -- * 234 * ---------------------- */ 235 236 /** 237 * get one bit from source stream 238 */ 239 pure nothrow @nogc 240 private int tinf_getbit(ref .TINF_DATA d) 241 242 do 243 { 244 uint bit; 245 246 /* check if tag is empty */ 247 if (!d.bitcount--) { 248 /* load next tag */ 249 d.tag = *d.source++; 250 d.bitcount = 7; 251 } 252 253 /* shift bit out of tag */ 254 bit = d.tag & 0x01; 255 d.tag >>= 1; 256 257 return bit; 258 } 259 260 /** 261 * read a num bit value from a stream and add base 262 */ 263 pure nothrow @nogc 264 private uint tinf_read_bits(ref .TINF_DATA d, int num, int base) 265 266 do 267 { 268 uint val = 0; 269 270 /* read num bits */ 271 if (num) { 272 uint limit = 1 << (num); 273 uint mask; 274 275 for (mask = 1; mask < limit; mask *= 2) 276 if (.tinf_getbit(d)) { 277 val += mask; 278 } 279 } 280 281 return val + base; 282 } 283 284 /** 285 * given a data stream and a tree, decode a symbol 286 */ 287 pure nothrow @nogc 288 private int tinf_decode_symbol(ref .TINF_DATA d, ref .TINF_TREE t) 289 290 do 291 { 292 int sum = 0; 293 int cur = 0; 294 int len = 0; 295 296 /* get more bits while code value is above sum */ 297 do { 298 cur = 2 * cur + .tinf_getbit(d); 299 300 ++len; 301 302 sum += t.table[len]; 303 cur -= t.table[len]; 304 } while (cur >= 0); 305 306 return t.trans[sum + cur]; 307 } 308 309 /** 310 * given a data stream, decode dynamic trees from it 311 */ 312 nothrow @nogc 313 private void tinf_decode_trees(ref .TINF_DATA d, ref .TINF_TREE lt, ref .TINF_TREE dt) 314 315 do 316 { 317 .TINF_TREE code_tree; 318 ubyte[288 + 32] lengths; 319 uint hlit; 320 uint hdist; 321 uint hclen; 322 size_t i; 323 uint num; 324 uint length; 325 326 /* get 5 bits HLIT (257-286) */ 327 hlit = .tinf_read_bits(d, 5, 257); 328 329 /* get 5 bits HDIST (1-32) */ 330 hdist = .tinf_read_bits(d, 5, 1); 331 332 /* get 4 bits HCLEN (4-19) */ 333 hclen = .tinf_read_bits(d, 4, 4); 334 335 for (i = 0; i < 19; ++i) { 336 lengths[i] = 0; 337 } 338 339 /* read code lengths for code length alphabet */ 340 for (i = 0; i < hclen; ++i) { 341 /* get 3 bits code length (0-7) */ 342 uint clen = .tinf_read_bits(d, 3, 0); 343 344 lengths[.clcidx[i]] = cast(ubyte)(clen); 345 } 346 347 /* build code length tree */ 348 .tinf_build_tree(code_tree, lengths, 19); 349 350 /* decode code lengths for the dynamic trees */ 351 for (num = 0; num < hlit + hdist; ) { 352 int sym = .tinf_decode_symbol(d, code_tree); 353 354 switch (sym) { 355 case 16: 356 /* copy previous code length 3-6 times (read 2 bits) */ 357 { 358 ubyte prev = lengths[num - 1]; 359 360 for (length = .tinf_read_bits(d, 2, 3); length; --length) { 361 lengths[num++] = prev; 362 } 363 } 364 365 break; 366 367 case 17: 368 /* repeat code length 0 for 3-10 times (read 3 bits) */ 369 for (length = .tinf_read_bits(d, 3, 3); length; --length) { 370 lengths[num++] = 0; 371 } 372 373 break; 374 375 case 18: 376 /* repeat code length 0 for 11-138 times (read 7 bits) */ 377 for (length = .tinf_read_bits(d, 7, 11); length; --length) { 378 lengths[num++] = 0; 379 } 380 381 break; 382 383 default: 384 /* values 0-15 represent the actual code lengths */ 385 lengths[num++] = cast(char)(sym); 386 387 break; 388 } 389 } 390 391 /* build dynamic trees */ 392 .tinf_build_tree(lt, lengths[0 .. $], hlit); 393 .tinf_build_tree(dt, lengths[hlit .. $], hdist); 394 } 395 396 /* ----------------------------- * 397 * -- block inflate functions -- * 398 * ----------------------------- */ 399 400 /** 401 * given a stream and two trees, inflate a block of data 402 */ 403 nothrow @nogc 404 private int tinf_inflate_block_data(ref .TINF_DATA d, ref .TINF_TREE lt, ref .TINF_TREE dt) 405 406 do 407 { 408 /* remember current output position */ 409 ubyte* start = d.dest; 410 411 for (;;) { 412 int sym = .tinf_decode_symbol(d, lt); 413 414 /* check for end of block */ 415 if (sym == 256) { 416 d.destLen += cast(uint)(d.dest - start); 417 418 return .TINF_OK; 419 } 420 421 if (sym < 256) { 422 *d.dest++ = cast(char)(sym); 423 } else { 424 int length; 425 int dist; 426 int offs; 427 int i; 428 429 sym -= 257; 430 431 /* possibly get more bits from length code */ 432 length = .tinf_read_bits(d, .length_bits[sym], .length_base[sym]); 433 434 dist = .tinf_decode_symbol(d, dt); 435 436 /* possibly get more bits from distance code */ 437 offs = .tinf_read_bits(d, .dist_bits[dist], .dist_base[dist]); 438 439 /* copy match */ 440 for (i = 0; i < length; ++i) { 441 d.dest[i] = d.dest[i - offs]; 442 } 443 444 d.dest += length; 445 } 446 } 447 } 448 449 /** 450 * inflate an uncompressed block of data 451 */ 452 pure nothrow @nogc 453 private int tinf_inflate_uncompressed_block(ref .TINF_DATA d) 454 455 do 456 { 457 uint length; 458 uint invlength; 459 uint i; 460 461 /* get length */ 462 length = d.source[1]; 463 length = 256 * length + d.source[0]; 464 465 /* get one's complement of length */ 466 invlength = d.source[3]; 467 invlength = 256 * invlength + d.source[2]; 468 469 /* check length */ 470 if (length != (~invlength & 0x0000FFFF)) { 471 return .TINF_DATA_ERROR; 472 } 473 474 d.source += 4; 475 476 /* copy block */ 477 for (i = length; i; --i) { 478 *d.dest++ = *d.source++; 479 } 480 481 /* make sure we start next block on a byte boundary */ 482 d.bitcount = 0; 483 484 d.destLen += length; 485 486 return .TINF_OK; 487 } 488 489 /** 490 * inflate a block of data compressed with fixed huffman trees 491 */ 492 nothrow @nogc 493 private int tinf_inflate_fixed_block(ref .TINF_DATA d) 494 495 do 496 { 497 /* decode block using fixed trees */ 498 return .tinf_inflate_block_data(d, .sltree, .sdtree); 499 } 500 501 /** 502 * inflate a block of data compressed with dynamic huffman trees 503 */ 504 nothrow @nogc 505 private int tinf_inflate_dynamic_block(ref .TINF_DATA d) 506 507 do 508 { 509 /* decode trees from stream */ 510 .tinf_decode_trees(d, d.ltree, d.dtree); 511 512 /* decode block using decoded trees */ 513 return .tinf_inflate_block_data(d, d.ltree, d.dtree); 514 } 515 516 /* ---------------------- * 517 * -- public functions -- * 518 * ---------------------- */ 519 520 /** 521 * initialize global (static) data 522 */ 523 nothrow @nogc 524 void tinf_init() 525 526 do 527 { 528 /* build fixed huffman trees */ 529 .tinf_build_fixed_trees(.sltree, .sdtree); 530 531 /* build extra bits and base tables */ 532 .tinf_build_bits_base(.length_bits, .length_base, 4, 3); 533 .tinf_build_bits_base(.dist_bits, .dist_base, 2, 1); 534 535 /* fix a special case */ 536 .length_bits[28] = 0; 537 .length_base[28] = 258; 538 } 539 540 /** 541 * inflate stream from source to dest 542 */ 543 nothrow @nogc 544 int tinf_uncompress(void[] dest, ref uint destLen, const void[] source) 545 546 do 547 { 548 .TINF_DATA d; 549 int bfinal; 550 551 /* initialise data */ 552 d.source = cast(const (ubyte)*)(&(source[0])); 553 d.bitcount = 0; 554 555 d.dest = cast(ubyte*)(&(dest[0])); 556 d.destLen = destLen; 557 558 destLen = 0; 559 560 do { 561 uint btype; 562 int res; 563 564 /* read final block flag */ 565 bfinal = .tinf_getbit(d); 566 567 /* read block type (2 bits) */ 568 btype = .tinf_read_bits(d, 2, 0); 569 570 /* decompress block */ 571 switch (btype) { 572 case 0: 573 /* decompress uncompressed block */ 574 res = .tinf_inflate_uncompressed_block(d); 575 576 break; 577 578 case 1: 579 /* decompress block with fixed huffman trees */ 580 res = .tinf_inflate_fixed_block(d); 581 582 break; 583 584 case 2: 585 /* decompress block with dynamic huffman trees */ 586 res = .tinf_inflate_dynamic_block(d); 587 588 break; 589 590 default: 591 return .TINF_DATA_ERROR; 592 } 593 594 if (res != .TINF_OK) { 595 return .TINF_DATA_ERROR; 596 } 597 } while (!bfinal); 598 599 return .TINF_OK; 600 }