Example #1
0
        public DeltaStream(Stream signatureStream, Stream inputStream)
        {
            SignatureFile signatures = SignatureHelpers.ParseSignatureFile(signatureStream);
            IEnumerable <OutputCommand> enumerable = DeltaCalculator.ComputeCommands(new BinaryReader(inputStream), signatures);

            commandsToOutput     = enumerable.GetEnumerator();
            currentCommandStream = new MemoryStream();
            BinaryWriter binaryWriter = new BinaryWriter(currentCommandStream);

            StreamHelpers.WriteBigEndian(binaryWriter, 1920139830uL);
            binaryWriter.Flush();
            currentCommandStream.Seek(0L, SeekOrigin.Begin);
        }
        public static SignatureFile ParseSignatureFile(Stream s)
        {
            var result = new SignatureFile();
            var r = new BinaryReader(s);
            uint magicNumber = StreamHelpers.ReadBigEndianUint32(r);
            if (magicNumber == (uint)MagicNumber.Blake2Signature)
            {
                result.StrongSumMethod = CalculateBlake2StrongSum;
            }
            else if (magicNumber == (uint)MagicNumber.Md5MagicNumber)
            {
                result.StrongSumMethod = CalculateMD5StrongSum;
            }
            else if (magicNumber == (uint)MagicNumber.MurMur3)
            {
                result.StrongSumMethod = CalculateMurmur3;
            }
            else
            {
                throw new InvalidDataException(string.Format("Unknown magic number {0}", magicNumber));
            }

            result.BlockLength = (int)StreamHelpers.ReadBigEndianUint32(r);
            result.StrongSumLength = (int)StreamHelpers.ReadBigEndianUint32(r);

            var signatures = new List<BlockSignature>();
            ulong i = 0;
            while (true)
            {
                byte[] weakSumBytes = r.ReadBytes(4);
                if (weakSumBytes.Length == 0)
                {
                    // we're at the end of the file
                    break;
                }

                int weakSum = (int)StreamHelpers.ConvertFromBigEndian(weakSumBytes);
                byte[] strongSum = r.ReadBytes(result.StrongSumLength);
                signatures.Add(new BlockSignature
                {
                    StartPos = (ulong)result.BlockLength * i,
                    WeakSum = weakSum,
                    StrongSum = strongSum
                });

                i++;
            }

            result.BlockLookup = signatures.ToLookup(sig => sig.WeakSum);
            return result;
        }
        public static SignatureFile ParseSignatureFile(Stream s)
        {
            var  result      = new SignatureFile();
            var  r           = new BinaryReader(s);
            uint magicNumber = StreamHelpers.ReadBigEndianUint32(r);

            if (magicNumber == (uint)MagicNumber.Blake2Signature)
            {
                result.StrongSumMethod = CalculateBlake2StrongSum;
            }
            else
            {
                throw new InvalidDataException(string.Format("Unknown magic number {0}", magicNumber));
            }

            result.BlockLength     = (int)StreamHelpers.ReadBigEndianUint32(r);
            result.StrongSumLength = (int)StreamHelpers.ReadBigEndianUint32(r);

            var   signatures = new List <BlockSignature>();
            ulong i          = 0;

            while (true)
            {
                byte[] weakSumBytes = r.ReadBytes(4);
                if (weakSumBytes.Length == 0)
                {
                    // we're at the end of the file
                    break;
                }

                int    weakSum   = (int)StreamHelpers.ConvertFromBigEndian(weakSumBytes);
                byte[] strongSum = r.ReadBytes(result.StrongSumLength);
                signatures.Add(new BlockSignature
                {
                    StartPos  = (ulong)result.BlockLength * i,
                    WeakSum   = weakSum,
                    StrongSum = strongSum
                });

                i++;
            }

            result.BlockLookup = signatures.ToLookup(sig => sig.WeakSum);
            return(result);
        }
Example #4
0
        public static SignatureFile ParseSignatureFile(Stream s)
        {
            SignatureFile signatureFile = default(SignatureFile);
            BinaryReader  binaryReader  = new BinaryReader(s);
            uint          num           = StreamHelpers.ReadBigEndianUint32(binaryReader);

            if (num != 1920139575)
            {
                throw new InvalidDataException($"Unknown magic number {num}");
            }
            signatureFile.StrongSumMethod = CalculateBlake2StrongSum;
            signatureFile.BlockLength     = (int)StreamHelpers.ReadBigEndianUint32(binaryReader);
            signatureFile.StrongSumLength = (int)StreamHelpers.ReadBigEndianUint32(binaryReader);
            Dictionary <int, List <BlockSignature> > dictionary = new Dictionary <int, List <BlockSignature> >();
            ulong num2 = 0uL;

            while (true)
            {
                byte[] array = binaryReader.ReadBytes(4);
                if (array.Length == 0)
                {
                    break;
                }
                int    num3                 = (int)StreamHelpers.ConvertFromBigEndian(array);
                byte[] strongSum            = binaryReader.ReadBytes(signatureFile.StrongSumLength);
                List <BlockSignature> value = null;
                if (!dictionary.TryGetValue(num3, out value))
                {
                    value = new List <BlockSignature>();
                    dictionary.Add(num3, value);
                }
                value.Add(new BlockSignature
                {
                    StartPos  = (ulong)((long)signatureFile.BlockLength * (long)num2),
                    WeakSum   = num3,
                    StrongSum = strongSum
                });
                num2++;
            }
            signatureFile.BlockLookup = dictionary;
            return(signatureFile);
        }
        public static IEnumerable<OutputCommand> ComputeCommands(
            BinaryReader inputStream,
            SignatureFile signatures)
        {
            OutputCommand currentCommand = new OutputCommand { Kind = CommandKind.Reserved };
            Rollsum currentSum;
            Queue<byte> currentBlock;

            // Read the first block to initialize
            ReadNewBlock(inputStream, signatures.BlockLength, out currentBlock, out currentSum);
            while (currentBlock.Count > 0)
            {
                // if the block has a matching rolling sum to any contained in the signature, those are candidates
                var matchCandidates = signatures.BlockLookup[currentSum.Digest];
                bool wasMatch = false;
                if (matchCandidates.Any())
                {
                    // now compute the strong sum and see if any of the signature blocks match it
                    byte[] currentStrongSum = signatures.StrongSumMethod(currentBlock.ToArray()).Take(signatures.StrongSumLength).ToArray();
                    var matchingBlock = matchCandidates.FirstOrDefault(s => s.StrongSum.SequenceEqual(currentStrongSum));

                    // if one of the signature blocks was a match, we can generate a Copy command
                    if (matchingBlock != null)
                    {
                        if (currentCommand.Kind == CommandKind.Copy &&
                            currentCommand.Position + currentCommand.Length == matchingBlock.StartPos)
                        {
                            // in this case, we can just add this copy onto the previous one
                            currentCommand.Length = currentCommand.Length + (ulong)currentBlock.Count;
                        }
                        else
                        {
                            // if we can't append to the current command, then return the current command and start a new one
                            if (currentCommand.Kind != CommandKind.Reserved)
                            {
                                yield return currentCommand;
                            }

                            currentCommand = new OutputCommand
                            {
                                Kind = CommandKind.Copy,
                                Position = matchingBlock.StartPos,
                                Length = (ulong)currentBlock.Count
                            };
                        }

                        // if we found a match, then we read a whole new block and reset the sum to it's hash
                        wasMatch = true;
                        ReadNewBlock(inputStream, signatures.BlockLength, out currentBlock, out currentSum);
                    }
                }

                // if there was no match for the current block, the we have to output it's first byte (at least)
                // as a literal value, and try again starting at the next byte
                if (!wasMatch)
                {
                    // pull out the oldest byte
                    byte oldestByte = currentBlock.Dequeue();

                    // if we're not at the end of the file
                    if (inputStream.BaseStream.Position != inputStream.BaseStream.Length)
                    {
                        // read a byte and add it in, hoping to find a match at the next spot
                        byte nextByte = inputStream.ReadByte();
                        currentBlock.Enqueue(nextByte);
                        currentSum.Rotate(byteOut: oldestByte, byteIn: nextByte);
                    }
                    else
                    {
                        // if we are at the end of the file, then just rollout the oldestByte and see if we have a match for the partial block
                        // (this could happen if we match the last block in the original file)
                        currentSum.Rollout(byteOut: oldestByte);
                    }

                    if (currentCommand.Kind == CommandKind.Literal && currentCommand.Literal.Count < MaxLiteralLength)
                    {
                        // if we already have a literal command, just append a new byte on
                        currentCommand.Literal.Add(oldestByte);
                    }
                    else
                    {
                        // otherwise we have to emit the current command and start a new literal command
                        if (currentCommand.Kind != CommandKind.Reserved)
                        {
                            yield return currentCommand;
                        }

                        currentCommand = new OutputCommand
                        {
                            Kind = CommandKind.Literal,
                            Literal = new List<byte> { oldestByte },
                        };
                    }
                }
            }

            yield return currentCommand;
            yield return new OutputCommand
            {
                Kind = CommandKind.End,
            };
        }
Example #6
0
        public static IEnumerable <OutputCommand> ComputeCommands(
            BinaryReader inputStream,
            SignatureFile signatures)
        {
            OutputCommand currentCommand = new OutputCommand {
                Kind = CommandKind.Reserved
            };
            Rollsum      currentSum;
            Queue <byte> currentBlock;

            // Read the first block to initialize
            ReadNewBlock(inputStream, signatures.BlockLength, out currentBlock, out currentSum);
            while (currentBlock.Count > 0)
            {
                // if the block has a matching rolling sum to any contained in the signature, those are candidates
                var  matchCandidates = signatures.BlockLookup[currentSum.Digest];
                bool wasMatch        = false;
                if (matchCandidates.Any())
                {
                    // now compute the strong sum and see if any of the signature blocks match it
                    byte[] currentStrongSum = signatures.StrongSumMethod(currentBlock.ToArray()).Take(signatures.StrongSumLength).ToArray();
                    var    matchingBlock    = matchCandidates.FirstOrDefault(s => s.StrongSum.SequenceEqual(currentStrongSum));

                    // if one of the signature blocks was a match, we can generate a Copy command
                    if (matchingBlock != null)
                    {
                        if (currentCommand.Kind == CommandKind.Copy &&
                            currentCommand.Position + currentCommand.Length == matchingBlock.StartPos)
                        {
                            // in this case, we can just add this copy onto the previous one
                            currentCommand.Length = currentCommand.Length + (ulong)currentBlock.Count;
                        }
                        else
                        {
                            // if we can't append to the current command, then return the current command and start a new one
                            if (currentCommand.Kind != CommandKind.Reserved)
                            {
                                yield return(currentCommand);
                            }

                            currentCommand = new OutputCommand
                            {
                                Kind     = CommandKind.Copy,
                                Position = matchingBlock.StartPos,
                                Length   = (ulong)currentBlock.Count
                            };
                        }

                        // if we found a match, then we read a whole new block and reset the sum to it's hash
                        wasMatch = true;
                        ReadNewBlock(inputStream, signatures.BlockLength, out currentBlock, out currentSum);
                    }
                }

                // if there was no match for the current block, the we have to output it's first byte (at least)
                // as a literal value, and try again starting at the next byte
                if (!wasMatch)
                {
                    // pull out the oldest byte
                    byte oldestByte = currentBlock.Dequeue();

                    // if we're not at the end of the file
                    if (inputStream.BaseStream.Position != inputStream.BaseStream.Length)
                    {
                        // read a byte and add it in, hoping to find a match at the next spot
                        byte nextByte = inputStream.ReadByte();
                        currentBlock.Enqueue(nextByte);
                        currentSum.Rotate(byteOut: oldestByte, byteIn: nextByte);
                    }
                    else
                    {
                        // if we are at the end of the file, then just rollout the oldestByte and see if we have a match for the partial block
                        // (this could happen if we match the last block in the original file)
                        currentSum.Rollout(byteOut: oldestByte);
                    }

                    if (currentCommand.Kind == CommandKind.Literal && currentCommand.Literal.Count < MaxLiteralLength)
                    {
                        // if we already have a literal command, just append a new byte on
                        currentCommand.Literal.Add(oldestByte);
                    }
                    else
                    {
                        // otherwise we have to emit the current command and start a new literal command
                        if (currentCommand.Kind != CommandKind.Reserved)
                        {
                            yield return(currentCommand);
                        }

                        currentCommand = new OutputCommand
                        {
                            Kind    = CommandKind.Literal,
                            Literal = new List <byte> {
                                oldestByte
                            },
                        };
                    }
                }
            }

            yield return(currentCommand);

            yield return(new OutputCommand
            {
                Kind = CommandKind.End,
            });
        }
Example #7
0
        public static IEnumerable <OutputCommand> ComputeCommands(BinaryReader inputStream, SignatureFile signatures)
        {
            OutputCommand outputCommand = default(OutputCommand);

            outputCommand.Kind = CommandKind.Reserved;
            OutputCommand outputCommand2 = outputCommand;
            long          inputLength    = inputStream.BaseStream.Length;

            ReadNewBlock(inputStream, signatures.BlockLength, out Queue <byte> currentBlock, out Rollsum currentSum);
            while (currentBlock.Count > 0)
            {
                List <BlockSignature> value = null;
                bool flag = false;
                if (signatures.BlockLookup.TryGetValue(currentSum.Digest, out value))
                {
                    byte[]         currentStrongSum = signatures.StrongSumMethod(currentBlock.ToArray());
                    BlockSignature matchingBlock    = FindBlockSignatureByStrongSum(value, currentStrongSum);
                    if (matchingBlock != null)
                    {
                        if (outputCommand2.Kind == CommandKind.Copy && outputCommand2.Position + outputCommand2.Length == matchingBlock.StartPos)
                        {
                            outputCommand2.Length = (ulong)((long)outputCommand2.Length + (long)currentBlock.Count);
                        }
                        else
                        {
                            if (outputCommand2.Kind != CommandKind.Reserved)
                            {
                                yield return(outputCommand2);
                            }
                            outputCommand          = default(OutputCommand);
                            outputCommand.Kind     = CommandKind.Copy;
                            outputCommand.Position = matchingBlock.StartPos;
                            outputCommand.Length   = (ulong)currentBlock.Count;
                            outputCommand2         = outputCommand;
                        }
                        flag = true;
                        ReadNewBlock(inputStream, signatures.BlockLength, out currentBlock, out currentSum);
                    }
                }
                if (!flag)
                {
                    byte oldestByte = currentBlock.Dequeue();
                    if (inputStream.BaseStream.Position != inputLength)
                    {
                        byte b = inputStream.ReadByte();
                        currentBlock.Enqueue(b);
                        currentSum.Rotate(oldestByte, b);
                    }
                    else
                    {
                        currentSum.Rollout(oldestByte);
                    }
                    if (outputCommand2.Kind == CommandKind.Literal && outputCommand2.Literal.Count < 4194304)
                    {
                        outputCommand2.Literal.Add(oldestByte);
                    }
                    else
                    {
                        if (outputCommand2.Kind != CommandKind.Reserved)
                        {
                            yield return(outputCommand2);
                        }
                        outputCommand         = default(OutputCommand);
                        outputCommand.Kind    = CommandKind.Literal;
                        outputCommand.Literal = new List <byte>
                        {
                            oldestByte
                        };
                        outputCommand2 = outputCommand;
                    }
                }
            }
            yield return(outputCommand2);

            outputCommand = new OutputCommand
            {
                Kind = CommandKind.End
            };
            yield return(outputCommand);
        }