1// Copyright 2013 The Flutter Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5part of engine; 6 7/// Write-only buffer for incrementally building a [ByteData] instance. 8/// 9/// A WriteBuffer instance can be used only once. Attempts to reuse will result 10/// in [NoSuchMethodError]s being thrown. 11/// 12/// The byte order used is [Endian.host] throughout. 13class WriteBuffer { 14 /// Creates an interface for incrementally building a [ByteData] instance. 15 WriteBuffer() { 16 _buffer = Uint8Buffer(); 17 _eightBytes = ByteData(8); 18 _eightBytesAsList = _eightBytes.buffer.asUint8List(); 19 } 20 21 Uint8Buffer _buffer; 22 ByteData _eightBytes; 23 Uint8List _eightBytesAsList; 24 25 /// Write a Uint8 into the buffer. 26 void putUint8(int byte) { 27 _buffer.add(byte); 28 } 29 30 /// Write a Uint16 into the buffer. 31 void putUint16(int value) { 32 _eightBytes.setUint16(0, value, Endian.host); 33 _buffer.addAll(_eightBytesAsList, 0, 2); 34 } 35 36 /// Write a Uint32 into the buffer. 37 void putUint32(int value) { 38 _eightBytes.setUint32(0, value, Endian.host); 39 _buffer.addAll(_eightBytesAsList, 0, 4); 40 } 41 42 /// Write an Int32 into the buffer. 43 void putInt32(int value) { 44 _eightBytes.setInt32(0, value, Endian.host); 45 _buffer.addAll(_eightBytesAsList, 0, 4); 46 } 47 48 /// Write an Int64 into the buffer. 49 void putInt64(int value) { 50 _eightBytes.setInt64(0, value, Endian.host); 51 _buffer.addAll(_eightBytesAsList, 0, 8); 52 } 53 54 /// Write an Float64 into the buffer. 55 void putFloat64(double value) { 56 _alignTo(8); 57 _eightBytes.setFloat64(0, value, Endian.host); 58 _buffer.addAll(_eightBytesAsList); 59 } 60 61 /// Write all the values from a [Uint8List] into the buffer. 62 void putUint8List(Uint8List list) { 63 _buffer.addAll(list); 64 } 65 66 /// Write all the values from a [Int32List] into the buffer. 67 void putInt32List(Int32List list) { 68 _alignTo(4); 69 _buffer 70 .addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length)); 71 } 72 73 /// Write all the values from an [Int64List] into the buffer. 74 void putInt64List(Int64List list) { 75 _alignTo(8); 76 _buffer 77 .addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); 78 } 79 80 /// Write all the values from a [Float64List] into the buffer. 81 void putFloat64List(Float64List list) { 82 _alignTo(8); 83 _buffer 84 .addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); 85 } 86 87 void _alignTo(int alignment) { 88 final int mod = _buffer.length % alignment; 89 if (mod != 0) { 90 for (int i = 0; i < alignment - mod; i++) { 91 _buffer.add(0); 92 } 93 } 94 } 95 96 /// Finalize and return the written [ByteData]. 97 ByteData done() { 98 final ByteData result = _buffer.buffer.asByteData(0, _buffer.lengthInBytes); 99 _buffer = null; 100 return result; 101 } 102} 103 104/// Read-only buffer for reading sequentially from a [ByteData] instance. 105/// 106/// The byte order used is [Endian.host] throughout. 107class ReadBuffer { 108 /// Creates a [ReadBuffer] for reading from the specified [data]. 109 ReadBuffer(this.data) : assert(data != null); 110 111 /// The underlying data being read. 112 final ByteData data; 113 114 /// The position to read next. 115 int _position = 0; 116 117 /// Whether the buffer has data remaining to read. 118 bool get hasRemaining => _position < data.lengthInBytes; 119 120 /// Reads a Uint8 from the buffer. 121 int getUint8() { 122 return data.getUint8(_position++); 123 } 124 125 /// Reads a Uint16 from the buffer. 126 int getUint16() { 127 final int value = data.getUint16(_position, Endian.host); 128 _position += 2; 129 return value; 130 } 131 132 /// Reads a Uint32 from the buffer. 133 int getUint32() { 134 final int value = data.getUint32(_position, Endian.host); 135 _position += 4; 136 return value; 137 } 138 139 /// Reads an Int32 from the buffer. 140 int getInt32() { 141 final int value = data.getInt32(_position, Endian.host); 142 _position += 4; 143 return value; 144 } 145 146 /// Reads an Int64 from the buffer. 147 int getInt64() { 148 final int value = data.getInt64(_position, Endian.host); 149 _position += 8; 150 return value; 151 } 152 153 /// Reads a Float64 from the buffer. 154 double getFloat64() { 155 _alignTo(8); 156 final double value = data.getFloat64(_position, Endian.host); 157 _position += 8; 158 return value; 159 } 160 161 /// Reads the given number of Uint8s from the buffer. 162 Uint8List getUint8List(int length) { 163 final Uint8List list = 164 data.buffer.asUint8List(data.offsetInBytes + _position, length); 165 _position += length; 166 return list; 167 } 168 169 /// Reads the given number of Int32s from the buffer. 170 Int32List getInt32List(int length) { 171 _alignTo(4); 172 final Int32List list = 173 data.buffer.asInt32List(data.offsetInBytes + _position, length); 174 _position += 4 * length; 175 return list; 176 } 177 178 /// Reads the given number of Int64s from the buffer. 179 Int64List getInt64List(int length) { 180 _alignTo(8); 181 final Int64List list = 182 data.buffer.asInt64List(data.offsetInBytes + _position, length); 183 _position += 8 * length; 184 return list; 185 } 186 187 /// Reads the given number of Float64s from the buffer. 188 Float64List getFloat64List(int length) { 189 _alignTo(8); 190 final Float64List list = 191 data.buffer.asFloat64List(data.offsetInBytes + _position, length); 192 _position += 8 * length; 193 return list; 194 } 195 196 void _alignTo(int alignment) { 197 final int mod = _position % alignment; 198 if (mod != 0) { 199 _position += alignment - mod; 200 } 201 } 202} 203