Skip to content

Commit 240b21c

Browse files
author
Kapil Borle
committed
Make accessing lines in TextLines faster (very likely)
1 parent a01d552 commit 240b21c

1 file changed

Lines changed: 95 additions & 19 deletions

File tree

Engine/EditableText.cs

Lines changed: 95 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ private int GetNumNewLineCharacters()
186186
private class TextLines : IList<String>
187187
{
188188
private LinkedList<String> lines;
189+
private int lastAccessedIndex;
190+
private LinkedListNode<String> lastAccessedNode;
189191

190192
private void ValidateIndex(int index)
191193
{
@@ -195,23 +197,94 @@ private void ValidateIndex(int index)
195197
}
196198
}
197199

200+
private void SetLastAccessed(int index, LinkedListNode<String> node)
201+
{
202+
lastAccessedIndex = index;
203+
lastAccessedNode = node;
204+
}
205+
206+
private void InvalidateLastAccessed()
207+
{
208+
lastAccessedIndex = -1;
209+
lastAccessedNode = null;
210+
}
211+
212+
private bool IsLastAccessedValid()
213+
{
214+
return lastAccessedIndex != -1;
215+
}
216+
198217
private LinkedListNode<String> GetNodeAt(int index)
199218
{
200-
var node = lines.First;
201-
int count = 0;
219+
if (index == 0)
220+
{
221+
return lines.First;
222+
}
223+
224+
if (index == Count - 1)
225+
{
226+
return lines.Last;
227+
}
228+
229+
LinkedListNode<string> node;
230+
int searchDirection;
231+
int count;
232+
GetClosestReference(index, out node, out count, out searchDirection);
202233
while (node != null)
203234
{
204-
if (count++ == index)
235+
if (count == index)
205236
{
206237
return node;
207238
}
208239

209-
node = node.Next;
240+
count += searchDirection;
241+
if (searchDirection > 0)
242+
{
243+
node = node.Next;
244+
}
245+
else
246+
{
247+
node = node.Previous;
248+
}
210249
}
211250

212251
throw new InvalidOperationException();
213252
}
214253

254+
private void GetClosestReference(
255+
int index,
256+
out LinkedListNode<string> refNode,
257+
out int refIndex,
258+
out int searchDirection)
259+
{
260+
var delta = index - lastAccessedIndex;
261+
var deltaAbs = Math.Abs(delta);
262+
263+
// lastAccessedIndex is closer to index than 0
264+
if (IsLastAccessedValid() && deltaAbs < index)
265+
{
266+
// lastAccessedIndex is closer to index than Count - 1
267+
if (deltaAbs < (Count - 1 - index))
268+
{
269+
refNode = lastAccessedNode;
270+
refIndex = lastAccessedIndex;
271+
searchDirection = Math.Sign(delta);
272+
}
273+
else
274+
{
275+
refNode = lines.Last;
276+
refIndex = Count - 1;
277+
searchDirection = -1;
278+
}
279+
}
280+
else
281+
{
282+
refNode = lines.First;
283+
refIndex = 0;
284+
searchDirection = 1;
285+
}
286+
}
287+
215288
public string this[int index]
216289
{
217290
get
@@ -235,9 +308,10 @@ public TextLines()
235308
{
236309
lines = new LinkedList<String>();
237310
Count = 0;
311+
InvalidateLastAccessed();
238312
}
239313

240-
public TextLines(IEnumerable<String> inputLines)
314+
public TextLines(IEnumerable<String> inputLines) : this()
241315
{
242316
if (inputLines == null)
243317
{
@@ -305,19 +379,7 @@ public int IndexOf(string item)
305379
public void Insert(int index, string item)
306380
{
307381
ValidateIndex(index);
308-
if (index == 0)
309-
{
310-
lines.AddFirst(item);
311-
}
312-
else if (index == Count - 1)
313-
{
314-
lines.AddBefore(lines.Last, item);
315-
}
316-
else
317-
{
318-
lines.AddBefore(GetNodeAt(index), item);
319-
}
320-
382+
SetLastAccessed(index, lines.AddBefore(GetNodeAt(index), item));
321383
Count++;
322384
}
323385

@@ -334,7 +396,21 @@ public bool Remove(string item)
334396

335397
public void RemoveAt(int index)
336398
{
337-
lines.Remove(GetNodeAt(index));
399+
var node = GetNodeAt(index);
400+
if (node.Next != null)
401+
{
402+
SetLastAccessed(index, node.Next);
403+
}
404+
else if (node.Previous != null)
405+
{
406+
SetLastAccessed(index - 1, node.Previous);
407+
}
408+
else
409+
{
410+
InvalidateLastAccessed();
411+
}
412+
413+
lines.Remove(node);
338414
Count--;
339415
}
340416

0 commit comments

Comments
 (0)