OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 @patch | 5 @patch class RegExp { |
6 class RegExp { | 6 @patch factory RegExp(String source, |
7 @patch | 7 {bool multiLine: false, |
8 factory RegExp(String source, | 8 bool caseSensitive: true}) { |
9 {bool multiLine: false, bool caseSensitive: true}) { | 9 _RegExpHashKey key = new _RegExpHashKey( |
10 _RegExpHashKey key = new _RegExpHashKey(source, multiLine, caseSensitive); | 10 source, multiLine, caseSensitive); |
11 _RegExpHashValue value = _cache[key]; | 11 _RegExpHashValue value = _cache[key]; |
12 | 12 |
13 if (value == null) { | 13 if (value == null) { |
14 if (_cache.length > _MAX_CACHE_SIZE) { | 14 if (_cache.length > _MAX_CACHE_SIZE) { |
15 _RegExpHashKey lastKey = _recentlyUsed.last; | 15 _RegExpHashKey lastKey = _recentlyUsed.last; |
16 lastKey.unlink(); | 16 lastKey.unlink(); |
17 _cache.remove(lastKey); | 17 _cache.remove(lastKey); |
18 } | 18 } |
19 | 19 |
20 value = new _RegExpHashValue( | 20 value = new _RegExpHashValue( |
21 new _RegExp(source, | 21 new _RegExp(source, |
22 multiLine: multiLine, caseSensitive: caseSensitive), | 22 multiLine: multiLine, |
| 23 caseSensitive: caseSensitive), |
23 key); | 24 key); |
24 _cache[key] = value; | 25 _cache[key] = value; |
25 } else { | 26 } else { |
26 value.key.unlink(); | 27 value.key.unlink(); |
27 } | 28 } |
28 | 29 |
29 assert(value != null); | 30 assert(value != null); |
30 | 31 |
31 _recentlyUsed.addFirst(value.key); | 32 _recentlyUsed.addFirst(value.key); |
32 assert(_recentlyUsed.length == _cache.length); | 33 assert(_recentlyUsed.length == _cache.length); |
(...skipping 10 matching lines...) Expand all Loading... |
43 // may not be removed from the cache. | 44 // may not be removed from the cache. |
44 // TODO(zerny): Use self-sizing cache similar to _AccessorCache in | 45 // TODO(zerny): Use self-sizing cache similar to _AccessorCache in |
45 // mirrors_impl.dart. | 46 // mirrors_impl.dart. |
46 static const int _MAX_CACHE_SIZE = 256; | 47 static const int _MAX_CACHE_SIZE = 256; |
47 static final Map<_RegExpHashKey, _RegExpHashValue> _cache = | 48 static final Map<_RegExpHashKey, _RegExpHashValue> _cache = |
48 new HashMap<_RegExpHashKey, _RegExpHashValue>(); | 49 new HashMap<_RegExpHashKey, _RegExpHashValue>(); |
49 static final LinkedList<_RegExpHashKey> _recentlyUsed = | 50 static final LinkedList<_RegExpHashKey> _recentlyUsed = |
50 new LinkedList<_RegExpHashKey>(); | 51 new LinkedList<_RegExpHashKey>(); |
51 } | 52 } |
52 | 53 |
| 54 |
53 // Represents both a key in the regular expression cache as well as its | 55 // Represents both a key in the regular expression cache as well as its |
54 // corresponding entry in the LRU list. | 56 // corresponding entry in the LRU list. |
55 class _RegExpHashKey extends LinkedListEntry<_RegExpHashKey> { | 57 class _RegExpHashKey extends LinkedListEntry<_RegExpHashKey> { |
56 final String pattern; | 58 final String pattern; |
57 final bool multiLine; | 59 final bool multiLine; |
58 final bool caseSensitive; | 60 final bool caseSensitive; |
59 | 61 |
60 _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive); | 62 _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive); |
61 | 63 |
62 int get hashCode => pattern.hashCode; | 64 int get hashCode => pattern.hashCode; |
63 bool operator ==(_RegExpHashKey that) { | 65 bool operator==(_RegExpHashKey that) { |
64 return (this.pattern == that.pattern) && | 66 return (this.pattern == that.pattern) && |
65 (this.multiLine == that.multiLine) && | 67 (this.multiLine == that.multiLine) && |
66 (this.caseSensitive == that.caseSensitive); | 68 (this.caseSensitive == that.caseSensitive); |
67 } | 69 } |
68 } | 70 } |
69 | 71 |
| 72 |
70 // Represents a value in the regular expression cache. Contains a pointer | 73 // Represents a value in the regular expression cache. Contains a pointer |
71 // back to the key in order to access the corresponding LRU entry. | 74 // back to the key in order to access the corresponding LRU entry. |
72 class _RegExpHashValue { | 75 class _RegExpHashValue { |
73 final _RegExp regexp; | 76 final _RegExp regexp; |
74 final _RegExpHashKey key; | 77 final _RegExpHashKey key; |
75 | 78 |
76 _RegExpHashValue(this.regexp, this.key); | 79 _RegExpHashValue(this.regexp, this.key); |
77 } | 80 } |
78 | 81 |
| 82 |
79 class _RegExpMatch implements Match { | 83 class _RegExpMatch implements Match { |
80 _RegExpMatch(this._regexp, this.input, this._match); | 84 _RegExpMatch(this._regexp, this.input, this._match); |
81 | 85 |
82 int get start => _start(0); | 86 int get start => _start(0); |
83 int get end => _end(0); | 87 int get end => _end(0); |
84 | 88 |
85 int _start(int groupIdx) { | 89 int _start(int groupIdx) { |
86 return _match[(groupIdx * _MATCH_PAIR)]; | 90 return _match[(groupIdx * _MATCH_PAIR)]; |
87 } | 91 } |
88 | 92 |
(...skipping 29 matching lines...) Expand all Loading... |
118 int get groupCount => _regexp._groupCount; | 122 int get groupCount => _regexp._groupCount; |
119 | 123 |
120 Pattern get pattern => _regexp; | 124 Pattern get pattern => _regexp; |
121 | 125 |
122 final RegExp _regexp; | 126 final RegExp _regexp; |
123 final String input; | 127 final String input; |
124 final List<int> _match; | 128 final List<int> _match; |
125 static const int _MATCH_PAIR = 2; | 129 static const int _MATCH_PAIR = 2; |
126 } | 130 } |
127 | 131 |
| 132 |
128 class _RegExp implements RegExp { | 133 class _RegExp implements RegExp { |
129 factory _RegExp(String pattern, | 134 factory _RegExp( |
| 135 String pattern, |
130 {bool multiLine: false, | 136 {bool multiLine: false, |
131 bool caseSensitive: true}) native "RegExp_factory"; | 137 bool caseSensitive: true}) native "RegExp_factory"; |
132 | 138 |
133 Match firstMatch(String str) { | 139 Match firstMatch(String str) { |
134 if (str is! String) throw new ArgumentError(str); | 140 if (str is! String) throw new ArgumentError(str); |
135 List match = _ExecuteMatch(str, 0); | 141 List match = _ExecuteMatch(str, 0); |
136 if (match == null) { | 142 if (match == null) { |
137 return null; | 143 return null; |
138 } | 144 } |
139 return new _RegExpMatch(this, str, match); | 145 return new _RegExpMatch(this, str, match); |
140 } | 146 } |
141 | 147 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 // character (digit, letter or underscore) and 0x00 otherwise. | 192 // character (digit, letter or underscore) and 0x00 otherwise. |
187 // Used by generated RegExp code. | 193 // Used by generated RegExp code. |
188 static const List<int> _wordCharacterMap = const <int>[ | 194 static const List<int> _wordCharacterMap = const <int>[ |
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
193 | 199 |
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
196 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // '0' - '7' | 202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // '0' - '7' |
197 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '8' - '9' | 203 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '8' - '9' |
198 | 204 |
199 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'A' - 'G' | 205 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'A' - 'G' |
200 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'H' - 'O' | 206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'H' - 'O' |
201 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'P' - 'W' | 207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'P' - 'W' |
202 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // 'X' - 'Z', '_' | 208 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // 'X' - 'Z', '_' |
203 | 209 |
204 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'a' - 'g' | 210 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'a' - 'g' |
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'h' - 'o' | 211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'h' - 'o' |
206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'p' - 'w' | 212 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'p' - 'w' |
207 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // 'x' - 'z' | 213 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // 'x' - 'z' |
208 // Latin-1 range | 214 // Latin-1 range |
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
213 | 219 |
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
218 | 224 |
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
223 | 229 |
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
228 ]; | 234 ]; |
229 | 235 |
230 List _ExecuteMatch(String str, int start_index) native "RegExp_ExecuteMatch"; | 236 List _ExecuteMatch(String str, int start_index) |
| 237 native "RegExp_ExecuteMatch"; |
231 | 238 |
232 List _ExecuteMatchSticky(String str, int start_index) | 239 List _ExecuteMatchSticky(String str, int start_index) |
233 native "RegExp_ExecuteMatchSticky"; | 240 native "RegExp_ExecuteMatchSticky"; |
234 } | 241 } |
235 | 242 |
236 class _AllMatchesIterable extends IterableBase<Match> { | 243 class _AllMatchesIterable extends IterableBase<Match> { |
237 final _RegExp _re; | 244 final _RegExp _re; |
238 final String _str; | 245 final String _str; |
239 final int _start; | 246 final int _start; |
240 | 247 |
241 _AllMatchesIterable(this._re, this._str, this._start); | 248 _AllMatchesIterable(this._re, this._str, this._start); |
242 | 249 |
243 Iterator<Match> get iterator => new _AllMatchesIterator(_re, _str, _start); | 250 Iterator<Match> get iterator => new _AllMatchesIterator(_re, _str, _start); |
244 } | 251 } |
245 | 252 |
246 class _AllMatchesIterator implements Iterator<Match> { | 253 class _AllMatchesIterator implements Iterator<Match> { |
247 final String _str; | 254 final String _str; |
248 int _nextIndex; | 255 int _nextIndex; |
249 _RegExp _re; | 256 _RegExp _re; |
250 Match _current; | 257 Match _current; |
251 | 258 |
252 _AllMatchesIterator(this._re, this._str, this._nextIndex); | 259 _AllMatchesIterator(this._re, this._str, this._nextIndex); |
253 | 260 |
254 Match get current => _current; | 261 Match get current => _current; |
255 | 262 |
256 bool moveNext() { | 263 bool moveNext() { |
257 if (_re == null) return false; // Cleared after a failed match. | 264 if (_re == null) return false; // Cleared after a failed match. |
258 if (_nextIndex <= _str.length) { | 265 if (_nextIndex <= _str.length) { |
259 var match = _re._ExecuteMatch(_str, _nextIndex); | 266 var match = _re._ExecuteMatch(_str, _nextIndex); |
260 if (match != null) { | 267 if (match != null) { |
261 _current = new _RegExpMatch(_re, _str, match); | 268 _current = new _RegExpMatch(_re, _str, match); |
262 _nextIndex = _current.end; | 269 _nextIndex = _current.end; |
263 if (_nextIndex == _current.start) { | 270 if (_nextIndex == _current.start) { |
264 // Zero-width match. Advance by one more. | 271 // Zero-width match. Advance by one more. |
265 _nextIndex++; | 272 _nextIndex++; |
266 } | 273 } |
267 return true; | 274 return true; |
268 } | 275 } |
269 } | 276 } |
270 _current = null; | 277 _current = null; |
271 _re = null; | 278 _re = null; |
272 return false; | 279 return false; |
273 } | 280 } |
274 } | 281 } |
OLD | NEW |