ICSharpCode.SharpZipLib.Zip.Compression.Inflater - Coverage Report

# Summary

Class: | ICSharpCode.SharpZipLib.Zip.Compression.Inflater
Assembly: | ICSharpCode.SharpZipLib
File(s): | C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Zip\Compression\Inflater.cs
Covered lines: | 173
Uncovered lines: | 57
Coverable lines: | 230
Total lines: | 788
Line coverage: | 75.2%
Branch coverage: | 59.8%

# Metrics

Method | Cyclomatic Complexity | Sequence Coverage | Branch Coverage
--- | --- | --- | ---
.ctor() | 1 | 100 | 100
.ctor(...) | 3 | 100 | 100
Reset() | 3 | 100 | 66.67
DecodeHeader() | 5 | 73.33 | 66.67
DecodeDict() | 3 | 0 | 0
DecodeHuffman() | 14 | 77.08 | 61.54
DecodeChksum() | 4 | 81.82 | 71.43
Decode() | 24 | 87.27 | 71.43
SetDictionary(...) | 1 | 0 | 0
SetDictionary(...) | 6 | 0 | 0
SetInput(...) | 1 | 0 | 0
SetInput(...) | 1 | 100 | 100
Inflate(...) | 2 | 0 | 0
Inflate(...) | 13 | 84 | 80
.cctor() | 1 | 100 | 100

# File(s)

## C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Zip\Compression\Inflater.cs

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | `using ICSharpCode.SharpZipLib.Checksum;`
|  | `3` |  | `using ICSharpCode.SharpZipLib.Zip.Compression.Streams;`
|  | `4` |  | ``
|  | `5` |  | `namespace ICSharpCode.SharpZipLib.Zip.Compression`
|  | `6` |  | `{`
|  | `7` |  | `/// <summary>`
|  | `8` |  | `/// Inflater is used to decompress data that has been compressed according`
|  | `9` |  | `/// to the "deflate" standard described in rfc1951.`
|  | `10` |  | `///`
|  | `11` |  | `/// By default Zlib (rfc1950) headers and footers are expected in the input.`
|  | `12` |  | `/// You can use constructor <code> public Inflater(bool noHeader)</code> passing true`
|  | `13` |  | `/// if there is no Zlib header information`
|  | `14` |  | `///`
|  | `15` |  | `/// The usage is as following. First you have to set some input with`
|  | `16` |  | `/// <code>SetInput()</code>, then Inflate() it. If inflate doesn't`
|  | `17` |  | `/// inflate any bytes there may be three reasons:`
|  | `18` |  | `/// <ul>`
|  | `19` |  | `/// <li>IsNeedingInput() returns true because the input buffer is empty.`
|  | `20` |  | `/// You have to provide more input with <code>SetInput()</code>.`
|  | `21` |  | `/// NOTE: IsNeedingInput() also returns true when, the stream is finished.`
|  | `22` |  | `/// </li>`
|  | `23` |  | `/// <li>IsNeedingDictionary() returns true, you have to provide a preset`
|  | `24` |  | `/// dictionary with <code>SetDictionary()</code>.</li>`
|  | `25` |  | `/// <li>IsFinished returns true, the inflater has finished.</li>`
|  | `26` |  | `/// </ul>`
|  | `27` |  | `/// Once the first output byte is produced, a dictionary will not be`
|  | `28` |  | `/// needed at a later stage.`
|  | `29` |  | `///`
|  | `30` |  | `/// author of the original java version : John Leuner, Jochen Hoenicke`
|  | `31` |  | `/// </summary>`
|  | `32` |  | `public class Inflater`
|  | `33` |  | `{`
|  | `34` |  | `#region Constants/Readonly`
|  | `35` |  | `/// <summary>`
|  | `36` |  | `/// Copy lengths for literal codes 257..285`
|  | `37` |  | `/// </summary>`
| 1 | `38` |  | `static readonly int[] CPLENS = {`
| 1 | `39` |  | `3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,`
| 1 | `40` |  | `35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258`
| 1 | `41` |  | `};`
|  | `42` |  | ``
|  | `43` |  | `/// <summary>`
|  | `44` |  | `/// Extra bits for literal codes 257..285`
|  | `45` |  | `/// </summary>`
| 1 | `46` |  | `static readonly int[] CPLEXT = {`
| 1 | `47` |  | `0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,`
| 1 | `48` |  | `3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0`
| 1 | `49` |  | `};`
|  | `50` |  | ``
|  | `51` |  | `/// <summary>`
|  | `52` |  | `/// Copy offsets for distance codes 0..29`
|  | `53` |  | `/// </summary>`
| 1 | `54` |  | `static readonly int[] CPDIST = {`
| 1 | `55` |  | `1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,`
| 1 | `56` |  | `257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,`
| 1 | `57` |  | `8193, 12289, 16385, 24577`
| 1 | `58` |  | `};`
|  | `59` |  | ``
|  | `60` |  | `/// <summary>`
|  | `61` |  | `/// Extra bits for distance codes`
|  | `62` |  | `/// </summary>`
| 1 | `63` |  | `static readonly int[] CPDEXT = {`
| 1 | `64` |  | `0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,`
| 1 | `65` |  | `7, 7, 8, 8, 9, 9, 10, 10, 11, 11,`
| 1 | `66` |  | `12, 12, 13, 13`
| 1 | `67` |  | `};`
|  | `68` |  | ``
|  | `69` |  | `/// <summary>`
|  | `70` |  | `/// These are the possible states for an inflater`
|  | `71` |  | `/// </summary>`
|  | `72` |  | `const int DECODE_HEADER = 0;`
|  | `73` |  | `const int DECODE_DICT = 1;`
|  | `74` |  | `const int DECODE_BLOCKS = 2;`
|  | `75` |  | `const int DECODE_STORED_LEN1 = 3;`
|  | `76` |  | `const int DECODE_STORED_LEN2 = 4;`
|  | `77` |  | `const int DECODE_STORED = 5;`
|  | `78` |  | `const int DECODE_DYN_HEADER = 6;`
|  | `79` |  | `const int DECODE_HUFFMAN = 7;`
|  | `80` |  | `const int DECODE_HUFFMAN_LENBITS = 8;`
|  | `81` |  | `const int DECODE_HUFFMAN_DIST = 9;`
|  | `82` |  | `const int DECODE_HUFFMAN_DISTBITS = 10;`
|  | `83` |  | `const int DECODE_CHKSUM = 11;`
|  | `84` |  | `const int FINISHED = 12;`
|  | `85` |  | `#endregion`
|  | `86` |  | ``
|  | `87` |  | `#region Instance Fields`
|  | `88` |  | `/// <summary>`
|  | `89` |  | `/// This variable contains the current state.`
|  | `90` |  | `/// </summary>`
|  | `91` |  | `int mode;`
|  | `92` |  | ``
|  | `93` |  | `/// <summary>`
|  | `94` |  | `/// The adler checksum of the dictionary or of the decompressed`
|  | `95` |  | `/// stream, as it is written in the header resp. footer of the`
|  | `96` |  | `/// compressed stream.`
|  | `97` |  | `/// Only valid if mode is DECODE_DICT or DECODE_CHKSUM.`
|  | `98` |  | `/// </summary>`
|  | `99` |  | `int readAdler;`
|  | `100` |  | ``
|  | `101` |  | `/// <summary>`
|  | `102` |  | `/// The number of bits needed to complete the current state. This`
|  | `103` |  | `/// is valid, if mode is DECODE_DICT, DECODE_CHKSUM,`
|  | `104` |  | `/// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.`
|  | `105` |  | `/// </summary>`
|  | `106` |  | `int neededBits;`
|  | `107` |  | `int repLength;`
|  | `108` |  | `int repDist;`
|  | `109` |  | `int uncomprLen;`
|  | `110` |  | ``
|  | `111` |  | `/// <summary>`
|  | `112` |  | `/// True, if the last block flag was set in the last block of the`
|  | `113` |  | `/// inflated stream. This means that the stream ends after the`
|  | `114` |  | `/// current block.`
|  | `115` |  | `/// </summary>`
|  | `116` |  | `bool isLastBlock;`
|  | `117` |  | ``
|  | `118` |  | `/// <summary>`
|  | `119` |  | `/// The total number of inflated bytes.`
|  | `120` |  | `/// </summary>`
|  | `121` |  | `long totalOut;`
|  | `122` |  | ``
|  | `123` |  | `/// <summary>`
|  | `124` |  | `/// The total number of bytes set with setInput(). This is not the`
|  | `125` |  | `/// value returned by the TotalIn property, since this also includes the`
|  | `126` |  | `/// unprocessed input.`
|  | `127` |  | `/// </summary>`
|  | `128` |  | `long totalIn;`
|  | `129` |  | ``
|  | `130` |  | `/// <summary>`
|  | `131` |  | `/// This variable stores the noHeader flag that was given to the constructor.`
|  | `132` |  | `/// True means, that the inflated stream doesn't contain a Zlib header or`
|  | `133` |  | `/// footer.`
|  | `134` |  | `/// </summary>`
|  | `135` |  | `bool noHeader;`
|  | `136` |  | `readonly StreamManipulator input;`
|  | `137` |  | `OutputWindow outputWindow;`
|  | `138` |  | `InflaterDynHeader dynHeader;`
|  | `139` |  | `InflaterHuffmanTree litlenTree, distTree;`
|  | `140` |  | `Adler32 adler;`
|  | `141` |  | `#endregion`
|  | `142` |  | ``
|  | `143` |  | `#region Constructors`
|  | `144` |  | `/// <summary>`
|  | `145` |  | `/// Creates a new inflater or RFC1951 decompressor`
|  | `146` |  | `/// RFC1950/Zlib headers and footers will be expected in the input data`
|  | `147` |  | `/// </summary>`
| 3 | `148` |  | `public Inflater() : this(false)`
|  | `149` |  | `{`
| 3 | `150` |  | `}`
|  | `151` |  | ``
|  | `152` |  | `/// <summary>`
|  | `153` |  | `/// Creates a new inflater.`
|  | `154` |  | `/// </summary>`
|  | `155` |  | `/// <param name="noHeader">`
|  | `156` |  | `/// True if no RFC1950/Zlib header and footer fields are expected in the input data`
|  | `157` |  | `///`
|  | `158` |  | `/// This is used for GZIPed/Zipped input.`
|  | `159` |  | `///`
|  | `160` |  | `/// For compatibility with`
|  | `161` |  | `/// Sun JDK you should provide one byte of input more than needed in`
|  | `162` |  | `/// this case.`
|  | `163` |  | `/// </param>`
| 435 | `164` |  | `public Inflater(bool noHeader)`
|  | `165` |  | `{`
| 435 | `166` |  | `this.noHeader = noHeader;`
| 435 | `167` |  | `this.adler = new Adler32();`
| 435 | `168` |  | `input = new StreamManipulator();`
| 435 | `169` |  | `outputWindow = new OutputWindow();`
| 435 | `170` |  | `mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;`
| 435 | `171` |  | `}`
|  | `172` |  | `#endregion`
|  | `173` |  | ``
|  | `174` |  | `/// <summary>`
|  | `175` |  | `/// Resets the inflater so that a new stream can be decompressed. All`
|  | `176` |  | `/// pending input and output will be discarded.`
|  | `177` |  | `/// </summary>`
|  | `178` |  | `public void Reset()`
|  | `179` |  | `{`
| 41 | `180` |  | `mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;`
| 41 | `181` |  | `totalIn = 0;`
| 41 | `182` |  | `totalOut = 0;`
| 41 | `183` |  | `input.Reset();`
| 41 | `184` |  | `outputWindow.Reset();`
| 41 | `185` |  | `dynHeader = null;`
| 41 | `186` |  | `litlenTree = null;`
| 41 | `187` |  | `distTree = null;`
| 41 | `188` |  | `isLastBlock = false;`
| 41 | `189` |  | `adler.Reset();`
| 41 | `190` |  | `}`
|  | `191` |  | ``
|  | `192` |  | `/// <summary>`
|  | `193` |  | `/// Decodes a zlib/RFC1950 header.`
|  | `194` |  | `/// </summary>`
|  | `195` |  | `/// <returns>`
|  | `196` |  | `/// False if more input is needed.`
|  | `197` |  | `/// </returns>`
|  | `198` |  | `/// <exception cref="SharpZipBaseException">`
|  | `199` |  | `/// The header is invalid.`
|  | `200` |  | `/// </exception>`
|  | `201` |  | `private bool DecodeHeader()`
|  | `202` |  | `{`
| 22 | `203` |  | `int header = input.PeekBits(16);`
| 22 | `204` |  | `if (header < 0) {`
| 11 | `205` |  | `return false;`
|  | `206` |  | `}`
| 11 | `207` |  | `input.DropBits(16);`
|  | `208` |  | ``
|  | `209` |  | `// The header is written in "wrong" byte order`
| 11 | `210` |  | `header = ((header << 8) | (header >> 8)) & 0xffff;`
| 11 | `211` |  | `if (header % 31 != 0) {`
| 0 | `212` |  | `throw new SharpZipBaseException("Header checksum illegal");`
|  | `213` |  | `}`
|  | `214` |  | ``
| 11 | `215` |  | `if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) {`
| 0 | `216` |  | `throw new SharpZipBaseException("Compression Method unknown");`
|  | `217` |  | `}`
|  | `218` |  | ``
|  | `219` |  | `/* Maximum size of the backwards window in bits.`
|  | `220` |  | `* We currently ignore this, but we could use it to make the`
|  | `221` |  | `* inflater window more space efficient. On the other hand the`
|  | `222` |  | `* full window (15 bits) is needed most times, anyway.`
|  | `223` |  | `int max_wbits = ((header & 0x7000) >> 12) + 8;`
|  | `224` |  | `*/`
|  | `225` |  | ``
| 11 | `226` |  | `if ((header & 0x0020) == 0) { // Dictionary flag?`
| 11 | `227` |  | `mode = DECODE_BLOCKS;`
| 11 | `228` |  | `} else {`
| 0 | `229` |  | `mode = DECODE_DICT;`
| 0 | `230` |  | `neededBits = 32;`
|  | `231` |  | `}`
| 11 | `232` |  | `return true;`
|  | `233` |  | `}`
|  | `234` |  | ``
|  | `235` |  | `/// <summary>`
|  | `236` |  | `/// Decodes the dictionary checksum after the deflate header.`
|  | `237` |  | `/// </summary>`
|  | `238` |  | `/// <returns>`
|  | `239` |  | `/// False if more input is needed.`
|  | `240` |  | `/// </returns>`
|  | `241` |  | `private bool DecodeDict()`
|  | `242` |  | `{`
| 0 | `243` |  | `while (neededBits > 0) {`
| 0 | `244` |  | `int dictByte = input.PeekBits(8);`
| 0 | `245` |  | `if (dictByte < 0) {`
| 0 | `246` |  | `return false;`
|  | `247` |  | `}`
| 0 | `248` |  | `input.DropBits(8);`
| 0 | `249` |  | `readAdler = (readAdler << 8) | dictByte;`
| 0 | `250` |  | `neededBits -= 8;`
|  | `251` |  | `}`
| 0 | `252` |  | `return false;`
|  | `253` |  | `}`
|  | `254` |  | ``
|  | `255` |  | `/// <summary>`
|  | `256` |  | `/// Decodes the huffman encoded symbols in the input stream.`
|  | `257` |  | `/// </summary>`
|  | `258` |  | `/// <returns>`
|  | `259` |  | `/// false if more input is needed, true if output window is`
|  | `260` |  | `/// full or the current block ends.`
|  | `261` |  | `/// </returns>`
|  | `262` |  | `/// <exception cref="SharpZipBaseException">`
|  | `263` |  | `/// if deflated stream is invalid.`
|  | `264` |  | `/// </exception>`
|  | `265` |  | `private bool DecodeHuffman()`
|  | `266` |  | `{`
| 371 | `267` |  | `int free = outputWindow.GetFreeSpace();`
| 468 | `268` |  | `while (free >= 258) {`
|  | `269` |  | `int symbol;`
| 468 | `270` |  | `switch (mode) {`
|  | `271` |  | `case DECODE_HUFFMAN:`
|  | `272` |  | `// This is the inner loop so it is optimized a bit`
| 9697 | `273` |  | `while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) {`
| 9229 | `274` |  | `outputWindow.Write(symbol);`
| 9229 | `275` |  | `if (--free < 258) {`
| 0 | `276` |  | `return true;`
|  | `277` |  | `}`
|  | `278` |  | `}`
|  | `279` |  | ``
| 468 | `280` |  | `if (symbol < 257) {`
| 371 | `281` |  | `if (symbol < 0) {`
| 0 | `282` |  | `return false;`
|  | `283` |  | `} else {`
|  | `284` |  | `// symbol == 256: end of block`
| 371 | `285` |  | `distTree = null;`
| 371 | `286` |  | `litlenTree = null;`
| 371 | `287` |  | `mode = DECODE_BLOCKS;`
| 371 | `288` |  | `return true;`
|  | `289` |  | `}`
|  | `290` |  | `}`
|  | `291` |  | ``
|  | `292` |  | `try {`
| 97 | `293` |  | `repLength = CPLENS[symbol - 257];`
| 97 | `294` |  | `neededBits = CPLEXT[symbol - 257];`
| 97 | `295` |  | `} catch (Exception) {`
| 0 | `296` |  | `throw new SharpZipBaseException("Illegal rep length code");`
|  | `297` |  | `}`
|  | `298` |  | `goto case DECODE_HUFFMAN_LENBITS; // fall through`
|  | `299` |  | ``
|  | `300` |  | `case DECODE_HUFFMAN_LENBITS:`
| 97 | `301` |  | `if (neededBits > 0) {`
| 25 | `302` |  | `mode = DECODE_HUFFMAN_LENBITS;`
| 25 | `303` |  | `int i = input.PeekBits(neededBits);`
| 25 | `304` |  | `if (i < 0) {`
| 0 | `305` |  | `return false;`
|  | `306` |  | `}`
| 25 | `307` |  | `input.DropBits(neededBits);`
| 25 | `308` |  | `repLength += i;`
|  | `309` |  | `}`
| 97 | `310` |  | `mode = DECODE_HUFFMAN_DIST;`
|  | `311` |  | `goto case DECODE_HUFFMAN_DIST; // fall through`
|  | `312` |  | ``
|  | `313` |  | `case DECODE_HUFFMAN_DIST:`
| 97 | `314` |  | `symbol = distTree.GetSymbol(input);`
| 97 | `315` |  | `if (symbol < 0) {`
| 0 | `316` |  | `return false;`
|  | `317` |  | `}`
|  | `318` |  | ``
|  | `319` |  | `try {`
| 97 | `320` |  | `repDist = CPDIST[symbol];`
| 97 | `321` |  | `neededBits = CPDEXT[symbol];`
| 97 | `322` |  | `} catch (Exception) {`
| 0 | `323` |  | `throw new SharpZipBaseException("Illegal rep dist code");`
|  | `324` |  | `}`
|  | `325` |  | ``
|  | `326` |  | `goto case DECODE_HUFFMAN_DISTBITS; // fall through`
|  | `327` |  | ``
|  | `328` |  | `case DECODE_HUFFMAN_DISTBITS:`
| 97 | `329` |  | `if (neededBits > 0) {`
| 68 | `330` |  | `mode = DECODE_HUFFMAN_DISTBITS;`
| 68 | `331` |  | `int i = input.PeekBits(neededBits);`
| 68 | `332` |  | `if (i < 0) {`
| 0 | `333` |  | `return false;`
|  | `334` |  | `}`
| 68 | `335` |  | `input.DropBits(neededBits);`
| 68 | `336` |  | `repDist += i;`
|  | `337` |  | `}`
|  | `338` |  | ``
| 97 | `339` |  | `outputWindow.Repeat(repLength, repDist);`
| 97 | `340` |  | `free -= repLength;`
| 97 | `341` |  | `mode = DECODE_HUFFMAN;`
| 97 | `342` |  | `break;`
|  | `343` |  | ``
|  | `344` |  | `default:`
| 0 | `345` |  | `throw new SharpZipBaseException("Inflater unknown mode");`
|  | `346` |  | `}`
|  | `347` |  | `}`
| 0 | `348` |  | `return true;`
|  | `349` |  | `}`
|  | `350` |  | ``
|  | `351` |  | `/// <summary>`
|  | `352` |  | `/// Decodes the adler checksum after the deflate stream.`
|  | `353` |  | `/// </summary>`
|  | `354` |  | `/// <returns>`
|  | `355` |  | `/// false if more input is needed.`
|  | `356` |  | `/// </returns>`
|  | `357` |  | `/// <exception cref="SharpZipBaseException">`
|  | `358` |  | `/// If checksum doesn't match.`
|  | `359` |  | `/// </exception>`
|  | `360` |  | `private bool DecodeChksum()`
|  | `361` |  | `{`
| 5 | `362` |  | `while (neededBits > 0) {`
| 4 | `363` |  | `int chkByte = input.PeekBits(8);`
| 4 | `364` |  | `if (chkByte < 0) {`
| 0 | `365` |  | `return false;`
|  | `366` |  | `}`
| 4 | `367` |  | `input.DropBits(8);`
| 4 | `368` |  | `readAdler = (readAdler << 8) | chkByte;`
| 4 | `369` |  | `neededBits -= 8;`
|  | `370` |  | `}`
|  | `371` |  | ``
| 1 | `372` |  | `if ((int)adler.Value != readAdler) {`
| 0 | `373` |  | `throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler);`
|  | `374` |  | `}`
|  | `375` |  | ``
| 1 | `376` |  | `mode = FINISHED;`
| 1 | `377` |  | `return false;`
|  | `378` |  | `}`
|  | `379` |  | ``
|  | `380` |  | `/// <summary>`
|  | `381` |  | `/// Decodes the deflated stream.`
|  | `382` |  | `/// </summary>`
|  | `383` |  | `/// <returns>`
|  | `384` |  | `/// false if more input is needed, or if finished.`
|  | `385` |  | `/// </returns>`
|  | `386` |  | `/// <exception cref="SharpZipBaseException">`
|  | `387` |  | `/// if deflated stream is invalid.`
|  | `388` |  | `/// </exception>`
|  | `389` |  | `private bool Decode()`
|  | `390` |  | `{`
| 4422 | `391` |  | `switch (mode) {`
|  | `392` |  | `case DECODE_HEADER:`
| 22 | `393` |  | `return DecodeHeader();`
|  | `394` |  | ``
|  | `395` |  | `case DECODE_DICT:`
| 0 | `396` |  | `return DecodeDict();`
|  | `397` |  | ``
|  | `398` |  | `case DECODE_CHKSUM:`
| 1 | `399` |  | `return DecodeChksum();`
|  | `400` |  | ``
|  | `401` |  | `case DECODE_BLOCKS:`
| 1412 | `402` |  | `if (isLastBlock) {`
| 387 | `403` |  | `if (noHeader) {`
| 376 | `404` |  | `mode = FINISHED;`
| 376 | `405` |  | `return false;`
|  | `406` |  | `} else {`
| 11 | `407` |  | `input.SkipToByteBoundary();`
| 11 | `408` |  | `neededBits = 32;`
| 11 | `409` |  | `mode = DECODE_CHKSUM;`
| 11 | `410` |  | `return true;`
|  | `411` |  | `}`
|  | `412` |  | `}`
|  | `413` |  | ``
| 1025 | `414` |  | `int type = input.PeekBits(3);`
| 1025 | `415` |  | `if (type < 0) {`
| 362 | `416` |  | `return false;`
|  | `417` |  | `}`
| 663 | `418` |  | `input.DropBits(3);`
|  | `419` |  | ``
| 663 | `420` |  | `isLastBlock |= (type & 1) != 0;`
| 663 | `421` |  | `switch (type >> 1) {`
|  | `422` |  | `case DeflaterConstants.STORED_BLOCK:`
| 292 | `423` |  | `input.SkipToByteBoundary();`
| 292 | `424` |  | `mode = DECODE_STORED_LEN1;`
| 292 | `425` |  | `break;`
|  | `426` |  | `case DeflaterConstants.STATIC_TREES:`
| 370 | `427` |  | `litlenTree = InflaterHuffmanTree.defLitLenTree;`
| 370 | `428` |  | `distTree = InflaterHuffmanTree.defDistTree;`
| 370 | `429` |  | `mode = DECODE_HUFFMAN;`
| 370 | `430` |  | `break;`
|  | `431` |  | `case DeflaterConstants.DYN_TREES:`
| 1 | `432` |  | `dynHeader = new InflaterDynHeader();`
| 1 | `433` |  | `mode = DECODE_DYN_HEADER;`
| 1 | `434` |  | `break;`
|  | `435` |  | `default:`
| 0 | `436` |  | `throw new SharpZipBaseException("Unknown block type " + type);`
|  | `437` |  | `}`
| 663 | `438` |  | `return true;`
|  | `439` |  | ``
|  | `440` |  | `case DECODE_STORED_LEN1: {`
| 292 | `441` |  | `if ((uncomprLen = input.PeekBits(16)) < 0) {`
| 0 | `442` |  | `return false;`
|  | `443` |  | `}`
| 292 | `444` |  | `input.DropBits(16);`
| 292 | `445` |  | `mode = DECODE_STORED_LEN2;`
|  | `446` |  | `}`
|  | `447` |  | `goto case DECODE_STORED_LEN2; // fall through`
|  | `448` |  | ``
|  | `449` |  | `case DECODE_STORED_LEN2: {`
| 292 | `450` |  | `int nlen = input.PeekBits(16);`
| 292 | `451` |  | `if (nlen < 0) {`
| 0 | `452` |  | `return false;`
|  | `453` |  | `}`
| 292 | `454` |  | `input.DropBits(16);`
| 292 | `455` |  | `if (nlen != (uncomprLen ^ 0xffff)) {`
| 0 | `456` |  | `throw new SharpZipBaseException("broken uncompressed block");`
|  | `457` |  | `}`
| 292 | `458` |  | `mode = DECODE_STORED;`
|  | `459` |  | `}`
|  | `460` |  | `goto case DECODE_STORED; // fall through`
|  | `461` |  | ``
|  | `462` |  | `case DECODE_STORED: {`
| 2280 | `463` |  | `int more = outputWindow.CopyStored(input, uncomprLen);`
| 2280 | `464` |  | `uncomprLen -= more;`
| 2280 | `465` |  | `if (uncomprLen == 0) {`
| 292 | `466` |  | `mode = DECODE_BLOCKS;`
| 292 | `467` |  | `return true;`
|  | `468` |  | `}`
| 1988 | `469` |  | `return !input.IsNeedingInput;`
|  | `470` |  | `}`
|  | `471` |  | ``
|  | `472` |  | `case DECODE_DYN_HEADER:`
| 1 | `473` |  | `if (!dynHeader.Decode(input)) {`
| 0 | `474` |  | `return false;`
|  | `475` |  | `}`
|  | `476` |  | ``
| 1 | `477` |  | `litlenTree = dynHeader.BuildLitLenTree();`
| 1 | `478` |  | `distTree = dynHeader.BuildDistTree();`
| 1 | `479` |  | `mode = DECODE_HUFFMAN;`
|  | `480` |  | `goto case DECODE_HUFFMAN; // fall through`
|  | `481` |  | ``
|  | `482` |  | `case DECODE_HUFFMAN:`
|  | `483` |  | `case DECODE_HUFFMAN_LENBITS:`
|  | `484` |  | `case DECODE_HUFFMAN_DIST:`
|  | `485` |  | `case DECODE_HUFFMAN_DISTBITS:`
| 371 | `486` |  | `return DecodeHuffman();`
|  | `487` |  | ``
|  | `488` |  | `case FINISHED:`
| 336 | `489` |  | `return false;`
|  | `490` |  | ``
|  | `491` |  | `default:`
| 0 | `492` |  | `throw new SharpZipBaseException("Inflater.Decode unknown mode");`
|  | `493` |  | `}`
|  | `494` |  | `}`
|  | `495` |  | ``
|  | `496` |  | `/// <summary>`
|  | `497` |  | `/// Sets the preset dictionary. This should only be called, if`
|  | `498` |  | `/// needsDictionary() returns true and it should set the same`
|  | `499` |  | `/// dictionary, that was used for deflating. The getAdler()`
|  | `500` |  | `/// function returns the checksum of the dictionary needed.`
|  | `501` |  | `/// </summary>`
|  | `502` |  | `/// <param name="buffer">`
|  | `503` |  | `/// The dictionary.`
|  | `504` |  | `/// </param>`
|  | `505` |  | `public void SetDictionary(byte[] buffer)`
|  | `506` |  | `{`
| 0 | `507` |  | `SetDictionary(buffer, 0, buffer.Length);`
| 0 | `508` |  | `}`
|  | `509` |  | ``
|  | `510` |  | `/// <summary>`
|  | `511` |  | `/// Sets the preset dictionary. This should only be called, if`
|  | `512` |  | `/// needsDictionary() returns true and it should set the same`
|  | `513` |  | `/// dictionary, that was used for deflating. The getAdler()`
|  | `514` |  | `/// function returns the checksum of the dictionary needed.`
|  | `515` |  | `/// </summary>`
|  | `516` |  | `/// <param name="buffer">`
|  | `517` |  | `/// The dictionary.`
|  | `518` |  | `/// </param>`
|  | `519` |  | `/// <param name="index">`
|  | `520` |  | `/// The index into buffer where the dictionary starts.`
|  | `521` |  | `/// </param>`
|  | `522` |  | `/// <param name="count">`
|  | `523` |  | `/// The number of bytes in the dictionary.`
|  | `524` |  | `/// </param>`
|  | `525` |  | `/// <exception cref="System.InvalidOperationException">`
|  | `526` |  | `/// No dictionary is needed.`
|  | `527` |  | `/// </exception>`
|  | `528` |  | `/// <exception cref="SharpZipBaseException">`
|  | `529` |  | `/// The adler checksum for the buffer is invalid`
|  | `530` |  | `/// </exception>`
|  | `531` |  | `public void SetDictionary(byte[] buffer, int index, int count)`
|  | `532` |  | `{`
| 0 | `533` |  | `if (buffer == null) {`
| 0 | `534` |  | `throw new ArgumentNullException(nameof(buffer));`
|  | `535` |  | `}`
|  | `536` |  | ``
| 0 | `537` |  | `if (index < 0) {`
| 0 | `538` |  | `throw new ArgumentOutOfRangeException(nameof(index));`
|  | `539` |  | `}`
|  | `540` |  | ``
| 0 | `541` |  | `if (count < 0) {`
| 0 | `542` |  | `throw new ArgumentOutOfRangeException(nameof(count));`
|  | `543` |  | `}`
|  | `544` |  | ``
| 0 | `545` |  | `if (!IsNeedingDictionary) {`
| 0 | `546` |  | `throw new InvalidOperationException("Dictionary is not needed");`
|  | `547` |  | `}`
|  | `548` |  | ``
| 0 | `549` |  | `adler.Update(buffer, index, count);`
|  | `550` |  | ``
| 0 | `551` |  | `if ((int)adler.Value != readAdler) {`
| 0 | `552` |  | `throw new SharpZipBaseException("Wrong adler checksum");`
|  | `553` |  | `}`
| 0 | `554` |  | `adler.Reset();`
| 0 | `555` |  | `outputWindow.CopyDict(buffer, index, count);`
| 0 | `556` |  | `mode = DECODE_BLOCKS;`
| 0 | `557` |  | `}`
|  | `558` |  | ``
|  | `559` |  | `/// <summary>`
|  | `560` |  | `/// Sets the input. This should only be called, if needsInput()`
|  | `561` |  | `/// returns true.`
|  | `562` |  | `/// </summary>`
|  | `563` |  | `/// <param name="buffer">`
|  | `564` |  | `/// the input.`
|  | `565` |  | `/// </param>`
|  | `566` |  | `public void SetInput(byte[] buffer)`
|  | `567` |  | `{`
| 0 | `568` |  | `SetInput(buffer, 0, buffer.Length);`
| 0 | `569` |  | `}`
|  | `570` |  | ``
|  | `571` |  | `/// <summary>`
|  | `572` |  | `/// Sets the input. This should only be called, if needsInput()`
|  | `573` |  | `/// returns true.`
|  | `574` |  | `/// </summary>`
|  | `575` |  | `/// <param name="buffer">`
|  | `576` |  | `/// The source of input data`
|  | `577` |  | `/// </param>`
|  | `578` |  | `/// <param name="index">`
|  | `579` |  | `/// The index into buffer where the input starts.`
|  | `580` |  | `/// </param>`
|  | `581` |  | `/// <param name="count">`
|  | `582` |  | `/// The number of bytes of input to use.`
|  | `583` |  | `/// </param>`
|  | `584` |  | `/// <exception cref="System.InvalidOperationException">`
|  | `585` |  | `/// No input is needed.`
|  | `586` |  | `/// </exception>`
|  | `587` |  | `/// <exception cref="System.ArgumentOutOfRangeException">`
|  | `588` |  | `/// The index and/or count are wrong.`
|  | `589` |  | `/// </exception>`
|  | `590` |  | `public void SetInput(byte[] buffer, int index, int count)`
|  | `591` |  | `{`
| 1433 | `592` |  | `input.SetInput(buffer, index, count);`
| 1433 | `593` |  | `totalIn += (long)count;`
| 1433 | `594` |  | `}`
|  | `595` |  | ``
|  | `596` |  | `/// <summary>`
|  | `597` |  | `/// Inflates the compressed stream to the output buffer. If this`
|  | `598` |  | `/// returns 0, you should check, whether IsNeedingDictionary(),`
|  | `599` |  | `/// IsNeedingInput() or IsFinished() returns true, to determine why no`
|  | `600` |  | `/// further output is produced.`
|  | `601` |  | `/// </summary>`
|  | `602` |  | `/// <param name="buffer">`
|  | `603` |  | `/// the output buffer.`
|  | `604` |  | `/// </param>`
|  | `605` |  | `/// <returns>`
|  | `606` |  | `/// The number of bytes written to the buffer, 0 if no further`
|  | `607` |  | `/// output can be produced.`
|  | `608` |  | `/// </returns>`
|  | `609` |  | `/// <exception cref="System.ArgumentOutOfRangeException">`
|  | `610` |  | `/// if buffer has length 0.`
|  | `611` |  | `/// </exception>`
|  | `612` |  | `/// <exception cref="System.FormatException">`
|  | `613` |  | `/// if deflated stream is invalid.`
|  | `614` |  | `/// </exception>`
|  | `615` |  | `public int Inflate(byte[] buffer)`
|  | `616` |  | `{`
| 0 | `617` |  | `if (buffer == null) {`
| 0 | `618` |  | `throw new ArgumentNullException(nameof(buffer));`
|  | `619` |  | `}`
|  | `620` |  | ``
| 0 | `621` |  | `return Inflate(buffer, 0, buffer.Length);`
|  | `622` |  | `}`
|  | `623` |  | ``
|  | `624` |  | `/// <summary>`
|  | `625` |  | `/// Inflates the compressed stream to the output buffer. If this`
|  | `626` |  | `/// returns 0, you should check, whether needsDictionary(),`
|  | `627` |  | `/// needsInput() or finished() returns true, to determine why no`
|  | `628` |  | `/// further output is produced.`
|  | `629` |  | `/// </summary>`
|  | `630` |  | `/// <param name="buffer">`
|  | `631` |  | `/// the output buffer.`
|  | `632` |  | `/// </param>`
|  | `633` |  | `/// <param name="offset">`
|  | `634` |  | `/// the offset in buffer where storing starts.`
|  | `635` |  | `/// </param>`
|  | `636` |  | `/// <param name="count">`
|  | `637` |  | `/// the maximum number of bytes to output.`
|  | `638` |  | `/// </param>`
|  | `639` |  | `/// <returns>`
|  | `640` |  | `/// the number of bytes written to the buffer, 0 if no further output can be produced.`
|  | `641` |  | `/// </returns>`
|  | `642` |  | `/// <exception cref="System.ArgumentOutOfRangeException">`
|  | `643` |  | `/// if count is less than 0.`
|  | `644` |  | `/// </exception>`
|  | `645` |  | `/// <exception cref="System.ArgumentOutOfRangeException">`
|  | `646` |  | `/// if the index and / or count are wrong.`
|  | `647` |  | `/// </exception>`
|  | `648` |  | `/// <exception cref="System.FormatException">`
|  | `649` |  | `/// if deflated stream is invalid.`
|  | `650` |  | `/// </exception>`
|  | `651` |  | `public int Inflate(byte[] buffer, int offset, int count)`
|  | `652` |  | `{`
| 2212 | `653` |  | `if (buffer == null) {`
| 0 | `654` |  | `throw new ArgumentNullException(nameof(buffer));`
|  | `655` |  | `}`
|  | `656` |  | ``
| 2212 | `657` |  | `if (count < 0) {`
| 0 | `658` |  | `throw new ArgumentOutOfRangeException(nameof(count), "count cannot be negative");`
|  | `659` |  | `}`
|  | `660` |  | ``
| 2212 | `661` |  | `if (offset < 0) {`
| 0 | `662` |  | `throw new ArgumentOutOfRangeException(nameof(offset), "offset cannot be negative");`
|  | `663` |  | `}`
|  | `664` |  | ``
| 2212 | `665` |  | `if (offset + count > buffer.Length) {`
| 0 | `666` |  | `throw new ArgumentException("count exceeds buffer bounds");`
|  | `667` |  | `}`
|  | `668` |  | ``
|  | `669` |  | `// Special case: count may be zero`
| 2212 | `670` |  | `if (count == 0) {`
| 20 | `671` |  | `if (!IsFinished) { // -jr- 08-Nov-2003 INFLATE_BUG fix..`
| 20 | `672` |  | `Decode();`
|  | `673` |  | `}`
| 20 | `674` |  | `return 0;`
|  | `675` |  | `}`
|  | `676` |  | ``
| 2192 | `677` |  | `int bytesCopied = 0;`
|  | `678` |  | ``
|  | `679` |  | `do {`
| 4524 | `680` |  | `if (mode != DECODE_CHKSUM) {`
|  | `681` |  | `/* Don't give away any output, if we are waiting for the`
|  | `682` |  | `* checksum in the input stream.`
|  | `683` |  | `*`
|  | `684` |  | `* With this trick we have always:`
|  | `685` |  | `* IsNeedingInput() and not IsFinished()`
|  | `686` |  | `* implies more output can be produced.`
|  | `687` |  | `*/`
| 4523 | `688` |  | `int more = outputWindow.CopyOutput(buffer, offset, count);`
| 4523 | `689` |  | `if (more > 0) {`
| 1679 | `690` |  | `adler.Update(buffer, offset, more);`
| 1679 | `691` |  | `offset += more;`
| 1679 | `692` |  | `bytesCopied += more;`
| 1679 | `693` |  | `totalOut += (long)more;`
| 1679 | `694` |  | `count -= more;`
| 1679 | `695` |  | `if (count == 0) {`
| 122 | `696` |  | `return bytesCopied;`
|  | `697` |  | `}`
|  | `698` |  | `}`
|  | `699` |  | `}`
| 4402 | `700` |  | `} while (Decode() || ((outputWindow.GetAvailable() > 0) && (mode != DECODE_CHKSUM)));`
| 2070 | `701` |  | `return bytesCopied;`
|  | `702` |  | `}`
|  | `703` |  | ``
|  | `704` |  | `/// <summary>`
|  | `705` |  | `/// Returns true, if the input buffer is empty.`
|  | `706` |  | `/// You should then call setInput().`
|  | `707` |  | `/// NOTE: This method also returns true when the stream is finished.`
|  | `708` |  | `/// </summary>`
|  | `709` |  | `public bool IsNeedingInput {`
|  | `710` |  | `get {`
| 1367 | `711` |  | `return input.IsNeedingInput;`
|  | `712` |  | `}`
|  | `713` |  | `}`
|  | `714` |  | ``
|  | `715` |  | `/// <summary>`
|  | `716` |  | `/// Returns true, if a preset dictionary is needed to inflate the input.`
|  | `717` |  | `/// </summary>`
|  | `718` |  | `public bool IsNeedingDictionary {`
|  | `719` |  | `get {`
| 845 | `720` |  | `return mode == DECODE_DICT && neededBits == 0;`
|  | `721` |  | `}`
|  | `722` |  | `}`
|  | `723` |  | ``
|  | `724` |  | `/// <summary>`
|  | `725` |  | `/// Returns true, if the inflater has finished. This means, that no`
|  | `726` |  | `/// input is needed and no output can be produced.`
|  | `727` |  | `/// </summary>`
|  | `728` |  | `public bool IsFinished {`
|  | `729` |  | `get {`
| 2106 | `730` |  | `return mode == FINISHED && outputWindow.GetAvailable() == 0;`
|  | `731` |  | `}`
|  | `732` |  | `}`
|  | `733` |  | ``
|  | `734` |  | `/// <summary>`
|  | `735` |  | `/// Gets the adler checksum. This is either the checksum of all`
|  | `736` |  | `/// uncompressed bytes returned by inflate(), or if needsDictionary()`
|  | `737` |  | `/// returns true (and thus no output was yet produced) this is the`
|  | `738` |  | `/// adler checksum of the expected dictionary.`
|  | `739` |  | `/// </summary>`
|  | `740` |  | `/// <returns>`
|  | `741` |  | `/// the adler checksum.`
|  | `742` |  | `/// </returns>`
|  | `743` |  | `public int Adler {`
|  | `744` |  | `get {`
| 0 | `745` |  | `return IsNeedingDictionary ? readAdler : (int)adler.Value;`
|  | `746` |  | `}`
|  | `747` |  | `}`
|  | `748` |  | ``
|  | `749` |  | `/// <summary>`
|  | `750` |  | `/// Gets the total number of output bytes returned by Inflate().`
|  | `751` |  | `/// </summary>`
|  | `752` |  | `/// <returns>`
|  | `753` |  | `/// the total number of output bytes.`
|  | `754` |  | `/// </returns>`
|  | `755` |  | `public long TotalOut {`
|  | `756` |  | `get {`
| 13 | `757` |  | `return totalOut;`
|  | `758` |  | `}`
|  | `759` |  | `}`
|  | `760` |  | ``
|  | `761` |  | `/// <summary>`
|  | `762` |  | `/// Gets the total number of processed compressed input bytes.`
|  | `763` |  | `/// </summary>`
|  | `764` |  | `/// <returns>`
|  | `765` |  | `/// The total number of bytes of processed input bytes.`
|  | `766` |  | `/// </returns>`
|  | `767` |  | `public long TotalIn {`
|  | `768` |  | `get {`
| 22 | `769` |  | `return totalIn - (long)RemainingInput;`
|  | `770` |  | `}`
|  | `771` |  | `}`
|  | `772` |  | ``
|  | `773` |  | `/// <summary>`
|  | `774` |  | `/// Gets the number of unprocessed input bytes. Useful, if the end of the`
|  | `775` |  | `/// stream is reached and you want to further process the bytes after`
|  | `776` |  | `/// the deflate stream.`
|  | `777` |  | `/// </summary>`
|  | `778` |  | `/// <returns>`
|  | `779` |  | `/// The number of bytes of the input which have not been processed.`
|  | `780` |  | `/// </returns>`
|  | `781` |  | `public int RemainingInput {`
|  | `782` |  | `// TODO: This should be a long?`
|  | `783` |  | `get {`
| 47 | `784` |  | `return input.AvailableBytes;`
|  | `785` |  | `}`
|  | `786` |  | `}`
|  | `787` |  | `}`
|  | `788` |  | `}`