| Index: runtime/lib/string_buffer_patch.dart
|
| diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
|
| index 8fadafaa1259f867a224224f38a8a58969df5692..a3a8cf1075a6a4e688a34bbf50736e4651b406d9 100644
|
| --- a/runtime/lib/string_buffer_patch.dart
|
| +++ b/runtime/lib/string_buffer_patch.dart
|
| @@ -3,12 +3,12 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| patch class StringBuffer {
|
| - List<String> _buffer;
|
| + List<int> _buffer;
|
| int _length;
|
|
|
| /// Creates the string buffer with an initial content.
|
| /* patch */ StringBuffer([Object content = ""]) {
|
| - _buffer = new List<String>();
|
| + _buffer = _newBuffer(16);
|
| _length = 0;
|
| write(content);
|
| }
|
| @@ -17,37 +17,74 @@ patch class StringBuffer {
|
|
|
| /// Adds [obj] to the buffer.
|
| /* patch */ void write(Object obj) {
|
| - // TODO(srdjan): The following four lines could be replaced by
|
| - // '$obj', but apparently this is too slow on the Dart VM.
|
| String str;
|
| if (obj is String) {
|
| str = obj;
|
| } else {
|
| + // TODO(srdjan): The following four lines could be replaced by
|
| + // '$obj', but apparently this is too slow on the Dart VM.
|
| str = obj.toString();
|
| if (str is! String) {
|
| throw new ArgumentError('toString() did not return a string');
|
| }
|
| }
|
| if (str.isEmpty) return;
|
| - _buffer.add(str);
|
| + _ensureCapacity(str.length);
|
| + for (int i = 0; i < str.length; i++) {
|
| + _buffer[_length + i] = str.codeUnitAt(i);
|
| + }
|
| _length += str.length;
|
| }
|
|
|
| - /// Clears the string buffer.
|
| + /* patch */ writeCharCode(int charCode) {
|
| + if (charCode < 0 || charCode > 0x10FFFF) {
|
| + throw new RangeError.range(charCode, 0, 0x10FFFF);
|
| + }
|
| + if (charCode <= 0xFFFF) {
|
| + _ensureCapacity(1);
|
| + _buffer[_length++] = charCode;
|
| + } else {
|
| + _ensureCapacity(2);
|
| + int bits = charCode - 0x10000;
|
| + _buffer[_length++] = 0xD800 | (bits >> 10);
|
| + _buffer[_length++] = 0xDC00 | (bits & 0x3FF);
|
| + }
|
| + }
|
| +
|
| + /** Makes the buffer empty. */
|
| /* patch */ void clear() {
|
| - _buffer = new List<String>();
|
| _length = 0;
|
| }
|
|
|
| - /// Returns the contents of buffer as a concatenated string.
|
| + /** Returns the contents of buffer as a string. */
|
| /* patch */ String toString() {
|
| - if (_buffer.length == 0) return "";
|
| - if (_buffer.length == 1) return _buffer[0];
|
| - String result = _StringBase.concatAll(_buffer);
|
| - _buffer.clear();
|
| - _buffer.add(result);
|
| - // Since we track the length at each add operation, there is no
|
| - // need to update it in this function.
|
| - return result;
|
| + if (_length == 0) return "";
|
| + return _create(_buffer, _length);
|
| + }
|
| +
|
| + /** Ensures that the buffer has enough capacity to contain n code units. */
|
| + void _ensureCapacity(int n) {
|
| + int requiredCapacity = _length + n;
|
| + if (requiredCapacity <= _buffer.length) return;
|
| + int newCapacity = _buffer.length;
|
| + do {
|
| + newCapacity *= 2;
|
| + } while (newCapacity < requiredCapacity);
|
| + List<int> newBuffer = _newBuffer(newCapacity);
|
| + newBuffer.setRange(0, _length, _buffer);
|
| + _buffer = newBuffer;
|
| }
|
| +
|
| + /**
|
| + * Create a [String] from the UFT-16 code units in buffer.
|
| + */
|
| + static String _create(List<int> buffer, int length)
|
| + native "StringBuffer_createStringFromUint16Array";
|
| +
|
| + /**
|
| + * Creates a Uint16Array, as the scalar list.
|
| + *
|
| + * Used as a native here to avoid importing scalar lists.
|
| + */
|
| + static _Uint16Array _newBuffer(int length) native "Uint16Array_new";
|
| }
|
|
|