• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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