1 /* Copyright 2015 Google Inc. All Rights Reserved. 2 3 Distributed under MIT license. 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 */ 6 namespace Org.Brotli.Dec 7 { 8 internal sealed class State 9 { 10 internal int runningState = Org.Brotli.Dec.RunningState.Uninitialized; 11 12 internal int nextRunningState; 13 14 internal readonly Org.Brotli.Dec.BitReader br = new Org.Brotli.Dec.BitReader(); 15 16 internal byte[] ringBuffer; 17 18 internal readonly int[] blockTypeTrees = new int[3 * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize]; 19 20 internal readonly int[] blockLenTrees = new int[3 * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize]; 21 22 internal int metaBlockLength; 23 24 internal bool inputEnd; 25 26 internal bool isUncompressed; 27 28 internal bool isMetadata; 29 30 internal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup0 = new Org.Brotli.Dec.HuffmanTreeGroup(); 31 32 internal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup1 = new Org.Brotli.Dec.HuffmanTreeGroup(); 33 34 internal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup2 = new Org.Brotli.Dec.HuffmanTreeGroup(); 35 36 internal readonly int[] blockLength = new int[3]; 37 38 internal readonly int[] numBlockTypes = new int[3]; 39 40 internal readonly int[] blockTypeRb = new int[6]; 41 42 internal readonly int[] distRb = new int[] { 16, 15, 11, 4 }; 43 44 internal int pos = 0; 45 46 internal int maxDistance = 0; 47 48 internal int distRbIdx = 0; 49 50 internal bool trivialLiteralContext = false; 51 52 internal int literalTreeIndex = 0; 53 54 internal int literalTree; 55 56 internal int j; 57 58 internal int insertLength; 59 60 internal byte[] contextModes; 61 62 internal byte[] contextMap; 63 64 internal int contextMapSlice; 65 66 internal int distContextMapSlice; 67 68 internal int contextLookupOffset1; 69 70 internal int contextLookupOffset2; 71 72 internal int treeCommandOffset; 73 74 internal int distanceCode; 75 76 internal byte[] distContextMap; 77 78 internal int numDirectDistanceCodes; 79 80 internal int distancePostfixMask; 81 82 internal int distancePostfixBits; 83 84 internal int distance; 85 86 internal int copyLength; 87 88 internal int copyDst; 89 90 internal int maxBackwardDistance; 91 92 internal int maxRingBufferSize; 93 94 internal int ringBufferSize = 0; 95 96 internal long expectedTotalSize = 0; 97 98 internal byte[] customDictionary = new byte[0]; 99 100 internal int bytesToIgnore = 0; 101 102 internal int outputOffset; 103 104 internal int outputLength; 105 106 internal int outputUsed; 107 108 internal int bytesWritten; 109 110 internal int bytesToWrite; 111 112 internal byte[] output; 113 114 // Current meta-block header information. 115 // TODO: Update to current spec. DecodeWindowBits(Org.Brotli.Dec.BitReader br)116 private static int DecodeWindowBits(Org.Brotli.Dec.BitReader br) 117 { 118 if (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 0) 119 { 120 return 16; 121 } 122 int n = Org.Brotli.Dec.BitReader.ReadBits(br, 3); 123 if (n != 0) 124 { 125 return 17 + n; 126 } 127 n = Org.Brotli.Dec.BitReader.ReadBits(br, 3); 128 if (n != 0) 129 { 130 return 8 + n; 131 } 132 return 17; 133 } 134 135 /// <summary>Associate input with decoder state.</summary> 136 /// <param name="state">uninitialized state without associated input</param> 137 /// <param name="input">compressed data source</param> SetInput(Org.Brotli.Dec.State state, System.IO.Stream input)138 internal static void SetInput(Org.Brotli.Dec.State state, System.IO.Stream input) 139 { 140 if (state.runningState != Org.Brotli.Dec.RunningState.Uninitialized) 141 { 142 throw new System.InvalidOperationException("State MUST be uninitialized"); 143 } 144 Org.Brotli.Dec.BitReader.Init(state.br, input); 145 int windowBits = DecodeWindowBits(state.br); 146 if (windowBits == 9) 147 { 148 /* Reserved case for future expansion. */ 149 throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid 'windowBits' code"); 150 } 151 state.maxRingBufferSize = 1 << windowBits; 152 state.maxBackwardDistance = state.maxRingBufferSize - 16; 153 state.runningState = Org.Brotli.Dec.RunningState.BlockStart; 154 } 155 156 /// <exception cref="System.IO.IOException"/> Close(Org.Brotli.Dec.State state)157 internal static void Close(Org.Brotli.Dec.State state) 158 { 159 if (state.runningState == Org.Brotli.Dec.RunningState.Uninitialized) 160 { 161 throw new System.InvalidOperationException("State MUST be initialized"); 162 } 163 if (state.runningState == Org.Brotli.Dec.RunningState.Closed) 164 { 165 return; 166 } 167 state.runningState = Org.Brotli.Dec.RunningState.Closed; 168 Org.Brotli.Dec.BitReader.Close(state.br); 169 } 170 } 171 } 172