blob: 91fd8affcac17db438919b2bc14143ef319ea7bd [file] [log] [blame]
part of archive;
class OutputStream {
int length;
final int byteOrder;
/**
* Create a byte buffer for writing.
*/
OutputStream({int size: _BLOCK_SIZE, this.byteOrder: LITTLE_ENDIAN}) :
_buffer = new Uint8List(size == null ? _BLOCK_SIZE : size),
length = 0;
/**
* Get the resulting bytes from the buffer.
*/
List<int> getBytes() {
return new Uint8List.view(_buffer.buffer, 0, length);
}
/**
* Clear the buffer.
*/
void clear() {
_buffer = new Uint8List(_BLOCK_SIZE);
length = 0;
}
/**
* Reset the buffer.
*/
void reset() {
length = 0;
}
/**
* Write a byte to the end of the buffer.
*/
void writeByte(int value) {
if (length == _buffer.length) {
_expandBuffer();
}
_buffer[length++] = value & 0xff;
}
/**
* Write a set of bytes to the end of the buffer.
*/
void writeBytes(List<int> bytes, [int len]) {
if (len == null) {
len = bytes.length;
}
while (length + len > _buffer.length) {
_expandBuffer((length + len) - _buffer.length);
}
_buffer.setRange(length, length + len, bytes);
length += len;
}
void writeInputStream(InputStream bytes) {
while (length + bytes.length > _buffer.length) {
_expandBuffer((length + bytes.length) - _buffer.length);
}
_buffer.setRange(length, length + bytes.length, bytes.buffer, bytes.offset);
length += bytes.length;
}
/**
* Write a 16-bit word to the end of the buffer.
*/
void writeUint16(int value) {
if (byteOrder == BIG_ENDIAN) {
writeByte((value >> 8) & 0xff);
writeByte((value) & 0xff);
return;
}
writeByte((value) & 0xff);
writeByte((value >> 8) & 0xff);
}
/**
* Write a 32-bit word to the end of the buffer.
*/
void writeUint32(int value) {
if (byteOrder == BIG_ENDIAN) {
writeByte((value >> 24) & 0xff);
writeByte((value >> 16) & 0xff);
writeByte((value >> 8) & 0xff);
writeByte((value) & 0xff);
return;
}
writeByte((value) & 0xff);
writeByte((value >> 8) & 0xff);
writeByte((value >> 16) & 0xff);
writeByte((value >> 24) & 0xff);
}
/**
* Return the subset of the buffer in the range [start:end].
* If [start] or [end] are < 0 then it is relative to the end of the buffer.
* If [end] is not specified (or null), then it is the end of the buffer.
* This is equivalent to the python list range operator.
*/
List<int> subset(int start, [int end]) {
if (start < 0) {
start = (length) + start;
}
if (end == null) {
end = length;
} else if (end < 0) {
end = length + end;
}
return new Uint8List.view(_buffer.buffer, start, end - start);
}
/**
* Grow the buffer to accommodate additional data.
*/
void _expandBuffer([int required]) {
int blockSize = _BLOCK_SIZE;
if (required != null) {
if (required > blockSize) {
blockSize = required;
}
}
int newLength = (_buffer.length + blockSize) * 2;
Uint8List newBuffer = new Uint8List(newLength);
newBuffer.setRange(0, _buffer.length, _buffer);
_buffer = newBuffer;
}
static const int _BLOCK_SIZE = 0x8000; // 32k block-size
Uint8List _buffer;
}