| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file |  | 
| 2 // for details. All rights reserved. Use of this source code is governed by a |  | 
| 3 // BSD-style license that can be found in the LICENSE file. |  | 
| 4 |  | 
| 5 part of tree; |  | 
| 6 |  | 
| 7 /** |  | 
| 8  * The [DartString] type represents a Dart string value as a sequence of Unicode |  | 
| 9  * Scalar Values. |  | 
| 10  * After parsing, any valid [LiteralString] will contain a [DartString] |  | 
| 11  * representing its content after removing quotes and resolving escapes in |  | 
| 12  * its source. |  | 
| 13  */ |  | 
| 14 abstract class DartString extends IterableBase<int> { |  | 
| 15   factory DartString.empty() => const LiteralDartString(""); |  | 
| 16   // This is a convenience constructor. If you need a const literal DartString, |  | 
| 17   // use [const LiteralDartString(string)] directly. |  | 
| 18   factory DartString.literal(String string) => new LiteralDartString(string); |  | 
| 19   factory DartString.rawString(String source, int length) => |  | 
| 20       new RawSourceDartString(source, length); |  | 
| 21   factory DartString.escapedString(String source, int length) => |  | 
| 22       new EscapedSourceDartString(source, length); |  | 
| 23   factory DartString.concat(DartString first, DartString second) { |  | 
| 24     if (first.isEmpty) return second; |  | 
| 25     if (second.isEmpty) return first; |  | 
| 26     return new ConsDartString(first, second); |  | 
| 27   } |  | 
| 28   const DartString(); |  | 
| 29 |  | 
| 30   /** |  | 
| 31    * The length of this [DartString], which is the string length after |  | 
| 32    * escapes have been resolved. |  | 
| 33    */ |  | 
| 34   int get length; |  | 
| 35   bool get isEmpty => length == 0; |  | 
| 36 |  | 
| 37   Iterator<int> get iterator; |  | 
| 38 |  | 
| 39   /** |  | 
| 40    * The string represented by this [DartString]. |  | 
| 41    */ |  | 
| 42   String slowToString(); |  | 
| 43 |  | 
| 44   bool operator ==(var other) { |  | 
| 45     if (other is !DartString) return false; |  | 
| 46     DartString otherString = other; |  | 
| 47     if (length != otherString.length) return false; |  | 
| 48     Iterator it1 = iterator; |  | 
| 49     Iterator it2 = otherString.iterator; |  | 
| 50     while (it1.moveNext()) { |  | 
| 51       if (!it2.moveNext()) return false; |  | 
| 52       if (it1.current != it2.current) return false; |  | 
| 53     } |  | 
| 54     return true; |  | 
| 55   } |  | 
| 56 |  | 
| 57   int get hashCode => throw new UnsupportedError('DartString.hashCode'); |  | 
| 58 |  | 
| 59   /** |  | 
| 60    * A textual representation of this [DartString] with some debugging |  | 
| 61    * information. |  | 
| 62    */ |  | 
| 63   String toString() => "DartString#${length}:${slowToString()}"; |  | 
| 64 } |  | 
| 65 |  | 
| 66 |  | 
| 67 /** |  | 
| 68  * A [DartString] where the content is represented by an actual [String]. |  | 
| 69  */ |  | 
| 70 class LiteralDartString extends DartString { |  | 
| 71   final String string; |  | 
| 72   const LiteralDartString(this.string); |  | 
| 73   int get length => string.length; |  | 
| 74   Iterator<int> get iterator => string.codeUnits.iterator; |  | 
| 75   String slowToString() => string; |  | 
| 76 } |  | 
| 77 |  | 
| 78 /** |  | 
| 79  * A [DartString] whereSource the content comes from a slice of the program |  | 
| 80  * source. |  | 
| 81  */ |  | 
| 82 abstract class SourceBasedDartString extends DartString { |  | 
| 83   /** |  | 
| 84    * The source string containing explicit escapes from which this [DartString] |  | 
| 85    * is built. |  | 
| 86    */ |  | 
| 87   final String source; |  | 
| 88   final int length; |  | 
| 89   SourceBasedDartString(this.source, this.length); |  | 
| 90   Iterator<int> get iterator; |  | 
| 91 } |  | 
| 92 |  | 
| 93 /** |  | 
| 94  * Special case of a [SourceBasedDartString] where we know the source doesn't |  | 
| 95  * contain any escapes. |  | 
| 96  */ |  | 
| 97 class RawSourceDartString extends SourceBasedDartString { |  | 
| 98   RawSourceDartString(source, length) : super(source, length); |  | 
| 99   Iterator<int> get iterator => source.codeUnits.iterator; |  | 
| 100   String slowToString() => source; |  | 
| 101 } |  | 
| 102 |  | 
| 103 /** |  | 
| 104  * General case of a [SourceBasedDartString] where the source might contain |  | 
| 105  * escapes. |  | 
| 106  */ |  | 
| 107 class EscapedSourceDartString extends SourceBasedDartString { |  | 
| 108   String toStringCache; |  | 
| 109   EscapedSourceDartString(source, length) : super(source, length); |  | 
| 110   Iterator<int> get iterator { |  | 
| 111     if (toStringCache != null) return toStringCache.codeUnits.iterator; |  | 
| 112     return new StringEscapeIterator(source); |  | 
| 113   } |  | 
| 114   String slowToString() { |  | 
| 115     if (toStringCache != null) return toStringCache; |  | 
| 116     StringBuffer buffer = new StringBuffer(); |  | 
| 117     StringEscapeIterator it = new StringEscapeIterator(source); |  | 
| 118     while (it.moveNext()) { |  | 
| 119       buffer.writeCharCode(it.current); |  | 
| 120     } |  | 
| 121     toStringCache = buffer.toString(); |  | 
| 122     return toStringCache; |  | 
| 123   } |  | 
| 124 } |  | 
| 125 |  | 
| 126 /** |  | 
| 127  * The concatenation of two [DartString]s. |  | 
| 128  */ |  | 
| 129 class ConsDartString extends DartString { |  | 
| 130   final DartString left; |  | 
| 131   final DartString right; |  | 
| 132   final int length; |  | 
| 133   String toStringCache; |  | 
| 134   ConsDartString(DartString left, DartString right) |  | 
| 135       : this.left = left, |  | 
| 136         this.right = right, |  | 
| 137         length = left.length + right.length; |  | 
| 138 |  | 
| 139   Iterator<int> get iterator => new ConsDartStringIterator(this); |  | 
| 140 |  | 
| 141   String slowToString() { |  | 
| 142     if (toStringCache != null) return toStringCache; |  | 
| 143     toStringCache = left.slowToString() + right.slowToString(); |  | 
| 144     return toStringCache; |  | 
| 145   } |  | 
| 146   String get source => slowToString(); |  | 
| 147 } |  | 
| 148 |  | 
| 149 class ConsDartStringIterator implements Iterator<int> { |  | 
| 150   HasNextIterator<int> currentIterator; |  | 
| 151   DartString right; |  | 
| 152   bool hasNextLookAhead; |  | 
| 153   int _current = null; |  | 
| 154 |  | 
| 155   ConsDartStringIterator(ConsDartString cons) |  | 
| 156       : currentIterator = new HasNextIterator<int>(cons.left.iterator), |  | 
| 157         right = cons.right { |  | 
| 158     hasNextLookAhead = currentIterator.hasNext; |  | 
| 159     if (!hasNextLookAhead) { |  | 
| 160       nextPart(); |  | 
| 161     } |  | 
| 162   } |  | 
| 163 |  | 
| 164   int get current => _current; |  | 
| 165 |  | 
| 166   bool moveNext() { |  | 
| 167     if (!hasNextLookAhead) { |  | 
| 168       _current = null; |  | 
| 169       return false; |  | 
| 170     } |  | 
| 171     _current = currentIterator.next(); |  | 
| 172     hasNextLookAhead = currentIterator.hasNext; |  | 
| 173     if (!hasNextLookAhead) { |  | 
| 174       nextPart(); |  | 
| 175     } |  | 
| 176     return true; |  | 
| 177   } |  | 
| 178   void nextPart() { |  | 
| 179     if (right != null) { |  | 
| 180       currentIterator = new HasNextIterator<int>(right.iterator); |  | 
| 181       right = null; |  | 
| 182       hasNextLookAhead = currentIterator.hasNext; |  | 
| 183     } |  | 
| 184   } |  | 
| 185 } |  | 
| 186 |  | 
| 187 /** |  | 
| 188  *Iterator that returns the actual string contents of a string with escapes. |  | 
| 189  */ |  | 
| 190 class StringEscapeIterator implements Iterator<int>{ |  | 
| 191   final Iterator<int> source; |  | 
| 192   int _current = null; |  | 
| 193 |  | 
| 194   StringEscapeIterator(String source) : this.source = source.codeUnits.iterator; |  | 
| 195 |  | 
| 196   int get current => _current; |  | 
| 197 |  | 
| 198   bool moveNext() { |  | 
| 199     if (!source.moveNext()) { |  | 
| 200       _current = null; |  | 
| 201       return false; |  | 
| 202     } |  | 
| 203     int code = source.current; |  | 
| 204     if (code != $BACKSLASH) { |  | 
| 205       _current = code; |  | 
| 206       return true; |  | 
| 207     } |  | 
| 208     source.moveNext(); |  | 
| 209     code = source.current; |  | 
| 210     switch (code) { |  | 
| 211       case $n: _current = $LF; break; |  | 
| 212       case $r: _current = $CR; break; |  | 
| 213       case $t: _current = $TAB; break; |  | 
| 214       case $b: _current = $BS; break; |  | 
| 215       case $f: _current = $FF; break; |  | 
| 216       case $v: _current = $VTAB; break; |  | 
| 217       case $x: |  | 
| 218         source.moveNext(); |  | 
| 219         int value = hexDigitValue(source.current); |  | 
| 220         source.moveNext(); |  | 
| 221         value = value * 16 + hexDigitValue(source.current); |  | 
| 222         _current = value; |  | 
| 223         break; |  | 
| 224       case $u: |  | 
| 225         int value = 0; |  | 
| 226         source.moveNext(); |  | 
| 227         code = source.current; |  | 
| 228         if (code == $OPEN_CURLY_BRACKET) { |  | 
| 229           source.moveNext(); |  | 
| 230           while (source.current != $CLOSE_CURLY_BRACKET) { |  | 
| 231             value = value * 16 + hexDigitValue(source.current); |  | 
| 232             source.moveNext(); |  | 
| 233           } |  | 
| 234           _current = value; |  | 
| 235           break; |  | 
| 236         } |  | 
| 237         // Four digit hex value. |  | 
| 238         value = hexDigitValue(code); |  | 
| 239         for (int i = 0; i < 3; i++) { |  | 
| 240           source.moveNext(); |  | 
| 241           value = value * 16 + hexDigitValue(source.current); |  | 
| 242         } |  | 
| 243         _current = value; |  | 
| 244         break; |  | 
| 245       default: |  | 
| 246         _current = code; |  | 
| 247     } |  | 
| 248     return true; |  | 
| 249   } |  | 
| 250 } |  | 
| 251 |  | 
| OLD | NEW | 
|---|