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

Unified Diff: sdk/lib/io/buffer_list.dart

Issue 14057010: Re-write _BufferList to keep an internal Uint8List buffer, that will grow on demand. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix comment Created 7 years, 8 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 | « no previous file | sdk/lib/io/file_impl.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/buffer_list.dart
diff --git a/sdk/lib/io/buffer_list.dart b/sdk/lib/io/buffer_list.dart
index 72dc92ff03d07d284b786402aab448d8bfe9c406..c61710f2fd20ca1b75e79e0079d1da6df5f87587 100644
--- a/sdk/lib/io/buffer_list.dart
+++ b/sdk/lib/io/buffer_list.dart
@@ -5,153 +5,91 @@
part of dart.io;
/**
- * Utility class that holds a number of byte buffers and can deliver
- * the bytes either one by one or in chunks.
+ * Utility class that can fast concatenate [List<int>]s of bytes. Use
+ * [readBytes] to get the final buffer.
*/
class _BufferList {
+ const int _INIT_SIZE = 1 * 1024;
+
_BufferList() {
clear();
}
- /**
- * Adds a new buffer to the list possibly with an offset of the
- * first byte of interest. The offset can only be specified if the
- * buffer list is empty.
- */
- void add(List<int> buffer, [int offset = 0]) {
- assert(offset == 0 || _buffers.isEmpty);
- _buffers.addLast(buffer);
- _length += buffer.length;
- if (offset != 0) _index = offset;
- }
-
- /** Alias for [add]. */
- void write(List<int> buffer, [int offset = 0]) {
- add(buffer, offset);
+ int pow2roundup(int x) {
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
}
/**
- * Returns the first buffer from the list. This returns the whole
- * buffer and does not remove the buffer from the list. Use
- * [index] to determine the index of the first byte in the buffer.
- */
- List<int> get first => _buffers.first;
-
- /**
- * Returns the current index of the next byte. This will always be
- * an index into the first buffer as when the index is advanced past
- * the end of a buffer it is removed from the list.
- */
- int get index => _index;
-
- /**
- * Peek at the next available byte.
- */
- int peek() => _buffers.first[_index];
-
- /**
- * Returns the next available byte removing it from the buffers.
+ * Adds a new buffer to the list.
*/
- int next() {
- int value = _buffers.first[_index++];
- _length--;
- if (_index == _buffers.first.length) {
- _buffers.removeFirst();
- _index = 0;
+ void add(List<int> buffer) {
+ int bufferLength = buffer.length;
+ int required = _length + bufferLength;
+ if (_buffer == null) {
+ int size = pow2roundup(required);
+ if (size < _INIT_SIZE) size = _INIT_SIZE;
+ _buffer = new Uint8List(size);
+ } else if (_buffer.length < required) {
+ // This will give is a list in the range of 2-4 times larger than
+ // required.
+ int size = pow2roundup(required) * 2;
+ Uint8List newBuffer = new Uint8List(size);
+ newBuffer.setRange(0, _buffer.length, _buffer);
+ _buffer = newBuffer;
}
- return value;
- }
-
- /**
- * Read [count] bytes from the buffer list. If the number of bytes
- * requested is not available null will be returned.
- */
- List<int> readBytes([int count]) {
- if (count == null) count = length;
- List<int> result;
- if (_length == 0) return new Uint8List(0);
- if (_length < count) return null;
- if (_index == 0 && _buffers.first.length == count) {
- result = _buffers.first;
- _buffers.removeFirst();
- _index = 0;
- _length -= count;
- return result;
+ assert(_buffer.length >= required);
+ if (buffer is Uint8List) {
+ _buffer.setRange(_length, required, buffer);
} else {
- int firstRemaining = _buffers.first.length - _index;
- if (firstRemaining >= count) {
- result = _buffers.first.sublist(_index, _index + count);
- _index += count;
- _length -= count;
- if (_index == _buffers.first.length) {
- _buffers.removeFirst();
- _index = 0;
- }
- return result;
- } else {
- result = new Uint8List(count);
- int remaining = count;
- while (remaining > 0) {
- int bytesInFirst = _buffers.first.length - _index;
- if (bytesInFirst <= remaining) {
- int startIndex = count - remaining;
- int endIndex = startIndex + bytesInFirst;
- result.setRange(startIndex, endIndex, _buffers.first, _index);
- _buffers.removeFirst();
- _index = 0;
- _length -= bytesInFirst;
- remaining -= bytesInFirst;
- } else {
- result.setRange(count - remaining, count, _buffers.first, _index);
- _index = remaining;
- _length -= remaining;
- remaining = 0;
- assert(_index < _buffers.first.length);
- }
- }
- return result;
+ for (int i = 0; i < bufferLength; i++) {
+ _buffer[_length + i] = buffer[i];
}
}
+ _length = required;
}
/**
- * Remove a number of bytes from the buffer list. Currently the
- * number of bytes to remove must be confined to the first buffer.
+ * Same as [add].
*/
- void removeBytes(int count) {
- int firstRemaining = first.length - _index;
- assert(count <= firstRemaining);
- if (count == firstRemaining) {
- _buffers.removeFirst();
- _index = 0;
- } else {
- _index += count;
- }
- _length -= count;
+ void write(List<int> buffer) {
+ add(buffer);
}
+ /**
+ * Read all the bytes from the buffer list. If it's empty, an empty list
+ * is returned. A call to [readBytes] will clear the buffer.
+ */
+ List<int> readBytes() {
+ if (_buffer == null) return new Uint8List(0);
+ var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
+ clear();
+ return buffer;
+ }
/**
- * Returns the total number of bytes remaining in the buffers.
+ * Returns the total number of bytes in the buffer.
*/
int get length => _length;
/**
- * Returns whether the buffer list is empty that is has no bytes
- * available.
+ * Returns whether the buffer list is empty.
*/
- bool get isEmpty => _buffers.isEmpty;
+ bool get isEmpty => _length == 0;
/**
* Clears the content of the buffer list.
*/
void clear() {
- _index = 0;
_length = 0;
- _buffers = new Queue();
+ _buffer = null;
}
- int _length; // Total number of bytes remaining in the buffers.
- Queue<List<int>> _buffers; // List of data buffers.
- int _index; // Index of the next byte in the first buffer.
+ int _length; // Total number of bytes in the buffer.
+ Uint8List _buffer; // Internal buffer.
}
« no previous file with comments | « no previous file | sdk/lib/io/file_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698