Exemplo n.º 1
0
        private static Lcs Backtrack(int[,] matrix, List <JToken> left, List <JToken> right, int li, int ri)
        {
            var result = new Lcs();

            for (int i = li, j = ri; i > 0 && j > 0;)
            {
                // If the JSON tokens at the same position are both Objects or both Arrays, we just say they
                // are the same even if they are not, because we can package smaller deltas than an entire
                // object or array replacement by doing object to object or array to array diff.
                if (left[i - 1].Equals(right[j - 1]) ||
                    (left[i - 1].Type == JTokenType.Object && right[j - 1].Type == JTokenType.Object) ||
                    (left[i - 1].Type == JTokenType.Array && right[j - 1].Type == JTokenType.Array))
                {
                    result.Sequence.Insert(0, left[i - 1]);
                    result.Indices1.Insert(0, i - 1);
                    result.Indices2.Insert(0, j - 1);
                    i--;
                    j--;
                    continue;
                }

                if (matrix[i, j - 1] > matrix[i - 1, j])
                {
                    j--;
                }
                else
                {
                    i--;
                }
            }

            return(result);
        }
Exemplo n.º 2
0
        private static Lcs Backtrack(int[,] matrix, List <JToken> left, List <JToken> right, int li, int ri, ItemMatch match)
        {
            var result = new Lcs();

            for (int i = 1, j = 1; i <= li && j <= ri;)
            {
                // If the JSON tokens at the same position are both Objects or both Arrays, we just say they
                // are the same even if they are not, because we can package smaller deltas than an entire
                // object or array replacement by doing object to object or array to array diff.
                if (match.Match(left[i - 1], right[j - 1]))
                {
                    result.Sequence.Add(left[i - 1]);
                    result.Indices1.Add(i - 1);
                    result.Indices2.Add(j - 1);
                    i++;
                    j++;
                    continue;
                }

                if (matrix[i, j - 1] > matrix[i - 1, j])
                {
                    i++;
                }
                else
                {
                    j++;
                }
            }

            return(result);
        }
Exemplo n.º 3
0
        private JObject ArrayDiff(JArray left, JArray right)
        {
            var objectHash = this._options.ObjectHash;
            var itemMatch  = new DefaultItemMatch(objectHash);
            var result     = JObject.Parse(@"{ ""_t"": ""a"" }");

            int commonHead = 0;
            int commonTail = 0;

            if (itemMatch.Match(left, right))
            {
                return(null);
            }

            var childContext = new List <JToken>();

            // Find common head
            while (commonHead < left.Count &&
                   commonHead < right.Count &&
                   itemMatch.Match(left[commonHead], right[commonHead]))
            {
                var index = commonHead;
                var child = Diff(left[index], right[index]);
                if (child != null)
                {
                    result[$"{index}"] = child;
                }
                commonHead++;
            }

            // Find common tail
            while (commonTail + commonHead < left.Count &&
                   commonTail + commonHead < right.Count &&
                   itemMatch.Match(left[left.Count - 1 - commonTail], right[right.Count - 1 - commonTail]))
            {
                var index1 = left.Count - 1 - commonTail;
                var index2 = right.Count - 1 - commonTail;
                var child  = Diff(left[index1], right[index2]);
                if (child != null)
                {
                    result[$"{index2}"] = child;
                }
                commonTail++;
            }

            if (commonHead + commonTail == left.Count)
            {
                // Trivial case, a block (1 or more consecutive items) was added
                for (int index = commonHead; index < right.Count - commonTail; ++index)
                {
                    result[$"{index}"] = new JArray(right[index]);
                }

                return(result);
            }
            if (commonHead + commonTail == right.Count)
            {
                // Trivial case, a block (1 or more consecutive items) was removed
                for (int index = commonHead; index < left.Count - commonTail; ++index)
                {
                    if (result.ContainsKey(index.ToString()))
                    {
                        result.Remove(index.ToString());
                    }
                    result[$"_{index}"] = new JArray(left[index], 0, (int)DiffOperation.Deleted);
                }

                return(result);
            }

            // Complex Diff, find the LCS (Longest Common Subsequence)
            List <JToken> trimmedLeft  = left.ToList().GetRange(commonHead, left.Count - commonTail - commonHead);
            List <JToken> trimmedRight = right.ToList().GetRange(commonHead, right.Count - commonTail - commonHead);
            Lcs           lcs          = Lcs.Get(trimmedLeft, trimmedRight, itemMatch);

            for (int index = commonHead; index < left.Count - commonTail; ++index)
            {
                if (lcs.Indices1.IndexOf(index - commonHead) < 0)
                {
                    // Removed
                    if (result.ContainsKey(index.ToString()))
                    {
                        result.Remove(index.ToString());
                    }
                    result[$"_{index}"] = new JArray(left[index], 0, (int)DiffOperation.Deleted);
                }
            }

            for (int index = commonHead; index < right.Count - commonTail; index++)
            {
                int indexRight = lcs.Indices2.IndexOf(index - commonHead);

                if (indexRight < 0)
                {
                    // Added
                    result[$"{index}"] = new JArray(right[index]);
                }
                else
                {
                    int li = lcs.Indices1[indexRight] + commonHead;
                    int ri = lcs.Indices2[indexRight] + commonHead;

                    JToken diff = Diff(left[li], right[ri]);

                    if (diff != null)
                    {
                        result[$"{index}"] = diff;
                    }
                }
            }

            return(result);
        }
Exemplo n.º 4
0
        private JObject ArrayDiff(JArray left, JArray right)
        {
            var result = JObject.Parse(@"{ ""_t"": ""a"" }");

            int commonHead = 0;
            int commonTail = 0;

            if (JToken.DeepEquals(left, right))
            {
                return(null);
            }

            // Find common head
            while (commonHead < left.Count &&
                   commonHead < right.Count &&
                   JToken.DeepEquals(left[commonHead], right[commonHead]))
            {
                commonHead++;
            }

            // Find common tail
            while (commonTail + commonHead < left.Count &&
                   commonTail + commonHead < right.Count &&
                   JToken.DeepEquals(left[left.Count - 1 - commonTail], right[right.Count - 1 - commonTail]))
            {
                commonTail++;
            }

            if (commonHead + commonTail == left.Count)
            {
                // Trivial case, a block (1 or more consecutive items) was added
                for (int index = commonHead; index < right.Count - commonTail; ++index)
                {
                    result[$"{index}"] = new JArray(right[index]);
                }

                return(result);
            }
            if (commonHead + commonTail == right.Count)
            {
                // Trivial case, a block (1 or more consecutive items) was removed
                for (int index = commonHead; index < left.Count - commonTail; ++index)
                {
                    result[$"_{index}"] = new JArray(left[index], 0, (int)DiffOperation.Deleted);
                }

                return(result);
            }

            // Complex Diff, find the LCS (Longest Common Subsequence)
            List <JToken> trimmedLeft  = left.ToList().GetRange(commonHead, left.Count - commonTail - commonHead);
            List <JToken> trimmedRight = right.ToList().GetRange(commonHead, right.Count - commonTail - commonHead);
            Lcs           lcs          = Lcs.Get(trimmedLeft, trimmedRight);

            for (int index = commonHead; index < left.Count - commonTail; ++index)
            {
                if (lcs.Indices1.IndexOf(index - commonHead) < 0)
                {
                    // Removed
                    result[$"_{index}"] = new JArray(left[index], 0, (int)DiffOperation.Deleted);
                }
            }

            for (int index = commonHead; index < right.Count - commonTail; index++)
            {
                int indexRight = lcs.Indices2.IndexOf(index - commonHead);

                if (indexRight < 0)
                {
                    // Added
                    result[$"{index}"] = new JArray(right[index]);
                }
                else
                {
                    int li = lcs.Indices1[indexRight] + commonHead;
                    int ri = lcs.Indices2[indexRight] + commonHead;

                    JToken diff = Diff(left[li], right[ri]);

                    if (diff != null)
                    {
                        result[$"{index}"] = diff;
                    }
                }
            }

            return(result);
        }
        private List <Microsoft.AspNetCore.JsonPatch.Operations.Operation> ArrayDiff(JArray left, JArray right)
        {
            var result = new List <Microsoft.AspNetCore.JsonPatch.Operations.Operation>();

            int commonHead = 0;
            int commonTail = 0;

            if (JToken.DeepEquals(left, right))
            {
                return(null);
            }

            // Find common head
            while (commonHead < left.Count &&
                   commonHead < right.Count &&
                   JToken.DeepEquals(left[commonHead], right[commonHead]))
            {
                commonHead++;
            }

            // Find common tail
            while (commonTail + commonHead < left.Count &&
                   commonTail + commonHead < right.Count &&
                   JToken.DeepEquals(left[left.Count - 1 - commonTail], right[right.Count - 1 - commonTail]))
            {
                commonTail++;
            }

            if (commonHead + commonTail == left.Count)
            {
                // Trivial case, a block (1 or more consecutive items) was added
                for (int index = commonHead; index < right.Count - commonTail; ++index)
                {
                    result.Add(new Microsoft.AspNetCore.JsonPatch.Operations.Operation("add", right.Path, null, right[index]));
                    //result[$"{index}"] = new JArray(right[index]);
                }

                return(result);
            }
            if (commonHead + commonTail == right.Count)
            {
                // Trivial case, a block (1 or more consecutive items) was removed
                for (int index = commonHead; index < left.Count - commonTail; ++index)
                {
                    result.Add(new Microsoft.AspNetCore.JsonPatch.Operations.Operation("remove", $"{right.Path}/{index}", null, null));

                    //result[$"_{index}"] = new JArray(left[index], 0, (int)DiffOperation.Deleted);
                }

                return(result);
            }

            // Complex Diff, find the LCS (Longest Common Subsequence)
            List <JToken> trimmedLeft  = left.ToList().GetRange(commonHead, left.Count - commonTail - commonHead);
            List <JToken> trimmedRight = right.ToList().GetRange(commonHead, right.Count - commonTail - commonHead);
            Lcs           lcs          = Lcs.Get(trimmedLeft, trimmedRight);

            for (int index = commonHead; index < left.Count - commonTail; ++index)
            {
                if (lcs.Indices1.IndexOf(index - commonHead) < 0)
                {
                    // Removed
                    result.Add(new Microsoft.AspNetCore.JsonPatch.Operations.Operation("remove", $"{right.Path}/{index}", null, null));

                    //result[$"_{index}"] = new JArray(left[index], 0, (int)DiffOperation.Deleted);
                }
            }

            for (int index = commonHead; index < right.Count - commonTail; index++)
            {
                int indexRight = lcs.Indices2.IndexOf(index - commonHead);

                if (indexRight < 0)
                {
                    // Added
                    result.Add(new Microsoft.AspNetCore.JsonPatch.Operations.Operation("add", right.Path, null, right[index]));

                    //result[$"{index}"] = new JArray(right[index]);
                }
                else
                {
                    int li = lcs.Indices1[indexRight] + commonHead;
                    int ri = lcs.Indices2[indexRight] + commonHead;

                    var diff = Diff(left[li], right[ri]);

                    if (diff != null)
                    {
                        foreach (var operation in diff)
                        {
                            result.Add(operation);
                        }
                        //result[$"{index}"] = diff;
                    }
                }
            }

            return(result);
        }