/// <summary>Reads the custom code table, if there is one</summary> void ReadCodeTable() { // The length given includes the nearSize and sameSize bytes int compressedTableLength = IOHelper.ReadBigEndian7BitEncodedInt(delta) - 2; int nearSize = IOHelper.CheckedReadByte(delta); int sameSize = IOHelper.CheckedReadByte(delta); byte[] compressedTableData = IOHelper.CheckedReadBytes(delta, compressedTableLength); byte[] defaultTableData = CodeTable.Default.GetBytes(); MemoryStream tableOriginal = new MemoryStream(defaultTableData, false); MemoryStream tableDelta = new MemoryStream(compressedTableData, false); byte[] decompressedTableData = new byte[1536]; MemoryStream tableOutput = new MemoryStream(decompressedTableData, true); Decode(tableOriginal, tableDelta, tableOutput, 0); if (tableOutput.Position != 1536) { throw new VcdiffFormatException("Compressed code table was incorrect size"); } codeTable = new CodeTable(decompressedTableData); cache = new AddressCache(nearSize, sameSize); }
private void ReadHeader() { byte[] array = IOHelper.CheckedReadBytes(delta, 4); if (array[0] != 214 || array[1] != 195 || array[2] != 196) { throw new VcdiffFormatException("Invalid VCDIFF header in delta stream"); } if (array[3] != 0) { throw new VcdiffFormatException("VcdiffDecoder can only read delta streams of version 0"); } byte b = IOHelper.CheckedReadByte(delta); if ((b & 1) != 0) { throw new VcdiffFormatException("VcdiffDecoder does not handle delta stream using secondary compressors"); } bool flag = (b & 2) != 0; bool flag2 = (b & 4) != 0; if ((b & 0xF8) != 0) { throw new VcdiffFormatException("Invalid header indicator - bits 3-7 not all zero."); } if (flag) { ReadCodeTable(); } if (flag2) { int size = IOHelper.ReadBigEndian7BitEncodedInt(delta); IOHelper.CheckedReadBytes(delta, size); } }
/// <summary>Read the header, including any custom code table. The delta stream is left positioned at the start of the first window.</summary> void ReadHeader() { byte[] header = IOHelper.CheckedReadBytes(delta, 4); if (header[0] != 0xd6 || header[1] != 0xc3 || header[2] != 0xc4) { throw new VcdiffFormatException("Invalid VCDIFF header in delta stream"); } if (header[3] != 0) { throw new VcdiffFormatException("VcdiffDecoder can only read delta streams of version 0"); } // Load the header indicator byte headerIndicator = IOHelper.CheckedReadByte(delta); if ((headerIndicator & 1) != 0) { throw new VcdiffFormatException ("VcdiffDecoder does not handle delta stream using secondary compressors"); } bool customCodeTable = ((headerIndicator & 2) != 0); bool applicationHeader = ((headerIndicator & 4) != 0); if ((headerIndicator & 0xf8) != 0) { throw new VcdiffFormatException("Invalid header indicator - bits 3-7 not all zero."); } // Load the custom code table, if there is one if (customCodeTable) { ReadCodeTable(); } // Ignore the application header if we have one. This tells xdelta3 what the right filenames are. if (applicationHeader) { int appHeaderLength = IOHelper.ReadBigEndian7BitEncodedInt(delta); IOHelper.CheckedReadBytes(delta, appHeaderLength); } }
private void ReadCodeTable() { int size = IOHelper.ReadBigEndian7BitEncodedInt(delta) - 2; int nearSize = IOHelper.CheckedReadByte(delta); int sameSize = IOHelper.CheckedReadByte(delta); byte[] buffer = IOHelper.CheckedReadBytes(delta, size); byte[] bytes = CodeTable.Default.GetBytes(); MemoryStream memoryStream = new MemoryStream(bytes, writable: false); MemoryStream memoryStream2 = new MemoryStream(buffer, writable: false); byte[] array = new byte[1536]; MemoryStream memoryStream3 = new MemoryStream(array, writable: true); Decode(memoryStream, memoryStream2, memoryStream3, 0L); if (memoryStream3.Position != 1536) { throw new VcdiffFormatException("Compressed code table was incorrect size"); } codeTable = new CodeTable(array); cache = new AddressCache(nearSize, sameSize); }
/// <summary>Reads and decodes a window, returning whether or not there was any more data to read.</summary> /// <returns>Whether or not the delta stream had reached the end of its data.</returns> bool DecodeWindow() { int windowIndicator = delta.ReadByte(); // Have we finished? if (windowIndicator == -1) { return(false); } // The stream to load source data from for this window, if any Stream sourceStream; // Where to reposition the source stream to after reading from it, if anywhere int sourceStreamPostReadSeek = -1; // xdelta3 uses an undocumented extra bit which indicates that there are an extra // 4 bytes at the end of the encoding for the window bool hasAdler32Checksum = ((windowIndicator & 4) == 4); // Get rid of the checksum bit for the rest windowIndicator &= 0xfb; // Work out what the source data is, and detect invalid window indicators switch (windowIndicator & 3) { // No source data used in this window case 0: sourceStream = null; break; // Source data comes from the original stream case 1: if (original == null) { throw new VcdiffFormatException ("Source stream requested by delta but not provided by caller."); } sourceStream = original; break; case 2: sourceStream = output; sourceStreamPostReadSeek = (int)output.Position; break; case 3: throw new VcdiffFormatException ("Invalid window indicator - bits 0 and 1 both set."); default: throw new VcdiffFormatException("Invalid window indicator - bits 3-7 not all zero."); } // Read the source data, if any byte[] sourceData = null; int sourceLength = 0; if (sourceStream != null) { sourceLength = IOHelper.ReadBigEndian7BitEncodedInt(delta); int sourcePosition = IOHelper.ReadBigEndian7BitEncodedInt(delta); sourceStream.Position = sourcePosition; sourceData = IOHelper.CheckedReadBytes(sourceStream, sourceLength); // Reposition the source stream if appropriate if (sourceStreamPostReadSeek != -1) { sourceStream.Position = sourceStreamPostReadSeek; } } // Read how long the delta encoding is - then ignore it IOHelper.ReadBigEndian7BitEncodedInt(delta); // Read how long the target window is int targetLength = IOHelper.ReadBigEndian7BitEncodedInt(delta); byte[] targetData = new byte[targetLength]; MemoryStream targetDataStream = new MemoryStream(targetData, true); // Read the indicator and the lengths of the different data sections byte deltaIndicator = IOHelper.CheckedReadByte(delta); if (deltaIndicator != 0) { throw new VcdiffFormatException("VcdiffDecoder is unable to handle compressed delta sections."); } int addRunDataLength = IOHelper.ReadBigEndian7BitEncodedInt(delta); int instructionsLength = IOHelper.ReadBigEndian7BitEncodedInt(delta); int addressesLength = IOHelper.ReadBigEndian7BitEncodedInt(delta); // If we've been given a checksum, we have to read it (whether we use it or not) if (hasAdler32Checksum) { IOHelper.CheckedReadBytes(delta, 4); } // Read all the data for this window byte[] addRunData = IOHelper.CheckedReadBytes(delta, addRunDataLength); byte[] instructions = IOHelper.CheckedReadBytes(delta, instructionsLength); byte[] addresses = IOHelper.CheckedReadBytes(delta, addressesLength); int addRunDataIndex = 0; MemoryStream instructionStream = new MemoryStream(instructions, false); cache.Reset(addresses); while (true) { int instructionIndex = instructionStream.ReadByte(); if (instructionIndex == -1) { break; } for (int i = 0; i < 2; i++) { Instruction instruction = codeTable[instructionIndex, i]; int size = instruction.Size; if (size == 0 && instruction.Type != InstructionType.NoOp) { size = IOHelper.ReadBigEndian7BitEncodedInt(instructionStream); } switch (instruction.Type) { case InstructionType.NoOp: break; case InstructionType.Add: targetDataStream.Write(addRunData, addRunDataIndex, size); addRunDataIndex += size; break; case InstructionType.Copy: int addr = cache.DecodeAddress((int)targetDataStream.Position + sourceLength, instruction.Mode); if (sourceData != null && addr < sourceData.Length) { targetDataStream.Write(sourceData, addr, size); } else // Data is in target data { // Get rid of the offset addr -= sourceLength; // Can we just ignore overlap issues? if (addr + size < targetDataStream.Position) { targetDataStream.Write(targetData, addr, size); } else { for (int j = 0; j < size; j++) { targetDataStream.WriteByte(targetData[addr++]); } } } break; case InstructionType.Run: byte data = addRunData[addRunDataIndex++]; for (int j = 0; j < size; j++) { targetDataStream.WriteByte(data); } break; default: throw new VcdiffFormatException("Invalid instruction type found."); } } } output.Write(targetData, 0, targetLength); // update the adler for the current window adler.Update(targetData, 0, targetLength); return(true); }
private bool DecodeWindow() { int num = delta.ReadByte(); if (num == -1) { return(false); } int num2 = -1; bool flag = (num & 4) == 4; num &= 0xFB; Stream stream; switch (num & 3) { case 0: stream = null; break; case 1: if (original == null) { throw new VcdiffFormatException("Source stream requested by delta but not provided by caller."); } stream = original; break; case 2: stream = output; num2 = (int)output.Position; break; case 3: throw new VcdiffFormatException("Invalid window indicator - bits 0 and 1 both set."); default: throw new VcdiffFormatException("Invalid window indicator - bits 3-7 not all zero."); } byte[] array = null; int num3 = 0; if (stream != null) { num3 = IOHelper.ReadBigEndian7BitEncodedInt(delta); int num4 = IOHelper.ReadBigEndian7BitEncodedInt(delta); stream.Position = num4; array = IOHelper.CheckedReadBytes(stream, num3); if (num2 != -1) { stream.Position = num2; } } IOHelper.ReadBigEndian7BitEncodedInt(delta); int num5 = IOHelper.ReadBigEndian7BitEncodedInt(delta); byte[] array2 = new byte[num5]; MemoryStream memoryStream = new MemoryStream(array2, writable: true); if (IOHelper.CheckedReadByte(delta) != 0) { throw new VcdiffFormatException("VcdiffDecoder is unable to handle compressed delta sections."); } int size = IOHelper.ReadBigEndian7BitEncodedInt(delta); int size2 = IOHelper.ReadBigEndian7BitEncodedInt(delta); int size3 = IOHelper.ReadBigEndian7BitEncodedInt(delta); if (flag) { IOHelper.CheckedReadBytes(delta, 4); } byte[] array3 = IOHelper.CheckedReadBytes(delta, size); byte[] buffer = IOHelper.CheckedReadBytes(delta, size2); byte[] addresses = IOHelper.CheckedReadBytes(delta, size3); int num6 = 0; MemoryStream memoryStream2 = new MemoryStream(buffer, writable: false); cache.Reset(addresses); while (true) { int num7 = memoryStream2.ReadByte(); if (num7 == -1) { break; } for (int i = 0; i < 2; i++) { Instruction instruction = codeTable[num7, i]; int num8 = instruction.Size; if (num8 == 0 && instruction.Type != 0) { num8 = IOHelper.ReadBigEndian7BitEncodedInt(memoryStream2); } switch (instruction.Type) { case InstructionType.Add: memoryStream.Write(array3, num6, num8); num6 += num8; break; case InstructionType.Copy: { int num9 = cache.DecodeAddress((int)memoryStream.Position + num3, instruction.Mode); if (array != null && num9 < array.Length) { memoryStream.Write(array, num9, num8); break; } num9 -= num3; if (num9 + num8 < memoryStream.Position) { memoryStream.Write(array2, num9, num8); break; } for (int k = 0; k < num8; k++) { memoryStream.WriteByte(array2[num9++]); } break; } case InstructionType.Run: { byte value = array3[num6++]; for (int j = 0; j < num8; j++) { memoryStream.WriteByte(value); } break; } default: throw new VcdiffFormatException("Invalid instruction type found."); case InstructionType.NoOp: break; } } } output.Write(array2, 0, num5); adler.Update(array2, 0, num5); return(true); }