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