예제 #1
0
        /// <summary>
        /// Writes the patched file into the output stream asynchronously.
        /// This method is only asynchronous for the final step of writing the patched data into the output stream.
        /// For large outputs, this may be beneficial.
        /// </summary>
        /// <returns></returns>
        public async Task <(VCDiffResult result, long bytesWritten)> DecodeAsync()
        {
            if (!Decode_Init(out var bytesWritten, out var result, out var decodeAsync))
            {
                return(decodeAsync);
            }
            while (delta.CanRead)
            {
                //delta is streamed in order aka not random access
                using var w = new WindowDecoder <TDeltaBuffer>(source.Length, delta, maxTargetFileSize);

                if (w.Decode(this.IsSDCHFormat))
                {
                    using var body = new BodyDecoder <TDeltaBuffer, TSourceBuffer, TDeltaBuffer>(w, source, delta, outputStream);
                    if (this.IsSDCHFormat && w.AddRunLength == 0 && w.AddressesForCopyLength == 0 && w.InstructionAndSizesLength > 0)
                    {
                        //interleaved
                        //decodedinterleave actually has an internal loop for waiting and streaming the incoming rest of the interleaved window
                        result = await body.DecodeInterleaveAsync();

                        if (result != VCDiffResult.SUCCESS && result != VCDiffResult.EOD)
                        {
                            return(result, bytesWritten);
                        }

                        bytesWritten += body.TotalBytesDecoded;
                    }
                    //technically add could be 0 if it is all copy instructions
                    //so do an or check on those two
                    else if (!this.IsSDCHFormat || (this.IsSDCHFormat && (w.AddRunLength > 0 || w.AddressesForCopyLength > 0) &&
                                                    w.InstructionAndSizesLength > 0))
                    {
                        //not interleaved
                        //expects the full window to be available
                        //in the stream
                        result = await body.DecodeAsync();

                        if (result != VCDiffResult.SUCCESS)
                        {
                            return(result, bytesWritten);
                        }

                        bytesWritten += body.TotalBytesDecoded;
                    }
                    else
                    {
                        //invalid file
                        return(VCDiffResult.ERROR, bytesWritten);
                    }
                }
                else
                {
                    return((VCDiffResult)w.Result, bytesWritten);
                }
            }

            return(result, bytesWritten);
        }
예제 #2
0
 /// <summary>
 /// The main decoder loop for the data
 /// </summary>
 /// <param name="w">the window decoder</param>
 /// <param name="source">The source dictionary data</param>
 /// <param name="delta">The delta</param>
 /// <param name="decodedTarget">the out stream</param>
 /// <param name="customTable">custom table if any. Default is null.</param>
 public BodyDecoder(WindowDecoder w, IByteBuffer source, IByteBuffer delta, Stream decodedTarget, CustomCodeTableDecoder?customTable = null)
 {
     if (customTable != null)
     {
         this.customTable = customTable;
         addressCache     = new AddressCache(customTable.NearSize, customTable.SameSize);
     }
     else
     {
         addressCache = new AddressCache();
     }
     window            = w;
     this.outputStream = decodedTarget;
     this.source       = source;
     this.delta        = delta;
     this.targetData   = new MemoryStream();
 }
예제 #3
0
 /// <summary>
 /// The main decoder loop for the data
 /// </summary>
 /// <param name="w">the window decoder</param>
 /// <param name="dictionary">the dictionary data</param>
 /// <param name="target">the target data</param>
 /// <param name="sout">the out stream</param>
 /// <param name="customTable">custom table if any. Default is null.</param>
 public BodyDecoder(WindowDecoder w, IByteBuffer dictionary, IByteBuffer target, ByteStreamWriter sout, CustomCodeTableDecoder customTable = null)
 {
     if (customTable != null)
     {
         this.customTable = customTable;
         addressCache     = new AddressCache((byte)customTable.NearSize, (byte)customTable.SameSize);
     }
     else
     {
         addressCache = new AddressCache();
     }
     window      = w;
     this.sout   = sout;
     this.dict   = dictionary;
     this.target = target;
     targetData  = new List <byte>();
 }
예제 #4
0
 /// <summary>
 /// The main decoder loop for the data
 /// </summary>
 /// <param name="w">the window decoder</param>
 /// <param name="source">The source dictionary data</param>
 /// <param name="delta">The delta</param>
 /// <param name="decodedTarget">the out stream</param>
 /// <param name="customTable">custom table if any. Default is null.</param>
 public BodyDecoder(WindowDecoder <TWindowDecoderByteBuffer> w, TSourceBuffer source, TDeltaBuffer delta, Stream decodedTarget, CustomCodeTableDecoder?customTable = null)
 {
     if (customTable != null)
     {
         this.customTable = customTable;
         addressCache     = new AddressCache(customTable.NearSize, customTable.SameSize);
     }
     else
     {
         addressCache = new AddressCache();
     }
     window            = w;
     this.outputStream = decodedTarget;
     this.source       = source;
     this.delta        = delta;
     this.targetData   = Pool.MemoryStreamManager.GetStream(nameof(BodyDecoder <TWindowDecoderByteBuffer, TSourceBuffer, TDeltaBuffer>), (int)w.TargetWindowLength);
 }
예제 #5
0
        /// <summary>
        /// Use this after calling Start
        /// Each time the decode is called it is expected
        /// that at least 1 Window header is available in the stream
        /// </summary>
        /// <param name="bytesWritten">bytes decoded for all available windows</param>
        /// <returns></returns>
        public VCDiffResult Decode(out long bytesWritten)
        {
            if (!isStarted)
            {
                bytesWritten = 0;
                return(VCDiffResult.ERRROR);
            }

            VCDiffResult result = VCDiffResult.SUCCESS;

            bytesWritten = 0;

            if (!delta.CanRead)
            {
                return(VCDiffResult.EOD);
            }

            while (delta.CanRead)
            {
                //delta is streamed in order aka not random access
                WindowDecoder w = new WindowDecoder(dict.Length, delta);

                if (w.Decode(googleVersion))
                {
                    using (BodyDecoder body = new BodyDecoder(w, dict, delta, sout))
                    {
                        if (googleVersion && w.AddRunLength == 0 && w.AddressesForCopyLength == 0 && w.InstructionAndSizesLength > 0)
                        {
                            //interleaved
                            //decodedinterleave actually has an internal loop for waiting and streaming the incoming rest of the interleaved window
                            result = body.DecodeInterleave();

                            if (result != VCDiffResult.SUCCESS && result != VCDiffResult.EOD)
                            {
                                return(result);
                            }

                            bytesWritten += body.Decoded;
                        }
                        //technically add could be 0 if it is all copy instructions
                        //so do an or check on those two
                        else if (googleVersion && (w.AddRunLength > 0 || w.AddressesForCopyLength > 0) && w.InstructionAndSizesLength > 0)
                        {
                            //not interleaved
                            //expects the full window to be available
                            //in the stream

                            result = body.Decode();

                            if (result != VCDiffResult.SUCCESS)
                            {
                                return(result);
                            }

                            bytesWritten += body.Decoded;
                        }
                        else if (!googleVersion)
                        {
                            //not interleaved
                            //expects the full window to be available
                            //in the stream
                            result = body.Decode();

                            if (result != VCDiffResult.SUCCESS)
                            {
                                return(result);
                            }

                            bytesWritten += body.Decoded;
                        }
                        else
                        {
                            //invalid file
                            return(VCDiffResult.ERRROR);
                        }
                    }
                }
                else
                {
                    return((VCDiffResult)w.Result);
                }
            }

            return(result);
        }
예제 #6
0
        /// <summary>
        /// Writes the patched file into the output stream.
        /// </summary>
        /// <param name="bytesWritten">Number of bytes written into the output stream.</param>
        /// <returns></returns>
        public VCDiffResult Decode(out long bytesWritten)
        {
            if (!this.IsInitialized)
            {
                var initializeResult = this.Initialize();
                if (initializeResult != VCDiffResult.SUCCESS || !this.IsInitialized)
                {
                    bytesWritten = 0;
                    return initializeResult;
                }
            }

            VCDiffResult result = VCDiffResult.SUCCESS;
            bytesWritten = 0;

            if (!delta.CanRead) return VCDiffResult.EOD;

            while (delta.CanRead)
            {
                //delta is streamed in order aka not random access
                WindowDecoder w = new WindowDecoder(source.Length, delta);

                if (w.Decode(this.IsSDCHFormat))
                {
                    using BodyDecoder body = new BodyDecoder(w, source, delta, outputStream);
                    if (this.IsSDCHFormat && w.AddRunLength == 0 && w.AddressesForCopyLength == 0 && w.InstructionAndSizesLength > 0)
                    {
                        //interleaved
                        //decodedinterleave actually has an internal loop for waiting and streaming the incoming rest of the interleaved window
                        result = body.DecodeInterleave();

                        if (result != VCDiffResult.SUCCESS && result != VCDiffResult.EOD)
                        {
                            return result;
                        }

                        bytesWritten += body.TotalBytesDecoded;
                    }
                    //technically add could be 0 if it is all copy instructions
                    //so do an or check on those two
                    else if (!this.IsSDCHFormat || (this.IsSDCHFormat && (w.AddRunLength > 0 || w.AddressesForCopyLength > 0) && w.InstructionAndSizesLength > 0))
                    {
                        //not interleaved
                        //expects the full window to be available
                        //in the stream

                        result = body.Decode();

                        if (result != VCDiffResult.SUCCESS)
                        {
                            return result;
                        }

                        bytesWritten += body.TotalBytesDecoded;
                    }
                    else
                    {
                        //invalid file
                        return VCDiffResult.ERROR;
                    }
                }
                else
                {
                    return (VCDiffResult)w.Result;
                }
            }

            return result;
        }