LCOV - code coverage report
Current view: top level - typed_data-1.3.0/lib/src - typed_queue.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 233 0.0 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2019, 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             : import "dart:collection";
       6             : import "dart:typed_data";
       7             : 
       8             : import "package:collection/collection.dart";
       9             : 
      10             : import 'typed_buffer.dart';
      11             : 
      12             : /// The shared superclass of all the typed queue subclasses.
      13             : abstract class _TypedQueue<E, L extends List<E>> with ListMixin<E> {
      14             :   /// The underlying data buffer.
      15             :   ///
      16             :   /// This is always both a List<E> and a TypedData, which we don't have a type
      17             :   /// for that. For example, for a `Uint8Queue`, this is a `Uint8List`.
      18             :   L _table;
      19             : 
      20             :   int _head;
      21             :   int _tail;
      22             : 
      23             :   /// Create an empty queue.
      24           0 :   _TypedQueue(List<E> table)
      25             :       : _table = table as L,
      26             :         _head = 0,
      27             :         _tail = 0;
      28             : 
      29             :   // Iterable interface.
      30             : 
      31           0 :   int get length => (_tail - _head) & (_table.length - 1);
      32             : 
      33           0 :   List<E> toList({bool growable = true}) {
      34           0 :     var list = growable ? _createBuffer(length) : _createList(length);
      35           0 :     _writeToList(list);
      36             :     return list;
      37             :   }
      38             : 
      39           0 :   QueueList<T> cast<T>() {
      40           0 :     if (this is QueueList<T>) return this as QueueList<T>;
      41           0 :     throw UnsupportedError("$this cannot be cast to the desired type.");
      42             :   }
      43             : 
      44           0 :   @deprecated
      45           0 :   QueueList<T> retype<T>() => cast<T>();
      46             : 
      47             :   // Queue interface.
      48             : 
      49           0 :   void addLast(E value) {
      50           0 :     _table[_tail] = value;
      51           0 :     _tail = (_tail + 1) & (_table.length - 1);
      52           0 :     if (_head == _tail) _growAtCapacity();
      53             :   }
      54             : 
      55           0 :   void addFirst(E value) {
      56           0 :     _head = (_head - 1) & (_table.length - 1);
      57           0 :     _table[_head] = value;
      58           0 :     if (_head == _tail) _growAtCapacity();
      59             :   }
      60             : 
      61           0 :   E removeFirst() {
      62           0 :     if (_head == _tail) throw StateError("No element");
      63           0 :     var result = _table[_head];
      64           0 :     _head = (_head + 1) & (_table.length - 1);
      65             :     return result;
      66             :   }
      67             : 
      68           0 :   E removeLast() {
      69           0 :     if (_head == _tail) throw StateError("No element");
      70           0 :     _tail = (_tail - 1) & (_table.length - 1);
      71           0 :     return _table[_tail];
      72             :   }
      73             : 
      74             :   // List interface.
      75             : 
      76           0 :   void add(E value) => addLast(value);
      77             : 
      78           0 :   set length(int value) {
      79           0 :     RangeError.checkNotNegative(value, "length");
      80             : 
      81           0 :     var delta = value - length;
      82           0 :     if (delta >= 0) {
      83           0 :       var needsToGrow = _table.length <= value;
      84           0 :       if (needsToGrow) _growTo(value);
      85           0 :       _tail = (_tail + delta) & (_table.length - 1);
      86             : 
      87             :       // If we didn't copy into a new table, make sure that we overwrite the
      88             :       // existing data so that users don't accidentally depend on it still
      89             :       // existing.
      90           0 :       if (!needsToGrow) fillRange(value - delta, value, _defaultValue);
      91             :     } else {
      92           0 :       removeRange(value, length);
      93             :     }
      94             :   }
      95             : 
      96           0 :   E operator [](int index) {
      97           0 :     RangeError.checkValidIndex(index, this, null, length);
      98           0 :     return _table[(_head + index) & (_table.length - 1)];
      99             :   }
     100             : 
     101           0 :   void operator []=(int index, E value) {
     102           0 :     RangeError.checkValidIndex(index, this);
     103           0 :     _table[(_head + index) & (_table.length - 1)] = value;
     104             :   }
     105             : 
     106           0 :   void removeRange(int start, int end) {
     107           0 :     var length = this.length;
     108           0 :     RangeError.checkValidRange(start, end, length);
     109             : 
     110             :     // Special-case removing an initial or final range because we can do it very
     111             :     // efficiently by adjusting `_head` or `_tail`.
     112           0 :     if (start == 0) {
     113           0 :       _head = (_head + end) & (_table.length - 1);
     114             :       return;
     115             :     }
     116             : 
     117           0 :     var elementsAfter = length - end;
     118           0 :     if (elementsAfter == 0) {
     119           0 :       _tail = (_head + start) & (_table.length - 1);
     120             :       return;
     121             :     }
     122             : 
     123             :     // Choose whether to copy from the beginning of the end of the queue based
     124             :     // on which will require fewer copied elements.
     125           0 :     var removedElements = end - start;
     126           0 :     if (start < elementsAfter) {
     127           0 :       setRange(removedElements, end, this);
     128           0 :       _head = (_head + removedElements) & (_table.length - 1);
     129             :     } else {
     130           0 :       setRange(start, length - removedElements, this, end);
     131           0 :       _tail = (_tail - removedElements) & (_table.length - 1);
     132             :     }
     133             :   }
     134             : 
     135           0 :   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     136           0 :     RangeError.checkValidRange(start, end, length);
     137           0 :     if (start == end) return;
     138             : 
     139           0 :     var targetStart = (_head + start) & (_table.length - 1);
     140           0 :     var targetEnd = (_head + end) & (_table.length - 1);
     141           0 :     var targetIsContiguous = targetStart < targetEnd;
     142             :     if (identical(iterable, this)) {
     143             :       // If we're copying this queue to itself, we can copy [_table] in directly
     144             :       // which requires some annoying case analysis but in return bottoms out on
     145             :       // an extremely efficient `memmove` call. However, we may need to do three
     146             :       // copies to avoid overwriting data we'll need to use later.
     147           0 :       var sourceStart = (_head + skipCount) & (_table.length - 1);
     148           0 :       var sourceEnd = (sourceStart + (end - start)) & (_table.length - 1);
     149           0 :       if (sourceStart == targetStart) return;
     150             : 
     151           0 :       var sourceIsContiguous = sourceStart < sourceEnd;
     152             :       if (targetIsContiguous && sourceIsContiguous) {
     153             :         // If both the source and destination ranges are contiguous, we can
     154             :         // do a single [setRange]. Hooray!
     155           0 :         _table.setRange(targetStart, targetEnd, _table, sourceStart);
     156             :       } else if (!targetIsContiguous && !sourceIsContiguous) {
     157             :         // If neither range is contiguous, we need to do three copies.
     158           0 :         if (sourceStart > targetStart) {
     159             :           // [=====| targetEnd                 targetStart |======]
     160             :           // [========| sourceEnd                 sourceStart |===]
     161             : 
     162             :           // Copy front to back.
     163           0 :           var startGap = sourceStart - targetStart;
     164           0 :           var firstEnd = _table.length - startGap;
     165           0 :           _table.setRange(targetStart, firstEnd, _table, sourceStart);
     166           0 :           _table.setRange(firstEnd, _table.length, _table);
     167           0 :           _table.setRange(0, targetEnd, _table, startGap);
     168           0 :         } else if (sourceEnd < targetEnd) {
     169             :           // [=====| targetEnd                 targetStart |======]
     170             :           // [==| sourceEnd                 sourceStart |=========]
     171             : 
     172             :           // Copy back to front.
     173           0 :           var firstStart = targetEnd - sourceEnd;
     174           0 :           _table.setRange(firstStart, targetEnd, _table);
     175           0 :           _table.setRange(0, firstStart, _table, _table.length - firstStart);
     176           0 :           _table.setRange(targetStart, _table.length, _table, sourceStart);
     177             :         }
     178           0 :       } else if (sourceStart < targetEnd) {
     179             :         // Copying twice is safe here as long as we copy front to back.
     180             :         if (sourceIsContiguous) {
     181             :           //       [=====| targetEnd            targetStart |======]
     182             :           //       [  |===========| sourceEnd                      ]
     183             :           // sourceStart
     184           0 :           _table.setRange(targetStart, _table.length, _table, sourceStart);
     185           0 :           _table.setRange(0, targetEnd, _table,
     186           0 :               sourceStart + (_table.length - targetStart));
     187             :         } else {
     188             :           //                                               targetEnd
     189             :           // [                         targetStart |===========|  ]
     190             :           // [=====| sourceEnd                 sourceStart |======]
     191           0 :           var firstEnd = _table.length - sourceStart;
     192           0 :           _table.setRange(targetStart, firstEnd, _table, sourceStart);
     193           0 :           _table.setRange(firstEnd, targetEnd, _table);
     194             :         }
     195             :       } else {
     196             :         // Copying twice is safe here as long as we copy back to front. This
     197             :         // also covers the case where there's no overlap between the source and
     198             :         // target ranges, in which case the direction doesn't matter.
     199             :         if (sourceIsContiguous) {
     200             :           // [=====| targetEnd                 targetStart |======]
     201             :           // [                         sourceStart |===========|  ]
     202             :           //                                             sourceEnd
     203           0 :           _table.setRange(0, targetEnd, _table,
     204           0 :               sourceStart + (_table.length - targetStart));
     205           0 :           _table.setRange(targetStart, _table.length, _table, sourceStart);
     206             :         } else {
     207             :           // targetStart
     208             :           //       [  |===========| targetEnd                      ]
     209             :           //       [=====| sourceEnd            sourceStart |======]
     210           0 :           var firstStart = targetEnd - sourceEnd;
     211           0 :           _table.setRange(firstStart, targetEnd, _table);
     212           0 :           _table.setRange(targetStart, firstStart, _table, sourceStart);
     213             :         }
     214             :       }
     215             :     } else if (targetIsContiguous) {
     216             :       // If the range is contiguous within the table, we can set it with a single
     217             :       // underlying [setRange] call.
     218           0 :       _table.setRange(targetStart, targetEnd, iterable, skipCount);
     219           0 :     } else if (iterable is List<E>) {
     220             :       // If the range isn't contiguous and [iterable] is actually a [List] (but
     221             :       // not this queue), set it with two underlying [setRange] calls.
     222           0 :       _table.setRange(targetStart, _table.length, iterable, skipCount);
     223           0 :       _table.setRange(
     224           0 :           0, targetEnd, iterable, skipCount + (_table.length - targetStart));
     225             :     } else {
     226             :       // If [iterable] isn't a [List], we don't want to make two different
     227             :       // [setRange] calls because it could materialize a lazy iterable twice.
     228             :       // Instead we just fall back to the default iteration-based
     229             :       // implementation.
     230           0 :       super.setRange(start, end, iterable, skipCount);
     231             :     }
     232             :   }
     233             : 
     234           0 :   void fillRange(int start, int end, [E? value]) {
     235           0 :     var startInTable = (_head + start) & (_table.length - 1);
     236           0 :     var endInTable = (_head + end) & (_table.length - 1);
     237           0 :     if (startInTable <= endInTable) {
     238           0 :       _table.fillRange(startInTable, endInTable, value);
     239             :     } else {
     240           0 :       _table.fillRange(startInTable, _table.length, value);
     241           0 :       _table.fillRange(0, endInTable, value);
     242             :     }
     243             :   }
     244             : 
     245           0 :   L sublist(int start, [int? end]) {
     246           0 :     var length = this.length;
     247           0 :     var nonNullEnd = RangeError.checkValidRange(start, end, length);
     248             : 
     249           0 :     var list = _createList(nonNullEnd - start);
     250           0 :     _writeToList(list, start, nonNullEnd);
     251             :     return list;
     252             :   }
     253             : 
     254             :   // Internal helper functions.
     255             : 
     256             :   /// Writes the contents of `this` between [start] (which defaults to 0) and
     257             :   /// [end] (which defaults to [length]) to the beginning of [target].
     258             :   ///
     259             :   /// This is functionally identical to `target.setRange(0, end - start, this,
     260             :   /// start)`, but it's more efficient when [target] is typed data.
     261             :   ///
     262             :   /// Returns the number of elements written to [target].
     263           0 :   int _writeToList(List<E> target, [int? start, int? end]) {
     264             :     start ??= 0;
     265           0 :     end ??= length;
     266           0 :     assert(target.length >= end - start);
     267           0 :     assert(start <= end);
     268             : 
     269           0 :     var elementsToWrite = end - start;
     270           0 :     var startInTable = (_head + start) & (_table.length - 1);
     271           0 :     var endInTable = (_head + end) & (_table.length - 1);
     272           0 :     if (startInTable <= endInTable) {
     273           0 :       target.setRange(0, elementsToWrite, _table, startInTable);
     274             :     } else {
     275           0 :       var firstPartSize = _table.length - startInTable;
     276           0 :       target.setRange(0, firstPartSize, _table, startInTable);
     277           0 :       target.setRange(firstPartSize, firstPartSize + endInTable, _table, 0);
     278             :     }
     279             :     return elementsToWrite;
     280             :   }
     281             : 
     282             :   /// Assumes the table is currently full to capacity, and grows it to the next
     283             :   /// power of two.
     284           0 :   void _growAtCapacity() {
     285           0 :     assert(_head == _tail);
     286             : 
     287           0 :     var newTable = _createList(_table.length * 2);
     288             : 
     289             :     // We can't use [_writeToList] here because when `_head == _tail` it thinks
     290             :     // the queue is empty rather than full.
     291           0 :     var partitionPoint = _table.length - _head;
     292           0 :     newTable.setRange(0, partitionPoint, _table, _head);
     293           0 :     if (partitionPoint != _table.length) {
     294           0 :       newTable.setRange(partitionPoint, _table.length, _table);
     295             :     }
     296           0 :     _head = 0;
     297           0 :     _tail = _table.length;
     298           0 :     _table = newTable;
     299             :   }
     300             : 
     301             :   /// Grows the tableso it's at least large enough size to include that many
     302             :   /// elements.
     303           0 :   void _growTo(int newElementCount) {
     304           0 :     assert(newElementCount >= length);
     305             : 
     306             :     // Add some extra room to ensure that there's room for more elements after
     307             :     // expansion.
     308           0 :     newElementCount += newElementCount >> 1;
     309           0 :     var newTable = _createList(_nextPowerOf2(newElementCount));
     310           0 :     _tail = _writeToList(newTable);
     311           0 :     _table = newTable;
     312           0 :     _head = 0;
     313             :   }
     314             : 
     315             :   // Specialization for the specific type.
     316             : 
     317             :   // Create a new typed list.
     318             :   L _createList(int size);
     319             : 
     320             :   // Create a new typed buffer of the given type.
     321             :   List<E> _createBuffer(int size);
     322             : 
     323             :   /// The default value used to fill the queue when changing length.
     324             :   E get _defaultValue;
     325             : }
     326             : 
     327             : abstract class _IntQueue<L extends List<int>> extends _TypedQueue<int, L> {
     328           0 :   _IntQueue(L queue) : super(queue);
     329             : 
     330           0 :   int get _defaultValue => 0;
     331             : }
     332             : 
     333             : abstract class _FloatQueue<L extends List<double>>
     334             :     extends _TypedQueue<double, L> {
     335           0 :   _FloatQueue(L queue) : super(queue);
     336             : 
     337           0 :   double get _defaultValue => 0.0;
     338             : }
     339             : 
     340             : /// A [QueueList] that efficiently stores 8-bit unsigned integers.
     341             : ///
     342             : /// For long queues, this implementation can be considerably more space- and
     343             : /// time-efficient than a default [QueueList] implementation.
     344             : ///
     345             : /// Integers stored in this are truncated to their low eight bits, interpreted
     346             : /// as an unsigned 8-bit integer with values in the range 0 to 255.
     347             : class Uint8Queue extends _IntQueue<Uint8List> implements QueueList<int> {
     348             :   /// Creates an empty [Uint8Queue] with the given initial internal capacity (in
     349             :   /// elements).
     350           0 :   Uint8Queue([int? initialCapacity])
     351           0 :       : super(Uint8List(_chooseRealInitialCapacity(initialCapacity)));
     352             : 
     353             :   /// Creates a [Uint8Queue] with the same length and contents as [elements].
     354           0 :   factory Uint8Queue.fromList(List<int> elements) =>
     355           0 :       Uint8Queue(elements.length)..addAll(elements);
     356             : 
     357           0 :   Uint8List _createList(int size) => Uint8List(size);
     358           0 :   Uint8Buffer _createBuffer(int size) => Uint8Buffer(size);
     359             : }
     360             : 
     361             : /// A [QueueList] that efficiently stores 8-bit signed integers.
     362             : ///
     363             : /// For long queues, this implementation can be considerably more space- and
     364             : /// time-efficient than a default [QueueList] implementation.
     365             : ///
     366             : /// Integers stored in this are truncated to their low eight bits, interpreted
     367             : /// as a signed 8-bit two's complement integer with values in the range -128 to
     368             : /// +127.
     369             : class Int8Queue extends _IntQueue<Int8List> implements QueueList<int> {
     370             :   /// Creates an empty [Int8Queue] with the given initial internal capacity (in
     371             :   /// elements).
     372           0 :   Int8Queue([int? initialCapacity])
     373           0 :       : super(Int8List(_chooseRealInitialCapacity(initialCapacity)));
     374             : 
     375             :   /// Creates a [Int8Queue] with the same length and contents as [elements].
     376           0 :   factory Int8Queue.fromList(List<int> elements) =>
     377           0 :       Int8Queue(elements.length)..addAll(elements);
     378             : 
     379           0 :   Int8List _createList(int size) => Int8List(size);
     380           0 :   Int8Buffer _createBuffer(int size) => Int8Buffer(size);
     381             : }
     382             : 
     383             : /// A [QueueList] that efficiently stores 8-bit unsigned integers.
     384             : ///
     385             : /// For long queues, this implementation can be considerably more space- and
     386             : /// time-efficient than a default [QueueList] implementation.
     387             : ///
     388             : /// Integers stored in this are clamped to an unsigned eight bit value. That is,
     389             : /// all values below zero are stored as zero and all values above 255 are stored
     390             : /// as 255.
     391             : class Uint8ClampedQueue extends _IntQueue<Uint8ClampedList>
     392             :     implements QueueList<int> {
     393             :   /// Creates an empty [Uint8ClampedQueue] with the given initial internal
     394             :   /// capacity (in elements).
     395           0 :   Uint8ClampedQueue([int? initialCapacity])
     396           0 :       : super(Uint8ClampedList(_chooseRealInitialCapacity(initialCapacity)));
     397             : 
     398             :   /// Creates a [Uint8ClampedQueue] with the same length and contents as
     399             :   /// [elements].
     400           0 :   factory Uint8ClampedQueue.fromList(List<int> elements) =>
     401           0 :       Uint8ClampedQueue(elements.length)..addAll(elements);
     402             : 
     403           0 :   Uint8ClampedList _createList(int size) => Uint8ClampedList(size);
     404           0 :   Uint8ClampedBuffer _createBuffer(int size) => Uint8ClampedBuffer(size);
     405             : }
     406             : 
     407             : /// A [QueueList] that efficiently stores 16-bit unsigned integers.
     408             : ///
     409             : /// For long queues, this implementation can be considerably more space- and
     410             : /// time-efficient than a default [QueueList] implementation.
     411             : ///
     412             : /// Integers stored in this are truncated to their low 16 bits, interpreted as
     413             : /// an unsigned 16-bit integer with values in the range 0 to 65535.
     414             : class Uint16Queue extends _IntQueue<Uint16List> implements QueueList<int> {
     415             :   /// Creates an empty [Uint16Queue] with the given initial internal capacity
     416             :   /// (in elements).
     417           0 :   Uint16Queue([int? initialCapacity])
     418           0 :       : super(Uint16List(_chooseRealInitialCapacity(initialCapacity)));
     419             : 
     420             :   /// Creates a [Uint16Queue] with the same length and contents as [elements].
     421           0 :   factory Uint16Queue.fromList(List<int> elements) =>
     422           0 :       Uint16Queue(elements.length)..addAll(elements);
     423             : 
     424           0 :   Uint16List _createList(int size) => Uint16List(size);
     425           0 :   Uint16Buffer _createBuffer(int size) => Uint16Buffer(size);
     426             : }
     427             : 
     428             : /// A [QueueList] that efficiently stores 16-bit signed integers.
     429             : ///
     430             : /// For long queues, this implementation can be considerably more space- and
     431             : /// time-efficient than a default [QueueList] implementation.
     432             : ///
     433             : /// Integers stored in this are truncated to their low 16 bits, interpreted as a
     434             : /// signed 16-bit two's complement integer with values in the range -32768 to
     435             : /// +32767.
     436             : class Int16Queue extends _IntQueue<Int16List> implements QueueList<int> {
     437             :   /// Creates an empty [Int16Queue] with the given initial internal capacity (in
     438             :   /// elements).
     439           0 :   Int16Queue([int? initialCapacity])
     440           0 :       : super(Int16List(_chooseRealInitialCapacity(initialCapacity)));
     441             : 
     442             :   /// Creates a [Int16Queue] with the same length and contents as [elements].
     443           0 :   factory Int16Queue.fromList(List<int> elements) =>
     444           0 :       Int16Queue(elements.length)..addAll(elements);
     445             : 
     446           0 :   Int16List _createList(int size) => Int16List(size);
     447           0 :   Int16Buffer _createBuffer(int size) => Int16Buffer(size);
     448             : }
     449             : 
     450             : /// A [QueueList] that efficiently stores 32-bit unsigned integers.
     451             : ///
     452             : /// For long queues, this implementation can be considerably more space- and
     453             : /// time-efficient than a default [QueueList] implementation.
     454             : ///
     455             : /// Integers stored in this are truncated to their low 32 bits, interpreted as
     456             : /// an unsigned 32-bit integer with values in the range 0 to 4294967295.
     457             : class Uint32Queue extends _IntQueue<Uint32List> implements QueueList<int> {
     458             :   /// Creates an empty [Uint32Queue] with the given initial internal capacity
     459             :   /// (in elements).
     460           0 :   Uint32Queue([int? initialCapacity])
     461           0 :       : super(Uint32List(_chooseRealInitialCapacity(initialCapacity)));
     462             : 
     463             :   /// Creates a [Uint32Queue] with the same length and contents as [elements].
     464           0 :   factory Uint32Queue.fromList(List<int> elements) =>
     465           0 :       Uint32Queue(elements.length)..addAll(elements);
     466             : 
     467           0 :   Uint32List _createList(int size) => Uint32List(size);
     468           0 :   Uint32Buffer _createBuffer(int size) => Uint32Buffer(size);
     469             : }
     470             : 
     471             : /// A [QueueList] that efficiently stores 32-bit signed integers.
     472             : ///
     473             : /// For long queues, this implementation can be considerably more space- and
     474             : /// time-efficient than a default [QueueList] implementation.
     475             : ///
     476             : /// Integers stored in this are truncated to their low 32 bits, interpreted as a
     477             : /// signed 32-bit two's complement integer with values in the range -2147483648
     478             : /// to 2147483647.
     479             : class Int32Queue extends _IntQueue<Int32List> implements QueueList<int> {
     480             :   /// Creates an empty [Int32Queue] with the given initial internal capacity (in
     481             :   /// elements).
     482           0 :   Int32Queue([int? initialCapacity])
     483           0 :       : super(Int32List(_chooseRealInitialCapacity(initialCapacity)));
     484             : 
     485             :   /// Creates a [Int32Queue] with the same length and contents as [elements].
     486           0 :   factory Int32Queue.fromList(List<int> elements) =>
     487           0 :       Int32Queue(elements.length)..addAll(elements);
     488             : 
     489           0 :   Int32List _createList(int size) => Int32List(size);
     490           0 :   Int32Buffer _createBuffer(int size) => Int32Buffer(size);
     491             : }
     492             : 
     493             : /// A [QueueList] that efficiently stores 64-bit unsigned integers.
     494             : ///
     495             : /// For long queues, this implementation can be considerably more space- and
     496             : /// time-efficient than a default [QueueList] implementation.
     497             : ///
     498             : /// Integers stored in this are truncated to their low 64 bits, interpreted as
     499             : /// an unsigned 64-bit integer with values in the range 0 to
     500             : /// 18446744073709551615.
     501             : class Uint64Queue extends _IntQueue<Uint64List> implements QueueList<int> {
     502             :   /// Creates an empty [Uint64Queue] with the given initial internal capacity
     503             :   /// (in elements).
     504           0 :   Uint64Queue([int? initialCapacity])
     505           0 :       : super(Uint64List(_chooseRealInitialCapacity(initialCapacity)));
     506             : 
     507             :   /// Creates a [Uint64Queue] with the same length and contents as [elements].
     508           0 :   factory Uint64Queue.fromList(List<int> elements) =>
     509           0 :       Uint64Queue(elements.length)..addAll(elements);
     510             : 
     511           0 :   Uint64List _createList(int size) => Uint64List(size);
     512           0 :   Uint64Buffer _createBuffer(int size) => Uint64Buffer(size);
     513             : }
     514             : 
     515             : /// A [QueueList] that efficiently stores 64-bit signed integers.
     516             : ///
     517             : /// For long queues, this implementation can be considerably more space- and
     518             : /// time-efficient than a default [QueueList] implementation.
     519             : ///
     520             : /// Integers stored in this are truncated to their low 64 bits, interpreted as a
     521             : /// signed 64-bit two's complement integer with values in the range
     522             : /// -9223372036854775808 to +9223372036854775807.
     523             : class Int64Queue extends _IntQueue<Int64List> implements QueueList<int> {
     524             :   /// Creates an empty [Int64Queue] with the given initial internal capacity (in
     525             :   /// elements).
     526           0 :   Int64Queue([int? initialCapacity])
     527           0 :       : super(Int64List(_chooseRealInitialCapacity(initialCapacity)));
     528             : 
     529             :   /// Creates a [Int64Queue] with the same length and contents as [elements].
     530           0 :   factory Int64Queue.fromList(List<int> elements) =>
     531           0 :       Int64Queue(elements.length)..addAll(elements);
     532             : 
     533           0 :   Int64List _createList(int size) => Int64List(size);
     534           0 :   Int64Buffer _createBuffer(int size) => Int64Buffer(size);
     535             : }
     536             : 
     537             : /// A [QueueList] that efficiently stores IEEE 754 single-precision binary
     538             : /// floating-point numbers.
     539             : ///
     540             : /// For long queues, this implementation can be considerably more space- and
     541             : /// time-efficient than a default [QueueList] implementation.
     542             : ///
     543             : /// Doubles stored in this are converted to the nearest single-precision value.
     544             : /// Values read are converted to a double value with the same value.
     545             : class Float32Queue extends _FloatQueue<Float32List>
     546             :     implements QueueList<double> {
     547             :   /// Creates an empty [Float32Queue] with the given initial internal capacity
     548             :   /// (in elements).
     549           0 :   Float32Queue([int? initialCapacity])
     550           0 :       : super(Float32List(_chooseRealInitialCapacity(initialCapacity)));
     551             : 
     552             :   /// Creates a [Float32Queue] with the same length and contents as [elements].
     553           0 :   factory Float32Queue.fromList(List<double> elements) =>
     554           0 :       Float32Queue(elements.length)..addAll(elements);
     555             : 
     556           0 :   Float32List _createList(int size) => Float32List(size);
     557           0 :   Float32Buffer _createBuffer(int size) => Float32Buffer(size);
     558             : }
     559             : 
     560             : /// A [QueueList] that efficiently stores IEEE 754 double-precision binary
     561             : /// floating-point numbers.
     562             : ///
     563             : /// For long queues, this implementation can be considerably more space- and
     564             : /// time-efficient than a default [QueueList] implementation.
     565             : class Float64Queue extends _FloatQueue<Float64List>
     566             :     implements QueueList<double> {
     567             :   /// Creates an empty [Float64Queue] with the given initial internal capacity
     568             :   /// (in elements).
     569           0 :   Float64Queue([int? initialCapacity])
     570           0 :       : super(Float64List(_chooseRealInitialCapacity(initialCapacity)));
     571             : 
     572             :   /// Creates a [Float64Queue] with the same length and contents as [elements].
     573           0 :   factory Float64Queue.fromList(List<double> elements) =>
     574           0 :       Float64Queue(elements.length)..addAll(elements);
     575             : 
     576           0 :   Float64List _createList(int size) => Float64List(size);
     577           0 :   Float64Buffer _createBuffer(int size) => Float64Buffer(size);
     578             : }
     579             : 
     580             : /// A [QueueList] that efficiently stores [Int32x4] numbers.
     581             : ///
     582             : /// For long queues, this implementation can be considerably more space- and
     583             : /// time-efficient than a default [QueueList] implementation.
     584             : class Int32x4Queue extends _TypedQueue<Int32x4, Int32x4List>
     585             :     implements QueueList<Int32x4> {
     586           0 :   static final Int32x4 _zero = Int32x4(0, 0, 0, 0);
     587             : 
     588             :   /// Creates an empty [Int32x4Queue] with the given initial internal capacity
     589             :   /// (in elements).
     590           0 :   Int32x4Queue([int? initialCapacity])
     591           0 :       : super(Int32x4List(_chooseRealInitialCapacity(initialCapacity)));
     592             : 
     593             :   /// Creates a [Int32x4Queue] with the same length and contents as [elements].
     594           0 :   factory Int32x4Queue.fromList(List<Int32x4> elements) =>
     595           0 :       Int32x4Queue(elements.length)..addAll(elements);
     596             : 
     597           0 :   Int32x4List _createList(int size) => Int32x4List(size);
     598           0 :   Int32x4Buffer _createBuffer(int size) => Int32x4Buffer(size);
     599           0 :   Int32x4 get _defaultValue => _zero;
     600             : }
     601             : 
     602             : /// A [QueueList] that efficiently stores [Float32x4] numbers.
     603             : ///
     604             : /// For long queues, this implementation can be considerably more space- and
     605             : /// time-efficient than a default [QueueList] implementation.
     606             : class Float32x4Queue extends _TypedQueue<Float32x4, Float32x4List>
     607             :     implements QueueList<Float32x4> {
     608             :   /// Creates an empty [Float32x4Queue] with the given initial internal capacity (in
     609             :   /// elements).
     610           0 :   Float32x4Queue([int? initialCapacity])
     611           0 :       : super(Float32x4List(_chooseRealInitialCapacity(initialCapacity)));
     612             : 
     613             :   /// Creates a [Float32x4Queue] with the same length and contents as [elements].
     614           0 :   factory Float32x4Queue.fromList(List<Float32x4> elements) =>
     615           0 :       Float32x4Queue(elements.length)..addAll(elements);
     616             : 
     617           0 :   Float32x4List _createList(int size) => Float32x4List(size);
     618           0 :   Float32x4Buffer _createBuffer(int size) => Float32x4Buffer(size);
     619           0 :   Float32x4 get _defaultValue => Float32x4.zero();
     620             : }
     621             : 
     622             : /// The initial capacity of queues if the user doesn't specify one.
     623             : const _defaultInitialCapacity = 16;
     624             : 
     625             : /// Choose the next-highest power of two given a user-specified
     626             : /// [initialCapacity] for a queue.
     627           0 : int _chooseRealInitialCapacity(int? initialCapacity) {
     628           0 :   if (initialCapacity == null || initialCapacity < _defaultInitialCapacity) {
     629             :     return _defaultInitialCapacity;
     630           0 :   } else if (!_isPowerOf2(initialCapacity)) {
     631           0 :     return _nextPowerOf2(initialCapacity);
     632             :   } else {
     633             :     return initialCapacity;
     634             :   }
     635             : }
     636             : 
     637             : /// Whether [number] is a power of two.
     638             : ///
     639             : /// Only works for positive numbers.
     640           0 : bool _isPowerOf2(int number) => (number & (number - 1)) == 0;
     641             : 
     642             : /// Rounds [number] up to the nearest power of 2.
     643             : ///
     644             : /// If [number] is a power of 2 already, it is returned.
     645             : ///
     646             : /// Only works for positive numbers.
     647           0 : int _nextPowerOf2(int number) {
     648           0 :   assert(number > 0);
     649           0 :   number = (number << 1) - 1;
     650             :   for (;;) {
     651           0 :     var nextNumber = number & (number - 1);
     652           0 :     if (nextNumber == 0) return number;
     653             :     number = nextNumber;
     654             :   }
     655             : }

Generated by: LCOV version 1.14