private static SvnDiffInstruction ReadInstruction(BinaryReaderEOF reader) { if (reader.EOF) { return(null); } SvnDiffInstruction instruction = new SvnDiffInstruction(); byte opCodeAndLength = reader.ReadByte(); instruction.OpCode = (SvnDiffInstructionOpCode)((opCodeAndLength & 0xC0) >> 6); byte length = (byte)(opCodeAndLength & 0x3F); if (length == 0) { instruction.Length = ReadInt(reader); } else { instruction.Length = length; } if (instruction.OpCode == SvnDiffInstructionOpCode.CopyFromSource || instruction.OpCode == SvnDiffInstructionOpCode.CopyFromTarget) { instruction.Offset = ReadInt(reader); } return(instruction); }
public static SvnDiff[] ParseSvnDiff(Stream inputStream) { BinaryReaderEOF reader = new BinaryReaderEOF(inputStream); byte[] signature = reader.ReadBytes(3); byte version = reader.ReadByte(); if (signature[0] != 'S' || signature[1] != 'V' || signature[2] != 'N') { throw new InvalidOperationException("The signature is invalid."); } if (version != 0) { throw new Exception("Unsupported SVN diff version"); } List <SvnDiff> diffs = new List <SvnDiff>(); while (!reader.EOF) { SvnDiff diff = new SvnDiff(); diff.SourceViewOffset = ReadInt(reader); diff.SourceViewLength = ReadInt(reader); diff.TargetViewLength = ReadInt(reader); int instructionSectionLength = (int)ReadInt(reader); int dataSectionLength = (int)ReadInt(reader); diff.InstructionSectionBytes = reader.ReadBytes(instructionSectionLength); diff.DataSectionBytes = reader.ReadBytes(dataSectionLength); diffs.Add(diff); } return(diffs.ToArray()); }
public static byte[] ApplySvnDiff(SvnDiff svnDiff, byte[] source, int sourceDataStartIndex) { const int BUFFER_EXPAND_SIZE = 5000; byte[] buffer = new byte[BUFFER_EXPAND_SIZE]; int targetIndex = 0; MemoryStream instructionStream = new MemoryStream(svnDiff.InstructionSectionBytes); BinaryReaderEOF instructionReader = new BinaryReaderEOF(instructionStream); MemoryStream dataStream = new MemoryStream(svnDiff.DataSectionBytes); BinaryReader dataReader = new BinaryReader(dataStream); SvnDiffInstruction instruction = ReadInstruction(instructionReader); while (instruction != null) { if (targetIndex + (int)instruction.Length > buffer.Length) { Array.Resize(ref buffer, buffer.Length + (int)instruction.Length + BUFFER_EXPAND_SIZE); } switch (instruction.OpCode) { case SvnDiffInstructionOpCode.CopyFromSource: Array.Copy(source, (int)instruction.Offset + sourceDataStartIndex, buffer, targetIndex, (int)instruction.Length); targetIndex += (int)instruction.Length; break; case SvnDiffInstructionOpCode.CopyFromTarget: // Cannot use Array.Copy because Offset + Length may be greater then starting targetIndex for (int i = 0; i < (int)instruction.Length; i++) { buffer[targetIndex] = buffer[(int)instruction.Offset + i]; targetIndex++; } break; case SvnDiffInstructionOpCode.CopyFromNewData: byte[] newData = dataReader.ReadBytes((int)instruction.Length); Array.Copy(newData, 0, buffer, targetIndex, newData.Length); targetIndex += newData.Length; break; } instruction = ReadInstruction(instructionReader); } Array.Resize(ref buffer, targetIndex); return(buffer); }
private static ulong ReadInt(BinaryReaderEOF reader, out int bytesRead) { ulong value = 0; bytesRead = 0; byte b = reader.ReadByte(); bytesRead++; while ((b & 0x80) != 0) { value |= (byte)(b & 0x7F); value <<= 7; b = reader.ReadByte(); bytesRead++; } value |= (ulong)b; return(value); }
private static ulong ReadInt(BinaryReaderEOF reader) { int bytesRead; return(ReadInt(reader, out bytesRead)); }