/// <summary> /// Decode if as expecting interleave /// </summary> /// <returns></returns> public VCDiffResult DecodeInterleave() { VCDiffResult result = VCDiffResult.SUCCESS; //since interleave expected then the last point that was most likely decoded was the lengths section //so following is all data for the add run copy etc long interleaveLength = window.InstructionAndSizesLength; List <byte> previous = new List <byte>(); bool didBreakBeforeComplete = false; int lastDecodedSize = 0; VCDiffInstructionType lastDecodedInstruction = VCDiffInstructionType.NOOP; while (interleaveLength > 0) { if (target.CanRead) { //read in didBreakBeforeComplete = false; //try to read in all interleaved bytes //if not then it will buffer for next time previous.AddRange(target.ReadBytes((int)interleaveLength)); ByteBuffer incoming = new ByteBuffer(previous.ToArray()); previous.Clear(); long initialLength = incoming.Length; InstructionDecoder instrDecoder = new InstructionDecoder(incoming, this.customTable); while (incoming.CanRead && decodedOnly < window.DecodedDeltaLength) { int decodedSize = 0; byte mode = 0; VCDiffInstructionType instruction = VCDiffInstructionType.NOOP; if (lastDecodedSize > 0 && lastDecodedInstruction != VCDiffInstructionType.NOOP) { decodedSize = lastDecodedSize; instruction = lastDecodedInstruction; } else { instruction = instrDecoder.Next(out decodedSize, out mode); switch (instruction) { case VCDiffInstructionType.EOD: didBreakBeforeComplete = true; break; case VCDiffInstructionType.ERROR: targetData.Clear(); return(VCDiffResult.ERRROR); default: break; } } //if instruction is EOD then decodedSize will be 0 as well //the last part of the buffer containing the instruction will be //buffered for the next loop lastDecodedInstruction = instruction; lastDecodedSize = decodedSize; if (didBreakBeforeComplete) { //we don't have all the data so store this pointer into a temporary list to resolve next loop didBreakBeforeComplete = true; interleaveLength -= incoming.Position; if (initialLength - incoming.Position > 0) { previous.AddRange(incoming.ReadBytes((int)(initialLength - incoming.Position))); } break; } switch (instruction) { case VCDiffInstructionType.ADD: result = DecodeAdd(decodedSize, incoming); break; case VCDiffInstructionType.RUN: result = DecodeRun(decodedSize, incoming); break; case VCDiffInstructionType.COPY: result = DecodeCopy(decodedSize, mode, incoming); break; default: targetData.Clear(); return(VCDiffResult.ERRROR); } if (result == VCDiffResult.EOD) { //we don't have all the data so store this pointer into a temporary list to resolve next loop didBreakBeforeComplete = true; interleaveLength -= incoming.Position; if (initialLength - incoming.Position > 0) { previous.AddRange(incoming.ReadBytes((int)(initialLength - incoming.Position))); } break; } //reset these as we have successfully used them lastDecodedInstruction = VCDiffInstructionType.NOOP; lastDecodedSize = 0; } if (!didBreakBeforeComplete) { interleaveLength -= initialLength; } } } if (window.HasChecksum) { uint adler = Checksum.ComputeAdler32(targetData.ToArray()); if (adler != window.Checksum) { result = VCDiffResult.ERRROR; } } targetData.Clear(); return(result); }
private VCDiffResult DecodeInterleaveCore() { VCDiffResult result = VCDiffResult.SUCCESS; //since interleave expected then the last point that was most likely decoded was the lengths section //so following is all data for the add run copy etc long interleaveLength = window.InstructionAndSizesLength; using var previous = new MemoryStream(); int lastDecodedSize = 0; VCDiffInstructionType lastDecodedInstruction = VCDiffInstructionType.NOOP; while (interleaveLength > 0) { if (!delta.CanRead) { continue; } //read in var didBreakBeforeComplete = false; //try to read in all interleaved bytes //if not then it will buffer for next time previous.Write(delta.ReadBytes((int)interleaveLength).Span); using ByteBuffer incoming = new ByteBuffer(previous.ToArray()); previous.SetLength(0); long initialLength = incoming.Length; InstructionDecoder instrDecoder = new InstructionDecoder(incoming, customTable); while (incoming.CanRead && TotalBytesDecoded < window.TargetWindowLength) { int decodedSize = 0; byte mode = 0; VCDiffInstructionType instruction = VCDiffInstructionType.NOOP; if (lastDecodedSize > 0 && lastDecodedInstruction != VCDiffInstructionType.NOOP) { decodedSize = lastDecodedSize; instruction = lastDecodedInstruction; } else { instruction = instrDecoder.Next(out decodedSize, out mode); switch (instruction) { case VCDiffInstructionType.EOD: didBreakBeforeComplete = true; break; case VCDiffInstructionType.ERROR: targetData.SetLength(0); return(VCDiffResult.ERROR); } } //if instruction is EOD then decodedSize will be 0 as well //the last part of the buffer containing the instruction will be //buffered for the next loop lastDecodedInstruction = instruction; lastDecodedSize = decodedSize; if (didBreakBeforeComplete) { //we don't have all the data so store this pointer into a temporary list to resolve next loop didBreakBeforeComplete = true; interleaveLength -= incoming.Position; if (initialLength - incoming.Position > 0) { previous.Write(incoming.ReadBytes((int)(initialLength - incoming.Position)).Span); } break; } switch (instruction) { case VCDiffInstructionType.ADD: result = DecodeAdd(decodedSize, incoming); break; case VCDiffInstructionType.RUN: result = DecodeRun(decodedSize, incoming); break; case VCDiffInstructionType.COPY: result = DecodeCopy(decodedSize, mode, incoming); break; default: targetData.SetLength(0); return(VCDiffResult.ERROR); } if (result == VCDiffResult.EOD) { //we don't have all the data so store this pointer into a temporary list to resolve next loop didBreakBeforeComplete = true; interleaveLength -= incoming.Position; if (initialLength - incoming.Position > 0) { previous.Write(incoming.ReadBytes((int)(initialLength - incoming.Position)).Span); } break; } //reset these as we have successfully used them lastDecodedInstruction = VCDiffInstructionType.NOOP; lastDecodedSize = 0; } if (!didBreakBeforeComplete) { interleaveLength -= initialLength; } } if (window.ChecksumFormat == ChecksumFormat.SDCH) { uint adler = Checksum.ComputeGoogleAdler32(targetData.GetBuffer().AsMemory(0, (int)targetData.Length)); if (adler != window.Checksum) { result = VCDiffResult.ERROR; } } return(result); }
/// <summary> /// Decode normally /// </summary> /// <returns></returns> public VCDiffResult Decode() { ByteBuffer instructionBuffer = new ByteBuffer(window.InstructionsAndSizesData); ByteBuffer addressBuffer = new ByteBuffer(window.AddressesForCopyData); ByteBuffer addRunBuffer = new ByteBuffer(window.AddRunData); InstructionDecoder instrDecoder = new InstructionDecoder(instructionBuffer, this.customTable); VCDiffResult result = VCDiffResult.SUCCESS; while (decodedOnly < window.DecodedDeltaLength && instructionBuffer.CanRead) { int decodedSize = 0; byte mode = 0; VCDiffInstructionType instruction = instrDecoder.Next(out decodedSize, out mode); switch (instruction) { case VCDiffInstructionType.EOD: targetData.Clear(); return(VCDiffResult.EOD); case VCDiffInstructionType.ERROR: targetData.Clear(); return(VCDiffResult.ERRROR); default: break; } switch (instruction) { case VCDiffInstructionType.ADD: result = DecodeAdd(decodedSize, addRunBuffer); break; case VCDiffInstructionType.RUN: result = DecodeRun(decodedSize, addRunBuffer); break; case VCDiffInstructionType.COPY: result = DecodeCopy(decodedSize, mode, addressBuffer); break; default: targetData.Clear(); return(VCDiffResult.ERRROR); } } if (window.HasChecksum) { uint adler = Checksum.ComputeAdler32(targetData.ToArray()); if (adler != window.Checksum) { result = VCDiffResult.ERRROR; } } targetData.Clear(); return(result); }