Chromium Code Reviews| 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 part of dart.core; | 5 part of dart.core; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The String class represents character strings. Strings are | 8 * The String class represents character strings. Strings are |
| 9 * immutable. A string is represented by a list of 32-bit Unicode | 9 * immutable. A string is represented by a list of 32-bit Unicode |
| 10 * scalar character codes accessible through the [charCodeAt] or the | 10 * scalar character codes accessible through the [charCodeAt] or the |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 * where all characters are made lower case. Returns [:this:] otherwise. | 182 * where all characters are made lower case. Returns [:this:] otherwise. |
| 183 */ | 183 */ |
| 184 String toLowerCase(); | 184 String toLowerCase(); |
| 185 | 185 |
| 186 /** | 186 /** |
| 187 * If this string is not already all uper case, returns a new string | 187 * If this string is not already all uper case, returns a new string |
| 188 * where all characters are made upper case. Returns [:this:] otherwise. | 188 * where all characters are made upper case. Returns [:this:] otherwise. |
| 189 */ | 189 */ |
| 190 String toUpperCase(); | 190 String toUpperCase(); |
| 191 } | 191 } |
| 192 | |
| 193 class Runes implements Iterable<int> { | |
| 194 String _string; | |
| 195 Runes(this._string); | |
| 196 RuneIterator get iterator => new RuneIterator(_string); | |
| 197 } | |
| 198 | |
| 199 /** [Iterator] for reading Unicode code points out of a Dart string. */ | |
| 200 class RuneIterator implements BiDirectionalIterator<int> { | |
| 201 /** String being iterated. */ | |
| 202 final String _string; | |
| 203 /** Position before the current code point. */ | |
| 204 int _position; | |
| 205 /** Position after the current code point. */ | |
| 206 int _nextPosition; | |
| 207 /** | |
| 208 * Current code point. | |
| 209 * | |
| 210 * If the iterator has hit either end, the [_currentCodePoint] is null | |
| 211 * and [: _position == _nextPosition :]. | |
| 212 */ | |
| 213 int _currentCodePoint; | |
| 214 | |
| 215 /** Create an iterator positioned at the beginning of the string. */ | |
| 216 RuneIterator(String string) | |
| 217 : _string = string, _position = 0, _nextPosition = 0; | |
| 218 | |
| 219 /** | |
| 220 * Create an iterator positioned before the [start]th code unit of the string. | |
| 221 * | |
| 222 * A [moveNext] will make the following code point the current value, and a | |
| 223 * [movePrevious] will make the preceding code pount the current value. | |
| 224 * | |
| 225 * If the [start] position is in the middle of a surrogate pair, then the | |
| 226 * first result in either direction will be an unmatched surrogate. | |
| 227 */ | |
| 228 RuneIterator.at(String string, int start) | |
| 229 : _string = string, _position = start, _nextPosition = start { | |
| 230 if (start < 0 || start > string.length) { | |
| 231 throw new RangeError.range(start, 0, string.length); | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 int get current => _currentCodePoint; | |
| 236 | |
| 237 bool moveNext() { | |
|
erikcorry
2013/01/30 13:26:55
This one is factored into two functions, whereas t
Lasse Reichstein Nielsen
2013/01/30 14:03:37
ACK. I was using _readCharForward in the .at const
| |
| 238 _position = _nextPosition; | |
| 239 if (_position == _string.length) { | |
| 240 _currentCodePoint = null; | |
| 241 return false; | |
| 242 } | |
| 243 _readCharForward(); | |
| 244 return true; | |
| 245 } | |
| 246 | |
| 247 // Decodes code units at _position, updates _currentCodePoint, _nextPosition. | |
| 248 void _readCharForward() { | |
| 249 int codeUnit = _string.charCodeAt(_position); | |
| 250 int nextPosition = _position + 1; | |
| 251 if ((codeUnit & 0xFC00) == 0xD800 && nextPosition < _string.length) { | |
| 252 int nextCodeUnit = _string.charCodeAt(nextPosition); | |
| 253 if ((nextCodeUnit & 0xFC00) == 0xDC00) { | |
| 254 _nextPosition = nextPosition + 1; | |
| 255 _currentCodePoint = | |
| 256 0x10000 + ((nextCodeUnit & 0x3FF) << 10) | (codeUnit & 0x3FF); | |
|
Lasse Reichstein Nielsen
2013/01/30 14:03:37
Good catch, these two are swapped (copy-n-paste bu
| |
| 257 return; | |
| 258 } | |
| 259 } | |
| 260 _nextPosition = nextPosition; | |
| 261 _currentCodePoint = codeUnit; | |
| 262 } | |
| 263 | |
| 264 bool movePrevious() { | |
| 265 if (_position == 0) { | |
| 266 _currentCodePoint = null; | |
| 267 return false; | |
| 268 } | |
| 269 int position = _position - 1; | |
| 270 _nextPosition = _position; | |
| 271 int codeUnit = _string.charCodeAt(position); | |
| 272 if ((codeUnit & 0xFC00) == 0xDC00 && position > 0) { | |
| 273 int prevCodeUnit = _string.charCodeAt(position - 1); | |
| 274 if ((prevCodeUnit & 0xFC00) == 0xD800) { | |
| 275 _position = position - 1; | |
| 276 _currentCodePoint = | |
| 277 0x10000 + ((prevCodeUnit & 0x3FF) << 10) | (codeUnit & 0x3FF); | |
| 278 return true; | |
| 279 } | |
| 280 } | |
| 281 _position = position; | |
| 282 _currentCodePoint = codeUnit; | |
| 283 return true; | |
| 284 } | |
| 285 } | |
| OLD | NEW |