| Index: sdk/lib/io/bytes_builder.dart
|
| diff --git a/sdk/lib/io/bytes_builder.dart b/sdk/lib/io/bytes_builder.dart
|
| index 2dca39d0c181d7bb5752711219d700611b2c89b6..1b61d30f4fa3f9744940133af1dc03208b058800 100644
|
| --- a/sdk/lib/io/bytes_builder.dart
|
| +++ b/sdk/lib/io/bytes_builder.dart
|
| @@ -83,24 +83,22 @@ class _CopyingBytesBuilder implements BytesBuilder {
|
| // Start with 1024 bytes.
|
| static const int _INIT_SIZE = 1024;
|
|
|
| + static final _emptyList = new Uint8List(0);
|
| +
|
| int _length = 0;
|
| Uint8List _buffer;
|
|
|
| + _CopyingBytesBuilder([int initialCapacity = 0])
|
| + : _buffer = (initialCapacity <= 0)
|
| + ? _emptyList
|
| + : new Uint8List(_pow2roundup(initialCapacity));
|
| +
|
| void add(List<int> bytes) {
|
| int bytesLength = bytes.length;
|
| if (bytesLength == 0) return;
|
| int required = _length + bytesLength;
|
| - if (_buffer == null) {
|
| - int size = _pow2roundup(required);
|
| - size = max(size, _INIT_SIZE);
|
| - _buffer = new Uint8List(size);
|
| - } else if (_buffer.length < required) {
|
| - // We will create a list in the range of 2-4 times larger than
|
| - // required.
|
| - int size = _pow2roundup(required) * 2;
|
| - var newBuffer = new Uint8List(size);
|
| - newBuffer.setRange(0, _buffer.length, _buffer);
|
| - _buffer = newBuffer;
|
| + if (_buffer.length < required) {
|
| + _grow(required);
|
| }
|
| assert(_buffer.length >= required);
|
| if (bytes is Uint8List) {
|
| @@ -113,17 +111,40 @@ class _CopyingBytesBuilder implements BytesBuilder {
|
| _length = required;
|
| }
|
|
|
| - void addByte(int byte) { add([byte]); }
|
| + void addByte(int byte) {
|
| + if (_buffer.length == _length) {
|
| + // The grow algorithm always at least doubles.
|
| + // If we added one to _length it would quadruple unnecessarily.
|
| + _grow(_length);
|
| + }
|
| + assert(_buffer.length > _length);
|
| + _buffer[_length] = byte;
|
| + _length++;
|
| + }
|
| +
|
| + void _grow(int required) {
|
| + // We will create a list in the range of 2-4 times larger than
|
| + // required.
|
| + int newSize = required * 2;
|
| + if (newSize < _INIT_SIZE) {
|
| + newSize = _INIT_SIZE;
|
| + } else {
|
| + newSize = _pow2roundup(newSize);
|
| + }
|
| + var newBuffer = new Uint8List(newSize);
|
| + newBuffer.setRange(0, _buffer.length, _buffer);
|
| + _buffer = newBuffer;
|
| + }
|
|
|
| List<int> takeBytes() {
|
| - if (_buffer == null) return new Uint8List(0);
|
| + if (_length == 0) return _emptyList;
|
| var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
|
| clear();
|
| return buffer;
|
| }
|
|
|
| List<int> toBytes() {
|
| - if (_buffer == null) return new Uint8List(0);
|
| + if (_length == 0) return _emptyList;
|
| return new Uint8List.fromList(
|
| new Uint8List.view(_buffer.buffer, 0, _length));
|
| }
|
| @@ -136,10 +157,11 @@ class _CopyingBytesBuilder implements BytesBuilder {
|
|
|
| void clear() {
|
| _length = 0;
|
| - _buffer = null;
|
| + _buffer = _emptyList;
|
| }
|
|
|
| - int _pow2roundup(int x) {
|
| + static int _pow2roundup(int x) {
|
| + assert(x > 0);
|
| --x;
|
| x |= x >> 1;
|
| x |= x >> 2;
|
| @@ -166,12 +188,15 @@ class _BytesBuilder implements BytesBuilder {
|
| _length += typedBytes.length;
|
| }
|
|
|
| - void addByte(int byte) { add([byte]); }
|
| + void addByte(int byte) {
|
| + _chunks.add(new Uint8List(1)..[0] = byte);
|
| + _length++;
|
| + }
|
|
|
| List<int> takeBytes() {
|
| - if (_chunks.length == 0) return new Uint8List(0);
|
| + if (_length == 0) return _CopyingBytesBuilder._emptyList;
|
| if (_chunks.length == 1) {
|
| - var buffer = _chunks.single;
|
| + var buffer = _chunks[0];
|
| clear();
|
| return buffer;
|
| }
|
| @@ -186,7 +211,7 @@ class _BytesBuilder implements BytesBuilder {
|
| }
|
|
|
| List<int> toBytes() {
|
| - if (_chunks.length == 0) return new Uint8List(0);
|
| + if (_length == 0) return _CopyingBytesBuilder._emptyList;
|
| var buffer = new Uint8List(_length);
|
| int offset = 0;
|
| for (var chunk in _chunks) {
|
|
|