namespace System.Net.ApiService.Compression.Brotli { internal sealed class State { internal int runningState = RunningState.Uninitialized; internal int nextRunningState; internal readonly BitReader br = new BitReader(); internal byte[] ringBuffer; internal readonly int[] blockTypeTrees = new int[3 * System.Net.ApiService.Compression.Brotli.Huffman.HuffmanMaxTableSize]; internal readonly int[] blockLenTrees = new int[3 * System.Net.ApiService.Compression.Brotli.Huffman.HuffmanMaxTableSize]; internal int metaBlockLength; internal bool inputEnd; internal bool isUncompressed; internal bool isMetadata; internal readonly System.Net.ApiService.Compression.Brotli.HuffmanTreeGroup hGroup0 = new System.Net.ApiService.Compression.Brotli.HuffmanTreeGroup(); internal readonly System.Net.ApiService.Compression.Brotli.HuffmanTreeGroup hGroup1 = new System.Net.ApiService.Compression.Brotli.HuffmanTreeGroup(); internal readonly System.Net.ApiService.Compression.Brotli.HuffmanTreeGroup hGroup2 = new System.Net.ApiService.Compression.Brotli.HuffmanTreeGroup(); internal readonly int[] blockLength = new int[3]; internal readonly int[] numBlockTypes = new int[3]; internal readonly int[] blockTypeRb = new int[6]; internal readonly int[] distRb = new int[] { 16, 15, 11, 4 }; internal int pos = 0; internal int maxDistance = 0; internal int distRbIdx = 0; internal bool trivialLiteralContext = false; internal int literalTreeIndex = 0; internal int literalTree; internal int j; internal int insertLength; internal byte[] contextModes; internal byte[] contextMap; internal int contextMapSlice; internal int distContextMapSlice; internal int contextLookupOffset1; internal int contextLookupOffset2; internal int treeCommandOffset; internal int distanceCode; internal byte[] distContextMap; internal int numDirectDistanceCodes; internal int distancePostfixMask; internal int distancePostfixBits; internal int distance; internal int copyLength; internal int copyDst; internal int maxBackwardDistance; internal int maxRingBufferSize; internal int ringBufferSize = 0; internal long expectedTotalSize = 0; internal byte[] customDictionary = new byte[0]; internal int bytesToIgnore = 0; internal int outputOffset; internal int outputLength; internal int outputUsed; internal int bytesWritten; internal int bytesToWrite; internal byte[] output; // Current meta-block header information. // TODO: Update to current spec. private static int DecodeWindowBits(BitReader br) { if (BitReader.ReadBits(br, 1) == 0) { return 16; } int n = BitReader.ReadBits(br, 3); if (n != 0) { return 17 + n; } n = BitReader.ReadBits(br, 3); if (n != 0) { return 8 + n; } return 17; } /// Associate input with decoder state. /// uninitialized state without associated input /// compressed data source internal static void SetInput(System.Net.ApiService.Compression.Brotli.State state, System.IO.Stream input) { if (state.runningState != System.Net.ApiService.Compression.Brotli.RunningState.Uninitialized) { throw new System.InvalidOperationException("State MUST be uninitialized"); } System.Net.ApiService.Compression.Brotli.BitReader.Init(state.br, input); int windowBits = DecodeWindowBits(state.br); if (windowBits == 9) { /* Reserved case for future expansion. */ throw new System.Net.ApiService.Compression.Brotli.BrotliRuntimeException("Invalid 'windowBits' code"); } state.maxRingBufferSize = 1 << windowBits; state.maxBackwardDistance = state.maxRingBufferSize - 16; state.runningState = System.Net.ApiService.Compression.Brotli.RunningState.BlockStart; } /// internal static void Close(System.Net.ApiService.Compression.Brotli.State state) { if (state.runningState == System.Net.ApiService.Compression.Brotli.RunningState.Uninitialized) { throw new System.InvalidOperationException("State MUST be initialized"); } if (state.runningState == System.Net.ApiService.Compression.Brotli.RunningState.Closed) { return; } state.runningState = System.Net.ApiService.Compression.Brotli.RunningState.Closed; System.Net.ApiService.Compression.Brotli.BitReader.Close(state.br); } } }