private static void DecodeBlockTypeAndLength(iText.IO.Codec.Brotli.Dec.State state, int treeType) { iText.IO.Codec.Brotli.Dec.BitReader br = state.br; int[] ringBuffers = state.blockTypeRb; int offset = treeType * 2; iText.IO.Codec.Brotli.Dec.BitReader.FillBitWindow(br); int blockType = ReadSymbol(state.blockTypeTrees, treeType * iText.IO.Codec.Brotli.Dec.Huffman.HuffmanMaxTableSize, br); state.blockLength[treeType] = ReadBlockLength(state.blockLenTrees, treeType * iText.IO.Codec.Brotli.Dec.Huffman.HuffmanMaxTableSize, br); if (blockType == 1) { blockType = ringBuffers[offset + 1] + 1; } else if (blockType == 0) { blockType = ringBuffers[offset]; } else { blockType -= 2; } if (blockType >= state.numBlockTypes[treeType]) { blockType -= state.numBlockTypes[treeType]; } ringBuffers[offset] = ringBuffers[offset + 1]; ringBuffers[offset + 1] = blockType; }
private static void CopyUncompressedData(iText.IO.Codec.Brotli.Dec.State state) { iText.IO.Codec.Brotli.Dec.BitReader br = state.br; byte[] ringBuffer = state.ringBuffer; // Could happen if block ends at ring buffer end. if (state.metaBlockLength <= 0) { iText.IO.Codec.Brotli.Dec.BitReader.Reload(br); state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.BlockStart; return; } int chunkLength = System.Math.Min(state.ringBufferSize - state.pos, state.metaBlockLength); iText.IO.Codec.Brotli.Dec.BitReader.CopyBytes(br, ringBuffer, state.pos, chunkLength); state.metaBlockLength -= chunkLength; state.pos += chunkLength; if (state.pos == state.ringBufferSize) { state.nextRunningState = iText.IO.Codec.Brotli.Dec.RunningState.CopyUncompressed; state.bytesToWrite = state.ringBufferSize; state.bytesWritten = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Write; return; } iText.IO.Codec.Brotli.Dec.BitReader.Reload(br); state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.BlockStart; }
/// <exception cref="System.IO.IOException"/> internal static void Close(iText.IO.Codec.Brotli.Dec.State state) { if (state.runningState == iText.IO.Codec.Brotli.Dec.RunningState.Uninitialized) { throw new System.InvalidOperationException("State MUST be initialized"); } if (state.runningState == iText.IO.Codec.Brotli.Dec.RunningState.Closed) { return; } state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Closed; iText.IO.Codec.Brotli.Dec.BitReader.Close(state.br); }
private static void DecodeLiteralBlockSwitch(iText.IO.Codec.Brotli.Dec.State state) { DecodeBlockTypeAndLength(state, 0); int literalBlockType = state.blockTypeRb[1]; state.contextMapSlice = literalBlockType << LiteralContextBits; state.literalTreeIndex = state.contextMap[state.contextMapSlice] & unchecked ((int)(0xFF)); state.literalTree = state.hGroup0.trees[state.literalTreeIndex]; int contextMode = state.contextModes[literalBlockType]; state.contextLookupOffset1 = iText.IO.Codec.Brotli.Dec.Context.LookupOffsets[contextMode]; state.contextLookupOffset2 = iText.IO.Codec.Brotli.Dec.Context.LookupOffsets[contextMode + 1]; }
private static void MaybeReallocateRingBuffer(iText.IO.Codec.Brotli.Dec.State state) { int newSize = state.maxRingBufferSize; if ((long)newSize > state.expectedTotalSize) { /* TODO: Handle 2GB+ cases more gracefully. */ int minimalNewSize = (int)state.expectedTotalSize + state.customDictionary.Length; while ((newSize >> 1) > minimalNewSize) { newSize >>= 1; } if (!state.inputEnd && newSize < 16384 && state.maxRingBufferSize >= 16384) { newSize = 16384; } } if (newSize <= state.ringBufferSize) { return; } int ringBufferSizeWithSlack = newSize + iText.IO.Codec.Brotli.Dec.Dictionary.MaxTransformedWordLength; byte[] newBuffer = new byte[ringBufferSizeWithSlack]; if (state.ringBuffer != null) { System.Array.Copy(state.ringBuffer, 0, newBuffer, 0, state.ringBufferSize); } else if (state.customDictionary.Length != 0) { /* Prepend custom dictionary, if any. */ int length = state.customDictionary.Length; int offset = 0; if (length > state.maxBackwardDistance) { offset = length - state.maxBackwardDistance; length = state.maxBackwardDistance; } System.Array.Copy(state.customDictionary, offset, newBuffer, 0, length); state.pos = length; state.bytesToIgnore = length; } state.ringBuffer = newBuffer; state.ringBufferSize = newSize; }
/// <summary>Associate input with decoder state.</summary> /// <param name="state">uninitialized state without associated input</param> /// <param name="input">compressed data source</param> internal static void SetInput(iText.IO.Codec.Brotli.Dec.State state, System.IO.Stream input) { if (state.runningState != iText.IO.Codec.Brotli.Dec.RunningState.Uninitialized) { throw new System.InvalidOperationException("State MUST be uninitialized"); } iText.IO.Codec.Brotli.Dec.BitReader.Init(state.br, input); int windowBits = DecodeWindowBits(state.br); if (windowBits == 9) { /* Reserved case for future expansion. */ throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Invalid 'windowBits' code"); } state.maxRingBufferSize = 1 << windowBits; state.maxBackwardDistance = state.maxRingBufferSize - 16; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.BlockStart; }
private static bool WriteRingBuffer(iText.IO.Codec.Brotli.Dec.State state) { /* Ignore custom dictionary bytes. */ if (state.bytesToIgnore != 0) { state.bytesWritten += state.bytesToIgnore; state.bytesToIgnore = 0; } int toWrite = System.Math.Min(state.outputLength - state.outputUsed, state.bytesToWrite - state.bytesWritten); if (toWrite != 0) { System.Array.Copy(state.ringBuffer, state.bytesWritten, state.output, state.outputOffset + state.outputUsed, toWrite); state.outputUsed += toWrite; state.bytesWritten += toWrite; } return(state.outputUsed < state.outputLength); }
/// <summary>Reads next metablock header.</summary> /// <param name="state">decoding state</param> private static void ReadMetablockInfo(iText.IO.Codec.Brotli.Dec.State state) { iText.IO.Codec.Brotli.Dec.BitReader br = state.br; if (state.inputEnd) { state.nextRunningState = iText.IO.Codec.Brotli.Dec.RunningState.Finished; state.bytesToWrite = state.pos; state.bytesWritten = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Write; return; } // TODO: Reset? Do we need this? state.hGroup0.codes = null; state.hGroup0.trees = null; state.hGroup1.codes = null; state.hGroup1.trees = null; state.hGroup2.codes = null; state.hGroup2.trees = null; iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); DecodeMetaBlockLength(br, state); if (state.metaBlockLength == 0 && !state.isMetadata) { return; } if (state.isUncompressed || state.isMetadata) { iText.IO.Codec.Brotli.Dec.BitReader.JumpToByteBoundary(br); state.runningState = state.isMetadata ? iText.IO.Codec.Brotli.Dec.RunningState.ReadMetadata : iText.IO.Codec.Brotli.Dec.RunningState.CopyUncompressed; } else { state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.CompressedBlockStart; } if (state.isMetadata) { return; } state.expectedTotalSize += state.metaBlockLength; if (state.ringBufferSize < state.maxRingBufferSize) { MaybeReallocateRingBuffer(state); } }
/// <summary>Actual decompress implementation.</summary> internal static void Decompress(iText.IO.Codec.Brotli.Dec.State state) { if (state.runningState == iText.IO.Codec.Brotli.Dec.RunningState.Uninitialized) { throw new System.InvalidOperationException("Can't decompress until initialized"); } if (state.runningState == iText.IO.Codec.Brotli.Dec.RunningState.Closed) { throw new System.InvalidOperationException("Can't decompress after close"); } iText.IO.Codec.Brotli.Dec.BitReader br = state.br; int ringBufferMask = state.ringBufferSize - 1; byte[] ringBuffer = state.ringBuffer; while (state.runningState != iText.IO.Codec.Brotli.Dec.RunningState.Finished) { switch (state.runningState) { case iText.IO.Codec.Brotli.Dec.RunningState.BlockStart: { // TODO: extract cases to methods for the better readability. if (state.metaBlockLength < 0) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Invalid metablock length"); } ReadMetablockInfo(state); /* Ring-buffer would be reallocated here. */ ringBufferMask = state.ringBufferSize - 1; ringBuffer = state.ringBuffer; continue; } case iText.IO.Codec.Brotli.Dec.RunningState.CompressedBlockStart: { ReadMetablockHuffmanCodesAndContextMaps(state); state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.MainLoop; goto case iText.IO.Codec.Brotli.Dec.RunningState.MainLoop; } case iText.IO.Codec.Brotli.Dec.RunningState.MainLoop: { // Fall through if (state.metaBlockLength <= 0) { state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.BlockStart; continue; } iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); if (state.blockLength[1] == 0) { DecodeCommandBlockSwitch(state); } state.blockLength[1]--; iText.IO.Codec.Brotli.Dec.BitReader.FillBitWindow(br); int cmdCode = ReadSymbol(state.hGroup1.codes, state.treeCommandOffset, br); int rangeIdx = (int)(((uint)cmdCode) >> 6); state.distanceCode = 0; if (rangeIdx >= 2) { rangeIdx -= 2; state.distanceCode = -1; } int insertCode = iText.IO.Codec.Brotli.Dec.Prefix.InsertRangeLut[rangeIdx] + (((int)(((uint)cmdCode) >> 3)) & 7); int copyCode = iText.IO.Codec.Brotli.Dec.Prefix.CopyRangeLut[rangeIdx] + (cmdCode & 7); state.insertLength = iText.IO.Codec.Brotli.Dec.Prefix.InsertLengthOffset[insertCode] + iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, iText.IO.Codec.Brotli.Dec.Prefix.InsertLengthNBits[insertCode]); state.copyLength = iText.IO.Codec.Brotli.Dec.Prefix.CopyLengthOffset[copyCode] + iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, iText.IO.Codec.Brotli.Dec.Prefix.CopyLengthNBits[copyCode]); state.j = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.InsertLoop; goto case iText.IO.Codec.Brotli.Dec.RunningState.InsertLoop; } case iText.IO.Codec.Brotli.Dec.RunningState.InsertLoop: { // Fall through if (state.trivialLiteralContext) { while (state.j < state.insertLength) { iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); if (state.blockLength[0] == 0) { DecodeLiteralBlockSwitch(state); } state.blockLength[0]--; iText.IO.Codec.Brotli.Dec.BitReader.FillBitWindow(br); ringBuffer[state.pos] = unchecked ((byte)ReadSymbol(state.hGroup0.codes, state.literalTree, br)); state.j++; if (state.pos++ == ringBufferMask) { state.nextRunningState = iText.IO.Codec.Brotli.Dec.RunningState.InsertLoop; state.bytesToWrite = state.ringBufferSize; state.bytesWritten = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Write; break; } } } else { int prevByte1 = ringBuffer[(state.pos - 1) & ringBufferMask] & unchecked ((int)(0xFF)); int prevByte2 = ringBuffer[(state.pos - 2) & ringBufferMask] & unchecked ((int)(0xFF)); while (state.j < state.insertLength) { iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); if (state.blockLength[0] == 0) { DecodeLiteralBlockSwitch(state); } int literalTreeIndex = state.contextMap[state.contextMapSlice + (iText.IO.Codec.Brotli.Dec.Context.Lookup[state.contextLookupOffset1 + prevByte1] | iText.IO.Codec.Brotli.Dec.Context.Lookup[state.contextLookupOffset2 + prevByte2])] & unchecked ((int)(0xFF)); state.blockLength[0]--; prevByte2 = prevByte1; iText.IO.Codec.Brotli.Dec.BitReader.FillBitWindow(br); prevByte1 = ReadSymbol(state.hGroup0.codes, state.hGroup0.trees[literalTreeIndex], br); ringBuffer[state.pos] = unchecked ((byte)prevByte1); state.j++; if (state.pos++ == ringBufferMask) { state.nextRunningState = iText.IO.Codec.Brotli.Dec.RunningState.InsertLoop; state.bytesToWrite = state.ringBufferSize; state.bytesWritten = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Write; break; } } } if (state.runningState != iText.IO.Codec.Brotli.Dec.RunningState.InsertLoop) { continue; } state.metaBlockLength -= state.insertLength; if (state.metaBlockLength <= 0) { state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.MainLoop; continue; } if (state.distanceCode < 0) { iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); if (state.blockLength[2] == 0) { DecodeDistanceBlockSwitch(state); } state.blockLength[2]--; iText.IO.Codec.Brotli.Dec.BitReader.FillBitWindow(br); state.distanceCode = ReadSymbol(state.hGroup2.codes, state.hGroup2.trees[state.distContextMap[state.distContextMapSlice + (state.copyLength > 4 ? 3 : state.copyLength - 2)] & unchecked ((int)(0xFF))], br); if (state.distanceCode >= state.numDirectDistanceCodes) { state.distanceCode -= state.numDirectDistanceCodes; int postfix = state.distanceCode & state.distancePostfixMask; state.distanceCode = (int)(((uint)state.distanceCode) >> state.distancePostfixBits); int n = ((int)(((uint)state.distanceCode) >> 1)) + 1; int offset = ((2 + (state.distanceCode & 1)) << n) - 4; state.distanceCode = state.numDirectDistanceCodes + postfix + ((offset + iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, n)) << state.distancePostfixBits); } } // Convert the distance code to the actual distance by possibly looking up past distances // from the ringBuffer. state.distance = TranslateShortCodes(state.distanceCode, state.distRb, state.distRbIdx); if (state.distance < 0) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Negative distance"); } // COV_NF_LINE if (state.maxDistance != state.maxBackwardDistance && state.pos < state.maxBackwardDistance) { state.maxDistance = state.pos; } else { state.maxDistance = state.maxBackwardDistance; } state.copyDst = state.pos; if (state.distance > state.maxDistance) { state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Transform; continue; } if (state.distanceCode > 0) { state.distRb[state.distRbIdx & 3] = state.distance; state.distRbIdx++; } if (state.copyLength > state.metaBlockLength) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Invalid backward reference"); } // COV_NF_LINE state.j = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.CopyLoop; goto case iText.IO.Codec.Brotli.Dec.RunningState.CopyLoop; } case iText.IO.Codec.Brotli.Dec.RunningState.CopyLoop: { // fall through int src = (state.pos - state.distance) & ringBufferMask; int dst = state.pos; int copyLength = state.copyLength - state.j; if ((src + copyLength < ringBufferMask) && (dst + copyLength < ringBufferMask)) { for (int k = 0; k < copyLength; ++k) { ringBuffer[dst++] = ringBuffer[src++]; } state.j += copyLength; state.metaBlockLength -= copyLength; state.pos += copyLength; } else { for (; state.j < state.copyLength;) { ringBuffer[state.pos] = ringBuffer[(state.pos - state.distance) & ringBufferMask]; state.metaBlockLength--; state.j++; if (state.pos++ == ringBufferMask) { state.nextRunningState = iText.IO.Codec.Brotli.Dec.RunningState.CopyLoop; state.bytesToWrite = state.ringBufferSize; state.bytesWritten = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Write; break; } } } if (state.runningState == iText.IO.Codec.Brotli.Dec.RunningState.CopyLoop) { state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.MainLoop; } continue; } case iText.IO.Codec.Brotli.Dec.RunningState.Transform: { if (state.copyLength >= iText.IO.Codec.Brotli.Dec.Dictionary.MinWordLength && state.copyLength <= iText.IO.Codec.Brotli.Dec.Dictionary.MaxWordLength) { int offset = iText.IO.Codec.Brotli.Dec.Dictionary.OffsetsByLength[state.copyLength]; int wordId = state.distance - state.maxDistance - 1; int shift = iText.IO.Codec.Brotli.Dec.Dictionary.SizeBitsByLength[state.copyLength]; int mask = (1 << shift) - 1; int wordIdx = wordId & mask; int transformIdx = (int)(((uint)wordId) >> shift); offset += wordIdx * state.copyLength; if (transformIdx < iText.IO.Codec.Brotli.Dec.Transform.Transforms.Length) { int len = iText.IO.Codec.Brotli.Dec.Transform.TransformDictionaryWord(ringBuffer, state.copyDst, iText.IO.Codec.Brotli.Dec.Dictionary.GetData(), offset, state.copyLength, iText.IO.Codec.Brotli.Dec.Transform.Transforms[transformIdx]); state.copyDst += len; state.pos += len; state.metaBlockLength -= len; if (state.copyDst >= state.ringBufferSize) { state.nextRunningState = iText.IO.Codec.Brotli.Dec.RunningState.CopyWrapBuffer; state.bytesToWrite = state.ringBufferSize; state.bytesWritten = 0; state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.Write; continue; } } else { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Invalid backward reference"); } } else { // COV_NF_LINE throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Invalid backward reference"); } // COV_NF_LINE state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.MainLoop; continue; } case iText.IO.Codec.Brotli.Dec.RunningState.CopyWrapBuffer: { System.Array.Copy(ringBuffer, state.ringBufferSize, ringBuffer, 0, state.copyDst - state.ringBufferSize); state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.MainLoop; continue; } case iText.IO.Codec.Brotli.Dec.RunningState.ReadMetadata: { while (state.metaBlockLength > 0) { iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); // Optimize iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 8); state.metaBlockLength--; } state.runningState = iText.IO.Codec.Brotli.Dec.RunningState.BlockStart; continue; } case iText.IO.Codec.Brotli.Dec.RunningState.CopyUncompressed: { CopyUncompressedData(state); continue; } case iText.IO.Codec.Brotli.Dec.RunningState.Write: { if (!WriteRingBuffer(state)) { // Output buffer is full. return; } if (state.pos >= state.maxBackwardDistance) { state.maxDistance = state.maxBackwardDistance; } state.pos &= ringBufferMask; state.runningState = state.nextRunningState; continue; } default: { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Unexpected state " + state.runningState); } } } if (state.runningState == iText.IO.Codec.Brotli.Dec.RunningState.Finished) { if (state.metaBlockLength < 0) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Invalid metablock length"); } iText.IO.Codec.Brotli.Dec.BitReader.JumpToByteBoundary(br); iText.IO.Codec.Brotli.Dec.BitReader.CheckHealth(state.br, true); } }
internal static void SetCustomDictionary(iText.IO.Codec.Brotli.Dec.State state, byte[] data) { state.customDictionary = (data == null) ? new byte[0] : data; }
private static void DecodeMetaBlockLength(iText.IO.Codec.Brotli.Dec.BitReader br, iText.IO.Codec.Brotli.Dec.State state) { state.inputEnd = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 1) == 1; state.metaBlockLength = 0; state.isUncompressed = false; state.isMetadata = false; if (state.inputEnd && iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 1) != 0) { return; } int sizeNibbles = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 2) + 4; if (sizeNibbles == 7) { state.isMetadata = true; if (iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 1) != 0) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Corrupted reserved bit"); } int sizeBytes = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 2); if (sizeBytes == 0) { return; } for (int i = 0; i < sizeBytes; i++) { int bits = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 8); if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Exuberant nibble"); } state.metaBlockLength |= bits << (i * 8); } } else { for (int i = 0; i < sizeNibbles; i++) { int bits = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 4); if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) { throw new iText.IO.Codec.Brotli.Dec.BrotliRuntimeException("Exuberant nibble"); } state.metaBlockLength |= bits << (i * 4); } } state.metaBlockLength++; if (!state.inputEnd) { state.isUncompressed = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 1) == 1; } }
private static void ReadMetablockHuffmanCodesAndContextMaps(iText.IO.Codec.Brotli.Dec.State state) { iText.IO.Codec.Brotli.Dec.BitReader br = state.br; for (int i = 0; i < 3; i++) { state.numBlockTypes[i] = DecodeVarLenUnsignedByte(br) + 1; state.blockLength[i] = 1 << 28; if (state.numBlockTypes[i] > 1) { ReadHuffmanCode(state.numBlockTypes[i] + 2, state.blockTypeTrees, i * iText.IO.Codec.Brotli.Dec.Huffman.HuffmanMaxTableSize, br); ReadHuffmanCode(NumBlockLengthCodes, state.blockLenTrees, i * iText.IO.Codec.Brotli.Dec.Huffman.HuffmanMaxTableSize, br); state.blockLength[i] = ReadBlockLength(state.blockLenTrees, i * iText.IO.Codec.Brotli.Dec.Huffman.HuffmanMaxTableSize, br); } } iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); state.distancePostfixBits = iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 2); state.numDirectDistanceCodes = NumDistanceShortCodes + (iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 4) << state.distancePostfixBits); state.distancePostfixMask = (1 << state.distancePostfixBits) - 1; int numDistanceCodes = state.numDirectDistanceCodes + (48 << state.distancePostfixBits); // TODO: Reuse? state.contextModes = new byte[state.numBlockTypes[0]]; for (int i = 0; i < state.numBlockTypes[0];) { /* Ensure that less than 256 bits read between readMoreInput. */ int limit = System.Math.Min(i + 96, state.numBlockTypes[0]); for (; i < limit; ++i) { state.contextModes[i] = unchecked ((byte)(iText.IO.Codec.Brotli.Dec.BitReader.ReadBits(br, 2) << 1)); } iText.IO.Codec.Brotli.Dec.BitReader.ReadMoreInput(br); } // TODO: Reuse? state.contextMap = new byte[state.numBlockTypes[0] << LiteralContextBits]; int numLiteralTrees = DecodeContextMap(state.numBlockTypes[0] << LiteralContextBits, state.contextMap, br); state.trivialLiteralContext = true; for (int j = 0; j < state.numBlockTypes[0] << LiteralContextBits; j++) { if (state.contextMap[j] != j >> LiteralContextBits) { state.trivialLiteralContext = false; break; } } // TODO: Reuse? state.distContextMap = new byte[state.numBlockTypes[2] << DistanceContextBits]; int numDistTrees = DecodeContextMap(state.numBlockTypes[2] << DistanceContextBits, state.distContextMap, br); iText.IO.Codec.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup0, NumLiteralCodes, numLiteralTrees); iText.IO.Codec.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup1, NumInsertAndCopyCodes, state.numBlockTypes[1]); iText.IO.Codec.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup2, numDistanceCodes, numDistTrees); iText.IO.Codec.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup0, br); iText.IO.Codec.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup1, br); iText.IO.Codec.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup2, br); state.contextMapSlice = 0; state.distContextMapSlice = 0; state.contextLookupOffset1 = iText.IO.Codec.Brotli.Dec.Context.LookupOffsets[state.contextModes[0]]; state.contextLookupOffset2 = iText.IO.Codec.Brotli.Dec.Context.LookupOffsets[state.contextModes[0] + 1]; state.literalTreeIndex = 0; state.literalTree = state.hGroup0.trees[0]; state.treeCommandOffset = state.hGroup1.trees[0]; // TODO: == 0? state.blockTypeRb[0] = state.blockTypeRb[2] = state.blockTypeRb[4] = 1; state.blockTypeRb[1] = state.blockTypeRb[3] = state.blockTypeRb[5] = 0; }
private static void DecodeDistanceBlockSwitch(iText.IO.Codec.Brotli.Dec.State state) { DecodeBlockTypeAndLength(state, 2); state.distContextMapSlice = state.blockTypeRb[5] << DistanceContextBits; }
private static void DecodeCommandBlockSwitch(iText.IO.Codec.Brotli.Dec.State state) { DecodeBlockTypeAndLength(state, 1); state.treeCommandOffset = state.hGroup1.trees[state.blockTypeRb[3]]; }