Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: packages/analyzer/lib/src/summary/flat_buffers.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, 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 library analyzer.src.summary.flat_buffers;
6
7 import 'dart:collection';
8 import 'dart:convert';
9 import 'dart:math';
10 import 'dart:typed_data';
11
12 /**
13 * Reader of lists of boolean values.
14 *
15 * The returned unmodifiable lists lazily read values on access.
16 */
17 class BoolListReader extends Reader<List<bool>> {
18 const BoolListReader();
19
20 @override
21 int get size => 4;
22
23 @override
24 List<bool> read(BufferContext bc, int offset) =>
25 new _FbBoolList(bc, bc.derefObject(offset));
26 }
27
28 /**
29 * The reader of booleans.
30 */
31 class BoolReader extends Reader<bool> {
32 const BoolReader() : super();
33
34 @override
35 int get size => 1;
36
37 @override
38 bool read(BufferContext bc, int offset) => bc._getInt8(offset) != 0;
39 }
40
41 /**
42 * Buffer with data and some context about it.
43 */
44 class BufferContext {
45 final ByteData _buffer;
46
47 factory BufferContext.fromBytes(List<int> byteList) {
48 Uint8List uint8List = _asUint8List(byteList);
49 ByteData buf = new ByteData.view(uint8List.buffer, uint8List.offsetInBytes);
50 return new BufferContext._(buf);
51 }
52
53 BufferContext._(this._buffer);
54
55 int derefObject(int offset) {
56 return offset + _getUint32(offset);
57 }
58
59 Uint8List _asUint8LIst(int offset, int length) =>
60 _buffer.buffer.asUint8List(_buffer.offsetInBytes + offset, length);
61
62 double _getFloat64(int offset) =>
63 _buffer.getFloat64(offset, Endianness.LITTLE_ENDIAN);
64
65 int _getInt32(int offset) =>
66 _buffer.getInt32(offset, Endianness.LITTLE_ENDIAN);
67
68 int _getInt8(int offset) => _buffer.getInt8(offset);
69
70 int _getUint16(int offset) =>
71 _buffer.getUint16(offset, Endianness.LITTLE_ENDIAN);
72
73 int _getUint32(int offset) =>
74 _buffer.getUint32(offset, Endianness.LITTLE_ENDIAN);
75
76 int _getUint8(int offset) => _buffer.getUint8(offset);
77
78 /**
79 * If the [byteList] is already a [Uint8List] return it.
80 * Otherwise return a [Uint8List] copy of the [byteList].
81 */
82 static Uint8List _asUint8List(List<int> byteList) {
83 if (byteList is Uint8List) {
84 return byteList;
85 } else {
86 return new Uint8List.fromList(byteList);
87 }
88 }
89 }
90
91 /**
92 * Class that helps building flat buffers.
93 */
94 class Builder {
95 final int initialSize;
96
97 /**
98 * The list of existing VTable(s).
99 */
100 final List<_VTable> _vTables = <_VTable>[];
101
102 ByteData _buf;
103
104 /**
105 * The maximum alignment that has been seen so far. If [_buf] has to be
106 * reallocated in the future (to insert room at its start for more bytes) the
107 * reallocation will need to be a multiple of this many bytes.
108 */
109 int _maxAlign;
110
111 /**
112 * The number of bytes that have been written to the buffer so far. The
113 * most recently written byte is this many bytes from the end of [_buf].
114 */
115 int _tail;
116
117 /**
118 * The location of the end of the current table, measured in bytes from the
119 * end of [_buf], or `null` if a table is not currently being built.
120 */
121 int _currentTableEndTail;
122
123 _VTable _currentVTable;
124
125 /**
126 * Map containing all strings that have been written so far. This allows us
127 * to avoid duplicating strings.
128 */
129 Map<String, Offset<String>> _strings = <String, Offset<String>>{};
130
131 Builder({this.initialSize: 1024}) {
132 reset();
133 }
134
135 /**
136 * Add the [field] with the given boolean [value]. The field is not added if
137 * the [value] is equal to [def]. Booleans are stored as 8-bit fields with
138 * `0` for `false` and `1` for `true`.
139 */
140 void addBool(int field, bool value, [bool def]) {
141 _ensureCurrentVTable();
142 if (value != null && value != def) {
143 int size = 1;
144 _prepare(size, 1);
145 _trackField(field);
146 _buf.setInt8(_buf.lengthInBytes - _tail, value ? 1 : 0);
147 }
148 }
149
150 /**
151 * Add the [field] with the given 32-bit signed integer [value]. The field is
152 * not added if the [value] is equal to [def].
153 */
154 void addInt32(int field, int value, [int def]) {
155 _ensureCurrentVTable();
156 if (value != null && value != def) {
157 int size = 4;
158 _prepare(size, 1);
159 _trackField(field);
160 _setInt32AtTail(_buf, _tail, value);
161 }
162 }
163
164 /**
165 * Add the [field] with the given 8-bit signed integer [value]. The field is
166 * not added if the [value] is equal to [def].
167 */
168 void addInt8(int field, int value, [int def]) {
169 _ensureCurrentVTable();
170 if (value != null && value != def) {
171 int size = 1;
172 _prepare(size, 1);
173 _trackField(field);
174 _buf.setInt8(_buf.lengthInBytes - _tail, value);
175 }
176 }
177
178 /**
179 * Add the [field] referencing an object with the given [offset].
180 */
181 void addOffset(int field, Offset offset) {
182 _ensureCurrentVTable();
183 if (offset != null) {
184 _prepare(4, 1);
185 _trackField(field);
186 _setUint32AtTail(_buf, _tail, _tail - offset._tail);
187 }
188 }
189
190 /**
191 * Add the [field] with the given 32-bit unsigned integer [value]. The field
192 * is not added if the [value] is equal to [def].
193 */
194 void addUint32(int field, int value, [int def]) {
195 _ensureCurrentVTable();
196 if (value != null && value != def) {
197 int size = 4;
198 _prepare(size, 1);
199 _trackField(field);
200 _setUint32AtTail(_buf, _tail, value);
201 }
202 }
203
204 /**
205 * Add the [field] with the given 8-bit unsigned integer [value]. The field
206 * is not added if the [value] is equal to [def].
207 */
208 void addUint8(int field, int value, [int def]) {
209 _ensureCurrentVTable();
210 if (value != null && value != def) {
211 int size = 1;
212 _prepare(size, 1);
213 _trackField(field);
214 _setUint8AtTail(_buf, _tail, value);
215 }
216 }
217
218 /**
219 * End the current table and return its offset.
220 */
221 Offset endTable() {
222 if (_currentVTable == null) {
223 throw new StateError('Start a table before ending it.');
224 }
225 // Prepare for writing the VTable.
226 _prepare(4, 1);
227 int tableTail = _tail;
228 // Prepare the size of the current table.
229 _currentVTable.tableSize = tableTail - _currentTableEndTail;
230 // Prepare the VTable to use for the current table.
231 int vTableTail;
232 {
233 _currentVTable.computeFieldOffsets(tableTail);
234 // Try to find an existing compatible VTable.
235 for (int i = 0; i < _vTables.length; i++) {
236 _VTable vTable = _vTables[i];
237 if (_currentVTable.canUseExistingVTable(vTable)) {
238 vTableTail = vTable.tail;
239 break;
240 }
241 }
242 // Write a new VTable.
243 if (vTableTail == null) {
244 _prepare(2, _currentVTable.numOfUint16);
245 vTableTail = _tail;
246 _currentVTable.tail = vTableTail;
247 _currentVTable.output(_buf, _buf.lengthInBytes - _tail);
248 _vTables.add(_currentVTable);
249 }
250 }
251 // Set the VTable offset.
252 _setInt32AtTail(_buf, tableTail, vTableTail - tableTail);
253 // Done with this table.
254 _currentVTable = null;
255 return new Offset(tableTail);
256 }
257
258 /**
259 * Finish off the creation of the buffer. The given [offset] is used as the
260 * root object offset, and usually references directly or indirectly every
261 * written object. If [fileIdentifier] is specified (and not `null`), it is
262 * interpreted as a 4-byte Latin-1 encoded string that should be placed at
263 * bytes 4-7 of the file.
264 */
265 Uint8List finish(Offset offset, [String fileIdentifier]) {
266 _prepare(max(4, _maxAlign), fileIdentifier == null ? 1 : 2);
267 int alignedTail = _tail + ((-_tail) % _maxAlign);
268 _setUint32AtTail(_buf, alignedTail, alignedTail - offset._tail);
269 if (fileIdentifier != null) {
270 for (int i = 0; i < 4; i++) {
271 _setUint8AtTail(
272 _buf, alignedTail - 4 - i, fileIdentifier.codeUnitAt(i));
273 }
274 }
275 return _buf.buffer.asUint8List(_buf.lengthInBytes - alignedTail);
276 }
277
278 /**
279 * This is a low-level method, it should not be invoked by clients.
280 */
281 Uint8List lowFinish() {
282 int alignedTail = _tail + ((-_tail) % _maxAlign);
283 return _buf.buffer.asUint8List(_buf.lengthInBytes - alignedTail);
284 }
285
286 /**
287 * This is a low-level method, it should not be invoked by clients.
288 */
289 void lowReset() {
290 _buf = new ByteData(initialSize);
291 _maxAlign = 1;
292 _tail = 0;
293 }
294
295 /**
296 * This is a low-level method, it should not be invoked by clients.
297 */
298 void lowWriteUint32(int value) {
299 _prepare(4, 1);
300 _setUint32AtTail(_buf, _tail, value);
301 }
302
303 /**
304 * This is a low-level method, it should not be invoked by clients.
305 */
306 void lowWriteUint8(int value) {
307 _prepare(1, 1);
308 _buf.setUint8(_buf.lengthInBytes - _tail, value);
309 }
310
311 /**
312 * Reset the builder and make it ready for filling a new buffer.
313 */
314 void reset() {
315 _buf = new ByteData(initialSize);
316 _maxAlign = 1;
317 _tail = 0;
318 _currentVTable = null;
319 }
320
321 /**
322 * Start a new table. Must be finished with [endTable] invocation.
323 */
324 void startTable() {
325 if (_currentVTable != null) {
326 throw new StateError('Inline tables are not supported.');
327 }
328 _currentVTable = new _VTable();
329 _currentTableEndTail = _tail;
330 }
331
332 /**
333 * Write the given list of [values].
334 */
335 Offset writeList(List<Offset> values) {
336 _ensureNoVTable();
337 _prepare(4, 1 + values.length);
338 Offset result = new Offset(_tail);
339 int tail = _tail;
340 _setUint32AtTail(_buf, tail, values.length);
341 tail -= 4;
342 for (Offset value in values) {
343 _setUint32AtTail(_buf, tail, tail - value._tail);
344 tail -= 4;
345 }
346 return result;
347 }
348
349 /**
350 * Write the given list of boolean [values].
351 */
352 Offset writeListBool(List<bool> values) {
353 int bitLength = values.length;
354 int padding = (-bitLength) % 8;
355 int byteLength = (bitLength + padding) ~/ 8;
356 // Prepare the backing Uint8List.
357 Uint8List bytes = new Uint8List(byteLength + 1);
358 // Record every bit.
359 int byteIndex = 0;
360 int byte = 0;
361 int mask = 1;
362 for (int bitIndex = 0; bitIndex < bitLength; bitIndex++) {
363 if (bitIndex != 0 && (bitIndex % 8 == 0)) {
364 bytes[byteIndex++] = byte;
365 byte = 0;
366 mask = 1;
367 }
368 if (values[bitIndex]) {
369 byte |= mask;
370 }
371 mask <<= 1;
372 }
373 // Write the last byte, even if it may be on the padding.
374 bytes[byteIndex] = byte;
375 // Write the padding length.
376 bytes[byteLength] = padding;
377 // Write as a Uint8 list.
378 return writeListUint8(bytes);
379 }
380
381 /**
382 * Write the given list of 64-bit float [values].
383 */
384 Offset writeListFloat64(List<double> values) {
385 _ensureNoVTable();
386 _prepare(8, 1 + values.length);
387 Offset result = new Offset(_tail);
388 int tail = _tail;
389 _setUint32AtTail(_buf, tail, values.length);
390 tail -= 8;
391 for (double value in values) {
392 _setFloat64AtTail(_buf, tail, value);
393 tail -= 8;
394 }
395 return result;
396 }
397
398 /**
399 * Write the given list of signed 32-bit integer [values].
400 */
401 Offset writeListInt32(List<int> values) {
402 _ensureNoVTable();
403 _prepare(4, 1 + values.length);
404 Offset result = new Offset(_tail);
405 int tail = _tail;
406 _setUint32AtTail(_buf, tail, values.length);
407 tail -= 4;
408 for (int value in values) {
409 _setInt32AtTail(_buf, tail, value);
410 tail -= 4;
411 }
412 return result;
413 }
414
415 /**
416 * Write the given list of unsigned 32-bit integer [values].
417 */
418 Offset writeListUint32(List<int> values) {
419 _ensureNoVTable();
420 _prepare(4, 1 + values.length);
421 Offset result = new Offset(_tail);
422 int tail = _tail;
423 _setUint32AtTail(_buf, tail, values.length);
424 tail -= 4;
425 for (int value in values) {
426 _setUint32AtTail(_buf, tail, value);
427 tail -= 4;
428 }
429 return result;
430 }
431
432 /**
433 * Write the given list of unsigned 8-bit integer [values].
434 */
435 Offset writeListUint8(List<int> values) {
436 _ensureNoVTable();
437 _prepare(4, 1, additionalBytes: values.length);
438 Offset result = new Offset(_tail);
439 int tail = _tail;
440 _setUint32AtTail(_buf, tail, values.length);
441 tail -= 4;
442 for (int value in values) {
443 _setUint8AtTail(_buf, tail, value);
444 tail -= 1;
445 }
446 return result;
447 }
448
449 /**
450 * Write the given string [value] and return its [Offset], or `null` if
451 * the [value] is equal to [def].
452 */
453 Offset<String> writeString(String value, [String def]) {
454 _ensureNoVTable();
455 if (value != def) {
456 return _strings.putIfAbsent(value, () {
457 // TODO(scheglov) optimize for ASCII strings
458 List<int> bytes = UTF8.encode(value);
459 int length = bytes.length;
460 _prepare(4, 1, additionalBytes: length);
461 Offset<String> result = new Offset(_tail);
462 _setUint32AtTail(_buf, _tail, length);
463 int offset = _buf.lengthInBytes - _tail + 4;
464 for (int i = 0; i < length; i++) {
465 _buf.setUint8(offset++, bytes[i]);
466 }
467 return result;
468 });
469 }
470 return null;
471 }
472
473 /**
474 * Throw an exception if there is not currently a vtable.
475 */
476 void _ensureCurrentVTable() {
477 if (_currentVTable == null) {
478 throw new StateError('Start a table before adding values.');
479 }
480 }
481
482 /**
483 * Throw an exception if there is currently a vtable.
484 */
485 void _ensureNoVTable() {
486 if (_currentVTable != null) {
487 throw new StateError(
488 'Cannot write a non-scalar value while writing a table.');
489 }
490 }
491
492 /**
493 * Prepare for writing the given [count] of scalars of the given [size].
494 * Additionally allocate the specified [additionalBytes]. Update the current
495 * tail pointer to point at the allocated space.
496 */
497 void _prepare(int size, int count, {int additionalBytes: 0}) {
498 // Update the alignment.
499 if (_maxAlign < size) {
500 _maxAlign = size;
501 }
502 // Prepare amount of required space.
503 int dataSize = size * count + additionalBytes;
504 int alignDelta = (-(_tail + dataSize)) % size;
505 int bufSize = alignDelta + dataSize;
506 // Ensure that we have the required amount of space.
507 {
508 int oldCapacity = _buf.lengthInBytes;
509 if (_tail + bufSize > oldCapacity) {
510 int desiredNewCapacity = (oldCapacity + bufSize) * 2;
511 int deltaCapacity = desiredNewCapacity - oldCapacity;
512 deltaCapacity += (-deltaCapacity) % _maxAlign;
513 int newCapacity = oldCapacity + deltaCapacity;
514 ByteData newBuf = new ByteData(newCapacity);
515 newBuf.buffer
516 .asUint8List()
517 .setAll(deltaCapacity, _buf.buffer.asUint8List());
518 _buf = newBuf;
519 }
520 }
521 // Update the tail pointer.
522 _tail += bufSize;
523 }
524
525 /**
526 * Record the offset of the given [field].
527 */
528 void _trackField(int field) {
529 _currentVTable.addField(field, _tail);
530 }
531
532 static void _setFloat64AtTail(ByteData _buf, int tail, double x) {
533 _buf.setFloat64(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
534 }
535
536 static void _setInt32AtTail(ByteData _buf, int tail, int x) {
537 _buf.setInt32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
538 }
539
540 static void _setUint32AtTail(ByteData _buf, int tail, int x) {
541 _buf.setUint32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
542 }
543
544 static void _setUint8AtTail(ByteData _buf, int tail, int x) {
545 _buf.setUint8(_buf.lengthInBytes - tail, x);
546 }
547 }
548
549 /**
550 * The reader of lists of 64-bit float values.
551 *
552 * The returned unmodifiable lists lazily read values on access.
553 */
554 class Float64ListReader extends Reader<List<double>> {
555 const Float64ListReader();
556
557 @override
558 int get size => 4;
559
560 @override
561 List<double> read(BufferContext bc, int offset) =>
562 new _FbFloat64List(bc, bc.derefObject(offset));
563 }
564
565 /**
566 * The reader of signed 32-bit integers.
567 */
568 class Int32Reader extends Reader<int> {
569 const Int32Reader() : super();
570
571 @override
572 int get size => 4;
573
574 @override
575 int read(BufferContext bc, int offset) => bc._getInt32(offset);
576 }
577
578 /**
579 * The reader of 8-bit signed integers.
580 */
581 class Int8Reader extends Reader<int> {
582 const Int8Reader() : super();
583
584 @override
585 int get size => 1;
586
587 @override
588 int read(BufferContext bc, int offset) => bc._getInt8(offset);
589 }
590
591 /**
592 * The reader of lists of objects.
593 *
594 * The returned unmodifiable lists lazily read objects on access.
595 */
596 class ListReader<E> extends Reader<List<E>> {
597 final Reader<E> _elementReader;
598
599 const ListReader(this._elementReader);
600
601 @override
602 int get size => 4;
603
604 @override
605 List<E> read(BufferContext bc, int offset) =>
606 new _FbGenericList<E>(_elementReader, bc, bc.derefObject(offset));
607 }
608
609 /**
610 * The offset from the end of the buffer to a serialized object of the type [T].
611 */
612 class Offset<T> {
613 final int _tail;
614
615 Offset(this._tail);
616 }
617
618 /**
619 * Object that can read a value at a [BufferContext].
620 */
621 abstract class Reader<T> {
622 const Reader();
623
624 /**
625 * The size of the value in bytes.
626 */
627 int get size;
628
629 /**
630 * Read the value at the given [offset] in [bc].
631 */
632 T read(BufferContext bc, int offset);
633
634 /**
635 * Read the value of the given [field] in the given [object].
636 */
637 T vTableGet(BufferContext object, int offset, int field, [T defaultValue]) {
638 int vTableSOffset = object._getInt32(offset);
639 int vTableOffset = offset - vTableSOffset;
640 int vTableSize = object._getUint16(vTableOffset);
641 int vTableFieldOffset = (1 + 1 + field) * 2;
642 if (vTableFieldOffset < vTableSize) {
643 int fieldOffsetInObject =
644 object._getUint16(vTableOffset + vTableFieldOffset);
645 if (fieldOffsetInObject != 0) {
646 return read(object, offset + fieldOffsetInObject);
647 }
648 }
649 return defaultValue;
650 }
651 }
652
653 /**
654 * The reader of string values.
655 */
656 class StringReader extends Reader<String> {
657 const StringReader() : super();
658
659 @override
660 int get size => 4;
661
662 @override
663 String read(BufferContext bc, int offset) {
664 int strOffset = bc.derefObject(offset);
665 int length = bc._getUint32(strOffset);
666 Uint8List bytes = bc._asUint8LIst(strOffset + 4, length);
667 if (_isLatin(bytes)) {
668 return new String.fromCharCodes(bytes);
669 }
670 return UTF8.decode(bytes);
671 }
672
673 static bool _isLatin(Uint8List bytes) {
674 int length = bytes.length;
675 for (int i = 0; i < length; i++) {
676 if (bytes[i] > 127) {
677 return false;
678 }
679 }
680 return true;
681 }
682 }
683
684 /**
685 * An abstract reader for tables.
686 */
687 abstract class TableReader<T> extends Reader<T> {
688 const TableReader();
689
690 @override
691 int get size => 4;
692
693 /**
694 * Return the object at [offset].
695 */
696 T createObject(BufferContext bc, int offset);
697
698 @override
699 T read(BufferContext bp, int offset) {
700 int objectOffset = bp.derefObject(offset);
701 return createObject(bp, objectOffset);
702 }
703 }
704
705 /**
706 * Reader of lists of unsigned 32-bit integer values.
707 *
708 * The returned unmodifiable lists lazily read values on access.
709 */
710 class Uint32ListReader extends Reader<List<int>> {
711 const Uint32ListReader();
712
713 @override
714 int get size => 4;
715
716 @override
717 List<int> read(BufferContext bc, int offset) =>
718 new _FbUint32List(bc, bc.derefObject(offset));
719 }
720
721 /**
722 * The reader of unsigned 32-bit integers.
723 */
724 class Uint32Reader extends Reader<int> {
725 const Uint32Reader() : super();
726
727 @override
728 int get size => 4;
729
730 @override
731 int read(BufferContext bc, int offset) => bc._getUint32(offset);
732 }
733
734 /**
735 * Reader of lists of unsigned 8-bit integer values.
736 *
737 * The returned unmodifiable lists lazily read values on access.
738 */
739 class Uint8ListReader extends Reader<List<int>> {
740 const Uint8ListReader();
741
742 @override
743 int get size => 4;
744
745 @override
746 List<int> read(BufferContext bc, int offset) =>
747 new _FbUint8List(bc, bc.derefObject(offset));
748 }
749
750 /**
751 * The reader of unsigned 8-bit integers.
752 */
753 class Uint8Reader extends Reader<int> {
754 const Uint8Reader() : super();
755
756 @override
757 int get size => 1;
758
759 @override
760 int read(BufferContext bc, int offset) => bc._getUint8(offset);
761 }
762
763 /**
764 * List of booleans backed by 8-bit unsigned integers.
765 */
766 class _FbBoolList extends Object with ListMixin<bool> implements List<bool> {
767 final BufferContext bc;
768 final int offset;
769 int _length;
770
771 _FbBoolList(this.bc, this.offset);
772
773 @override
774 int get length {
775 if (_length == null) {
776 int byteLength = bc._getUint32(offset);
777 _length = (byteLength - 1) * 8 - _getByte(byteLength - 1);
778 }
779 return _length;
780 }
781
782 @override
783 void set length(int i) =>
784 throw new StateError('Attempt to modify immutable list');
785
786 @override
787 bool operator [](int i) {
788 int index = i ~/ 8;
789 int mask = 1 << i % 8;
790 return _getByte(index) & mask != 0;
791 }
792
793 @override
794 void operator []=(int i, bool e) =>
795 throw new StateError('Attempt to modify immutable list');
796
797 int _getByte(int index) => bc._getUint8(offset + 4 + index);
798 }
799
800 /**
801 * The list backed by 64-bit values - Uint64 length and Float64.
802 */
803 class _FbFloat64List extends _FbList<double> {
804 _FbFloat64List(BufferContext bc, int offset) : super(bc, offset);
805
806 @override
807 double operator [](int i) {
808 return bc._getFloat64(offset + 8 + 8 * i);
809 }
810 }
811
812 /**
813 * List backed by a generic object which may have any size.
814 */
815 class _FbGenericList<E> extends _FbList<E> {
816 final Reader<E> elementReader;
817
818 List<E> _items;
819
820 _FbGenericList(this.elementReader, BufferContext bp, int offset)
821 : super(bp, offset);
822
823 @override
824 E operator [](int i) {
825 _items ??= new List<E>(length);
826 E item = _items[i];
827 if (item == null) {
828 item = elementReader.read(bc, offset + 4 + elementReader.size * i);
829 _items[i] = item;
830 }
831 return item;
832 }
833 }
834
835 /**
836 * The base class for immutable lists read from flat buffers.
837 */
838 abstract class _FbList<E> extends Object with ListMixin<E> implements List<E> {
839 final BufferContext bc;
840 final int offset;
841 int _length;
842
843 _FbList(this.bc, this.offset);
844
845 @override
846 int get length {
847 _length ??= bc._getUint32(offset);
848 return _length;
849 }
850
851 @override
852 void set length(int i) =>
853 throw new StateError('Attempt to modify immutable list');
854
855 @override
856 void operator []=(int i, E e) =>
857 throw new StateError('Attempt to modify immutable list');
858 }
859
860 /**
861 * List backed by 32-bit unsigned integers.
862 */
863 class _FbUint32List extends _FbList<int> {
864 _FbUint32List(BufferContext bc, int offset) : super(bc, offset);
865
866 @override
867 int operator [](int i) {
868 return bc._getUint32(offset + 4 + 4 * i);
869 }
870 }
871
872 /**
873 * List backed by 8-bit unsigned integers.
874 */
875 class _FbUint8List extends _FbList<int> {
876 _FbUint8List(BufferContext bc, int offset) : super(bc, offset);
877
878 @override
879 int operator [](int i) {
880 return bc._getUint8(offset + 4 + i);
881 }
882 }
883
884 /**
885 * Class that describes the structure of a table.
886 */
887 class _VTable {
888 final List<int> fieldTails = <int>[];
889 final List<int> fieldOffsets = <int>[];
890
891 /**
892 * The size of the table that uses this VTable.
893 */
894 int tableSize;
895
896 /**
897 * The tail of this VTable. It is used to share the same VTable between
898 * multiple tables of identical structure.
899 */
900 int tail;
901
902 int get numOfUint16 => 1 + 1 + fieldTails.length;
903
904 void addField(int field, int offset) {
905 while (fieldTails.length <= field) {
906 fieldTails.add(null);
907 }
908 fieldTails[field] = offset;
909 }
910
911 /**
912 * Return `true` if the [existing] VTable can be used instead of this.
913 */
914 bool canUseExistingVTable(_VTable existing) {
915 assert(tail == null);
916 assert(existing.tail != null);
917 if (tableSize == existing.tableSize &&
918 fieldOffsets.length == existing.fieldOffsets.length) {
919 for (int i = 0; i < fieldOffsets.length; i++) {
920 if (fieldOffsets[i] != existing.fieldOffsets[i]) {
921 return false;
922 }
923 }
924 return true;
925 }
926 return false;
927 }
928
929 /**
930 * Fill the [fieldOffsets] field.
931 */
932 void computeFieldOffsets(int tableTail) {
933 assert(fieldOffsets.isEmpty);
934 for (int fieldTail in fieldTails) {
935 int fieldOffset = fieldTail == null ? 0 : tableTail - fieldTail;
936 fieldOffsets.add(fieldOffset);
937 }
938 }
939
940 /**
941 * Outputs this VTable to [buf], which is is expected to be aligned to 16-bit
942 * and have at least [numOfUint16] 16-bit words available.
943 */
944 void output(ByteData buf, int bufOffset) {
945 // VTable size.
946 buf.setUint16(bufOffset, numOfUint16 * 2, Endianness.LITTLE_ENDIAN);
947 bufOffset += 2;
948 // Table size.
949 buf.setUint16(bufOffset, tableSize, Endianness.LITTLE_ENDIAN);
950 bufOffset += 2;
951 // Field offsets.
952 for (int fieldOffset in fieldOffsets) {
953 buf.setUint16(bufOffset, fieldOffset, Endianness.LITTLE_ENDIAN);
954 bufOffset += 2;
955 }
956 }
957 }
OLDNEW
« no previous file with comments | « packages/analyzer/lib/src/summary/bazel_summary.dart ('k') | packages/analyzer/lib/src/summary/format.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698