Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1381)

Unified Diff: sdk/lib/core/string.dart

Issue 12094056: Runes, a bi-directional code-point iterator/iterable. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/core/iterable.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/core/string.dart
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 7f2dcbd48b4fc51306c3fcf896c0c1c91a876b14..e685523b4e98caced7f2e3e03f777a66403ee7b0 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -189,3 +189,97 @@ abstract class String implements Comparable, Pattern {
*/
String toUpperCase();
}
+
+class Runes implements Iterable<int> {
+ String _string;
+ Runes(this._string);
+ RuneIterator get iterator => new RuneIterator(_string);
+}
+
+/** [Iterator] for reading Unicode code points out of a Dart string. */
+class RuneIterator implements BiDirectionalIterator<int> {
+ /** String being iterated. */
+ final String _string;
+ /** Position before the current code point. */
+ int _position;
+ /** Position after the current code point. */
+ int _nextPosition;
+ /**
+ * Current code point.
+ *
+ * If the iterator has hit either end, the [_currentCodePoint] is null
+ * and [: _position == _nextPosition :].
+ */
+ int _currentCodePoint;
+
+ /** Create an iterator positioned at the beginning of the string. */
+ RuneIterator(String string)
+ : _string = string, _position = 0, _nextPosition = 0;
+
+ /**
+ * Create an iterator positioned before the [start]th code unit of the string.
+ *
+ * A [moveNext] will make the following code point the current value, and a
+ * [movePrevious] will make the preceding code pount the current value.
+ *
+ * If the [start] position is in the middle of a surrogate pair, then the
+ * first result in either direction will be an unmatched surrogate.
+ */
+ RuneIterator.at(String string, int start)
+ : _string = string, _position = start, _nextPosition = start {
+ if (start < 0 || start > string.length) {
+ throw new RangeError.range(start, 0, string.length);
+ }
+ }
+
+ int get current => _currentCodePoint;
+
+ 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
+ _position = _nextPosition;
+ if (_position == _string.length) {
+ _currentCodePoint = null;
+ return false;
+ }
+ _readCharForward();
+ return true;
+ }
+
+ // Decodes code units at _position, updates _currentCodePoint, _nextPosition.
+ void _readCharForward() {
+ int codeUnit = _string.charCodeAt(_position);
+ int nextPosition = _position + 1;
+ if ((codeUnit & 0xFC00) == 0xD800 && nextPosition < _string.length) {
+ int nextCodeUnit = _string.charCodeAt(nextPosition);
+ if ((nextCodeUnit & 0xFC00) == 0xDC00) {
+ _nextPosition = nextPosition + 1;
+ _currentCodePoint =
+ 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
+ return;
+ }
+ }
+ _nextPosition = nextPosition;
+ _currentCodePoint = codeUnit;
+ }
+
+ bool movePrevious() {
+ if (_position == 0) {
+ _currentCodePoint = null;
+ return false;
+ }
+ int position = _position - 1;
+ _nextPosition = _position;
+ int codeUnit = _string.charCodeAt(position);
+ if ((codeUnit & 0xFC00) == 0xDC00 && position > 0) {
+ int prevCodeUnit = _string.charCodeAt(position - 1);
+ if ((prevCodeUnit & 0xFC00) == 0xD800) {
+ _position = position - 1;
+ _currentCodePoint =
+ 0x10000 + ((prevCodeUnit & 0x3FF) << 10) | (codeUnit & 0x3FF);
+ return true;
+ }
+ }
+ _position = position;
+ _currentCodePoint = codeUnit;
+ return true;
+ }
+}
« no previous file with comments | « sdk/lib/core/iterable.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698