Пример #1
0
        protected static void BuildModificationData(ModificationData A, ModificationData B)
        {
            int N               = A.HashedPieces.Length;
            int M               = B.HashedPieces.Length;
            int MAX             = M + N + 1;
            var forwardDiagonal = new int[MAX + 1];
            var reverseDiagonal = new int[MAX + 1];

            BuildModificationData(A, 0, N, B, 0, M, forwardDiagonal, reverseDiagonal);
        }
Пример #2
0
        private static void CreatePieceHashes(IDictionary <string, int> pieceHash, ModificationData data, bool ignoreWhitespace, bool ignoreCase, Func <string, string[]> chunker)
        {
            string[] pieces;

            if (string.IsNullOrEmpty(data.RawData))
            {
                pieces = new string[0];
            }
            else
            {
                pieces = chunker(data.RawData);
            }

            data.Pieces        = pieces;
            data.HashedPieces  = new int[pieces.Length];
            data.Modifications = new bool[pieces.Length];

            for (int i = 0; i < pieces.Length; i++)
            {
                string piece = pieces[i];
                if (ignoreWhitespace)
                {
                    piece = piece.Trim();
                }
                if (ignoreCase)
                {
                    piece = piece.ToUpperInvariant();
                }

                if (pieceHash.ContainsKey(piece))
                {
                    data.HashedPieces[i] = pieceHash[piece];
                }
                else
                {
                    data.HashedPieces[i] = pieceHash.Count;
                    pieceHash[piece]     = pieceHash.Count;
                }
            }
        }
Пример #3
0
        private static void BuildModificationData(ModificationData A, int startA, int endA, ModificationData B, int startB, int endB, int[] forwardDiagonal, int[] reverseDiagonal)
        {
            while (startA < endA && startB < endB && A.HashedPieces[startA].Equals(B.HashedPieces[startB]))
            {
                startA++;
                startB++;
            }
            while (startA < endA && startB < endB && A.HashedPieces[endA - 1].Equals(B.HashedPieces[endB - 1]))
            {
                endA--;
                endB--;
            }

            int aLength = endA - startA;
            int bLength = endB - startB;

            if (aLength > 0 && bLength > 0)
            {
                EditLengthResult res = CalculateEditLength(A.HashedPieces, startA, endA, B.HashedPieces, startB, endB, forwardDiagonal, reverseDiagonal);
                if (res.EditLength <= 0)
                {
                    return;
                }

                if (res.LastEdit == Edit.DeleteRight && res.StartX - 1 > startA)
                {
                    A.Modifications[--res.StartX] = true;
                }
                else if (res.LastEdit == Edit.InsertDown && res.StartY - 1 > startB)
                {
                    B.Modifications[--res.StartY] = true;
                }
                else if (res.LastEdit == Edit.DeleteLeft && res.EndX < endA)
                {
                    A.Modifications[res.EndX++] = true;
                }
                else if (res.LastEdit == Edit.InsertUp && res.EndY < endB)
                {
                    B.Modifications[res.EndY++] = true;
                }

                BuildModificationData(A, startA, res.StartX, B, startB, res.StartY, forwardDiagonal, reverseDiagonal);

                BuildModificationData(A, res.EndX, endA, B, res.EndY, endB, forwardDiagonal, reverseDiagonal);
            }
            else if (aLength > 0)
            {
                for (int i = startA; i < endA; i++)
                {
                    A.Modifications[i] = true;
                }
            }
            else if (bLength > 0)
            {
                for (int i = startB; i < endB; i++)
                {
                    B.Modifications[i] = true;
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Creates a result containing the differences between the two given strings, using a given predicate to split the strings.
        /// </summary>
        /// <returns>A model holding all the differences.</returns>
        /// <param name="firstText">First text.</param>
        /// <param name="secondText">Second text.</param>
        /// <param name="ignoreWhiteSpace">If set to <c>true</c> ignore white space.</param>
        /// <param name="ignoreCase">If set to <c>true</c> ignore case.</param>
        /// <param name="stringSplitter">Predicate used to split the strings in pieces for comparison.</param>
        public Result CreateCustomDifferences(string firstText, string secondText, bool ignoreWhiteSpace, bool ignoreCase, Func <string, string[]> stringSplitter)
        {
            if (firstText == null)
            {
                throw new ArgumentNullException("Given first text is null");
            }
            if (secondText == null)
            {
                throw new ArgumentNullException("Given second text is null");
            }
            if (stringSplitter == null)
            {
                throw new ArgumentNullException("The provided splitter predicate is null");
            }

            var pieceHash       = new Dictionary <string, int>();
            var lineDifferences = new List <Block>();

            var modificationFirst  = new ModificationData(firstText);
            var modificationSecond = new ModificationData(secondText);

            CreatePieceHashes(pieceHash, modificationFirst, ignoreWhiteSpace, ignoreCase, stringSplitter);
            CreatePieceHashes(pieceHash, modificationSecond, ignoreWhiteSpace, ignoreCase, stringSplitter);

            BuildModificationData(modificationFirst, modificationSecond);

            int lengthFirstPieces = modificationFirst.HashedPieces.Length;
            int lengthSecondPieces = modificationSecond.HashedPieces.Length;
            int positionFirst = 0, positionSecond = 0;

            do
            {
                while (positionFirst < lengthFirstPieces &&
                       positionSecond < lengthSecondPieces &&
                       !modificationFirst.Modifications[positionFirst] &&
                       !modificationSecond.Modifications[positionSecond])
                {
                    positionFirst++;
                    positionSecond++;
                }

                int startOfFirst  = positionFirst;
                int startOfSecond = positionSecond;
                for (; positionFirst < lengthFirstPieces && modificationFirst.Modifications[positionFirst]; positionFirst++)
                {
                    ;
                }

                for (; positionSecond < lengthSecondPieces && modificationSecond.Modifications[positionSecond]; positionSecond++)
                {
                    ;
                }

                int numberRemoved = positionFirst - startOfFirst;
                int numberInsertd = positionSecond - startOfSecond;
                if (numberRemoved > 0 || numberInsertd > 0)
                {
                    lineDifferences.Add(new Block(startOfFirst, numberRemoved, startOfSecond, numberInsertd));
                }
            } while (positionFirst < lengthFirstPieces && positionSecond < lengthSecondPieces);

            return(new Result(modificationFirst.Pieces, modificationSecond.Pieces, lineDifferences));
        }