LCOV - code coverage report
Current view: top level - typed_data-1.1.5/lib - typed_buffers.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 0 135 0.0 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2013, 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             : /// Growable typed-data lists.
       6             : ///
       7             : /// These lists works just as a typed-data list, except that they are growable.
       8             : /// They use an underlying buffer, and when that buffer becomes too small, it
       9             : /// is replaced by a new buffer.
      10             : ///
      11             : /// That means that using the [TypedDataView.buffer] getter is not guaranteed
      12             : /// to return the same result each time it is used, and that the buffer may
      13             : /// be larger than what the list is using.
      14             : library typed_data.typed_buffers;
      15             : 
      16             : import "dart:collection" show ListBase;
      17             : import "dart:typed_data";
      18             : 
      19             : abstract class _TypedDataBuffer<E> extends ListBase<E> {
      20             :   static const int INITIAL_LENGTH = 8;
      21             : 
      22             :   /// The underlying data buffer.
      23             :   ///
      24             :   /// This is always both a List<E> and a TypedData, which we don't have a type
      25             :   /// for here. For example, for a `Uint8Buffer`, this is a `Uint8List`.
      26             :   List<E> _buffer;
      27             : 
      28             :   /// Returns a view of [_buffer] as a [TypedData].
      29           0 :   TypedData get _typedBuffer => _buffer as TypedData;
      30             : 
      31             :   /// The length of the list being built.
      32             :   int _length;
      33             : 
      34             :   _TypedDataBuffer(List<E> buffer)
      35             :       : this._buffer = buffer,
      36           0 :         this._length = buffer.length;
      37             : 
      38           0 :   int get length => _length;
      39             :   E operator [](int index) {
      40           0 :     if (index >= length) throw new RangeError.index(index, this);
      41           0 :     return _buffer[index];
      42             :   }
      43             : 
      44             :   void operator []=(int index, E value) {
      45           0 :     if (index >= length) throw new RangeError.index(index, this);
      46           0 :     _buffer[index] = value;
      47             :   }
      48             : 
      49             :   void set length(int newLength) {
      50           0 :     if (newLength < _length) {
      51           0 :       E defaultValue = _defaultValue;
      52           0 :       for (int i = newLength; i < _length; i++) {
      53           0 :         _buffer[i] = defaultValue;
      54             :       }
      55           0 :     } else if (newLength > _buffer.length) {
      56             :       List<E> newBuffer;
      57           0 :       if (_buffer.length == 0) {
      58           0 :         newBuffer = _createBuffer(newLength);
      59             :       } else {
      60           0 :         newBuffer = _createBiggerBuffer(newLength);
      61             :       }
      62           0 :       newBuffer.setRange(0, _length, _buffer);
      63           0 :       _buffer = newBuffer;
      64             :     }
      65           0 :     _length = newLength;
      66             :   }
      67             : 
      68             :   void _add(E value) {
      69           0 :     if (_length == _buffer.length) _grow(_length);
      70           0 :     _buffer[_length++] = value;
      71             :   }
      72             : 
      73             :   // We override the default implementation of `add` because it grows the list
      74             :   // by setting the length in increments of one. We want to grow by doubling
      75             :   // capacity in most cases.
      76             :   void add(E value) {
      77           0 :     _add(value);
      78             :   }
      79             : 
      80             :   /// Appends all objects of [values] to the end of this buffer.
      81             :   ///
      82             :   /// This adds values from [start] (inclusive) to [end] (exclusive) in
      83             :   /// [values]. If [end] is omitted, it defaults to adding all elements of
      84             :   /// [values] after [start].
      85             :   ///
      86             :   /// The [start] value must be non-negative. The [values] iterable must have at
      87             :   /// least [start] elements, and if [end] is specified, it must be greater than
      88             :   /// or equal to [start] and [values] must have at least [end] elements.
      89             :   void addAll(Iterable<E> values, [int start = 0, int end]) {
      90           0 :     RangeError.checkNotNegative(start, "start");
      91           0 :     if (end != null && start > end) {
      92           0 :       throw new RangeError.range(end, start, null, "end");
      93             :     }
      94             : 
      95           0 :     _addAll(values, start, end);
      96             :   }
      97             : 
      98             :   /// Inserts all objects of [values] at position [index] in this list.
      99             :   ///
     100             :   /// This adds values from [start] (inclusive) to [end] (exclusive) in
     101             :   /// [values]. If [end] is omitted, it defaults to adding all elements of
     102             :   /// [values] after [start].
     103             :   ///
     104             :   /// The [start] value must be non-negative. The [values] iterable must have at
     105             :   /// least [start] elements, and if [end] is specified, it must be greater than
     106             :   /// or equal to [start] and [values] must have at least [end] elements.
     107             :   void insertAll(int index, Iterable<E> values, [int start = 0, int end]) {
     108           0 :     RangeError.checkValidIndex(index, this, "index", _length + 1);
     109           0 :     RangeError.checkNotNegative(start, "start");
     110             :     if (end != null) {
     111           0 :       if (start > end) {
     112           0 :         throw new RangeError.range(end, start, null, "end");
     113             :       }
     114           0 :       if (start == end) return;
     115             :     }
     116             : 
     117             :     // If we're adding to the end of the list anyway, use [_addAll]. This lets
     118             :     // us avoid converting [values] into a list even if [end] is null, since we
     119             :     // can add values iteratively to the end of the list. We can't do so in the
     120             :     // center because copying the trailing elements every time is non-linear.
     121           0 :     if (index == _length) {
     122           0 :       _addAll(values, start, end);
     123             :       return;
     124             :     }
     125             : 
     126           0 :     if (end == null && values is List) {
     127           0 :       end = values.length;
     128             :     }
     129             :     if (end != null) {
     130           0 :       _insertKnownLength(index, values, start, end);
     131             :       return;
     132             :     }
     133             : 
     134             :     // Add elements at end, growing as appropriate, then put them back at
     135             :     // position [index] using flip-by-double-reverse.
     136           0 :     var writeIndex = _length;
     137             :     var skipCount = start;
     138           0 :     for (var value in values) {
     139           0 :       if (skipCount > 0) {
     140           0 :         skipCount--;
     141             :         continue;
     142             :       }
     143           0 :       if (writeIndex == _buffer.length) {
     144           0 :         _grow(writeIndex);
     145             :       }
     146           0 :       _buffer[writeIndex++] = value;
     147             :     }
     148             : 
     149           0 :     if (skipCount > 0) {
     150           0 :       throw new StateError("Too few elements");
     151             :     }
     152           0 :     if (end != null && writeIndex < end) {
     153           0 :       throw new RangeError.range(end, start, writeIndex, "end");
     154             :     }
     155             : 
     156             :     // Swap [index.._length) and [_length..writeIndex) by double-reversing.
     157           0 :     _reverse(_buffer, index, _length);
     158           0 :     _reverse(_buffer, _length, writeIndex);
     159           0 :     _reverse(_buffer, index, writeIndex);
     160           0 :     _length = writeIndex;
     161             :     return;
     162             :   }
     163             : 
     164             :   // Reverses the range [start..end) of buffer.
     165             :   static void _reverse(List buffer, int start, int end) {
     166           0 :     end--; // Point to last element, not after last element.
     167           0 :     while (start < end) {
     168           0 :       var first = buffer[start];
     169           0 :       var last = buffer[end];
     170           0 :       buffer[end] = first;
     171           0 :       buffer[start] = last;
     172           0 :       start++;
     173           0 :       end--;
     174             :     }
     175             :   }
     176             : 
     177             :   /// Does the same thing as [addAll].
     178             :   ///
     179             :   /// This allows [addAll] and [insertAll] to share implementation without a
     180             :   /// subclass unexpectedly overriding both when it intended to only override
     181             :   /// [addAll].
     182             :   void _addAll(Iterable<E> values, [int start = 0, int end]) {
     183           0 :     if (values is List) end ??= values.length;
     184             : 
     185             :     // If we know the length of the segment to add, do so with [addRange]. This
     186             :     // way we know how much to grow the buffer in advance, and it may be even
     187             :     // more efficient for typed data input.
     188             :     if (end != null) {
     189           0 :       _insertKnownLength(_length, values, start, end);
     190             :       return;
     191             :     }
     192             : 
     193             :     // Otherwise, just add values one at a time.
     194             :     var i = 0;
     195           0 :     for (var value in values) {
     196           0 :       if (i >= start) add(value);
     197           0 :       i++;
     198             :     }
     199           0 :     if (i < start) throw new StateError("Too few elements");
     200             :   }
     201             : 
     202             :   /// Like [insertAll], but with a guaranteed non-`null` [start] and [end].
     203             :   void _insertKnownLength(int index, Iterable<E> values, int start, int end) {
     204           0 :     if (values is List) {
     205           0 :       end ??= values.length;
     206           0 :       if (start > values.length || end > values.length) {
     207           0 :         throw new StateError("Too few elements");
     208             :       }
     209             :     } else {
     210             :       assert(end != null);
     211             :     }
     212             : 
     213           0 :     var valuesLength = end - start;
     214           0 :     var newLength = _length + valuesLength;
     215           0 :     _ensureCapacity(newLength);
     216             : 
     217           0 :     _buffer.setRange(
     218           0 :         index + valuesLength, _length + valuesLength, _buffer, index);
     219           0 :     _buffer.setRange(index, index + valuesLength, values, start);
     220           0 :     _length = newLength;
     221             :   }
     222             : 
     223             :   void insert(int index, E element) {
     224           0 :     if (index < 0 || index > _length) {
     225           0 :       throw new RangeError.range(index, 0, _length);
     226             :     }
     227           0 :     if (_length < _buffer.length) {
     228           0 :       _buffer.setRange(index + 1, _length + 1, _buffer, index);
     229           0 :       _buffer[index] = element;
     230           0 :       _length++;
     231             :       return;
     232             :     }
     233           0 :     List<E> newBuffer = _createBiggerBuffer(null);
     234           0 :     newBuffer.setRange(0, index, _buffer);
     235           0 :     newBuffer.setRange(index + 1, _length + 1, _buffer, index);
     236           0 :     newBuffer[index] = element;
     237           0 :     _length++;
     238           0 :     _buffer = newBuffer;
     239             :   }
     240             : 
     241             :   /// Ensures that [_buffer] is at least [requiredCapacity] long,
     242             :   ///
     243             :   /// Grows the buffer if necessary, preserving existing data.
     244             :   void _ensureCapacity(int requiredCapacity) {
     245           0 :     if (requiredCapacity <= _buffer.length) return;
     246           0 :     var newBuffer = _createBiggerBuffer(requiredCapacity);
     247           0 :     newBuffer.setRange(0, _length, _buffer);
     248           0 :     _buffer = newBuffer;
     249             :   }
     250             : 
     251             :   /// Create a bigger buffer.
     252             :   ///
     253             :   /// This method determines how much bigger a bigger buffer should
     254             :   /// be. If [requiredCapacity] is not null, it will be at least that
     255             :   /// size. It will always have at least have double the capacity of
     256             :   /// the current buffer.
     257             :   List<E> _createBiggerBuffer(int requiredCapacity) {
     258           0 :     int newLength = _buffer.length * 2;
     259           0 :     if (requiredCapacity != null && newLength < requiredCapacity) {
     260             :       newLength = requiredCapacity;
     261           0 :     } else if (newLength < INITIAL_LENGTH) {
     262             :       newLength = INITIAL_LENGTH;
     263             :     }
     264           0 :     return _createBuffer(newLength);
     265             :   }
     266             : 
     267             :   /// Grows the buffer.
     268             :   ///
     269             :   /// This copies the first [length] elements into the new buffer.
     270             :   void _grow(int length) {
     271           0 :     _buffer = _createBiggerBuffer(null)..setRange(0, length, _buffer);
     272             :   }
     273             : 
     274             :   void setRange(int start, int end, Iterable<E> source, [int skipCount = 0]) {
     275           0 :     if (end > _length) throw new RangeError.range(end, 0, _length);
     276           0 :     _setRange(start, end, source, skipCount);
     277             :   }
     278             : 
     279             :   /// Like [setRange], but with no bounds checking.
     280             :   void _setRange(int start, int end, Iterable<E> source, int skipCount) {
     281           0 :     if (source is _TypedDataBuffer<E>) {
     282           0 :       _buffer.setRange(start, end, source._buffer, skipCount);
     283             :     } else {
     284           0 :       _buffer.setRange(start, end, source, skipCount);
     285             :     }
     286             :   }
     287             : 
     288             :   // TypedData.
     289             : 
     290           0 :   int get elementSizeInBytes => _typedBuffer.elementSizeInBytes;
     291             : 
     292           0 :   int get lengthInBytes => _length * _typedBuffer.elementSizeInBytes;
     293             : 
     294           0 :   int get offsetInBytes => _typedBuffer.offsetInBytes;
     295             : 
     296             :   /// Returns the underlying [ByteBuffer].
     297             :   ///
     298             :   /// The returned buffer may be replaced by operations that change the [length]
     299             :   /// of this list.
     300             :   ///
     301             :   /// The buffer may be larger than [lengthInBytes] bytes, but never smaller.
     302           0 :   ByteBuffer get buffer => _typedBuffer.buffer;
     303             : 
     304             :   // Specialization for the specific type.
     305             : 
     306             :   // Return zero for integers, 0.0 for floats, etc.
     307             :   // Used to fill buffer when changing length.
     308             :   E get _defaultValue;
     309             : 
     310             :   // Create a new typed list to use as buffer.
     311             :   List<E> _createBuffer(int size);
     312             : }
     313             : 
     314             : abstract class _IntBuffer extends _TypedDataBuffer<int> {
     315           0 :   _IntBuffer(List<int> buffer) : super(buffer);
     316             : 
     317             :   int get _defaultValue => 0;
     318             : }
     319             : 
     320             : abstract class _FloatBuffer extends _TypedDataBuffer<double> {
     321           0 :   _FloatBuffer(List<double> buffer) : super(buffer);
     322             : 
     323             :   double get _defaultValue => 0.0;
     324             : }
     325             : 
     326             : class Uint8Buffer extends _IntBuffer {
     327           0 :   Uint8Buffer([int initialLength = 0]) : super(new Uint8List(initialLength));
     328           0 :   Uint8List _createBuffer(int size) => new Uint8List(size);
     329             : }
     330             : 
     331             : class Int8Buffer extends _IntBuffer {
     332           0 :   Int8Buffer([int initialLength = 0]) : super(new Int8List(initialLength));
     333           0 :   Int8List _createBuffer(int size) => new Int8List(size);
     334             : }
     335             : 
     336             : class Uint8ClampedBuffer extends _IntBuffer {
     337             :   Uint8ClampedBuffer([int initialLength = 0])
     338           0 :       : super(new Uint8ClampedList(initialLength));
     339           0 :   Uint8ClampedList _createBuffer(int size) => new Uint8ClampedList(size);
     340             : }
     341             : 
     342             : class Uint16Buffer extends _IntBuffer {
     343           0 :   Uint16Buffer([int initialLength = 0]) : super(new Uint16List(initialLength));
     344           0 :   Uint16List _createBuffer(int size) => new Uint16List(size);
     345             : }
     346             : 
     347             : class Int16Buffer extends _IntBuffer {
     348           0 :   Int16Buffer([int initialLength = 0]) : super(new Int16List(initialLength));
     349           0 :   Int16List _createBuffer(int size) => new Int16List(size);
     350             : }
     351             : 
     352             : class Uint32Buffer extends _IntBuffer {
     353           0 :   Uint32Buffer([int initialLength = 0]) : super(new Uint32List(initialLength));
     354           0 :   Uint32List _createBuffer(int size) => new Uint32List(size);
     355             : }
     356             : 
     357             : class Int32Buffer extends _IntBuffer {
     358           0 :   Int32Buffer([int initialLength = 0]) : super(new Int32List(initialLength));
     359           0 :   Int32List _createBuffer(int size) => new Int32List(size);
     360             : }
     361             : 
     362             : class Uint64Buffer extends _IntBuffer {
     363           0 :   Uint64Buffer([int initialLength = 0]) : super(new Uint64List(initialLength));
     364           0 :   Uint64List _createBuffer(int size) => new Uint64List(size);
     365             : }
     366             : 
     367             : class Int64Buffer extends _IntBuffer {
     368           0 :   Int64Buffer([int initialLength = 0]) : super(new Int64List(initialLength));
     369           0 :   Int64List _createBuffer(int size) => new Int64List(size);
     370             : }
     371             : 
     372             : class Float32Buffer extends _FloatBuffer {
     373             :   Float32Buffer([int initialLength = 0])
     374           0 :       : super(new Float32List(initialLength));
     375           0 :   Float32List _createBuffer(int size) => new Float32List(size);
     376             : }
     377             : 
     378             : class Float64Buffer extends _FloatBuffer {
     379             :   Float64Buffer([int initialLength = 0])
     380           0 :       : super(new Float64List(initialLength));
     381           0 :   Float64List _createBuffer(int size) => new Float64List(size);
     382             : }
     383             : 
     384             : class Int32x4Buffer extends _TypedDataBuffer<Int32x4> {
     385             :   static Int32x4 _zero = new Int32x4(0, 0, 0, 0);
     386             :   Int32x4Buffer([int initialLength = 0])
     387           0 :       : super(new Int32x4List(initialLength));
     388           0 :   Int32x4 get _defaultValue => _zero;
     389           0 :   Int32x4List _createBuffer(int size) => new Int32x4List(size);
     390             : }
     391             : 
     392             : class Float32x4Buffer extends _TypedDataBuffer<Float32x4> {
     393             :   Float32x4Buffer([int initialLength = 0])
     394           0 :       : super(new Float32x4List(initialLength));
     395           0 :   Float32x4 get _defaultValue => new Float32x4.zero();
     396           0 :   Float32x4List _createBuffer(int size) => new Float32x4List(size);
     397             : }

Generated by: LCOV version 1.13