public IEnumerable <HashBlock> ProcessStream(Stream inputStream)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException("inputStream");
            }
            int  read;
            var  buffer = new byte[_blockSize];
            long offset = 0;

            while ((read = inputStream.Read(buffer, 0, _blockSize)) > 0)
            {
                ChecksumProvider.ProcessBlock(buffer, 0, read);
                yield return(new HashBlock
                {
                    Hash = HashAlgorithm.ComputeHash(buffer, 0, read),
                    Checksum = ChecksumProvider.Value,
                    Offset = (uint)offset,
                    Length = read
                });

                offset += read;
            }
        }
Exemple #2
0
        public IEnumerable <IDelta> GetDeltas(Stream inputStream)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException("inputStream");
            }
            if (_initialized == false)
            {
                throw new InvalidOperationException("Initialize must be called");
            }

            ChecksumProvider.Reset();
            var slidingBuffer = new SlidingStreamBuffer(inputStream, _blockSize);

            slidingBuffer.Warmup();
            bool startingNewBlock = true;
            long offset           = 0;
            var  deltas           = new List <IDelta>();
            var  currentByteDelta = new ByteDelta();

#if DEBUG
            Statistics.Matching        = 0;
            Statistics.PossibleMatches = 0;
            Statistics.NonMatching     = 0;
#endif
            int currentBlockSize;
            while ((currentBlockSize = (int)slidingBuffer.GetNumBytesAvailable()) > 0)
            {
                // Deal with signed integer limits
                if (IsSignedIntLength(offset - currentByteDelta.Offset))
                {
                    currentByteDelta.Length = (int)(offset - currentByteDelta.Offset);
                    deltas.Add(currentByteDelta);
                    startingNewBlock = true;
                }

                if (startingNewBlock)
                {
                    currentByteDelta = new ByteDelta {
                        Offset = offset
                    };
                    ChecksumProvider.ProcessBlock(slidingBuffer.GetBuffer(), 0, currentBlockSize);
                }
                else if (currentBlockSize < _blockSize)
                {
                    ChecksumProvider.TrimFront(); // remaining bytes < block_size, so read nothing new - just trim
                }
                else
                {
                    ChecksumProvider.RollByte(slidingBuffer[(int)(currentBlockSize - 1)]);
                }
                // at this point, sigGen needs the last byte of the current block

                uint   currentBlockChecksum     = ChecksumProvider.Value;
                ushort currentBlockChecksumHash = RollingChecksum.HashChecksum(currentBlockChecksum);
                if (_remoteBlocksIndexTable.ContainsKey(currentBlockChecksumHash))
                {
                    List <HashBlock> possibleRemoteBlockMatches = _remoteBlocksIndexTable[currentBlockChecksumHash];
                    if (possibleRemoteBlockMatches.Any(entry => entry.Checksum == currentBlockChecksum))
                    {
#if DEBUG
                        ++Statistics.PossibleMatches;
#endif
                        byte[] currentBlockHash = HashProvider.ComputeHash(slidingBuffer.GetBuffer(), 0,
                                                                           (int)currentBlockSize);
                        HashBlock matchingTargetBlock;
                        if ((matchingTargetBlock =
                                 possibleRemoteBlockMatches.FirstOrDefault(
                                     entry => entry.Hash.SequenceEqual(currentBlockHash))) != null)
                        {
#if DEBUG
                            Statistics.Matching += 1;
#endif
                            if ((currentByteDelta.Length = (int)(offset - currentByteDelta.Offset)) > 0)
                            {
                                deltas.Add(currentByteDelta);
                            }
                            deltas.Add(new CopyDelta
                            {
                                Offset = matchingTargetBlock.Offset,
                                Length = matchingTargetBlock.Length
                            });
                            slidingBuffer.MoveForward((int)currentBlockSize);
                            offset          += currentBlockSize;
                            startingNewBlock = true;
                            continue;
                        }
                    }
                }
#if DEBUG
                ++Statistics.NonMatching;
#endif
                slidingBuffer.MoveForward(1);
                ++offset;
                startingNewBlock = false;
            }
            Statistics.FileLength = offset;
            if (!startingNewBlock && (currentByteDelta.Length = (int)(offset - currentByteDelta.Offset)) > 0)
            {
                deltas.Add(currentByteDelta);
            }
#if DEBUG
            Statistics.FileLength = offset;
#endif
            return(deltas);
        }