Welcome to mirror list, hosted at ThFree Co, Russian Federation.

TextDiff.cs « MonoDevelop.Components.Diff « MonoDevelop.Ide « core « src « main - github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bbab4ab86d1d5e46c38d58528a7fb3cd4cf74491 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using System;
using System.Collections;

namespace MonoDevelop.Components.Diff {
	
	public class TextDiff : IDiff {
		Node left, right;
		ArrayList hunks = new ArrayList();
		
		public TextDiff(string left, string right) : this (left, right, null) {
		}
		
		public TextDiff(string left, string right, IComparer comparer) {
			this.left = new Node(left, 0, left.Length, 0);
			this.right = new Node(right, 0, right.Length, 0);
			

			TextDiffStructuredDiff diff = new TextDiffStructuredDiff(hunks, left.ToCharArray(), right.ToCharArray());
			diff.AddInterface(typeof(Node), new TextDiffNodeInterface(comparer));
			diff.Compare(this.left, this.right);
		}
		
		public IList Left { get { return left.ToString().ToCharArray(); } }
		public  IList Right { get { return right.ToString().ToCharArray(); } }
		
		IEnumerator IEnumerable.GetEnumerator() {
			return hunks.GetEnumerator();
		}

		private class TextDiffStructuredDiff : StructuredDiff {
			ArrayList hunks;
			IList leftlist, rightlist;
			
			public TextDiffStructuredDiff(ArrayList hunks, IList leftlist, IList rightlist) {
				this.hunks = hunks;
				this.leftlist = leftlist;
				this.rightlist = rightlist;
			}
			
			protected override void WritePushNode(NodeInterface nodeInterface, object left, object right) {
			}
	
			protected override void WritePushSame() {
			}
			
			private void AddHunk(int lcount, int rcount, bool same) {
				if (hunks.Count > 0 && same == ((Diff.Hunk)hunks[hunks.Count-1]).Same) {
					Diff.Hunk prev = (Diff.Hunk)hunks[hunks.Count-1];
					hunks[hunks.Count-1] = new Diff.Hunk(
						leftlist,
						rightlist,
						prev.Left.Start,
						prev.Left.End + lcount,
						prev.Right.Start,
						prev.Right.End + rcount,
						same);
					return;
				}
				
				int le = -1;
				int re = -1;
				if (hunks.Count > 0) {
					Diff.Hunk prev = (Diff.Hunk)hunks[hunks.Count-1];
					le = prev.Left.End;
					re = prev.Right.End;
				}
				
				hunks.Add( new Diff.Hunk(
						leftlist,
						rightlist,
						le + 1,
						le + lcount,
						re + 1,
						re + rcount,
						same) );
			}
		
			protected override void WriteNodeSame(NodeInterface nodeInterface, object left, object right) {
				AddHunk(((Node)left).count, ((Node)right).count, true);
			}

			protected override void WritePopSame() {
			}
	
			protected override void WriteNodeChange(NodeInterface leftInterface, object left, NodeInterface rightInterface, object right) {
				AddHunk(((Node)left).count, ((Node)right).count, false);
			}
	
			protected override void WriteNodesRemoved(IList objects) {
				int start = ((Node)objects[0]).start;
				int end = ((Node)objects[objects.Count-1]).start + ((Node)objects[objects.Count-1]).count - 1;
				
				AddHunk(end - start + 1, 0, false);
			}
	
			protected override void WriteNodesAdded(IList objects) {
				int start = ((Node)objects[0]).start;
				int end = ((Node)objects[objects.Count-1]).start + ((Node)objects[objects.Count-1]).count - 1;
				
				AddHunk(0, end - start + 1, false);
			}
	
			protected override void WritePopNode() {
			}
		}
		
		private class TextDiffNodeInterface : NodeInterface {
			IComparer comparer;
			
			public TextDiffNodeInterface(IComparer comparer) { this.comparer = comparer; }
			
			public override IList GetChildren(object node) {
				if (((Node)node).children.Count == 0) return null;
				return ((Node)node).children;
			}
			
			private bool Equal(string a, string b) {
				if (comparer == null)
					return a == b;
				return comparer.Compare(a, b) == 0;
			}
			
			public override float Compare(object left, object right, StructuredDiff comparer) {
				string l = left.ToString(), r = right.ToString();
				if (Equal(l, r)) return 0;
				if (l.Length == 1 || r.Length == 1) return 1;
				float d = comparer.CompareLists(GetChildren(left), GetChildren(right));
				if (((Node)left).level == 2 && d >= .75) d = 1.1f;
				return d;
			}
			
			public override int GetHashCode(object node) {
				return node.ToString().GetHashCode();
			}
		}	
		
		private class Node {
			public string source;
			public int start, count;
			
			public int level;
			public ArrayList children = new ArrayList();
			
			static char[][] delims = new char[][] {
				new char[] { '\n', '\r' },
				new char[] { ' ', '\t', '.', ',' }
				};
			
			public Node(string source, int start, int count, int level) {
				this.source = source;
				this.start = start;
				this.count = count;
				this.level = level;
				
				if (level <= 1) {
					int pos = start;
					foreach (string child in ToString().Split(delims[level])) {
						if (child.Length >= 1)
							children.Add(new Node(source, pos, child.Length, level+1));
						if (pos + child.Length < count)
							children.Add(new Node(source, pos+child.Length, 1, level+1));
						pos += child.Length + 1;
					}
				} else if (level == 2) {
					for (int i = start; i < start + count; i++)
						children.Add(new Node(source, i, 1, level+1));
				}
				
			}
			
			public override string ToString() {
				return source.Substring(start, count);
			}
		}
	}
	
}