Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.AvalonEdit/5.0.1/AvalonEdit-5.0.1/Utils/RopeTextReader.cs @ 16147

Last change on this file since 16147 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 3.8 KB
Line 
1// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.IO;
23
24namespace ICSharpCode.AvalonEdit.Utils
25{
26  /// <summary>
27  /// TextReader implementation that reads text from a rope.
28  /// </summary>
29  public sealed class RopeTextReader : TextReader
30  {
31    Stack<RopeNode<char>> stack = new Stack<RopeNode<char>>();
32    RopeNode<char> currentNode;
33    int indexInsideNode;
34   
35    /// <summary>
36    /// Creates a new RopeTextReader.
37    /// Internally, this method creates a Clone of the rope; so the text reader will always read through the old
38    /// version of the rope if it is modified. <seealso cref="Rope{T}.Clone()"/>
39    /// </summary>
40    public RopeTextReader(Rope<char> rope)
41    {
42      if (rope == null)
43        throw new ArgumentNullException("rope");
44     
45      // We force the user to iterate through a clone of the rope to keep the API contract of RopeTextReader simple
46      // (what happens when a rope is modified while iterating through it?)
47      rope.root.Publish();
48     
49      // special case for the empty rope:
50      // leave currentNode initialized to null (RopeTextReader doesn't support empty nodes)
51      if (rope.Length != 0) {
52        currentNode = rope.root;
53        GoToLeftMostLeaf();
54      }
55    }
56   
57    void GoToLeftMostLeaf()
58    {
59      while (currentNode.contents == null) {
60        if (currentNode.height == 0) {
61          // this is a function node - move to its contained rope
62          currentNode = currentNode.GetContentNode();
63          continue;
64        }
65        Debug.Assert(currentNode.right != null);
66        stack.Push(currentNode.right);
67        currentNode = currentNode.left;
68      }
69      Debug.Assert(currentNode.height == 0);
70    }
71   
72    /// <inheritdoc/>
73    public override int Peek()
74    {
75      if (currentNode == null)
76        return -1;
77      return currentNode.contents[indexInsideNode];
78    }
79   
80    /// <inheritdoc/>
81    public override int Read()
82    {
83      if (currentNode == null)
84        return -1;
85      char result = currentNode.contents[indexInsideNode++];
86      if (indexInsideNode >= currentNode.length)
87        GoToNextNode();
88      return result;
89    }
90   
91    void GoToNextNode()
92    {
93      if (stack.Count == 0) {
94        currentNode = null;
95      } else {
96        indexInsideNode = 0;
97        currentNode = stack.Pop();
98        GoToLeftMostLeaf();
99      }
100    }
101   
102    /// <inheritdoc/>
103    public override int Read(char[] buffer, int index, int count)
104    {
105      if (currentNode == null)
106        return 0;
107      int amountInCurrentNode = currentNode.length - indexInsideNode;
108      if (count < amountInCurrentNode) {
109        Array.Copy(currentNode.contents, indexInsideNode, buffer, index, count);
110        indexInsideNode += count;
111        return count;
112      } else {
113        // read to end of current node
114        Array.Copy(currentNode.contents, indexInsideNode, buffer, index, amountInCurrentNode);
115        GoToNextNode();
116        return amountInCurrentNode;
117      }
118    }
119  }
120}
Note: See TracBrowser for help on using the repository browser.