Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Difference.cs
1using System;
3
5{
9 public static class Difference
10 {
25 public static EditScript<T> Analyze<T>(T[] S1, T[] S2)
26 {
27 int c1 = S1.Length;
28 int c2 = S2.Length;
29
30 if (c1 == 0 && c2 == 0)
31 return new EditScript<T>(S1, S2, Array.Empty<Step<T>>());
32
33 int StartOffset = 0;
34
35 while (StartOffset < c1 && StartOffset < c2 &&
36 S1[StartOffset].Equals(S2[StartOffset]))
37 {
38 StartOffset++;
39 }
40
41 int EndOffset1 = c1;
42 int EndOffset2 = c2;
43
44 while (EndOffset1 > StartOffset && EndOffset2 > StartOffset &&
45 S1[EndOffset1 - 1].Equals(S2[EndOffset2 - 1]))
46 {
47 EndOffset1--;
48 EndOffset2--;
49 }
50
51 int c1p = EndOffset1 - StartOffset + 1;
52 int c2p = EndOffset2 - StartOffset + 1;
53 long NrBits = ((long)c1p) * c2p;
54 long NrBytes = (NrBits + 7) >> 3;
55
56 if (NrBytes > int.MaxValue)
57 throw new OutOfMemoryException("Unable to allocate enough memory to process the difference between the two sequences.");
58
59 byte[] Processed = new byte[NrBytes];
60
65 State<T> P, Q;
66 bool b1, b2;
67 int i, j, iByte;
68 byte iBit;
69
70 P = null;
71 for (i = 0; i <= StartOffset; i++)
72 {
73 P = new State<T>()
74 {
75 Op = EditOperation.Keep,
76 i1 = i,
77 i2 = i,
78 Prev = P
79 };
80 }
81
82 while (true)
83 {
84 if (P.i1 == EndOffset1 && P.i2 == EndOffset2)
85 break;
86
87 i = P.i1 - StartOffset + (P.i2 - StartOffset) * c1p;
88 iByte = i >> 3;
89 iBit = (byte)(1 << (i & 7));
90
91 if ((Processed[iByte] & iBit) == 0)
92 {
93 Processed[iByte] |= iBit;
94
95 if (b2 = P.i2 < EndOffset2)
96 {
97 j = i + c1p;
98 if ((Processed[j >> 3] & (byte)(1 << (j & 7))) == 0)
99 {
100 Q = new State<T>()
101 {
103 i1 = P.i1,
104 i2 = P.i2 + 1,
105 Prev = P
106 };
107
108 if (P.Op == EditOperation.Insert)
109 Next.AddLastItem(Q);
110 else
111 NextNext.AddLastItem(Q);
112 }
113 }
114
115 if (b1 = P.i1 < EndOffset1)
116 {
117 j = i + 1;
118 if ((Processed[j >> 3] & (byte)(1 << (j & 7))) == 0)
119 {
120 Q = new State<T>()
121 {
122 Op = EditOperation.Delete,
123 i1 = P.i1 + 1,
124 i2 = P.i2,
125 Prev = P
126 };
127
128 if (P.Op == EditOperation.Delete)
129 Next.AddLastItem(Q);
130 else
131 NextNext.AddLastItem(Q);
132 }
133 }
134
135 if (b1 && b2 && S1[P.i1].Equals(S2[P.i2]))
136 {
137 j = i + 1 + c1p;
138 if ((Processed[j >> 3] & (byte)(1 << (j & 7))) == 0)
139 {
140 Q = new State<T>()
141 {
142 Op = EditOperation.Keep,
143 i1 = P.i1 + 1,
144 i2 = P.i2 + 1,
145 Prev = P
146 };
147
148 Current.AddLastItem(Q);
149
150 if (Q.i1 == EndOffset1 && Q.i2 == EndOffset2)
151 {
152 P = Q;
153 break;
154 }
155 }
156 }
157 }
158
159 if (!Current.HasFirstItem)
160 {
161 Temp = Current;
162
163 if (!Next.HasFirstItem)
164 Current = NextNext;
165 else
166 {
167 Current = Next;
168 Next = NextNext;
169 }
170
171 NextNext = Temp;
172 }
173
174 P = Current.RemoveLast();
175 }
176
177 while (EndOffset1 < c1 && EndOffset2 < c2)
178 {
179 P = new State<T>()
180 {
181 Op = EditOperation.Keep,
182 i1 = ++EndOffset1,
183 i2 = ++EndOffset2,
184 Prev = P
185 };
186 }
187
188 State<T> Loop = P;
189 int NrSteps = 0;
190
191 while (!(Loop.Prev is null))
192 {
193 NrSteps++;
194 Loop = Loop.Prev;
195 }
196
197 State<T>[] Steps = new State<T>[NrSteps];
198 for (i = NrSteps, Loop = P; i > 0; Loop = Loop.Prev)
199 Steps[--i] = Loop;
200
201 ChunkedList<T> Elements = new ChunkedList<T>();
202 ChunkedList<Step<T>> Operations = new ChunkedList<Step<T>>();
203 EditOperation Op;
204
205 Q = Steps[0];
206 Op = Q.Op;
207
208 for (i = 0; i < NrSteps; i++)
209 {
210 P = Steps[i];
211 if (P.Op != Op)
212 {
213 Operations.Add(new Step<T>(Elements.ToArray(), Q.i1, Q.i2, Op));
214 Q = P;
215 Op = P.Op;
216 Elements.Clear();
217 }
218
219 if (Op == EditOperation.Insert)
220 Elements.Add(S2[P.i2 - 1]);
221 else
222 Elements.Add(S1[P.i1 - 1]);
223 }
224
225 Operations.Add(new Step<T>(Elements.ToArray(), Q.i1, Q.i2, Op));
226
227 return new EditScript<T>(S1, S2, Operations.ToArray());
228 }
229
230 private class State<T>
231 {
232 public EditOperation Op;
233 public int i1;
234 public int i2;
235 public State<T> Prev;
236
237 public override string ToString()
238 {
239 return this.Op.ToString() + " " + this.i1.ToString() + "," + this.i2.ToString();
240 }
241 }
242
249 public static EditScript<char> AnalyzeStrings(string s1, string s2)
250 {
251 return Analyze(s1.ToCharArray(), s2.ToCharArray());
252 }
253
260 public static EditScript<string> AnalyzeRows(string Text1, string Text2)
261 {
262 return Analyze(ExtractRows(Text1), ExtractRows(Text2));
263 }
264
270 public static string[] ExtractRows(string Text)
271 {
272 return Text.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
273 }
274
275 }
276}
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
void Clear()
Clears the collection.
Definition: ChunkedList.cs:306
bool HasFirstItem
If there is a first item in the collection
Definition: ChunkedList.cs:778
void Insert(int Index, T Item)
Inserts an item to the list at the specified index.
T RemoveLast()
Removes the last item in the collection.
Definition: ChunkedList.cs:911
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
void AddLastItem(T Value)
Adds a new item last in the collection.
Definition: ChunkedList.cs:867
T[] ToArray()
Returns an array containing all elements of the collection.
Computes the difference between two sequences of symbols.
Definition: Difference.cs:10
static EditScript< string > AnalyzeRows(string Text1, string Text2)
Analyzes two texts, estimating the difference between them, as a sequence of rows.
Definition: Difference.cs:260
static string[] ExtractRows(string Text)
Extracts the rows from a text.
Definition: Difference.cs:270
static EditScript< char > AnalyzeStrings(string s1, string s2)
Analyzes two text strings, estimating the difference between them.
Definition: Difference.cs:249
static EditScript< T > Analyze< T >(T[] S1, T[] S2)
Analyzes two sequences of symbols to estimate the difference between them.
Definition: Difference.cs:25
Represents an Edit-script, converting one sequence of symbols to another.
Definition: EditScript.cs:11
Represents a sub-sequence of symbols.
Definition: Step.cs:12
EditOperation
Type of edit-operation