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

# Summary

Class: | ICSharpCode.SharpZipLib.Zip.Compression.Streams.OutputWindow
Assembly: | ICSharpCode.SharpZipLib
File(s): | C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Zip\Compression\Streams\OutputWindow.cs
Covered lines: | 46
Uncovered lines: | 20
Coverable lines: | 66
Total lines: | 195
Line coverage: | 69.6%
Branch coverage: | 53.3%

# Metrics

Method | Cyclomatic Complexity | Sequence Coverage | Branch Coverage
--- | --- | --- | ---
Write(...) | 2 | 80 | 66.67
SlowRepeat(...) | 2 | 0 | 0
Repeat(...) | 6 | 78.57 | 72.73
CopyStored(...) | 3 | 100 | 80
CopyDict(...) | 4 | 0 | 0
GetFreeSpace() | 1 | 100 | 100
GetAvailable() | 1 | 100 | 100
CopyOutput(...) | 4 | 93.75 | 85.71
Reset() | 1 | 100 | 100
.ctor() | 1 | 100 | 100

# File(s)

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

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | ``
|  | `3` |  | `namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams`
|  | `4` |  | `{`
|  | `5` |  | `/// <summary>`
|  | `6` |  | `/// Contains the output from the Inflation process.`
|  | `7` |  | `/// We need to have a window so that we can refer backwards into the output stream`
|  | `8` |  | `/// to repeat stuff.<br/>`
|  | `9` |  | `/// Author of the original java version : John Leuner`
|  | `10` |  | `/// </summary>`
|  | `11` |  | `public class OutputWindow`
|  | `12` |  | `{`
|  | `13` |  | `#region Constants`
|  | `14` |  | `const int WindowSize = 1 << 15;`
|  | `15` |  | `const int WindowMask = WindowSize - 1;`
|  | `16` |  | `#endregion`
|  | `17` |  | ``
|  | `18` |  | `#region Instance Fields`
| 435 | `19` |  | `byte[] window = new byte[WindowSize]; //The window is 2^15 bytes`
|  | `20` |  | `int windowEnd;`
|  | `21` |  | `int windowFilled;`
|  | `22` |  | `#endregion`
|  | `23` |  | ``
|  | `24` |  | `/// <summary>`
|  | `25` |  | `/// Write a byte to this output window`
|  | `26` |  | `/// </summary>`
|  | `27` |  | `/// <param name="value">value to write</param>`
|  | `28` |  | `/// <exception cref="InvalidOperationException">`
|  | `29` |  | `/// if window is full`
|  | `30` |  | `/// </exception>`
|  | `31` |  | `public void Write(int value)`
|  | `32` |  | `{`
| 9229 | `33` |  | `if (windowFilled++ == WindowSize) {`
| 0 | `34` |  | `throw new InvalidOperationException("Window full");`
|  | `35` |  | `}`
| 9229 | `36` |  | `window[windowEnd++] = (byte)value;`
| 9229 | `37` |  | `windowEnd &= WindowMask;`
| 9229 | `38` |  | `}`
|  | `39` |  | ``
|  | `40` |  | ``
|  | `41` |  | `private void SlowRepeat(int repStart, int length, int distance)`
|  | `42` |  | `{`
| 0 | `43` |  | `while (length-- > 0) {`
| 0 | `44` |  | `window[windowEnd++] = window[repStart++];`
| 0 | `45` |  | `windowEnd &= WindowMask;`
| 0 | `46` |  | `repStart &= WindowMask;`
|  | `47` |  | `}`
| 0 | `48` |  | `}`
|  | `49` |  | ``
|  | `50` |  | `/// <summary>`
|  | `51` |  | `/// Append a byte pattern already in the window itself`
|  | `52` |  | `/// </summary>`
|  | `53` |  | `/// <param name="length">length of pattern to copy</param>`
|  | `54` |  | `/// <param name="distance">distance from end of window pattern occurs</param>`
|  | `55` |  | `/// <exception cref="InvalidOperationException">`
|  | `56` |  | `/// If the repeated data overflows the window`
|  | `57` |  | `/// </exception>`
|  | `58` |  | `public void Repeat(int length, int distance)`
|  | `59` |  | `{`
| 97 | `60` |  | `if ((windowFilled += length) > WindowSize) {`
| 0 | `61` |  | `throw new InvalidOperationException("Window full");`
|  | `62` |  | `}`
|  | `63` |  | ``
| 97 | `64` |  | `int repStart = (windowEnd - distance) & WindowMask;`
| 97 | `65` |  | `int border = WindowSize - length;`
| 97 | `66` |  | `if ((repStart <= border) && (windowEnd < border)) {`
| 97 | `67` |  | `if (length <= distance) {`
| 37 | `68` |  | `System.Array.Copy(window, repStart, window, windowEnd, length);`
| 37 | `69` |  | `windowEnd += length;`
| 37 | `70` |  | `} else {`
|  | `71` |  | `// We have to copy manually, since the repeat pattern overlaps.`
| 11461 | `72` |  | `while (length-- > 0) {`
| 11401 | `73` |  | `window[windowEnd++] = window[repStart++];`
|  | `74` |  | `}`
|  | `75` |  | `}`
| 60 | `76` |  | `} else {`
| 0 | `77` |  | `SlowRepeat(repStart, length, distance);`
|  | `78` |  | `}`
| 0 | `79` |  | `}`
|  | `80` |  | ``
|  | `81` |  | `/// <summary>`
|  | `82` |  | `/// Copy from input manipulator to internal window`
|  | `83` |  | `/// </summary>`
|  | `84` |  | `/// <param name="input">source of data</param>`
|  | `85` |  | `/// <param name="length">length of data to copy</param>`
|  | `86` |  | `/// <returns>the number of bytes copied</returns>`
|  | `87` |  | `public int CopyStored(StreamManipulator input, int length)`
|  | `88` |  | `{`
| 2280 | `89` |  | `length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes);`
|  | `90` |  | `int copied;`
|  | `91` |  | ``
| 2280 | `92` |  | `int tailLen = WindowSize - windowEnd;`
| 2280 | `93` |  | `if (length > tailLen) {`
| 96 | `94` |  | `copied = input.CopyBytes(window, windowEnd, tailLen);`
| 96 | `95` |  | `if (copied == tailLen) {`
| 96 | `96` |  | `copied += input.CopyBytes(window, 0, length - tailLen);`
|  | `97` |  | `}`
| 96 | `98` |  | `} else {`
| 2184 | `99` |  | `copied = input.CopyBytes(window, windowEnd, length);`
|  | `100` |  | `}`
|  | `101` |  | ``
| 2280 | `102` |  | `windowEnd = (windowEnd + copied) & WindowMask;`
| 2280 | `103` |  | `windowFilled += copied;`
| 2280 | `104` |  | `return copied;`
|  | `105` |  | `}`
|  | `106` |  | ``
|  | `107` |  | `/// <summary>`
|  | `108` |  | `/// Copy dictionary to window`
|  | `109` |  | `/// </summary>`
|  | `110` |  | `/// <param name="dictionary">source dictionary</param>`
|  | `111` |  | `/// <param name="offset">offset of start in source dictionary</param>`
|  | `112` |  | `/// <param name="length">length of dictionary</param>`
|  | `113` |  | `/// <exception cref="InvalidOperationException">`
|  | `114` |  | `/// If window isnt empty`
|  | `115` |  | `/// </exception>`
|  | `116` |  | `public void CopyDict(byte[] dictionary, int offset, int length)`
|  | `117` |  | `{`
| 0 | `118` |  | `if (dictionary == null) {`
| 0 | `119` |  | `throw new ArgumentNullException(nameof(dictionary));`
|  | `120` |  | `}`
|  | `121` |  | ``
| 0 | `122` |  | `if (windowFilled > 0) {`
| 0 | `123` |  | `throw new InvalidOperationException();`
|  | `124` |  | `}`
|  | `125` |  | ``
| 0 | `126` |  | `if (length > WindowSize) {`
| 0 | `127` |  | `offset += length - WindowSize;`
| 0 | `128` |  | `length = WindowSize;`
|  | `129` |  | `}`
| 0 | `130` |  | `System.Array.Copy(dictionary, offset, window, 0, length);`
| 0 | `131` |  | `windowEnd = length & WindowMask;`
| 0 | `132` |  | `}`
|  | `133` |  | ``
|  | `134` |  | `/// <summary>`
|  | `135` |  | `/// Get remaining unfilled space in window`
|  | `136` |  | `/// </summary>`
|  | `137` |  | `/// <returns>Number of bytes left in window</returns>`
|  | `138` |  | `public int GetFreeSpace()`
|  | `139` |  | `{`
| 371 | `140` |  | `return WindowSize - windowFilled;`
|  | `141` |  | `}`
|  | `142` |  | ``
|  | `143` |  | `/// <summary>`
|  | `144` |  | `/// Get bytes available for output in window`
|  | `145` |  | `/// </summary>`
|  | `146` |  | `/// <returns>Number of bytes filled</returns>`
|  | `147` |  | `public int GetAvailable()`
|  | `148` |  | `{`
| 3783 | `149` |  | `return windowFilled;`
|  | `150` |  | `}`
|  | `151` |  | ``
|  | `152` |  | `/// <summary>`
|  | `153` |  | `/// Copy contents of window to output`
|  | `154` |  | `/// </summary>`
|  | `155` |  | `/// <param name="output">buffer to copy to</param>`
|  | `156` |  | `/// <param name="offset">offset to start at</param>`
|  | `157` |  | `/// <param name="len">number of bytes to count</param>`
|  | `158` |  | `/// <returns>The number of bytes copied</returns>`
|  | `159` |  | `/// <exception cref="InvalidOperationException">`
|  | `160` |  | `/// If a window underflow occurs`
|  | `161` |  | `/// </exception>`
|  | `162` |  | `public int CopyOutput(byte[] output, int offset, int len)`
|  | `163` |  | `{`
| 4523 | `164` |  | `int copyEnd = windowEnd;`
| 4523 | `165` |  | `if (len > windowFilled) {`
| 4401 | `166` |  | `len = windowFilled;`
| 4401 | `167` |  | `} else {`
| 122 | `168` |  | `copyEnd = (windowEnd - windowFilled + len) & WindowMask;`
|  | `169` |  | `}`
|  | `170` |  | ``
| 4523 | `171` |  | `int copied = len;`
| 4523 | `172` |  | `int tailLen = len - copyEnd;`
|  | `173` |  | ``
| 4523 | `174` |  | `if (tailLen > 0) {`
| 102 | `175` |  | `System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen);`
| 102 | `176` |  | `offset += tailLen;`
| 102 | `177` |  | `len = copyEnd;`
|  | `178` |  | `}`
| 4523 | `179` |  | `System.Array.Copy(window, copyEnd - len, output, offset, len);`
| 4523 | `180` |  | `windowFilled -= copied;`
| 4523 | `181` |  | `if (windowFilled < 0) {`
| 0 | `182` |  | `throw new InvalidOperationException();`
|  | `183` |  | `}`
| 4523 | `184` |  | `return copied;`
|  | `185` |  | `}`
|  | `186` |  | ``
|  | `187` |  | `/// <summary>`
|  | `188` |  | `/// Reset by clearing window so <see cref="GetAvailable">GetAvailable</see> returns 0`
|  | `189` |  | `/// </summary>`
|  | `190` |  | `public void Reset()`
|  | `191` |  | `{`
| 41 | `192` |  | `windowFilled = windowEnd = 0;`
| 41 | `193` |  | `}`
|  | `194` |  | `}`
|  | `195` |  | `}`