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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/io/file_impl.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 part of dart.io; 5 part of dart.io;
6 6
7 /** 7 /**
8 * Utility class that holds a number of byte buffers and can deliver 8 * Utility class that can fast concatenate [List<int>]s of bytes. Use
9 * the bytes either one by one or in chunks. 9 * [readBytes] to get the final buffer.
10 */ 10 */
11 class _BufferList { 11 class _BufferList {
12 const int _INIT_SIZE = 1 * 1024;
13
12 _BufferList() { 14 _BufferList() {
13 clear(); 15 clear();
14 } 16 }
15 17
16 /** 18 int pow2roundup(int x) {
17 * Adds a new buffer to the list possibly with an offset of the 19 --x;
18 * first byte of interest. The offset can only be specified if the 20 x |= x >> 1;
19 * buffer list is empty. 21 x |= x >> 2;
20 */ 22 x |= x >> 4;
21 void add(List<int> buffer, [int offset = 0]) { 23 x |= x >> 8;
22 assert(offset == 0 || _buffers.isEmpty); 24 x |= x >> 16;
23 _buffers.addLast(buffer); 25 return x + 1;
24 _length += buffer.length;
25 if (offset != 0) _index = offset;
26 }
27
28 /** Alias for [add]. */
29 void write(List<int> buffer, [int offset = 0]) {
30 add(buffer, offset);
31 } 26 }
32 27
33 /** 28 /**
34 * Returns the first buffer from the list. This returns the whole 29 * Adds a new buffer to the list.
35 * buffer and does not remove the buffer from the list. Use
36 * [index] to determine the index of the first byte in the buffer.
37 */ 30 */
38 List<int> get first => _buffers.first; 31 void add(List<int> buffer) {
39 32 int bufferLength = buffer.length;
40 /** 33 int required = _length + bufferLength;
41 * Returns the current index of the next byte. This will always be 34 if (_buffer == null) {
42 * an index into the first buffer as when the index is advanced past 35 int size = pow2roundup(required);
43 * the end of a buffer it is removed from the list. 36 if (size < _INIT_SIZE) size = _INIT_SIZE;
44 */ 37 _buffer = new Uint8List(size);
45 int get index => _index; 38 } else if (_buffer.length < required) {
46 39 // This will give is a list in the range of 2-4 times larger than
47 /** 40 // required.
48 * Peek at the next available byte. 41 int size = pow2roundup(required) * 2;
49 */ 42 Uint8List newBuffer = new Uint8List(size);
50 int peek() => _buffers.first[_index]; 43 newBuffer.setRange(0, _buffer.length, _buffer);
51 44 _buffer = newBuffer;
52 /**
53 * Returns the next available byte removing it from the buffers.
54 */
55 int next() {
56 int value = _buffers.first[_index++];
57 _length--;
58 if (_index == _buffers.first.length) {
59 _buffers.removeFirst();
60 _index = 0;
61 } 45 }
62 return value; 46 assert(_buffer.length >= required);
47 if (buffer is Uint8List) {
48 _buffer.setRange(_length, required, buffer);
49 } else {
50 for (int i = 0; i < bufferLength; i++) {
51 _buffer[_length + i] = buffer[i];
52 }
53 }
54 _length = required;
63 } 55 }
64 56
65 /** 57 /**
66 * Read [count] bytes from the buffer list. If the number of bytes 58 * Same as [add].
67 * requested is not available null will be returned.
68 */ 59 */
69 List<int> readBytes([int count]) { 60 void write(List<int> buffer) {
70 if (count == null) count = length; 61 add(buffer);
71 List<int> result;
72 if (_length == 0) return new Uint8List(0);
73 if (_length < count) return null;
74 if (_index == 0 && _buffers.first.length == count) {
75 result = _buffers.first;
76 _buffers.removeFirst();
77 _index = 0;
78 _length -= count;
79 return result;
80 } else {
81 int firstRemaining = _buffers.first.length - _index;
82 if (firstRemaining >= count) {
83 result = _buffers.first.sublist(_index, _index + count);
84 _index += count;
85 _length -= count;
86 if (_index == _buffers.first.length) {
87 _buffers.removeFirst();
88 _index = 0;
89 }
90 return result;
91 } else {
92 result = new Uint8List(count);
93 int remaining = count;
94 while (remaining > 0) {
95 int bytesInFirst = _buffers.first.length - _index;
96 if (bytesInFirst <= remaining) {
97 int startIndex = count - remaining;
98 int endIndex = startIndex + bytesInFirst;
99 result.setRange(startIndex, endIndex, _buffers.first, _index);
100 _buffers.removeFirst();
101 _index = 0;
102 _length -= bytesInFirst;
103 remaining -= bytesInFirst;
104 } else {
105 result.setRange(count - remaining, count, _buffers.first, _index);
106 _index = remaining;
107 _length -= remaining;
108 remaining = 0;
109 assert(_index < _buffers.first.length);
110 }
111 }
112 return result;
113 }
114 }
115 } 62 }
116 63
117 /** 64 /**
118 * Remove a number of bytes from the buffer list. Currently the 65 * Read all the bytes from the buffer list. If it's empty, an empty list
119 * number of bytes to remove must be confined to the first buffer. 66 * is returned. A call to [readBytes] will clear the buffer.
120 */ 67 */
121 void removeBytes(int count) { 68 List<int> readBytes() {
122 int firstRemaining = first.length - _index; 69 if (_buffer == null) return new Uint8List(0);
123 assert(count <= firstRemaining); 70 var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
124 if (count == firstRemaining) { 71 clear();
125 _buffers.removeFirst(); 72 return buffer;
126 _index = 0;
127 } else {
128 _index += count;
129 }
130 _length -= count;
131 } 73 }
132 74
133
134 /** 75 /**
135 * Returns the total number of bytes remaining in the buffers. 76 * Returns the total number of bytes in the buffer.
136 */ 77 */
137 int get length => _length; 78 int get length => _length;
138 79
139 /** 80 /**
140 * Returns whether the buffer list is empty that is has no bytes 81 * Returns whether the buffer list is empty.
141 * available.
142 */ 82 */
143 bool get isEmpty => _buffers.isEmpty; 83 bool get isEmpty => _length == 0;
144 84
145 /** 85 /**
146 * Clears the content of the buffer list. 86 * Clears the content of the buffer list.
147 */ 87 */
148 void clear() { 88 void clear() {
149 _index = 0;
150 _length = 0; 89 _length = 0;
151 _buffers = new Queue(); 90 _buffer = null;
152 } 91 }
153 92
154 int _length; // Total number of bytes remaining in the buffers. 93 int _length; // Total number of bytes in the buffer.
155 Queue<List<int>> _buffers; // List of data buffers. 94 Uint8List _buffer; // Internal buffer.
156 int _index; // Index of the next byte in the first buffer.
157 } 95 }
OLDNEW
« 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