4 using System.Collections.Generic;
7 namespace SiliconStudio.
Paradox.Diffs
9 internal static class ThreeWayMergeOrdered
11 public static void Merge<T, TKey>(
IList<T> result,
IList<T> listBase,
IList<T> list1,
IList<T> list2, Func<T, TKey> keyExtractor, Func<T, T, bool> contentComparer, Action<ThreeWayConflictType, IList<T>[],
int[],
IList<T>> conflictResolver)
13 var keyComparer = Comparer<TKey>.Default;
15 if (contentComparer == null)
21 var lists =
new[] { listBase, list1, list2 };
22 var indices =
new[] { 0, 0, 0 };
23 var reachedEnd =
new bool[3];
24 var keys =
new TKey[3];
25 var isMinKey =
new bool[3];
27 while (indices[0] < lists[0].Count || indices[1] < lists[1].Count || indices[2] < lists[2].Count)
29 bool minKeyDefined =
false;
30 TKey minKey =
default(TKey);
33 for (
int i = 0; i < 3; ++i)
35 reachedEnd[i] = indices[i] >= lists[i].Count;
38 keys[i] = keyExtractor(lists[i][indices[i]]);
39 if (!minKeyDefined || keyComparer.Compare(minKey, keys[i]) > 0)
48 for (
int i = 0; i < 3; ++i)
50 isMinKey[i] = (!reachedEnd[i]) && (keyComparer.Compare(minKey, keys[i]) == 0);
53 if (!minKeyDefined || (!isMinKey[0] && !isMinKey[1] && !isMinKey[2]))
54 throw new InvalidOperationException();
59 if (isMinKey[1] && !isMinKey[2])
62 result.Add(lists[1][indices[1]]);
64 else if (!isMinKey[1] && isMinKey[2])
67 result.Add(lists[2][indices[2]]);
69 else if (isMinKey[1] && isMinKey[2])
72 if (!contentComparer(lists[1][indices[1]], lists[2][indices[2]]))
75 conflictResolver(ThreeWayConflictType.Insertion1And2, lists.ToArray(), indices.ToArray(), result);
80 result.Add(lists[1][indices[1]]);
85 throw new InvalidOperationException();
90 if (!isMinKey[1] && !isMinKey[2])
93 conflictResolver(ThreeWayConflictType.Deleted1And2, lists.ToArray(), indices.ToArray(), result);
95 else if (isMinKey[1] && isMinKey[2])
98 bool compare01 = contentComparer(lists[0][indices[0]], lists[1][indices[1]]);
99 bool compare02 = contentComparer(lists[0][indices[0]], lists[2][indices[2]]);
100 bool compare12 = contentComparer(lists[1][indices[1]], lists[2][indices[2]]);
102 if (compare01 && compare02)
105 result.Add(lists[0][indices[0]]);
110 result.Add(lists[1][indices[1]]);
112 else if (!compare01 && !compare02)
115 conflictResolver(ThreeWayConflictType.Modified1And2, lists.ToArray(), indices.ToArray(), result);
118 else if (!compare01 || !compare02)
122 result.Add(lists[1][indices[1]]);
124 result.Add(lists[2][indices[2]]);
127 else if (isMinKey[1] && !isMinKey[2])
130 if (!contentComparer(lists[0][indices[0]], lists[1][indices[1]]))
133 conflictResolver(ThreeWayConflictType.Modified1Deleted2, lists.ToArray(), indices.ToArray(), result);
137 else if (!isMinKey[1] && isMinKey[2])
140 if (!contentComparer(lists[0][indices[0]], lists[2][indices[2]]))
143 conflictResolver(ThreeWayConflictType.Modified2Deleted1, lists.ToArray(), indices.ToArray(), result);
150 for (
int i = 0; i < 3; ++i)