OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 /** |
| 6 * A dynamic byte buffer that acts as a buffering pipe/queue for data. |
| 7 */ |
| 8 class PbByteBuffer { |
| 9 /** |
| 10 * Build empty buffer |
| 11 */ |
| 12 PbByteBuffer() : _buffer = new Queue<List<int>>(); |
| 13 |
| 14 /** |
| 15 * Build with an optional queue of lists (the initial buffer). |
| 16 */ |
| 17 PbByteBuffer.fromQueueOfLists([Queue<List<int>> this._buffer]) { |
| 18 if (null !== _buffer) { |
| 19 for (List<int> l in _buffer) { |
| 20 _length += l.length; |
| 21 } |
| 22 } else { |
| 23 _buffer = new Queue<List<int>>(); |
| 24 } |
| 25 _updateBuffers(); |
| 26 } |
| 27 |
| 28 /** |
| 29 * Build buffer from a single list. |
| 30 */ |
| 31 PbByteBuffer.fromList(List<int> buffer) { |
| 32 _buffer = new Queue<List<int>>(); |
| 33 _buffer.add(buffer); |
| 34 _length = buffer.length; |
| 35 _updateBuffers(); |
| 36 } |
| 37 |
| 38 /** |
| 39 * Add a list of bytes to the internal buffer queue. |
| 40 */ |
| 41 void add(List<int> more) { |
| 42 _length += more.length; |
| 43 _buffer.add(more); |
| 44 } |
| 45 |
| 46 /** |
| 47 * Read a single byte. |
| 48 */ |
| 49 int readByte() { |
| 50 if(isEmpty) { |
| 51 return null; |
| 52 } else { |
| 53 int value = _buffer.first()[_index++]; |
| 54 _length--; |
| 55 _updateBuffers(); |
| 56 return value; |
| 57 } |
| 58 } |
| 59 |
| 60 /** |
| 61 * Read the specified bytes (or as many as are available) and |
| 62 * return these as a list of int. |
| 63 */ |
| 64 List<int> readBytes([int count = -1]) { |
| 65 List<int> result; |
| 66 |
| 67 // USe temporary variables to work around |
| 68 // http://code.google.com/p/dart/issues/detail?id=3806 |
| 69 int c = count; |
| 70 int l = _length; |
| 71 if (l == 0) return []; |
| 72 int remaining = (c < 0 || l < c) ? l : c; |
| 73 |
| 74 // optimization -- perhaps you can just pass back the top list. |
| 75 if (_index == 0 && _buffer.first().length == remaining) { |
| 76 _length -= remaining; |
| 77 return _buffer.removeFirst(); |
| 78 } |
| 79 |
| 80 result = createIntArray(remaining); |
| 81 int cursor = 0; |
| 82 while (remaining > 0) { |
| 83 int bytesInFirst = _buffer.first().length - _index; |
| 84 if (bytesInFirst <= remaining) { |
| 85 result.setRange(cursor, |
| 86 bytesInFirst, |
| 87 _buffer.first(), |
| 88 _index); |
| 89 _buffer.removeFirst(); |
| 90 _index = 0; |
| 91 _length -= bytesInFirst; |
| 92 cursor += bytesInFirst; |
| 93 remaining -= bytesInFirst; |
| 94 } else { |
| 95 result.setRange(cursor, |
| 96 remaining, |
| 97 _buffer.first(), |
| 98 _index); |
| 99 _index += remaining; |
| 100 _length -= remaining; |
| 101 remaining = 0; |
| 102 _updateBuffers(); |
| 103 assert(_index < _buffer.first().length); |
| 104 } |
| 105 } |
| 106 return result; |
| 107 } |
| 108 |
| 109 /** |
| 110 * Return the length (remaining bytes available). |
| 111 */ |
| 112 int get length() => _length; |
| 113 |
| 114 /** |
| 115 * Return true if no more data is available in the buffer. |
| 116 */ |
| 117 bool get isEmpty() { |
| 118 return _buffer.isEmpty(); |
| 119 } |
| 120 |
| 121 /** |
| 122 * Provide the remainder of the byte buffer as a list. |
| 123 */ |
| 124 List<int> toList() => readBytes(length); |
| 125 |
| 126 void _updateBuffers() { |
| 127 while (!_buffer.isEmpty() && _index == _buffer.first().length) { |
| 128 _buffer.removeFirst(); |
| 129 _index = 0; |
| 130 } |
| 131 } |
| 132 |
| 133 /** |
| 134 * Data structure for buffered bytes. |
| 135 */ |
| 136 Queue<List<int>> _buffer; |
| 137 |
| 138 /** |
| 139 * Index within the current buffer ([List<int>]). |
| 140 */ |
| 141 int _index = 0; |
| 142 |
| 143 /** |
| 144 * Total number of bytes remaining in buffers. |
| 145 */ |
| 146 int _length = 0; |
| 147 } |
OLD | NEW |