private static int[] DecompressTagSlow(byte[] input, int inputIndex, byte[] output, int outputLimit, int outputOffset, int outputIndex) { int opCode = DataHelper.LoadByte(input, inputIndex++); int entry = DataHelper.LookupShort(_opLookupTable, opCode); int trailerBytes = entry.BitwiseUnsignedRightShift(11); int trailer = 0; switch (trailerBytes) { case 4: trailer = (input[inputIndex + 3] & 0xff) << 24; break; case 3: trailer |= (input[inputIndex + 2] & 0xff) << 16; break; case 2: trailer |= (input[inputIndex + 1] & 0xff) << 8; break; case 1: trailer |= (input[inputIndex] & 0xff); break; } inputIndex += trailerBytes; int length = entry & 0xff; if ((opCode & 0x3) == LITERAL) { int literalLength = length + trailer; CopyLiteral(input, inputIndex, output, outputIndex, literalLength); inputIndex += literalLength; outputIndex += literalLength; } else { int copyOffset = entry & 0x700; copyOffset += trailer; int spaceLeft = outputLimit - outputIndex; int srcIndex = outputIndex - copyOffset; if (srcIndex < outputOffset) { throw new CorruptionException("Invalid copy offset for opcode starting at " + (inputIndex - trailerBytes - 1)); } if (length <= 16 && copyOffset >= 8 && spaceLeft >= 16) { DataHelper.CopyLong(output, srcIndex, output, outputIndex); DataHelper.CopyLong(output, srcIndex + 8, output, outputIndex + 8); } else if (spaceLeft >= length + MAX_INCREMENT_COPY_OVERFLOW) { IncrementalCopyFastPath(output, srcIndex, outputIndex, length); } else { IncrementalCopy(output, srcIndex, output, outputIndex, length); } outputIndex += length; } return(new int[] { inputIndex, outputIndex }); }
private static int DecompressAllTags(byte[] input, int inputOffset, int inputSize, byte[] output, int outputOffset) { int outputLimit = output.Length; int inputLimit = inputOffset + inputSize; int outputIndex = outputOffset; int inputIndex = inputOffset; while (inputIndex < inputLimit - 5) { int opCode = DataHelper.LoadByte(input, inputIndex++); int entry = DataHelper.LookupShort(_opLookupTable, opCode); int trailerBytes = entry.BitwiseUnsignedRightShift(11); int trailer = ReadTrailer(input, inputIndex, trailerBytes); inputIndex += entry.BitwiseUnsignedRightShift(11); int length = entry & 0xff; if ((opCode & 0x3) == LITERAL) { int literalLength = length + trailer; CopyLiteral(input, inputIndex, output, outputIndex, literalLength); inputIndex += literalLength; outputIndex += literalLength; } else { int copyOffset = entry & 0x700; copyOffset += trailer; int spaceLeft = outputLimit - outputIndex; int srcIndex = outputIndex - copyOffset; if (srcIndex < outputOffset) { throw new CorruptionException("Invalid copy offset for opcode starting at " + (inputIndex - trailerBytes - 1)); } if (length <= 16 && copyOffset >= 8 && spaceLeft >= 16) { DataHelper.CopyLong(output, srcIndex, output, outputIndex); DataHelper.CopyLong(output, srcIndex + 8, output, outputIndex + 8); } else if (spaceLeft >= length + MAX_INCREMENT_COPY_OVERFLOW) { IncrementalCopyFastPath(output, srcIndex, outputIndex, length); } else { IncrementalCopy(output, srcIndex, output, outputIndex, length); } outputIndex += length; } } while (inputIndex < inputLimit) { int[] result = DecompressTagSlow(input, inputIndex, output, outputLimit, outputOffset, outputIndex); inputIndex = result[0]; outputIndex = result[1]; } return(outputIndex - outputOffset); }