1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2005-2008 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 namespace Antlr.Runtime.Misc 34 { 35 using System.Collections.Generic; 36 using ArgumentException = System.ArgumentException; 37 using InvalidOperationException = System.InvalidOperationException; 38 39 /** A queue that can dequeue and get(i) in O(1) and grow arbitrarily large. 40 * A linked list is fast at dequeue but slow at get(i). An array is 41 * the reverse. This is O(1) for both operations. 42 * 43 * List grows until you dequeue last element at end of buffer. Then 44 * it resets to start filling at 0 again. If adds/removes are balanced, the 45 * buffer will not grow too large. 46 * 47 * No iterator stuff as that's not how we'll use it. 48 */ 49 public class FastQueue<T> 50 { 51 /** <summary>dynamically-sized buffer of elements</summary> */ 52 internal List<T> _data = new List<T>(); 53 /** <summary>index of next element to fill</summary> */ 54 internal int _p = 0; 55 56 public virtual int Count 57 { 58 get 59 { 60 return _data.Count - _p; 61 } 62 } 63 64 /// <summary> 65 /// How deep have we gone? 66 /// </summary> 67 public virtual int Range 68 { 69 get; 70 protected set; 71 } 72 73 /** <summary> 74 * Return element i elements ahead of current element. i==0 gets 75 * current element. This is not an absolute index into the data list 76 * since p defines the start of the real list. 77 * </summary> 78 */ 79 public virtual T this[int i] 80 { 81 get 82 { 83 int absIndex = _p + i; 84 if (absIndex >= _data.Count) 85 throw new ArgumentException(string.Format("queue index {0} > last index {1}", absIndex, _data.Count - 1)); 86 if (absIndex < 0) 87 throw new ArgumentException(string.Format("queue index {0} < 0", absIndex)); 88 89 if (absIndex > Range) 90 Range = absIndex; 91 92 return _data[absIndex]; 93 } 94 } 95 96 /** <summary>Get and remove first element in queue</summary> */ Dequeue()97 public virtual T Dequeue() 98 { 99 if (Count == 0) 100 throw new InvalidOperationException(); 101 102 T o = this[0]; 103 _p++; 104 // have we hit end of buffer? 105 if ( _p == _data.Count ) 106 { 107 // if so, it's an opportunity to start filling at index 0 again 108 Clear(); // size goes to 0, but retains memory 109 } 110 return o; 111 } 112 Enqueue( T o )113 public virtual void Enqueue( T o ) 114 { 115 _data.Add( o ); 116 } 117 Peek()118 public virtual T Peek() 119 { 120 return this[0]; 121 } 122 Clear()123 public virtual void Clear() 124 { 125 _p = 0; 126 _data.Clear(); 127 } 128 129 /** <summary>Return string of current buffer contents; non-destructive</summary> */ ToString()130 public override string ToString() 131 { 132 System.Text.StringBuilder buf = new System.Text.StringBuilder(); 133 int n = Count; 134 for ( int i = 0; i < n; i++ ) 135 { 136 buf.Append( this[i] ); 137 if ( ( i + 1 ) < n ) 138 buf.Append( " " ); 139 } 140 return buf.ToString(); 141 } 142 } 143 } 144