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

Side by Side Diff: runtime/lib/string_patch.dart

Issue 864463002: Create string efficiently from Uint16List/View. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 const int _maxAscii = 0x7f;
6 const int _maxLatin1 = 0xff;
7 const int _maxUtf16 = 0xffff;
8 const int _maxUnicode = 0x10ffff;
9
5 patch class String { 10 patch class String {
6 /* patch */ factory String.fromCharCodes(Iterable<int> charCodes, 11 /* patch */ factory String.fromCharCodes(Iterable<int> charCodes,
7 [int start = 0, int end]) { 12 [int start = 0, int end]) {
8 return _StringBase.createFromCharCodes(charCodes, start, end); 13 if (charCodes is! Iterable) throw new ArgumentError.value(charCodes, "charCo des");
14 if (start is! int) throw new ArgumentError.value(start, "start");
15 if (end != null && end is! int) throw new ArgumentError.value(end, "end");
16 return _StringBase.createFromCharCodes(charCodes, start, end, null);
9 } 17 }
10 18
11 /* patch */ factory String.fromCharCode(int charCode) { 19 /* patch */ factory String.fromCharCode(int charCode) {
12 if (charCode >= 0) { 20 if (charCode >= 0) {
13 if (charCode <= 0xff) { 21 if (charCode <= 0xff) {
14 return _OneByteString._allocate(1).._setAt(0, charCode); 22 return _OneByteString._allocate(1).._setAt(0, charCode);
15 } 23 }
16 if (charCode <= 0xffff) { 24 if (charCode <= 0xffff) {
17 return _StringBase._createFromCodePoints(new _List(1)..[0] = charCode, 25 return _StringBase._createFromCodePoints(new _List(1)..[0] = charCode,
18 0, 1); 26 0, 1);
(...skipping 25 matching lines...) Expand all
44 factory _StringBase._uninstantiable() { 52 factory _StringBase._uninstantiable() {
45 throw new UnsupportedError( 53 throw new UnsupportedError(
46 "_StringBase can't be instaniated"); 54 "_StringBase can't be instaniated");
47 } 55 }
48 56
49 Type get runtimeType => String; 57 Type get runtimeType => String;
50 58
51 int get hashCode native "String_getHashCode"; 59 int get hashCode native "String_getHashCode";
52 60
53 /** 61 /**
54 * Create the most efficient string representation for specified 62 * Create the most efficient string representation for specified
55 * [codePoints]. 63 * [codePoints].
siva 2015/01/20 23:50:26 The parameter name is not documented correctly, th
Lasse Reichstein Nielsen 2015/01/22 07:16:32 Done.
64 *
65 * The [limit] is an upper limit on the character codes in the iterable.
66 * It's `null` if unknown.
siva 2015/01/20 23:50:26 Since limit is documented maybe we should also doc
Lasse Reichstein Nielsen 2015/01/22 07:16:33 Done.
56 */ 67 */
57 static String createFromCharCodes(Iterable<int> charCodes, 68 static String createFromCharCodes(Iterable<int> charCodes,
58 int start, int end) { 69 int start, int end,
70 int limit) {
71 if (start == null) throw new ArgumentError.notNull("start");
59 if (charCodes == null) throw new ArgumentError(charCodes); 72 if (charCodes == null) throw new ArgumentError(charCodes);
60 // TODO(srdjan): Also skip copying of wide typed arrays. 73 // TODO(srdjan): Also skip copying of wide typed arrays.
61 final ccid = ClassID.getID(charCodes); 74 final ccid = ClassID.getID(charCodes);
62 bool isOneByteString = false; 75 bool isOneByteString = false;
63 if ((ccid != ClassID.cidArray) && 76 if ((ccid != ClassID.cidArray) &&
64 (ccid != ClassID.cidGrowableObjectArray) && 77 (ccid != ClassID.cidGrowableObjectArray) &&
65 (ccid != ClassID.cidImmutableArray)) { 78 (ccid != ClassID.cidImmutableArray)) {
66 if (charCodes is Uint8List) { 79 if (charCodes is Uint8List) {
67 isOneByteString = true; 80 end = RangeError.checkValidRange(start, end, charCodes.length);
68 } else { 81 return _createOneByteString(charCodes, start, end - start);
69 // Treat charCodes as Iterable. 82 } else if (charCodes is! Uint16List) {
70 if (start < 0) throw new RangeError.range(start, 0, charCodes.length); 83 return _createStringFromIterable(charCodes, start, end);
71 if (end != null && end < start) {
72 throw new RangeError.range(end, start, charCodes.length);
73 }
74 var it = charCodes.iterator;
75 for (int i = 0; i < start; i++) {
76 if (!it.moveNext()) {
77 throw new RangeError.range(start, 0, i);
78 }
79 }
80 int bits = 0; // Bitwise or of all char codes in list.
81 var list = [];
82 if (end == null) {
83 while (it.moveNext()) {
84 int code = it.current;
85 bits |= code;
86 list.add(code);
87 }
88 } else {
89 for (int i = start; i < end; i++) {
90 if (!it.moveNext()) {
91 throw new RangeError.range(end, start, i);
92 }
93 int code = it.current;
94 bits |= code;
95 list.add(code);
96 }
97 }
98 charCodes = list;
99 isOneByteString = (bits >= 0 && bits <= 0xff);
100 start = 0;
101 end = list.length;
102 } 84 }
103 } 85 }
104 int codeCount = charCodes.length; 86 int codeCount = charCodes.length;
105 if (start < 0 || start > codeCount) { 87 end = RangeError.checkValidRange(start, end, codeCount);
106 throw new RangeError.range(start, 0, codeCount);
107 }
108 if (end == null) {
109 end = codeCount;
110 } else if (end < start || end > codeCount) {
111 throw new RangeError.range(end, start, codeCount);
112 }
113 final len = end - start; 88 final len = end - start;
114 if (!isOneByteString) { 89 if (len == 0) return "";
115 for (int i = start; i < end; i++) { 90 if (limit == null) {
116 int e = charCodes[i]; 91 limit = _scanCodeUnits(charCodes, start, end);
117 if (e is! _Smi) throw new ArgumentError(e); 92 if (limit < 0) {
118 // Is e Latin1? 93 throw new ArgumentError(charCodes);
119 if ((e < 0) || (e > 0xFF)) {
120 return _createFromCodePoints(charCodes, start, end);
121 }
122 } 94 }
siva 2015/01/20 23:50:26 the (limit < 0) should be pulled outside the if (l
Lasse Reichstein Nielsen 2015/01/22 07:16:32 While that shouldn't happen (we check that elsewhe
123 } 95 }
124 // Allocate a one byte string. When the list is 128 entries or longer, 96 if (limit <= _maxLatin1) {
125 // it's faster to perform a runtime-call. 97 return _createOneByteString(charCodes, start, len);
126 if (len >= 128) {
127 return _OneByteString._allocateFromOneByteList(charCodes, start, end);
128 } 98 }
siva 2015/01/20 23:50:26 Since you are checking for 'limit' not being < 0 a
Lasse Reichstein Nielsen 2015/01/22 07:16:32 True. I'll consider if it's worth it for another C
99 if (limit <= _maxUtf16) {
100 return _TwoByteString._allocateFromTwoByteList(charCodes, start, end);
101 }
102 return _createFromCodePoints(charCodes, start, end);
siva 2015/01/20 23:50:26 The same TODO applies to this call of createFromCo
Lasse Reichstein Nielsen 2015/01/22 07:16:33 If we get here, then limit > 0xffff, so there is a
103 }
104
105 static int _scanCodeUnits(List<int> charCodes, int start, int end) {
106 int bits = 0;
107 for (int i = start; i < end; i++) {
108 int code = charCodes[i];
109 if (code is! _Smi) throw new ArgumentError(charCodes);
110 bits |= code;
111 }
112 return bits;
113 }
114
115 static String _createStringFromIterable(Iterable<int> charCodes,
116 int start, int end) {
117 // Treat charCodes as Iterable.
118 if (charCodes is EfficientLength) {
119 int length = charCodes.length;
120 end = RangeError.checkValidRange(start, end, length);
121 List charCodeList = new List.from(charCodes.take(end).skip(start),
122 growable: false);
123 return createFromCharCodes(charCodeList, 0, charCodeList.length, null);
124 }
125 // Don't know length of iterable, so iterate and see if all the values
126 // are there.
127 if (start < 0) throw new RangeError.range(start, 0, charCodes.length);
128 if (end != null && end < start) {
129 throw new RangeError.range(end, start, charCodes.length);
130 }
131 var it = charCodes.iterator;
132 for (int i = 0; i < start; i++) {
133 if (!it.moveNext()) {
134 throw new RangeError.range(start, 0, i);
135 }
136 }
137 List charCodeList;
138 int bits = 0; // Bitwise-or of all char codes in list.
139 if (end == null) {
140 var list = [];
141 while (it.moveNext()) {
142 int code = it.current;
143 bits |= code;
144 list.add(code);
145 }
146 charCodeList = makeListFixedLength(list);
147 } else {
siva 2015/01/20 23:50:26 why not move the end < start check here to avoid h
Lasse Reichstein Nielsen 2015/01/22 07:16:32 Done.
148 int len = end - start;
149 var list = new List(len);
150 for (int i = 0; i < len; i++) {
151 if (!it.moveNext()) {
152 throw new RangeError.range(end, start, start + i);
153 }
154 int code = it.current;
155 bits |= code;
156 list[i] = code;
157 }
158 charCodeList = list;
159 }
160 int length = charCodeList.length;
161 if (bits < 0) throw new ArgumentError(charCodes);
siva 2015/01/20 23:50:26 This style of not using a '{' ... '}' seems incons
Lasse Reichstein Nielsen 2015/01/22 07:16:32 I use it when it fits on a line, but not consisten
162 bool isOneByteString = (bits <= _maxLatin1);
163 if (isOneByteString) {
164 return _createOneByteString(charCodeList, 0, length);
165 }
166 return createFromCharCodes(charCodeList, 0, length, bits);
167 }
168
169 static String _createOneByteString(List<int> charCodes, int start, int len) {
170 // It's always faster to do this in Dart than to call into the runtime.
129 var s = _OneByteString._allocate(len); 171 var s = _OneByteString._allocate(len);
130 for (int i = 0; i < len; i++) { 172 for (int i = 0; i < len; i++) {
131 s._setAt(i, charCodes[start + i]); 173 s._setAt(i, charCodes[start + i]);
132 } 174 }
133 return s; 175 return s;
134 } 176 }
135 177
178 static String _createTwoByteString(List<int> charCodes, int start, int len) {
179 // TODO(lrn): Create string without scanning charCodes again - all values
180 // in the [start..end] range are uint16 values.
181 return _createFromCodePoints(charCodes, start, end);
182 }
183
136 static String _createFromCodePoints(List<int> codePoints, int start, int end) 184 static String _createFromCodePoints(List<int> codePoints, int start, int end)
137 native "StringBase_createFromCodePoints"; 185 native "StringBase_createFromCodePoints";
138 186
139 String operator [](int index) native "String_charAt"; 187 String operator [](int index) native "String_charAt";
140 188
141 int codeUnitAt(int index) native "String_codeUnitAt"; 189 int codeUnitAt(int index) native "String_codeUnitAt";
142 190
143 int get length native "String_getLength"; 191 int get length native "String_getLength";
144 192
145 bool get isEmpty { 193 bool get isEmpty {
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 void _setAt(int index, int codePoint) native "OneByteString_setAt"; 1037 void _setAt(int index, int codePoint) native "OneByteString_setAt";
990 } 1038 }
991 1039
992 1040
993 class _TwoByteString extends _StringBase implements String { 1041 class _TwoByteString extends _StringBase implements String {
994 factory _TwoByteString._uninstantiable() { 1042 factory _TwoByteString._uninstantiable() {
995 throw new UnsupportedError( 1043 throw new UnsupportedError(
996 "_TwoByteString can only be allocated by the VM"); 1044 "_TwoByteString can only be allocated by the VM");
997 } 1045 }
998 1046
1047 static String _allocateFromTwoByteList(List list, int start, int end)
1048 native "TwoByteString_allocateFromTwoByteList";
1049
999 bool _isWhitespace(int codeUnit) { 1050 bool _isWhitespace(int codeUnit) {
1000 return _StringBase._isTwoByteWhitespace(codeUnit); 1051 return _StringBase._isTwoByteWhitespace(codeUnit);
1001 } 1052 }
1002 1053
1003 bool operator ==(Object other) { 1054 bool operator ==(Object other) {
1004 return super == other; 1055 return super == other;
1005 } 1056 }
1006 } 1057 }
1007 1058
1008 1059
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 class _CodeUnits extends Object with ListMixin<int>, 1126 class _CodeUnits extends Object with ListMixin<int>,
1076 UnmodifiableListMixin<int> { 1127 UnmodifiableListMixin<int> {
1077 /** The string that this is the code units of. */ 1128 /** The string that this is the code units of. */
1078 String _string; 1129 String _string;
1079 1130
1080 _CodeUnits(this._string); 1131 _CodeUnits(this._string);
1081 1132
1082 int get length => _string.length; 1133 int get length => _string.length;
1083 int operator[](int i) => _string.codeUnitAt(i); 1134 int operator[](int i) => _string.codeUnitAt(i);
1084 } 1135 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698