Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.Xml-5.5.0/TokenReader.cs @ 15938

Last change on this file since 15938 was 11804, checked in by jkarder, 10 years ago

#2077:

  • added fancy xml documentation
  • fixed configurations and plattforms
File size: 9.6 KB
Line 
1// Copyright (c) 2009-2013 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.Linq;
23using ICSharpCode.NRefactory.Editor;
24
25namespace ICSharpCode.NRefactory.Xml
26{
27  class TokenReader
28  {
29    protected readonly ITextSource input;
30    protected readonly int inputLength;
31    int currentLocation;
32   
33    // CurrentLocation is assumed to be touched and the fact does not
34    //   have to be recorded in this variable.
35    // This stores any value bigger than that if applicable.
36    // Actual value is max(currentLocation, maxTouchedLocation).
37    int maxTouchedLocation;
38   
39    public int InputLength {
40      get { return inputLength; }
41    }
42   
43    public int CurrentLocation {
44      get { return currentLocation; }
45    }
46   
47    public int MaxTouchedLocation {
48      // add 1 to currentLocation because single-char-peek does not increment maxTouchedLocation
49      get { return Math.Max(currentLocation + 1, maxTouchedLocation); }
50    }
51   
52    public TokenReader(ITextSource input)
53    {
54      this.input = input;
55      this.inputLength = input.TextLength;
56    }
57   
58    protected bool IsEndOfFile()
59    {
60      return currentLocation == inputLength;
61    }
62   
63    protected bool HasMoreData()
64    {
65      return currentLocation < inputLength;
66    }
67   
68    protected void AssertHasMoreData()
69    {
70      Log.Assert(HasMoreData(), "Unexpected end of file");
71    }
72   
73    protected bool TryMoveNext()
74    {
75      if (currentLocation == inputLength) return false;
76     
77      currentLocation++;
78      return true;
79    }
80   
81    protected void Skip(int count)
82    {
83      Log.Assert(currentLocation + count <= inputLength, "Skipping after the end of file");
84      currentLocation += count;
85    }
86   
87    protected void GoBack(int oldLocation)
88    {
89      Log.Assert(oldLocation <= currentLocation, "Trying to move forward");
90      // add 1 because single-char-peek does not increment maxTouchedLocation
91      maxTouchedLocation = Math.Max(maxTouchedLocation, currentLocation + 1);
92      currentLocation = oldLocation;
93    }
94   
95    protected bool TryRead(char c)
96    {
97      if (currentLocation == inputLength) return false;
98     
99      if (input.GetCharAt(currentLocation) == c) {
100        currentLocation++;
101        return true;
102      } else {
103        return false;
104      }
105    }
106   
107    protected bool TryReadAnyOf(params char[] c)
108    {
109      if (currentLocation == inputLength) return false;
110     
111      if (c.Contains(input.GetCharAt(currentLocation))) {
112        currentLocation++;
113        return true;
114      } else {
115        return false;
116      }
117    }
118   
119    protected bool TryRead(string text)
120    {
121      if (TryPeek(text)) {
122        currentLocation += text.Length;
123        return true;
124      } else {
125        return false;
126      }
127    }
128   
129    protected bool TryPeekPrevious(char c, int back)
130    {
131      if (currentLocation - back == inputLength) return false;
132      if (currentLocation - back < 0 ) return false;
133     
134      return input.GetCharAt(currentLocation - back) == c;
135    }
136   
137    protected bool TryPeek(char c)
138    {
139      if (currentLocation == inputLength) return false;
140     
141      return input.GetCharAt(currentLocation) == c;
142    }
143   
144    protected bool TryPeekAnyOf(params char[] chars)
145    {
146      if (currentLocation == inputLength) return false;
147     
148      return chars.Contains(input.GetCharAt(currentLocation));
149    }
150   
151    protected bool TryPeek(string text)
152    {
153      if (!TryPeek(text[0])) return false; // Early exit
154     
155      maxTouchedLocation = Math.Max(maxTouchedLocation, currentLocation + text.Length);
156      // The following comparison 'touches' the end of file - it does depend on the end being there
157      if (currentLocation + text.Length > inputLength) return false;
158     
159      return input.GetText(currentLocation, text.Length) == text;
160    }
161   
162    protected bool TryPeekWhiteSpace()
163    {
164      if (currentLocation == inputLength) return false;
165     
166      char c = input.GetCharAt(currentLocation);
167      return ((int)c <= 0x20) && (c == ' ' || c == '\t' || c == '\n' || c == '\r');
168    }
169   
170    // The move functions do not have to move if already at target
171    // The move functions allow 'overriding' of the document length
172   
173    protected bool TryMoveTo(char c)
174    {
175      return TryMoveTo(c, inputLength);
176    }
177   
178    protected bool TryMoveTo(char c, int inputLength)
179    {
180      if (currentLocation == inputLength) return false;
181      int index = input.IndexOf(c, currentLocation, inputLength - currentLocation);
182      if (index != -1) {
183        currentLocation = index;
184        return true;
185      } else {
186        currentLocation = inputLength;
187        return false;
188      }
189    }
190   
191    protected bool TryMoveToAnyOf(params char[] c)
192    {
193      return TryMoveToAnyOf(c, inputLength);
194    }
195   
196    protected bool TryMoveToAnyOf(char[] c, int inputLength)
197    {
198      if (currentLocation == inputLength) return false;
199      int index = input.IndexOfAny(c, currentLocation, inputLength - currentLocation);
200      if (index != -1) {
201        currentLocation = index;
202        return true;
203      } else {
204        currentLocation = inputLength;
205        return false;
206      }
207    }
208   
209    protected bool TryMoveTo(string text)
210    {
211      return TryMoveTo(text, inputLength);
212    }
213   
214    protected bool TryMoveTo(string text, int inputLength)
215    {
216      if (currentLocation == inputLength) return false;
217      int index = input.IndexOf(text, currentLocation, inputLength - currentLocation, StringComparison.Ordinal);
218      if (index != -1) {
219        maxTouchedLocation = index + text.Length;
220        currentLocation = index;
221        return true;
222      } else {
223        currentLocation = inputLength;
224        return false;
225      }
226    }
227   
228    protected bool TryMoveToNonWhiteSpace()
229    {
230      return TryMoveToNonWhiteSpace(inputLength);
231    }
232   
233    protected bool TryMoveToNonWhiteSpace(int inputLength)
234    {
235      while(true) {
236        if (currentLocation == inputLength) return false; // Reject end of file
237        char c = input.GetCharAt(currentLocation);
238        if (((int)c <= 0x20) && (c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
239          currentLocation++;                            // Accept white-space
240          continue;
241        } else {
242          return true;  // Found non-white-space
243        }
244      }
245    }
246   
247    /// <summary>
248    /// Read a name token.
249    /// The following characters are not allowed:
250    ///   ""         End of file
251    ///   " \n\r\t"  Whitesapce
252    ///   "=\'\""    Attribute value
253    ///   "&lt;>/?"  Tags
254    /// </summary>
255    /// <returns>Returns the length of the name</returns>
256    protected bool TryReadName()
257    {
258      int start = currentLocation;
259      // Keep reading up to invalid character
260      while (HasMoreData()) {
261        char c = input.GetCharAt(currentLocation);
262        if (0x41 <= (int)c) {                                   // Accpet from 'A' onwards
263          currentLocation++;
264          continue;
265        }
266        if (c == ' ' || c == '\n' || c == '\r' || c == '\t' ||  // Reject whitesapce
267            c == '=' || c == '\'' || c == '"'  ||               // Reject attributes
268            c == '<' || c == '>'  || c == '/'  || c == '?') {   // Reject tags
269          break;
270        } else {
271          currentLocation++;
272          continue;                                            // Accept other character
273        }
274      }
275      return currentLocation > start;
276    }
277   
278    protected bool TryReadName(out string name)
279    {
280      int start = currentLocation;
281      if (TryReadName()) {
282        name = GetCachedString(GetText(start, currentLocation));
283        return true;
284      } else {
285        name = string.Empty;
286        return false;
287      }
288    }
289   
290    protected string GetText(int start, int end)
291    {
292      Log.Assert(end <= currentLocation, "Reading ahead of current location");
293      return input.GetText(start, end - start);
294    }
295   
296    Dictionary<string, string> stringCache = new Dictionary<string, string>();
297   
298    #if DEBUG
299    int stringCacheRequestedCount;
300    int stringCacheRequestedSize;
301    int stringCacheStoredCount;
302    int stringCacheStoredSize;
303    #endif
304   
305    internal void PrintStringCacheStats()
306    {
307      #if DEBUG
308      Log.WriteLine("String cache: Requested {0} ({1} bytes);  Actaully stored {2} ({3} bytes); {4}% stored", stringCacheRequestedCount, stringCacheRequestedSize, stringCacheStoredCount, stringCacheStoredSize, stringCacheRequestedSize == 0 ? 0 : stringCacheStoredSize * 100 / stringCacheRequestedSize);
309      #endif
310    }
311   
312    [Conditional("DEBUG")]
313    void AddToRequestedSize(string text)
314    {
315      #if DEBUG
316      stringCacheRequestedCount += 1;
317      stringCacheRequestedSize += 8 + 2 * text.Length;
318      #endif
319    }
320   
321    [Conditional("DEBUG")]
322    void AddToStoredSize(string text)
323    {
324      #if DEBUG
325      stringCacheStoredCount += 1;
326      stringCacheStoredSize += 8 + 2 * text.Length;
327      #endif
328    }
329   
330    protected string GetCachedString(string cached)
331    {
332      AddToRequestedSize(cached);
333      // Do not bother with long strings
334      if (cached.Length > 32) {
335        AddToStoredSize(cached);
336        return cached;
337      }
338      string result;
339      if (stringCache.TryGetValue(cached, out result)) {
340        // Get the instance from the cache instead
341        return result;
342      } else {
343        // Add to cache
344        AddToStoredSize(cached);
345        stringCache.Add(cached, cached);
346        return cached;
347      }
348    }
349  }
350}
Note: See TracBrowser for help on using the repository browser.