| 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 |