Index: runtime/lib/typed_data.dart |
=================================================================== |
--- runtime/lib/typed_data.dart (revision 31662) |
+++ runtime/lib/typed_data.dart (working copy) |
@@ -62,6 +62,8 @@ |
int length]) { |
return new _Uint8ClampedArrayView(buffer, offsetInBytes, length); |
} |
+ |
+ bool _isClamped() { return true; } |
} |
@@ -523,15 +525,63 @@ |
return IterableMixinWorkaround.getRangeList(this, start, end); |
} |
- void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { |
- if (!_setRange(start, end - start, iterable, skipCount)) { |
- IterableMixinWorkaround.setRangeList(this, start, |
- end, iterable, skipCount); |
+ bool _isClamped() { return false; } |
+ |
+ void setRange(int start, int end, Iterable from, [int skipCount = 0]) { |
+ // Check ranges. |
+ if ((start < 0) || (start > length)) { |
+ _throwRangeError(start, length + 1); |
} |
+ if ((end < 0) || (end > length)) { |
+ _throwRangeError(end, length + 1); |
+ } |
+ if (start > end) { |
+ _throwRangeError(start, end + 1); |
+ } |
+ if (skipCount < 0) { |
+ throw new ArgumentError(skipCount); |
+ } |
+ |
+ final count = end - start; |
+ if ((from.length - skipCount) < count) { |
+ throw new StateError("Not enough elements"); |
+ } |
+ |
+ if (from is _TypedListBase) { |
+ final needsClamping = |
+ this._isClamped() && (this._isClamped() != from._isClamped()); |
+ if (this.elementSizeInBytes == from.elementSizeInBytes) { |
+ if (needsClamping) { |
+ Lists.copy(from, skipCount, this, start, count); |
+ return; |
+ } else if (this.buffer._setRange( |
+ start * elementSizeInBytes + this.offsetInBytes, |
+ count * elementSizeInBytes, |
+ from.buffer, |
+ skipCount * elementSizeInBytes + from.offsetInBytes)) { |
+ return; |
+ } |
+ } else if (from.buffer == this.buffer) { |
+ // Different element sizes, but same buffer means that we need |
+ // an intermediate structure. |
+ // TODO(srdjan): Optimize to skip copying if the range does not overlap. |
+ final temp_buffer = new List(count); |
+ for (int i = 0; i < count; i++) { |
+ temp_buffer[i] = from[skipCount + i]; |
+ } |
+ for (int i = start; i < end; i++) { |
+ this[i] = temp_buffer[i - start]; |
+ } |
+ return; |
+ } |
+ } |
+ IterableMixinWorkaround.setRangeList(this, start, |
+ end, from, skipCount); |
} |
void setAll(int index, Iterable iterable) { |
- IterableMixinWorkaround.setAllList(this, index, iterable); |
+ final end = iterable.length + index; |
+ setRange(index, end, iterable); |
} |
void fillRange(int start, int end, [fillValue]) { |
@@ -548,7 +598,11 @@ |
// Internal utility methods. |
- bool _setRange(int start, int length, Iterable from, int startFrom) |
+ // Returns true if operation succeeds. |
+ // Returns false if 'from' and 'this' do not have the same element types. |
+ // The copy occurs using a memory copy (no clamping, conversion, etc). |
+ bool _setRange(int startInBytes, int lengthInBytes, |
+ _TypedListBase from, int startFromInBytes) |
native "TypedData_setRange"; |
} |
@@ -567,12 +621,10 @@ |
return this; |
} |
- |
// Methods implementing the collection interface. |
int get length native "TypedData_length"; |
- |
// Internal utility methods. |
int _getInt8(int offsetInBytes) native "TypedData_GetInt8"; |
@@ -738,6 +790,7 @@ |
return new _Uint8ClampedArrayView(buffer, offsetInBytes, length); |
} |
+ bool _isClamped() { return true; } |
// Methods implementing List interface. |
@@ -1503,6 +1556,7 @@ |
return _new(length); |
} |
+ bool _isClamped() { return true; } |
// Method(s) implementing the List interface. |
@@ -2286,7 +2340,6 @@ |
length = _length { |
} |
- |
// Method(s) implementing the TypedData interface. |
int get lengthInBytes { |
@@ -2419,6 +2472,8 @@ |
} |
+ bool _isClamped() { return true; } |
+ |
// Method(s) implementing List interface. |
int operator[](int index) { |