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

Side by Side Diff: sdk/lib/io/bytes_builder.dart

Issue 218493012: Make non-copying version of BytesBuidler and make file-reads faster. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix readAsBytes to not complete in a long future chain. Created 6 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 | « runtime/bin/builtin.dart ('k') | sdk/lib/io/data_transformer.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 * Builds a list of bytes, allowing bytes and lists of bytes to be added at the 8 * Builds a list of bytes, allowing bytes and lists of bytes to be added at the
9 * end. 9 * end.
10 * 10 *
11 * Used to efficiently collect bytes and lists of bytes, using an internal 11 * Used to efficiently collect bytes and lists of bytes, using an internal
12 * buffer. Note that it's optimized for IO, using an initial buffer of 1K bytes. 12 * buffer. Note that it's optimized for IO, using an initial buffer of 1K bytes.
Søren Gjesse 2014/04/01 08:58:40 I am not sure the "optimized of IO" is actually tr
Anders Johnsen 2014/04/01 09:29:07 Removed.
13 */ 13 */
14 class BytesBuilder { 14 abstract class BytesBuilder {
15 // Start with 1024 bytes.
16 static const int _INIT_SIZE = 1024;
17
18 int _length = 0;
19 Uint8List _buffer;
20
21 /** 15 /**
22 * Construct a new empty [BytesBuilder]. 16 * Construct a new empty [BytesBuilder].
17 *
18 * If [copy] is true, the data is copied when added to the list. Default is
19 * `true`.
Søren Gjesse 2014/04/01 08:58:40 I think some more documentation on what happens if
Anders Johnsen 2014/04/01 09:29:07 Done.
23 */ 20 */
24 BytesBuilder(); 21 factory BytesBuilder({bool copy: true}) {
Søren Gjesse 2014/04/01 08:58:40 The argument name 'copy' is not totally correct. I
Anders Johnsen 2014/04/01 09:29:07 I think cacheBuffers and ownBuffers is confusing.
22 if (copy) {
23 return new _CopyingBytesBuilder();
24 } else {
25 return new _NonCopyingBytesBuilder();
26 }
27 }
25 28
26 /** 29 /**
27 * Appends [bytes] to the current contents of the builder. 30 * Appends [bytes] to the current contents of the builder.
28 * 31 *
29 * Each value of [bytes] will be bit-representation truncated to the range 32 * Each value of [bytes] will be bit-representation truncated to the range
30 * 0 .. 255. 33 * 0 .. 255.
31 */ 34 */
35 void add(List<int> bytes);
36
37 /**
38 * Append [byte] to the current contents of the builder.
39 *
40 * The [byte] will be bit-representation truncated to the range 0 .. 255.
41 */
42 void addByte(int byte);
43
44 /**
45 * Returns the contents of `this` and clears `this`.
46 *
47 * The list returned is a view of the the internal buffer, limited to the
48 * [length].
49 */
50 List<int> takeBytes();
51
52 /**
53 * Returns a copy of the current contents of the builder.
54 *
55 * Leaves the contents of the builder intact.
56 */
57 List<int> toBytes();
58
59 /**
60 * The number of bytes in the builder.
61 */
62 int get length;
63
64 /**
65 * Returns `true` if the buffer is empty.
66 */
67 bool get isEmpty;
68
69 /**
70 * Returns `true` if the buffer is not empty.
71 */
72 bool get isNotEmpty;
73
74 /**
75 * Clear the contents of the builder.
76 */
77 void clear();
78 }
79
80
81 class _CopyingBytesBuilder implements BytesBuilder {
82 // Start with 1024 bytes.
83 static const int _INIT_SIZE = 1024;
84
85 int _length = 0;
86 Uint8List _buffer;
87
32 void add(List<int> bytes) { 88 void add(List<int> bytes) {
33 int bytesLength = bytes.length; 89 int bytesLength = bytes.length;
34 if (bytesLength == 0) return; 90 if (bytesLength == 0) return;
35 int required = _length + bytesLength; 91 int required = _length + bytesLength;
36 if (_buffer == null) { 92 if (_buffer == null) {
37 int size = _pow2roundup(required); 93 int size = _pow2roundup(required);
38 size = max(size, _INIT_SIZE); 94 size = max(size, _INIT_SIZE);
39 _buffer = new Uint8List(size); 95 _buffer = new Uint8List(size);
40 } else if (_buffer.length < required) { 96 } else if (_buffer.length < required) {
41 // We will create a list in the range of 2-4 times larger than 97 // We will create a list in the range of 2-4 times larger than
42 // required. 98 // required.
43 int size = _pow2roundup(required) * 2; 99 int size = _pow2roundup(required) * 2;
44 var newBuffer = new Uint8List(size); 100 var newBuffer = new Uint8List(size);
45 newBuffer.setRange(0, _buffer.length, _buffer); 101 newBuffer.setRange(0, _buffer.length, _buffer);
46 _buffer = newBuffer; 102 _buffer = newBuffer;
47 } 103 }
48 assert(_buffer.length >= required); 104 assert(_buffer.length >= required);
49 if (bytes is Uint8List) { 105 if (bytes is Uint8List) {
50 _buffer.setRange(_length, required, bytes); 106 _buffer.setRange(_length, required, bytes);
51 } else { 107 } else {
52 for (int i = 0; i < bytesLength; i++) { 108 for (int i = 0; i < bytesLength; i++) {
53 _buffer[_length + i] = bytes[i]; 109 _buffer[_length + i] = bytes[i];
54 } 110 }
55 } 111 }
56 _length = required; 112 _length = required;
57 } 113 }
58 114
59 /**
60 * Append [byte] to the current contents of the builder.
61 *
62 * The [byte] will be bit-representation truncated to the range 0 .. 255.
63 */
64 void addByte(int byte) => add([byte]); 115 void addByte(int byte) => add([byte]);
65 116
66 /**
67 * Returns the contents of `this` and clears `this`.
68 *
69 * The list returned is a view of the the internal buffer, limited to the
70 * [length].
71 */
72 List<int> takeBytes() { 117 List<int> takeBytes() {
73 if (_buffer == null) return new Uint8List(0); 118 if (_buffer == null) return new Uint8List(0);
74 var buffer = new Uint8List.view(_buffer.buffer, 0, _length); 119 var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
75 clear(); 120 clear();
76 return buffer; 121 return buffer;
77 } 122 }
78 123
79 /**
80 * Returns a copy of the current contents of the builder.
81 *
82 * Leaves the contents of the builder intact.
83 */
84 List<int> toBytes() { 124 List<int> toBytes() {
85 if (_buffer == null) return new Uint8List(0); 125 if (_buffer == null) return new Uint8List(0);
86 return new Uint8List.fromList( 126 return new Uint8List.fromList(
87 new Uint8List.view(_buffer.buffer, 0, _length)); 127 new Uint8List.view(_buffer.buffer, 0, _length));
88 } 128 }
89 129
90 /**
91 * The number of bytes in the builder.
92 */
93 int get length => _length; 130 int get length => _length;
94 131
95 /**
96 * Returns `true` if the buffer is empty.
97 */
98 bool get isEmpty => _length == 0; 132 bool get isEmpty => _length == 0;
99 133
100 /**
101 * Returns `true` if the buffer is not empty.
102 */
103 bool get isNotEmpty => _length != 0; 134 bool get isNotEmpty => _length != 0;
104 135
105 /**
106 * Clear the contents of the builder.
107 */
108 void clear() { 136 void clear() {
109 _length = 0; 137 _length = 0;
110 _buffer = null; 138 _buffer = null;
111 } 139 }
112 140
113 int _pow2roundup(int x) { 141 int _pow2roundup(int x) {
114 --x; 142 --x;
115 x |= x >> 1; 143 x |= x >> 1;
116 x |= x >> 2; 144 x |= x >> 2;
117 x |= x >> 4; 145 x |= x >> 4;
118 x |= x >> 8; 146 x |= x >> 8;
119 x |= x >> 16; 147 x |= x >> 16;
120 return x + 1; 148 return x + 1;
121 } 149 }
122 } 150 }
151
152
153 class _NonCopyingBytesBuilder implements BytesBuilder {
154 int _length = 0;
155 final List _chunks = [];
156
157 void add(List<int> bytes) {
158 if (bytes is! Uint8List) {
Søren Gjesse 2014/04/01 08:58:40 This might be surprising, as for the non-copying w
Anders Johnsen 2014/04/01 09:29:07 We do say that there is an internal list and promi
159 bytes = new Uint8List.fromList(bytes);
160 }
161 _chunks.add(bytes);
162 _length += bytes.length;
163 }
164
165 void addByte(int byte) => add([byte]);
166
167 List<int> takeBytes() {
168 if (_chunks.length == 0) return new Uint8List(0);
169 if (_chunks.length == 1) {
170 var buffer = _chunks.single;
171 clear();
172 return buffer;
173 }
174 var buffer = new Uint8List(_length);
175 int offset = 0;
176 for (var chunk in _chunks) {
177 buffer.setRange(offset, offset + chunk.length, chunk);
178 offset += chunk.length;
179 }
180 clear();
181 return buffer;
182 }
183
184 List<int> toBytes() {
185 if (_chunks.length == 0) return new Uint8List(0);
186 var buffer = new Uint8List(_length);
187 int offset = 0;
188 for (var chunk in _chunks) {
189 buffer.setRange(offset, offset + chunk.length, chunk);
190 offset += chunk.length;
191 }
192 return buffer;
193 }
194
195 int get length => _length;
196
197 bool get isEmpty => _length == 0;
198
199 bool get isNotEmpty => _length != 0;
200
201 void clear() {
202 _length = 0;
203 _chunks.clear();
204 }
205 }
OLDNEW
« no previous file with comments | « runtime/bin/builtin.dart ('k') | sdk/lib/io/data_transformer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698