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

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

Issue 2618523005: Make HTTP headers use a growing buffer, not a fixed-size 8K one. (Closed)
Patch Set: Remove error message and tests expecting it. Created 3 years, 11 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
« no previous file with comments | « no previous file | sdk/lib/io/http_headers.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 *
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 * Clear the contents of the builder. 76 * Clear the contents of the builder.
77 */ 77 */
78 void clear(); 78 void clear();
79 } 79 }
80 80
81 81
82 class _CopyingBytesBuilder implements BytesBuilder { 82 class _CopyingBytesBuilder implements BytesBuilder {
83 // Start with 1024 bytes. 83 // Start with 1024 bytes.
84 static const int _INIT_SIZE = 1024; 84 static const int _INIT_SIZE = 1024;
85 85
86 static final _emptyList = new Uint8List(0);
87
86 int _length = 0; 88 int _length = 0;
87 Uint8List _buffer; 89 Uint8List _buffer;
88 90
91 _CopyingBytesBuilder([int initialCapacity = 0])
92 : _buffer = (initialCapacity <= 0)
93 ? _emptyList
94 : new Uint8List(_pow2roundup(initialCapacity));
95
89 void add(List<int> bytes) { 96 void add(List<int> bytes) {
90 int bytesLength = bytes.length; 97 int bytesLength = bytes.length;
91 if (bytesLength == 0) return; 98 if (bytesLength == 0) return;
92 int required = _length + bytesLength; 99 int required = _length + bytesLength;
93 if (_buffer == null) { 100 if (_buffer.length < required) {
94 int size = _pow2roundup(required); 101 _grow(required);
95 size = max(size, _INIT_SIZE);
96 _buffer = new Uint8List(size);
97 } else if (_buffer.length < required) {
98 // We will create a list in the range of 2-4 times larger than
99 // required.
100 int size = _pow2roundup(required) * 2;
101 var newBuffer = new Uint8List(size);
102 newBuffer.setRange(0, _buffer.length, _buffer);
103 _buffer = newBuffer;
104 } 102 }
105 assert(_buffer.length >= required); 103 assert(_buffer.length >= required);
106 if (bytes is Uint8List) { 104 if (bytes is Uint8List) {
107 _buffer.setRange(_length, required, bytes); 105 _buffer.setRange(_length, required, bytes);
108 } else { 106 } else {
109 for (int i = 0; i < bytesLength; i++) { 107 for (int i = 0; i < bytesLength; i++) {
110 _buffer[_length + i] = bytes[i]; 108 _buffer[_length + i] = bytes[i];
111 } 109 }
112 } 110 }
113 _length = required; 111 _length = required;
114 } 112 }
115 113
116 void addByte(int byte) { add([byte]); } 114 void addByte(int byte) {
115 if (_buffer.length == _length) {
116 // The grow algorithm always at least doubles.
117 // If we added one to _length it would quadruple unnecessarily.
118 _grow(_length);
119 }
120 assert(_buffer.length > _length);
121 _buffer[_length] = byte;
122 _length++;
123 }
124
125 void _grow(int required) {
126 // We will create a list in the range of 2-4 times larger than
127 // required.
128 int newSize = required * 2;
129 if (newSize < _INIT_SIZE) {
130 newSize = _INIT_SIZE;
131 } else {
132 newSize = _pow2roundup(newSize);
133 }
134 var newBuffer = new Uint8List(newSize);
135 newBuffer.setRange(0, _buffer.length, _buffer);
136 _buffer = newBuffer;
137 }
117 138
118 List<int> takeBytes() { 139 List<int> takeBytes() {
119 if (_buffer == null) return new Uint8List(0); 140 if (_length == 0) return _emptyList;
120 var buffer = new Uint8List.view(_buffer.buffer, 0, _length); 141 var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
121 clear(); 142 clear();
122 return buffer; 143 return buffer;
123 } 144 }
124 145
125 List<int> toBytes() { 146 List<int> toBytes() {
126 if (_buffer == null) return new Uint8List(0); 147 if (_length == 0) return _emptyList;
127 return new Uint8List.fromList( 148 return new Uint8List.fromList(
128 new Uint8List.view(_buffer.buffer, 0, _length)); 149 new Uint8List.view(_buffer.buffer, 0, _length));
129 } 150 }
130 151
131 int get length => _length; 152 int get length => _length;
132 153
133 bool get isEmpty => _length == 0; 154 bool get isEmpty => _length == 0;
134 155
135 bool get isNotEmpty => _length != 0; 156 bool get isNotEmpty => _length != 0;
136 157
137 void clear() { 158 void clear() {
138 _length = 0; 159 _length = 0;
139 _buffer = null; 160 _buffer = _emptyList;
140 } 161 }
141 162
142 int _pow2roundup(int x) { 163 static int _pow2roundup(int x) {
164 assert(x > 0);
143 --x; 165 --x;
144 x |= x >> 1; 166 x |= x >> 1;
145 x |= x >> 2; 167 x |= x >> 2;
146 x |= x >> 4; 168 x |= x >> 4;
147 x |= x >> 8; 169 x |= x >> 8;
148 x |= x >> 16; 170 x |= x >> 16;
149 return x + 1; 171 return x + 1;
150 } 172 }
151 } 173 }
152 174
153 175
154 class _BytesBuilder implements BytesBuilder { 176 class _BytesBuilder implements BytesBuilder {
155 int _length = 0; 177 int _length = 0;
156 final List<Uint8List> _chunks = []; 178 final List<Uint8List> _chunks = [];
157 179
158 void add(List<int> bytes) { 180 void add(List<int> bytes) {
159 Uint8List typedBytes; 181 Uint8List typedBytes;
160 if (bytes is Uint8List) { 182 if (bytes is Uint8List) {
161 typedBytes = bytes; 183 typedBytes = bytes;
162 } else { 184 } else {
163 typedBytes = new Uint8List.fromList(bytes); 185 typedBytes = new Uint8List.fromList(bytes);
164 } 186 }
165 _chunks.add(typedBytes); 187 _chunks.add(typedBytes);
166 _length += typedBytes.length; 188 _length += typedBytes.length;
167 } 189 }
168 190
169 void addByte(int byte) { add([byte]); } 191 void addByte(int byte) {
192 _chunks.add(new Uint8List(1)..[0] = byte);
193 _length++;
194 }
170 195
171 List<int> takeBytes() { 196 List<int> takeBytes() {
172 if (_chunks.length == 0) return new Uint8List(0); 197 if (_length == 0) return _CopyingBytesBuilder._emptyList;
173 if (_chunks.length == 1) { 198 if (_chunks.length == 1) {
174 var buffer = _chunks.single; 199 var buffer = _chunks[0];
175 clear(); 200 clear();
176 return buffer; 201 return buffer;
177 } 202 }
178 var buffer = new Uint8List(_length); 203 var buffer = new Uint8List(_length);
179 int offset = 0; 204 int offset = 0;
180 for (var chunk in _chunks) { 205 for (var chunk in _chunks) {
181 buffer.setRange(offset, offset + chunk.length, chunk); 206 buffer.setRange(offset, offset + chunk.length, chunk);
182 offset += chunk.length; 207 offset += chunk.length;
183 } 208 }
184 clear(); 209 clear();
185 return buffer; 210 return buffer;
186 } 211 }
187 212
188 List<int> toBytes() { 213 List<int> toBytes() {
189 if (_chunks.length == 0) return new Uint8List(0); 214 if (_length == 0) return _CopyingBytesBuilder._emptyList;
190 var buffer = new Uint8List(_length); 215 var buffer = new Uint8List(_length);
191 int offset = 0; 216 int offset = 0;
192 for (var chunk in _chunks) { 217 for (var chunk in _chunks) {
193 buffer.setRange(offset, offset + chunk.length, chunk); 218 buffer.setRange(offset, offset + chunk.length, chunk);
194 offset += chunk.length; 219 offset += chunk.length;
195 } 220 }
196 return buffer; 221 return buffer;
197 } 222 }
198 223
199 int get length => _length; 224 int get length => _length;
200 225
201 bool get isEmpty => _length == 0; 226 bool get isEmpty => _length == 0;
202 227
203 bool get isNotEmpty => _length != 0; 228 bool get isNotEmpty => _length != 0;
204 229
205 void clear() { 230 void clear() {
206 _length = 0; 231 _length = 0;
207 _chunks.clear(); 232 _chunks.clear();
208 } 233 }
209 } 234 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/http_headers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698