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