@@ -7,40 +7,36 @@ import 'dart:typed_data';
77
88/// Puts a buffer in front of a [Sink<List<int>>] .
99class BufferedSink {
10- static const int SIZE = 100000 ;
11- static const int SAFE_SIZE = SIZE - 5 ;
12- static const int SMALL = 10000 ;
10+ static const int _SIZE = 128 * 1024 ;
11+ static const int _SAFE_LENGTH = _SIZE - 5 ;
1312
14- final ByteSink _sink ;
13+ final BytesBuilder _builder = BytesBuilder (copy : false ) ;
1514
16- int flushedLength = 0 ;
17-
18- Uint8List _buffer = Uint8List (SIZE );
19- int length = 0 ;
15+ Uint8List _buffer = Uint8List (_SIZE );
16+ int _length = 0 ;
2017
2118 final Float64List _doubleBuffer = Float64List (1 );
22- Uint8List ? _doubleBufferUint8;
19+ late final Uint8List _doubleBufferUint8 = _doubleBuffer.buffer. asUint8List () ;
2320
24- BufferedSink (this ._sink );
21+ BufferedSink ();
2522
26- int get offset => flushedLength + length ;
23+ int get offset => _builder.length + _length ;
2724
2825 @pragma ("vm:prefer-inline" )
2926 void addByte (int byte) {
30- _buffer[length++ ] = byte;
31- if (length == SIZE ) {
32- _sink.add (_buffer);
33- _buffer = Uint8List (SIZE );
34- length = 0 ;
35- flushedLength += SIZE ;
27+ _buffer[_length++ ] = byte;
28+ if (_length == _SIZE ) {
29+ _builder.add (_buffer);
30+ _buffer = Uint8List (_SIZE );
31+ _length = 0 ;
3632 }
3733 }
3834
3935 @pragma ("vm:prefer-inline" )
4036 void addByte2 (int byte1, int byte2) {
41- if (length < SAFE_SIZE ) {
42- _buffer[length ++ ] = byte1;
43- _buffer[length ++ ] = byte2;
37+ if (_length < _SAFE_LENGTH ) {
38+ _buffer[_length ++ ] = byte1;
39+ _buffer[_length ++ ] = byte2;
4440 } else {
4541 addByte (byte1);
4642 addByte (byte2);
@@ -49,11 +45,11 @@ class BufferedSink {
4945
5046 @pragma ("vm:prefer-inline" )
5147 void addByte4 (int byte1, int byte2, int byte3, int byte4) {
52- if (length < SAFE_SIZE ) {
53- _buffer[length ++ ] = byte1;
54- _buffer[length ++ ] = byte2;
55- _buffer[length ++ ] = byte3;
56- _buffer[length ++ ] = byte4;
48+ if (_length < _SAFE_LENGTH ) {
49+ _buffer[_length ++ ] = byte1;
50+ _buffer[_length ++ ] = byte2;
51+ _buffer[_length ++ ] = byte3;
52+ _buffer[_length ++ ] = byte4;
5753 } else {
5854 addByte (byte1);
5955 addByte (byte2);
@@ -63,51 +59,58 @@ class BufferedSink {
6359 }
6460
6561 void addBytes (Uint8List bytes) {
66- // Avoid copying a large buffer into the another large buffer. Also, if
67- // the bytes buffer is too large to fit in our own buffer, just emit both.
68- if (length + bytes.length < SIZE &&
69- (bytes.length < SMALL || length < SMALL )) {
70- _buffer.setRange (length, length + bytes.length, bytes);
71- length += bytes.length;
72- } else if (bytes.length < SMALL ) {
73- // Flush as much as we can in the current buffer.
74- _buffer.setRange (length, SIZE , bytes);
75- _sink.add (_buffer);
76- // Copy over the remainder into a new buffer. It is guaranteed to fit
77- // because the input byte array is small.
78- int alreadyEmitted = SIZE - length;
79- int remainder = bytes.length - alreadyEmitted;
80- _buffer = Uint8List (SIZE );
81- _buffer.setRange (0 , remainder, bytes, alreadyEmitted);
82- length = remainder;
83- flushedLength += SIZE ;
84- } else {
85- flush ();
86- _sink.add (bytes);
87- flushedLength += bytes.length;
62+ if (bytes.isEmpty) {
63+ return ;
64+ }
65+
66+ // Usually the bytes is short, and fits the current buffer.
67+ if (_length + bytes.length < _SIZE ) {
68+ _buffer.setRange (_length, _length + bytes.length, bytes);
69+ _length += bytes.length;
70+ return ;
8871 }
72+
73+ // If the bytes is too long, add separate buffers.
74+ if (bytes.length >= _SIZE ) {
75+ _builder.add (_buffer.sublist (0 , _length));
76+ _builder.add (bytes);
77+ // Start a new buffer.
78+ _buffer = Uint8List (_SIZE );
79+ _length = 0 ;
80+ return ;
81+ }
82+
83+ // Copy as much as we can into the current buffer.
84+ _buffer.setRange (_length, _SIZE , bytes);
85+ _builder.add (_buffer);
86+
87+ // Copy the remainder into a new buffer.
88+ var alreadyCopied = _SIZE - _length;
89+ var remainder = bytes.length - alreadyCopied;
90+ _buffer = Uint8List (_SIZE );
91+ _buffer.setRange (0 , remainder, bytes, alreadyCopied);
92+ _length = remainder;
8993 }
9094
9195 void addDouble (double value) {
92- var doubleBufferUint8 =
93- _doubleBufferUint8 ?? = _doubleBuffer.buffer.asUint8List ();
9496 _doubleBuffer[0 ] = value;
95- addByte4 (doubleBufferUint8[0 ], doubleBufferUint8[1 ], doubleBufferUint8[2 ],
96- doubleBufferUint8[3 ]);
97- addByte4 (doubleBufferUint8[4 ], doubleBufferUint8[5 ], doubleBufferUint8[6 ],
98- doubleBufferUint8[7 ]);
97+ addByte4 (
98+ _doubleBufferUint8[0 ],
99+ _doubleBufferUint8[1 ],
100+ _doubleBufferUint8[2 ],
101+ _doubleBufferUint8[3 ],
102+ );
103+ addByte4 (
104+ _doubleBufferUint8[4 ],
105+ _doubleBufferUint8[5 ],
106+ _doubleBufferUint8[6 ],
107+ _doubleBufferUint8[7 ],
108+ );
99109 }
100110
101- void flush () {
102- _sink.add (_buffer.sublist (0 , length));
103- _buffer = Uint8List (SIZE );
104- flushedLength += length;
105- length = 0 ;
106- }
107-
108- Uint8List flushAndTake () {
109- _sink.add (_buffer.sublist (0 , length));
110- return _sink.builder.takeBytes ();
111+ Uint8List takeBytes () {
112+ _builder.add (_buffer.sublist (0 , _length));
113+ return _builder.takeBytes ();
111114 }
112115
113116 @pragma ("vm:prefer-inline" )
@@ -258,16 +261,3 @@ class BufferedSink {
258261 writeStringUtf8 (uriStr);
259262 }
260263}
261-
262- /// A [Sink] that directly writes data into a byte builder.
263- class ByteSink implements Sink <List <int >> {
264- final BytesBuilder builder = BytesBuilder (copy: false );
265-
266- @override
267- void add (List <int > data) {
268- builder.add (data);
269- }
270-
271- @override
272- void close () {}
273- }
0 commit comments