/// <summary> /// Encodes the file /// </summary> /// <param name="interleaved">Set this to true to enable SDHC interleaved vcdiff google format</param> /// <param name="checksum">Set this to true to add checksum for encoded data windows</param> /// <returns></returns> public VCDiffResult Encode(bool interleaved = false, bool checksum = false) { if (newData.Length == 0 || oldData.Length == 0) { return(VCDiffResult.ERRROR); } VCDiffResult result = VCDiffResult.SUCCESS; oldData.Position = 0; newData.Position = 0; //file header //write magic bytes if (!interleaved && !checksum) { sout.writeBytes(MagicBytes); } else { sout.writeBytes(MagicBytesExtended); } //buffer the whole olddata (dictionary) //otherwise it will be a slow process //even Google's version reads in the entire dictionary file to memory //it is just faster that way because of having to move the memory pointer around //to find all the hash comparisons and stuff. //It is much slower trying to random access read from file with FileStream class //however the newData is read in chunks and processed for memory efficiency and speed oldData.BufferAll(); //read in all the dictionary it is the only thing that needs to be BlockHash dictionary = new BlockHash(oldData, 0, hasher); dictionary.AddAllBlocks(); oldData.Position = 0; ChunkEncoder chunker = new ChunkEncoder(dictionary, oldData, hasher, interleaved, checksum); while (newData.CanRead) { using (ByteBuffer ntarget = new ByteBuffer(newData.ReadBytes(bufferSize))) { chunker.EncodeChunk(ntarget, sout); } //just in case System.GC.Collect(); } return(result); }
/// <summary> /// Calculate and write a diff for the file. /// </summary> /// <param name="interleaved">Whether to output in SDCH interleaved diff format.</param> /// <param name="checksumFormat"> /// Whether to include Adler32 checksums for encoded data windows. If interleaved is true, <see cref="ChecksumFormat.Xdelta3"/> /// is not supported. /// </param> /// <returns> /// <see cref="VCDiffResult.SUCCESS"/> if successful, <see cref="VCDiffResult.ERROR"/> if the sourceStream or target are zero-length.</returns> /// <exception cref="ArgumentException">If interleaved is true, and <see cref="ChecksumFormat.Xdelta3"/> is chosen.</exception> public VCDiffResult Encode(bool interleaved = false, ChecksumFormat checksumFormat = ChecksumFormat.None) { if (oldData == null) { this.oldData = new ByteBuffer(sourceStream); } if (interleaved && checksumFormat == ChecksumFormat.Xdelta3) { throw new ArgumentException("Interleaved diffs can not have an xdelta3 checksum!"); } if (targetData.Length == 0 || oldData.Length == 0) { return(VCDiffResult.ERROR); } VCDiffResult result = VCDiffResult.SUCCESS; oldData.Position = 0; targetData.Position = 0; // file header // write magic bytes if (!interleaved && checksumFormat != ChecksumFormat.SDCH) { outputStream.Write(MagicBytes); } else { outputStream.Write(MagicBytesExtended); } //read in all the dictionary it is the only thing that needs to be BlockHash dictionary = new BlockHash(oldData, 0, hasher, blockSize); dictionary.AddAllBlocks(); oldData.Position = 0; ChunkEncoder chunker = new ChunkEncoder(dictionary, oldData, hasher, checksumFormat, interleaved, chunkSize); while (targetData.CanRead) { using ByteBuffer ntarget = new ByteBuffer(targetData.ReadBytesAsBuf(bufferSize)); chunker.EncodeChunk(ntarget, outputStream); } return(result); }