Code Coverage Statistics for Source File

c:\Tools\SD3\src\Libraries\ICSharpCode.TextEditor\Project\Src\Document\TextBufferStrategy\GapTextBufferStrategy.cs

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
179
Highlight: Uncovered Code Covered Code
L V Source
1
// <file>
2
//     <copyright see="prj:///doc/copyright.txt"/>
3
//     <license see="prj:///doc/license.txt"/>
4
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
5
//     <version>$Revision: 2667 $</version>
6
// </file>
7
8
using System;
9
using System.Text;
10
11
namespace ICSharpCode.TextEditor.Document
12
{
13
	public class GapTextBufferStrategy : ITextBufferStrategy
14
	{
15
		#if DEBUG
16
		int creatorThread = System.Threading.Thread.CurrentThread.ManagedThreadId;
17
		
18
		void CheckThread()
19
		{
20
			if (System.Threading.Thread.CurrentThread.ManagedThreadId != creatorThread)
21
				throw new InvalidOperationException("GapTextBufferStategy is not thread-safe!");
22
		}
23
		#endif
24
		
25
		char[] buffer = new char[0];
26
		
27
		int gapBeginOffset = 0;
28
		int gapEndOffset = 0;
29
		int gapLength = 0; // gapLength == gapEndOffset - gapBeginOffset
30
		
31
		const int minGapLength = 128;
32
		const int maxGapLength = 2048;
33
		
34
		public int Length {
35
			get {
36
				return buffer.Length - gapLength;
37
			}
38
		}
39
		
40
		public void SetContent(string text)
41
		{
42
			if (text == null) {
43
				text = String.Empty;
44
			}
45
			buffer = text.ToCharArray();
46
			gapBeginOffset = gapEndOffset = gapLength = 0;
47
		}
48
		
49
		public char GetCharAt(int offset)
50
		{
51
			#if DEBUG
52
			CheckThread();
53
			#endif
54
			
55
			if (offset < 0 || offset >= Length) {
56
				throw new ArgumentOutOfRangeException("offset", offset, "0 <= offset < " + Length.ToString());
57
			}
58
			
59
			return offset < gapBeginOffset ? buffer[offset] : buffer[offset + gapLength];
60
		}
61
		
62
		public string GetText(int offset, int length)
63
		{
64
			#if DEBUG
65
			CheckThread();
66
			#endif
67
			
68
			if (offset < 0 || offset > Length) {
69
				throw new ArgumentOutOfRangeException("offset", offset, "0 <= offset <= " + Length.ToString());
70
			}
71
			if (length < 0 || offset + length > Length) {
72
				throw new ArgumentOutOfRangeException("length", length, "0 <= length, offset(" + offset + ")+length <= " + Length.ToString());
73
			}
74
			
75
			int end = offset + length;
76
			
77
			if (end < gapBeginOffset) {
78
				return new string(buffer, offset, length);
79
			}
80
			
81
			if (offset > gapBeginOffset) {
82
				return new string(buffer, offset + gapLength, length);
83
			}
84
			
85
			int block1Size = gapBeginOffset - offset;
86
			int block2Size = end - gapBeginOffset;
87
			
88
			StringBuilder buf = new StringBuilder(block1Size + block2Size);
89
			buf.Append(buffer, offset,       block1Size);
90
			buf.Append(buffer, gapEndOffset, block2Size);
91
			return buf.ToString();
92
		}
93
		
94
		public void Insert(int offset, string text)
95
		{
96
			Replace(offset, 0, text);
97
		}
98
		
99
		public void Remove(int offset, int length)
100
		{
101
			Replace(offset, length, String.Empty);
102
		}
103
		
104
		public void Replace(int offset, int length, string text)
105
		{
106
			if (text == null) {
107
				text = String.Empty;
108
			}
109
			
110
			#if DEBUG
111
			CheckThread();
112
			#endif
113
			
114
			if (offset < 0 || offset > Length) {
115
				throw new ArgumentOutOfRangeException("offset", offset, "0 <= offset <= " + Length.ToString());
116
			}
117
			if (length < 0 || offset + length > Length) {
118
				throw new ArgumentOutOfRangeException("length", length, "0 <= length, offset+length <= " + Length.ToString());
119
			}
120
			
121
			// Math.Max is used so that if we need to resize the array
122
			// the new array has enough space for all old chars
123
			PlaceGap(offset, text.Length - length);
124
			gapEndOffset += length; // delete removed text
125
			text.CopyTo(0, buffer, gapBeginOffset, text.Length);
126
			gapBeginOffset += text.Length;
127
			gapLength = gapEndOffset - gapBeginOffset;
128
			if (gapLength > maxGapLength) {
129
				MakeNewBuffer(gapBeginOffset, minGapLength);
130
			}
131
		}
132
		
133
		void PlaceGap(int newGapOffset, int minRequiredGapLength)
134
		{
135
			if (gapLength < minRequiredGapLength) {
136
				// enlarge gap
137
				MakeNewBuffer(newGapOffset, minRequiredGapLength);
138
			} else {
139
				while (newGapOffset < gapBeginOffset) {
140
					buffer[--gapEndOffset] = buffer[--gapBeginOffset];
141
				}
142
				while (newGapOffset > gapBeginOffset) {
143
					buffer[gapBeginOffset++] = buffer[gapEndOffset++];
144
				}
145
			}
146
		}
147
		
148
		void MakeNewBuffer(int newGapOffset, int newGapLength)
149
		{
150
			if (newGapLength < minGapLength) newGapLength = minGapLength;
151
			
152
			char[] newBuffer = new char[Length + newGapLength];
153
			if (newGapOffset < gapBeginOffset) {
154
				// gap is moving backwards
155
				
156
				// first part:
157
				Array.Copy(buffer, 0, newBuffer, 0, newGapOffset);
158
				// moving middle part:
159
				Array.Copy(buffer, newGapOffset, newBuffer, newGapOffset + newGapLength, gapBeginOffset - newGapOffset);
160
				// last part:
161
				Array.Copy(buffer, gapEndOffset, newBuffer, newBuffer.Length - (buffer.Length - gapEndOffset), buffer.Length - gapEndOffset);
162
			} else {
163
				// gap is moving forwards
164
				// first part:
165
				Array.Copy(buffer, 0, newBuffer, 0, gapBeginOffset);
166
				// moving middle part:
167
				Array.Copy(buffer, gapEndOffset, newBuffer, gapBeginOffset, newGapOffset - gapBeginOffset);
168
				// last part:
169
				int lastPartLength = newBuffer.Length - (newGapOffset + newGapLength);
170
				Array.Copy(buffer, buffer.Length - lastPartLength, newBuffer, newGapOffset + newGapLength, lastPartLength);
171
			}
172
			
173
			gapBeginOffset = newGapOffset;
174
			gapEndOffset = newGapOffset + newGapLength;
175
			gapLength = newGapLength;
176
			buffer = newBuffer;
177
		}
178
	}
179
}