Пример #1
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,
            });
        }
Пример #2
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,
            };
        }
Пример #3
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);
        }