LCOV - code coverage report
Current view: top level - collection-1.14.3/lib/src - queue_list.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 16 88 18.2 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2014, 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             : 
       7             : /// A class that efficiently implements both [Queue] and [List].
       8             : // TODO(nweiz): Currently this code is copied almost verbatim from
       9             : // dart:collection. The only changes are to implement List and to remove methods
      10             : // that are redundant with ListMixin. Remove or simplify it when issue 21330 is
      11             : // fixed.
      12             : class QueueList<E> extends Object with ListMixin<E> implements Queue<E> {
      13             :   static const int _INITIAL_CAPACITY = 8;
      14             :   List<E> _table;
      15             :   int _head;
      16             :   int _tail;
      17             : 
      18             :   /// Create an empty queue.
      19             :   ///
      20             :   /// If [initialCapacity] is given, prepare the queue for at least that many
      21             :   /// elements.
      22             :   QueueList([int initialCapacity])
      23             :       : _head = 0,
      24           5 :         _tail = 0 {
      25           0 :     if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) {
      26             :       initialCapacity = _INITIAL_CAPACITY;
      27           0 :     } else if (!_isPowerOf2(initialCapacity)) {
      28           0 :       initialCapacity = _nextPowerOf2(initialCapacity);
      29             :     }
      30             :     assert(_isPowerOf2(initialCapacity));
      31          10 :     _table = new List<E>(initialCapacity);
      32             :   }
      33             : 
      34             :   /// Create a queue initially containing the elements of [source].
      35             :   factory QueueList.from(Iterable<E> source) {
      36           0 :     if (source is List) {
      37           0 :       int length = source.length;
      38           0 :       QueueList<E> queue = new QueueList(length + 1);
      39             :       assert(queue._table.length > length);
      40             :       var sourceList = source;
      41           0 :       queue._table.setRange(0, length, sourceList, 0);
      42           0 :       queue._tail = length;
      43             :       return queue;
      44             :     } else {
      45           0 :       return new QueueList<E>()..addAll(source);
      46             :     }
      47             :   }
      48             : 
      49             :   // Collection interface.
      50             : 
      51             :   void add(E element) {
      52           5 :     _add(element);
      53             :   }
      54             : 
      55             :   void addAll(Iterable<E> elements) {
      56           0 :     if (elements is List) {
      57             :       var list = elements;
      58           0 :       int addCount = list.length;
      59           0 :       int length = this.length;
      60           0 :       if (length + addCount >= _table.length) {
      61           0 :         _preGrow(length + addCount);
      62             :         // After preGrow, all elements are at the start of the list.
      63           0 :         _table.setRange(length, length + addCount, list, 0);
      64           0 :         _tail += addCount;
      65             :       } else {
      66             :         // Adding addCount elements won't reach _head.
      67           0 :         int endSpace = _table.length - _tail;
      68           0 :         if (addCount < endSpace) {
      69           0 :           _table.setRange(_tail, _tail + addCount, list, 0);
      70           0 :           _tail += addCount;
      71             :         } else {
      72           0 :           int preSpace = addCount - endSpace;
      73           0 :           _table.setRange(_tail, _tail + endSpace, list, 0);
      74           0 :           _table.setRange(0, preSpace, list, endSpace);
      75           0 :           _tail = preSpace;
      76             :         }
      77             :       }
      78             :     } else {
      79           0 :       for (E element in elements) _add(element);
      80             :     }
      81             :   }
      82             : 
      83           0 :   String toString() => IterableBase.iterableToFullString(this, "{", "}");
      84             : 
      85             :   // Queue interface.
      86             : 
      87             :   void addLast(E element) {
      88           0 :     _add(element);
      89             :   }
      90             : 
      91             :   void addFirst(E element) {
      92           0 :     _head = (_head - 1) & (_table.length - 1);
      93           0 :     _table[_head] = element;
      94           0 :     if (_head == _tail) _grow();
      95             :   }
      96             : 
      97             :   E removeFirst() {
      98           0 :     if (_head == _tail) throw new StateError("No element");
      99           0 :     E result = _table[_head];
     100           0 :     _table[_head] = null;
     101           0 :     _head = (_head + 1) & (_table.length - 1);
     102             :     return result;
     103             :   }
     104             : 
     105             :   E removeLast() {
     106           0 :     if (_head == _tail) throw new StateError("No element");
     107           0 :     _tail = (_tail - 1) & (_table.length - 1);
     108           0 :     E result = _table[_tail];
     109           0 :     _table[_tail] = null;
     110             :     return result;
     111             :   }
     112             : 
     113             :   // List interface.
     114             : 
     115          35 :   int get length => (_tail - _head) & (_table.length - 1);
     116             : 
     117             :   void set length(int value) {
     118           5 :     if (value < 0) throw new RangeError("Length $value may not be negative.");
     119             : 
     120          10 :     int delta = value - length;
     121           5 :     if (delta >= 0) {
     122           0 :       if (_table.length <= value) {
     123           0 :         _preGrow(value);
     124             :       }
     125           0 :       _tail = (_tail + delta) & (_table.length - 1);
     126             :       return;
     127             :     }
     128             : 
     129          10 :     int newTail = _tail + delta; // [delta] is negative.
     130           5 :     if (newTail >= 0) {
     131          15 :       _table.fillRange(newTail, _tail, null);
     132             :     } else {
     133           0 :       newTail += _table.length;
     134           0 :       _table.fillRange(0, _tail, null);
     135           0 :       _table.fillRange(newTail, _table.length, null);
     136             :     }
     137           5 :     _tail = newTail;
     138             :   }
     139             : 
     140             :   E operator [](int index) {
     141          15 :     if (index < 0 || index >= length) {
     142           0 :       throw new RangeError("Index $index must be in the range [0..$length).");
     143             :     }
     144             : 
     145          40 :     return _table[(_head + index) & (_table.length - 1)];
     146             :   }
     147             : 
     148             :   void operator []=(int index, E value) {
     149           0 :     if (index < 0 || index >= length) {
     150           0 :       throw new RangeError("Index $index must be in the range [0..$length).");
     151             :     }
     152             : 
     153           0 :     _table[(_head + index) & (_table.length - 1)] = value;
     154             :   }
     155             : 
     156             :   // Internal helper functions.
     157             : 
     158             :   /// Whether [number] is a power of two.
     159             :   ///
     160             :   /// Only works for positive numbers.
     161           0 :   static bool _isPowerOf2(int number) => (number & (number - 1)) == 0;
     162             : 
     163             :   /// Rounds [number] up to the nearest power of 2.
     164             :   ///
     165             :   /// If [number] is a power of 2 already, it is returned.
     166             :   ///
     167             :   /// Only works for positive numbers.
     168             :   static int _nextPowerOf2(int number) {
     169             :     assert(number > 0);
     170           0 :     number = (number << 1) - 1;
     171             :     for (;;) {
     172           0 :       int nextNumber = number & (number - 1);
     173           0 :       if (nextNumber == 0) return number;
     174             :       number = nextNumber;
     175             :     }
     176             :   }
     177             : 
     178             :   /// Adds element at end of queue. Used by both [add] and [addAll].
     179             :   void _add(E element) {
     180          15 :     _table[_tail] = element;
     181          35 :     _tail = (_tail + 1) & (_table.length - 1);
     182          15 :     if (_head == _tail) _grow();
     183             :   }
     184             : 
     185             :   /// Grow the table when full.
     186             :   void _grow() {
     187           0 :     List<E> newTable = new List<E>(_table.length * 2);
     188           0 :     int split = _table.length - _head;
     189           0 :     newTable.setRange(0, split, _table, _head);
     190           0 :     newTable.setRange(split, split + _head, _table, 0);
     191           0 :     _head = 0;
     192           0 :     _tail = _table.length;
     193           0 :     _table = newTable;
     194             :   }
     195             : 
     196             :   int _writeToList(List<E> target) {
     197             :     assert(target.length >= length);
     198           0 :     if (_head <= _tail) {
     199           0 :       int length = _tail - _head;
     200           0 :       target.setRange(0, length, _table, _head);
     201             :       return length;
     202             :     } else {
     203           0 :       int firstPartSize = _table.length - _head;
     204           0 :       target.setRange(0, firstPartSize, _table, _head);
     205           0 :       target.setRange(firstPartSize, firstPartSize + _tail, _table, 0);
     206           0 :       return _tail + firstPartSize;
     207             :     }
     208             :   }
     209             : 
     210             :   /// Grows the table even if it is not full.
     211             :   void _preGrow(int newElementCount) {
     212             :     assert(newElementCount >= length);
     213             : 
     214             :     // Add 1.5x extra room to ensure that there's room for more elements after
     215             :     // expansion.
     216           0 :     newElementCount += newElementCount >> 1;
     217           0 :     int newCapacity = _nextPowerOf2(newElementCount);
     218           0 :     List<E> newTable = new List<E>(newCapacity);
     219           0 :     _tail = _writeToList(newTable);
     220           0 :     _table = newTable;
     221           0 :     _head = 0;
     222             :   }
     223             : }

Generated by: LCOV version 1.13