# ICSharpCode.SharpZipLib.Zip.Compression.Streams.StreamManipulator - Coverage Report

# Summary

Class: | ICSharpCode.SharpZipLib.Zip.Compression.Streams.StreamManipulator
Assembly: | ICSharpCode.SharpZipLib
File(s): | C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Zip\Compression\Streams\StreamManipulator.cs
Covered lines: | 51
Uncovered lines: | 12
Coverable lines: | 63
Total lines: | 241
Line coverage: | 80.9%
Branch coverage: | 67.6%

# Metrics

Method | Cyclomatic Complexity | Sequence Coverage | Branch Coverage
--- | --- | --- | ---
PeekBits(...) | 3 | 100 | 100
DropBits(...) | 1 | 100 | 100
GetBits(...) | 2 | 0 | 0
SkipToByteBoundary() | 1 | 100 | 100
CopyBytes(...) | 8 | 86.36 | 80
Reset() | 1 | 100 | 100
SetInput(...) | 8 | 72.22 | 60

# File(s)

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

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | ``
|  | `3` |  | `namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams`
|  | `4` |  | `{`
|  | `5` |  | `/// <summary>`
|  | `6` |  | `/// This class allows us to retrieve a specified number of bits from`
|  | `7` |  | `/// the input buffer, as well as copy big byte blocks.`
|  | `8` |  | `///`
|  | `9` |  | `/// It uses an int buffer to store up to 31 bits for direct`
|  | `10` |  | `/// manipulation. This guarantees that we can get at least 16 bits,`
|  | `11` |  | `/// but we only need at most 15, so this is all safe.`
|  | `12` |  | `///`
|  | `13` |  | `/// There are some optimizations in this class, for example, you must`
|  | `14` |  | `/// never peek more than 8 bits more than needed, and you must first`
|  | `15` |  | `/// peek bits before you may drop them. This is not a general purpose`
|  | `16` |  | `/// class but optimized for the behaviour of the Inflater.`
|  | `17` |  | `///`
|  | `18` |  | `/// authors of the original java version : John Leuner, Jochen Hoenicke`
|  | `19` |  | `/// </summary>`
|  | `20` |  | `public class StreamManipulator`
|  | `21` |  | `{`
|  | `22` |  | `/// <summary>`
|  | `23` |  | `/// Get the next sequence of bits but don't increase input pointer. bitCount must be`
|  | `24` |  | `/// less or equal 16 and if this call succeeds, you must drop`
|  | `25` |  | `/// at least n - 8 bits in the next call.`
|  | `26` |  | `/// </summary>`
|  | `27` |  | `/// <param name="bitCount">The number of bits to peek.</param>`
|  | `28` |  | `/// <returns>`
|  | `29` |  | `/// the value of the bits, or -1 if not enough bits available. */`
|  | `30` |  | `/// </returns>`
|  | `31` |  | `public int PeekBits(int bitCount)`
|  | `32` |  | `{`
| 11620 | `33` |  | `if (bitsInBuffer_ < bitCount) {`
| 6287 | `34` |  | `if (windowStart_ == windowEnd_) {`
| 396 | `35` |  | `return -1; // ok`
|  | `36` |  | `}`
| 5891 | `37` |  | `buffer_ |= (uint)((window_[windowStart_++] & 0xff |`
| 5891 | `38` |  | `(window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_);`
| 5891 | `39` |  | `bitsInBuffer_ += 16;`
|  | `40` |  | `}`
| 11224 | `41` |  | `return (int)(buffer_ & ((1 << bitCount) - 1));`
|  | `42` |  | `}`
|  | `43` |  | ``
|  | `44` |  | `/// <summary>`
|  | `45` |  | `/// Drops the next n bits from the input. You should have called PeekBits`
|  | `46` |  | `/// with a bigger or equal n before, to make sure that enough bits are in`
|  | `47` |  | `/// the bit buffer.`
|  | `48` |  | `/// </summary>`
|  | `49` |  | `/// <param name="bitCount">The number of bits to drop.</param>`
|  | `50` |  | `public void DropBits(int bitCount)`
|  | `51` |  | `{`
| 11224 | `52` |  | `buffer_ >>= bitCount;`
| 11224 | `53` |  | `bitsInBuffer_ -= bitCount;`
| 11224 | `54` |  | `}`
|  | `55` |  | ``
|  | `56` |  | `/// <summary>`
|  | `57` |  | `/// Gets the next n bits and increases input pointer. This is equivalent`
|  | `58` |  | `/// to <see cref="PeekBits"/> followed by <see cref="DropBits"/>, except for correct error handling.`
|  | `59` |  | `/// </summary>`
|  | `60` |  | `/// <param name="bitCount">The number of bits to retrieve.</param>`
|  | `61` |  | `/// <returns>`
|  | `62` |  | `/// the value of the bits, or -1 if not enough bits available.`
|  | `63` |  | `/// </returns>`
|  | `64` |  | `public int GetBits(int bitCount)`
|  | `65` |  | `{`
| 0 | `66` |  | `int bits = PeekBits(bitCount);`
| 0 | `67` |  | `if (bits >= 0) {`
| 0 | `68` |  | `DropBits(bitCount);`
|  | `69` |  | `}`
| 0 | `70` |  | `return bits;`
|  | `71` |  | `}`
|  | `72` |  | ``
|  | `73` |  | `/// <summary>`
|  | `74` |  | `/// Gets the number of bits available in the bit buffer. This must be`
|  | `75` |  | `/// only called when a previous PeekBits() returned -1.`
|  | `76` |  | `/// </summary>`
|  | `77` |  | `/// <returns>`
|  | `78` |  | `/// the number of bits available.`
|  | `79` |  | `/// </returns>`
|  | `80` |  | `public int AvailableBits {`
|  | `81` |  | `get {`
| 23 | `82` |  | `return bitsInBuffer_;`
|  | `83` |  | `}`
|  | `84` |  | `}`
|  | `85` |  | ``
|  | `86` |  | `/// <summary>`
|  | `87` |  | `/// Gets the number of bytes available.`
|  | `88` |  | `/// </summary>`
|  | `89` |  | `/// <returns>`
|  | `90` |  | `/// The number of bytes available.`
|  | `91` |  | `/// </returns>`
|  | `92` |  | `public int AvailableBytes {`
|  | `93` |  | `get {`
| 2327 | `94` |  | `return windowEnd_ - windowStart_ + (bitsInBuffer_ >> 3);`
|  | `95` |  | `}`
|  | `96` |  | `}`
|  | `97` |  | ``
|  | `98` |  | `/// <summary>`
|  | `99` |  | `/// Skips to the next byte boundary.`
|  | `100` |  | `/// </summary>`
|  | `101` |  | `public void SkipToByteBoundary()`
|  | `102` |  | `{`
| 303 | `103` |  | `buffer_ >>= (bitsInBuffer_ & 7);`
| 303 | `104` |  | `bitsInBuffer_ &= ~7;`
| 303 | `105` |  | `}`
|  | `106` |  | ``
|  | `107` |  | `/// <summary>`
|  | `108` |  | `/// Returns true when SetInput can be called`
|  | `109` |  | `/// </summary>`
|  | `110` |  | `public bool IsNeedingInput {`
|  | `111` |  | `get {`
| 3355 | `112` |  | `return windowStart_ == windowEnd_;`
|  | `113` |  | `}`
|  | `114` |  | `}`
|  | `115` |  | ``
|  | `116` |  | `/// <summary>`
|  | `117` |  | `/// Copies bytes from input buffer to output buffer starting`
|  | `118` |  | `/// at output[offset]. You have to make sure, that the buffer is`
|  | `119` |  | `/// byte aligned. If not enough bytes are available, copies fewer`
|  | `120` |  | `/// bytes.`
|  | `121` |  | `/// </summary>`
|  | `122` |  | `/// <param name="output">`
|  | `123` |  | `/// The buffer to copy bytes to.`
|  | `124` |  | `/// </param>`
|  | `125` |  | `/// <param name="offset">`
|  | `126` |  | `/// The offset in the buffer at which copying starts`
|  | `127` |  | `/// </param>`
|  | `128` |  | `/// <param name="length">`
|  | `129` |  | `/// The length to copy, 0 is allowed.`
|  | `130` |  | `/// </param>`
|  | `131` |  | `/// <returns>`
|  | `132` |  | `/// The number of bytes copied, 0 if no bytes were available.`
|  | `133` |  | `/// </returns>`
|  | `134` |  | `/// <exception cref="ArgumentOutOfRangeException">`
|  | `135` |  | `/// Length is less than zero`
|  | `136` |  | `/// </exception>`
|  | `137` |  | `/// <exception cref="InvalidOperationException">`
|  | `138` |  | `/// Bit buffer isnt byte aligned`
|  | `139` |  | `/// </exception>`
|  | `140` |  | `public int CopyBytes(byte[] output, int offset, int length)`
|  | `141` |  | `{`
| 2376 | `142` |  | `if (length < 0) {`
| 0 | `143` |  | `throw new ArgumentOutOfRangeException(nameof(length));`
|  | `144` |  | `}`
|  | `145` |  | ``
| 2376 | `146` |  | `if ((bitsInBuffer_ & 7) != 0) {`
|  | `147` |  | `// bits_in_buffer may only be 0 or a multiple of 8`
| 0 | `148` |  | `throw new InvalidOperationException("Bit buffer is not byte aligned!");`
|  | `149` |  | `}`
|  | `150` |  | ``
| 2376 | `151` |  | `int count = 0;`
| 2600 | `152` |  | `while ((bitsInBuffer_ > 0) && (length > 0)) {`
| 224 | `153` |  | `output[offset++] = (byte)buffer_;`
| 224 | `154` |  | `buffer_ >>= 8;`
| 224 | `155` |  | `bitsInBuffer_ -= 8;`
| 224 | `156` |  | `length--;`
| 224 | `157` |  | `count++;`
|  | `158` |  | `}`
|  | `159` |  | ``
| 2376 | `160` |  | `if (length == 0) {`
| 996 | `161` |  | `return count;`
|  | `162` |  | `}`
|  | `163` |  | ``
| 1380 | `164` |  | `int avail = windowEnd_ - windowStart_;`
| 1380 | `165` |  | `if (length > avail) {`
| 0 | `166` |  | `length = avail;`
|  | `167` |  | `}`
| 1380 | `168` |  | `System.Array.Copy(window_, windowStart_, output, offset, length);`
| 1380 | `169` |  | `windowStart_ += length;`
|  | `170` |  | ``
| 1380 | `171` |  | `if (((windowStart_ - windowEnd_) & 1) != 0) {`
|  | `172` |  | `// We always want an even number of bytes in input, see peekBits`
| 210 | `173` |  | `buffer_ = (uint)(window_[windowStart_++] & 0xff);`
| 210 | `174` |  | `bitsInBuffer_ = 8;`
|  | `175` |  | `}`
| 1380 | `176` |  | `return count + length;`
|  | `177` |  | `}`
|  | `178` |  | ``
|  | `179` |  | `/// <summary>`
|  | `180` |  | `/// Resets state and empties internal buffers`
|  | `181` |  | `/// </summary>`
|  | `182` |  | `public void Reset()`
|  | `183` |  | `{`
| 41 | `184` |  | `buffer_ = 0;`
| 41 | `185` |  | `windowStart_ = windowEnd_ = bitsInBuffer_ = 0;`
| 41 | `186` |  | `}`
|  | `187` |  | ``
|  | `188` |  | `/// <summary>`
|  | `189` |  | `/// Add more input for consumption.`
|  | `190` |  | `/// Only call when IsNeedingInput returns true`
|  | `191` |  | `/// </summary>`
|  | `192` |  | `/// <param name="buffer">data to be input</param>`
|  | `193` |  | `/// <param name="offset">offset of first byte of input</param>`
|  | `194` |  | `/// <param name="count">number of bytes of input to add.</param>`
|  | `195` |  | `public void SetInput(byte[] buffer, int offset, int count)`
|  | `196` |  | `{`
| 1433 | `197` |  | `if (buffer == null) {`
| 0 | `198` |  | `throw new ArgumentNullException(nameof(buffer));`
|  | `199` |  | `}`
|  | `200` |  | ``
| 1433 | `201` |  | `if (offset < 0) {`
| 0 | `202` |  | `throw new ArgumentOutOfRangeException(nameof(offset), "Cannot be negative");`
|  | `203` |  | `}`
|  | `204` |  | ``
| 1433 | `205` |  | `if (count < 0) {`
| 0 | `206` |  | `throw new ArgumentOutOfRangeException(nameof(count), "Cannot be negative");`
|  | `207` |  | `}`
|  | `208` |  | ``
| 1433 | `209` |  | `if (windowStart_ < windowEnd_) {`
| 0 | `210` |  | `throw new InvalidOperationException("Old input was not completely processed");`
|  | `211` |  | `}`
|  | `212` |  | ``
| 1433 | `213` |  | `int end = offset + count;`
|  | `214` |  | ``
|  | `215` |  | `// We want to throw an ArrayIndexOutOfBoundsException early.`
|  | `216` |  | `// Note the check also handles integer wrap around.`
| 1433 | `217` |  | `if ((offset > end) || (end > buffer.Length)) {`
| 0 | `218` |  | `throw new ArgumentOutOfRangeException(nameof(count));`
|  | `219` |  | `}`
|  | `220` |  | ``
| 1433 | `221` |  | `if ((count & 1) != 0) {`
|  | `222` |  | `// We always want an even number of bytes in input, see PeekBits`
| 214 | `223` |  | `buffer_ |= (uint)((buffer[offset++] & 0xff) << bitsInBuffer_);`
| 214 | `224` |  | `bitsInBuffer_ += 8;`
|  | `225` |  | `}`
|  | `226` |  | ``
| 1433 | `227` |  | `window_ = buffer;`
| 1433 | `228` |  | `windowStart_ = offset;`
| 1433 | `229` |  | `windowEnd_ = end;`
| 1433 | `230` |  | `}`
|  | `231` |  | ``
|  | `232` |  | `#region Instance Fields`
|  | `233` |  | `private byte[] window_;`
|  | `234` |  | `private int windowStart_;`
|  | `235` |  | `private int windowEnd_;`
|  | `236` |  | ``
|  | `237` |  | `private uint buffer_;`
|  | `238` |  | `private int bitsInBuffer_;`
|  | `239` |  | `#endregion`
|  | `240` |  | `}`
|  | `241` |  | `}`