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

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: 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.
12 * buffer. Note that it's optimized for IO, using an initial buffer of 1K bytes.
13 */ 12 */
14 class BytesBuilder { 13 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 /** 14 /**
22 * Construct a new empty [BytesBuilder]. 15 * Construct a new empty [BytesBuilder].
16 *
17 * If [copy] is true, the data is always copied when added to the list. If
18 * it [copy] is false, the data is only copied if needed. That means that if
19 * the lists are changed after added to the [BytesBuilder], it may effect the
20 * output. Default is `true`.
23 */ 21 */
24 BytesBuilder(); 22 factory BytesBuilder({bool copy: true}) {
23 if (copy) {
24 return new _CopyingBytesBuilder();
25 } else {
26 return new _BytesBuilder();
27 }
28 }
25 29
26 /** 30 /**
27 * Appends [bytes] to the current contents of the builder. 31 * Appends [bytes] to the current contents of the builder.
28 * 32 *
29 * Each value of [bytes] will be bit-representation truncated to the range 33 * Each value of [bytes] will be bit-representation truncated to the range
30 * 0 .. 255. 34 * 0 .. 255.
31 */ 35 */
36 void add(List<int> bytes);
37
38 /**
39 * Append [byte] to the current contents of the builder.
40 *
41 * The [byte] will be bit-representation truncated to the range 0 .. 255.
42 */
43 void addByte(int byte);
44
45 /**
46 * Returns the contents of `this` and clears `this`.
47 *
48 * The list returned is a view of the the internal buffer, limited to the
49 * [length].
50 */
51 List<int> takeBytes();
52
53 /**
54 * Returns a copy of the current contents of the builder.
55 *
56 * Leaves the contents of the builder intact.
57 */
58 List<int> toBytes();
59
60 /**
61 * The number of bytes in the builder.
62 */
63 int get length;
64
65 /**
66 * Returns `true` if the buffer is empty.
67 */
68 bool get isEmpty;
69
70 /**
71 * Returns `true` if the buffer is not empty.
72 */
73 bool get isNotEmpty;
74
75 /**
76 * Clear the contents of the builder.
77 */
78 void clear();
79 }
80
81
82 class _CopyingBytesBuilder implements BytesBuilder {
83 // Start with 1024 bytes.
84 static const int _INIT_SIZE = 1024;
85
86 int _length = 0;
87 Uint8List _buffer;
88
32 void add(List<int> bytes) { 89 void add(List<int> bytes) {
33 int bytesLength = bytes.length; 90 int bytesLength = bytes.length;
34 if (bytesLength == 0) return; 91 if (bytesLength == 0) return;
35 int required = _length + bytesLength; 92 int required = _length + bytesLength;
36 if (_buffer == null) { 93 if (_buffer == null) {
37 int size = _pow2roundup(required); 94 int size = _pow2roundup(required);
38 size = max(size, _INIT_SIZE); 95 size = max(size, _INIT_SIZE);
39 _buffer = new Uint8List(size); 96 _buffer = new Uint8List(size);
40 } else if (_buffer.length < required) { 97 } else if (_buffer.length < required) {
41 // We will create a list in the range of 2-4 times larger than 98 // We will create a list in the range of 2-4 times larger than
42 // required. 99 // required.
43 int size = _pow2roundup(required) * 2; 100 int size = _pow2roundup(required) * 2;
44 var newBuffer = new Uint8List(size); 101 var newBuffer = new Uint8List(size);
45 newBuffer.setRange(0, _buffer.length, _buffer); 102 newBuffer.setRange(0, _buffer.length, _buffer);
46 _buffer = newBuffer; 103 _buffer = newBuffer;
47 } 104 }
48 assert(_buffer.length >= required); 105 assert(_buffer.length >= required);
49 if (bytes is Uint8List) { 106 if (bytes is Uint8List) {
50 _buffer.setRange(_length, required, bytes); 107 _buffer.setRange(_length, required, bytes);
51 } else { 108 } else {
52 for (int i = 0; i < bytesLength; i++) { 109 for (int i = 0; i < bytesLength; i++) {
53 _buffer[_length + i] = bytes[i]; 110 _buffer[_length + i] = bytes[i];
54 } 111 }
55 } 112 }
56 _length = required; 113 _length = required;
57 } 114 }
58 115
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]); 116 void addByte(int byte) => add([byte]);
65 117
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() { 118 List<int> takeBytes() {
73 if (_buffer == null) return new Uint8List(0); 119 if (_buffer == null) return new Uint8List(0);
74 var buffer = new Uint8List.view(_buffer.buffer, 0, _length); 120 var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
75 clear(); 121 clear();
76 return buffer; 122 return buffer;
77 } 123 }
78 124
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() { 125 List<int> toBytes() {
85 if (_buffer == null) return new Uint8List(0); 126 if (_buffer == null) return new Uint8List(0);
86 return new Uint8List.fromList( 127 return new Uint8List.fromList(
87 new Uint8List.view(_buffer.buffer, 0, _length)); 128 new Uint8List.view(_buffer.buffer, 0, _length));
88 } 129 }
89 130
90 /**
91 * The number of bytes in the builder.
92 */
93 int get length => _length; 131 int get length => _length;
94 132
95 /**
96 * Returns `true` if the buffer is empty.
97 */
98 bool get isEmpty => _length == 0; 133 bool get isEmpty => _length == 0;
99 134
100 /**
101 * Returns `true` if the buffer is not empty.
102 */
103 bool get isNotEmpty => _length != 0; 135 bool get isNotEmpty => _length != 0;
104 136
105 /**
106 * Clear the contents of the builder.
107 */
108 void clear() { 137 void clear() {
109 _length = 0; 138 _length = 0;
110 _buffer = null; 139 _buffer = null;
111 } 140 }
112 141
113 int _pow2roundup(int x) { 142 int _pow2roundup(int x) {
114 --x; 143 --x;
115 x |= x >> 1; 144 x |= x >> 1;
116 x |= x >> 2; 145 x |= x >> 2;
117 x |= x >> 4; 146 x |= x >> 4;
118 x |= x >> 8; 147 x |= x >> 8;
119 x |= x >> 16; 148 x |= x >> 16;
120 return x + 1; 149 return x + 1;
121 } 150 }
122 } 151 }
152
153
154 class _BytesBuilder implements BytesBuilder {
155 int _length = 0;
156 final List _chunks = [];
157
158 void add(List<int> bytes) {
159 if (bytes is! Uint8List) {
160 bytes = new Uint8List.fromList(bytes);
161 }
162 _chunks.add(bytes);
163 _length += bytes.length;
164 }
165
166 void addByte(int byte) => add([byte]);
167
168 List<int> takeBytes() {
169 if (_chunks.length == 0) return new Uint8List(0);
170 if (_chunks.length == 1) {
171 var buffer = _chunks.single;
172 clear();
173 return buffer;
174 }
175 var buffer = new Uint8List(_length);
176 int offset = 0;
177 for (var chunk in _chunks) {
178 buffer.setRange(offset, offset + chunk.length, chunk);
179 offset += chunk.length;
180 }
181 clear();
182 return buffer;
183 }
184
185 List<int> toBytes() {
186 if (_chunks.length == 0) return new Uint8List(0);
187 var buffer = new Uint8List(_length);
188 int offset = 0;
189 for (var chunk in _chunks) {
190 buffer.setRange(offset, offset + chunk.length, chunk);
191 offset += chunk.length;
192 }
193 return buffer;
194 }
195
196 int get length => _length;
197
198 bool get isEmpty => _length == 0;
199
200 bool get isNotEmpty => _length != 0;
201
202 void clear() {
203 _length = 0;
204 _chunks.clear();
205 }
206 }
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