Beispiel #1
0
        public static void WriteCommand(BinaryWriter s, OutputCommand command)
        {
            if (command.Kind == CommandKind.Literal)
            {
                if (command.Literal.Count <= 64)
                {
                    if (command.Literal.Count == 0)
                    {
                        throw new ArgumentException("Literal must have at least 1 byte");
                    }

                    // literals from 1..64 have a command code equal to the length
                    s.Write((byte)command.Literal.Count);
                }
                else
                {
                    // longer literals encode the length
                    int lengthBytes = GetSizeNeeded((ulong)command.Literal.Count);
                    int idx = SizeToIdx(lengthBytes);
                    byte commandCode = (byte)(MinVariableLiteral + idx);
                    s.Write(commandCode);
                    StreamHelpers.WriteBigEndian(s, (ulong)command.Literal.Count, lengthBytes);
                }

                s.Write(command.Literal.ToArray());
            }
            else if (command.Kind == CommandKind.Copy)
            {
                int positionBytes = GetSizeNeeded(command.Position);
                int lengthBytes = GetSizeNeeded(command.Length);
                byte positionIdx = SizeToIdx(positionBytes);
                byte lengthIdx = SizeToIdx(lengthBytes);

                byte commandCode = (byte)(MinCopyCommand + positionIdx * 4 + lengthIdx);
                s.Write(commandCode);
                StreamHelpers.WriteBigEndian(s, command.Position, positionBytes);
                StreamHelpers.WriteBigEndian(s, command.Length, lengthBytes);
            }
            else if (command.Kind == CommandKind.End)
            {
                s.Write(0); // command code for end
            }
        }
Beispiel #2
0
        public static void WriteCommand(BinaryWriter s, OutputCommand command)
        {
            if (command.Kind == CommandKind.Literal)
            {
                if (command.Literal.Count <= 64)
                {
                    if (command.Literal.Count == 0)
                    {
                        throw new ArgumentException("Literal must have at least 1 byte");
                    }

                    // literals from 1..64 have a command code equal to the length
                    s.Write((byte)command.Literal.Count);
                }
                else
                {
                    // longer literals encode the length
                    int  lengthBytes = GetSizeNeeded((ulong)command.Literal.Count);
                    int  idx         = SizeToIdx(lengthBytes);
                    byte commandCode = (byte)(MinVariableLiteral + idx);
                    s.Write(commandCode);
                    StreamHelpers.WriteBigEndian(s, (ulong)command.Literal.Count, lengthBytes);
                }

                s.Write(command.Literal.ToArray());
            }
            else if (command.Kind == CommandKind.Copy)
            {
                int  positionBytes = GetSizeNeeded(command.Position);
                int  lengthBytes   = GetSizeNeeded(command.Length);
                byte positionIdx   = SizeToIdx(positionBytes);
                byte lengthIdx     = SizeToIdx(lengthBytes);

                byte commandCode = (byte)(MinCopyCommand + positionIdx * 4 + lengthIdx);
                s.Write(commandCode);
                StreamHelpers.WriteBigEndian(s, command.Position, positionBytes);
                StreamHelpers.WriteBigEndian(s, command.Length, lengthBytes);
            }
            else if (command.Kind == CommandKind.End)
            {
                s.Write(0); // command code for end
            }
        }
Beispiel #3
0
 public static void WriteCommand(BinaryWriter s, OutputCommand command)
 {
     if (command.Kind == CommandKind.Literal)
     {
         if (command.Literal.Count <= 64)
         {
             if (command.Literal.Count == 0)
             {
                 throw new ArgumentException("Literal must have at least 1 byte");
             }
             s.Write((byte)command.Literal.Count);
         }
         else
         {
             int  sizeNeeded = GetSizeNeeded((ulong)command.Literal.Count);
             int  num        = SizeToIdx(sizeNeeded);
             byte value      = (byte)(65 + num);
             s.Write(value);
             StreamHelpers.WriteBigEndian(s, (ulong)command.Literal.Count, sizeNeeded);
         }
         s.Write(command.Literal.ToArray());
     }
     else if (command.Kind == CommandKind.Copy)
     {
         int  sizeNeeded2 = GetSizeNeeded(command.Position);
         int  sizeNeeded3 = GetSizeNeeded(command.Length);
         byte b           = SizeToIdx(sizeNeeded2);
         byte b2          = SizeToIdx(sizeNeeded3);
         byte value2      = (byte)(69 + b * 4 + b2);
         s.Write(value2);
         StreamHelpers.WriteBigEndian(s, command.Position, sizeNeeded2);
         StreamHelpers.WriteBigEndian(s, command.Length, sizeNeeded3);
     }
     else if (command.Kind == CommandKind.End)
     {
         s.Write(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,
            };
        }
Beispiel #5
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,
            });
        }
Beispiel #6
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);
        }