OLD | NEW |
| (Empty) |
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 /** | |
6 * Specialized integers and floating point numbers, | |
7 * with SIMD support and efficient lists. | |
8 */ | |
9 library dart.typed_data.implementation; | |
10 | |
11 import 'dart:collection'; | |
12 import 'dart:_internal'; | |
13 import 'dart:_interceptors' show JSIndexable, JSUInt32, JSUInt31; | |
14 import 'dart:_js_helper' | |
15 show Creates, JavaScriptIndexingBehavior, JSName, Null, Returns; | |
16 import 'dart:_foreign_helper' show JS; | |
17 import 'dart:math' as Math; | |
18 | |
19 import 'dart:typed_data'; | |
20 | |
21 /** | |
22 * Describes endianness to be used when accessing a sequence of bytes. | |
23 */ | |
24 class Endianness { | |
25 const Endianness._(this._littleEndian); | |
26 | |
27 static const Endianness BIG_ENDIAN = const Endianness._(false); | |
28 static const Endianness LITTLE_ENDIAN = const Endianness._(true); | |
29 static final Endianness HOST_ENDIAN = | |
30 (new ByteData.view(new Int16List.fromList([1]).buffer)).getInt8(0) == 1 | |
31 ? LITTLE_ENDIAN | |
32 : BIG_ENDIAN; | |
33 | |
34 final bool _littleEndian; | |
35 } | |
36 | |
37 | |
38 class NativeByteBuffer implements ByteBuffer native "ArrayBuffer" { | |
39 @JSName('byteLength') | |
40 final int lengthInBytes; | |
41 | |
42 Type get runtimeType => ByteBuffer; | |
43 | |
44 Uint8List asUint8List([int offsetInBytes = 0, int length]) { | |
45 return new NativeUint8List.view(this, offsetInBytes, length); | |
46 } | |
47 Int8List asInt8List([int offsetInBytes = 0, int length]) { | |
48 return new NativeInt8List.view(this, offsetInBytes, length); | |
49 } | |
50 Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) { | |
51 return new NativeUint8ClampedList.view(this, offsetInBytes, length); | |
52 } | |
53 Uint16List asUint16List([int offsetInBytes = 0, int length]) { | |
54 return new NativeUint16List.view(this, offsetInBytes, length); | |
55 } | |
56 Int16List asInt16List([int offsetInBytes = 0, int length]) { | |
57 return new NativeInt16List.view(this, offsetInBytes, length); | |
58 } | |
59 Uint32List asUint32List([int offsetInBytes = 0, int length]) { | |
60 return new NativeUint32List.view(this, offsetInBytes, length); | |
61 } | |
62 Int32List asInt32List([int offsetInBytes = 0, int length]) { | |
63 return new NativeInt32List.view(this, offsetInBytes, length); | |
64 } | |
65 Uint64List asUint64List([int offsetInBytes = 0, int length]) { | |
66 throw new UnsupportedError("Uint64List not supported by dart2js."); | |
67 } | |
68 Int64List asInt64List([int offsetInBytes = 0, int length]) { | |
69 throw new UnsupportedError("Int64List not supported by dart2js."); | |
70 } | |
71 Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) { | |
72 throw new UnimplementedError(); | |
73 } | |
74 Float32List asFloat32List([int offsetInBytes = 0, int length]) { | |
75 return new NativeFloat32List.view(this, offsetInBytes, length); | |
76 } | |
77 Float64List asFloat64List([int offsetInBytes = 0, int length]) { | |
78 return new NativeFloat64List.view(this, offsetInBytes, length); | |
79 } | |
80 Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) { | |
81 throw new UnimplementedError(); | |
82 } | |
83 Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) { | |
84 throw new UnimplementedError(); | |
85 } | |
86 ByteData asByteData([int offsetInBytes = 0, int length]) { | |
87 return new NativeByteData.view(this, offsetInBytes, length); | |
88 } | |
89 } | |
90 | |
91 class NativeTypedData implements TypedData native "ArrayBufferView" { | |
92 /** | |
93 * Returns the byte buffer associated with this object. | |
94 */ | |
95 @Creates('NativeByteBuffer') | |
96 // May be Null for IE's CanvasPixelArray. | |
97 @Returns('NativeByteBuffer|Null') | |
98 final ByteBuffer buffer; | |
99 | |
100 /** | |
101 * Returns the length of this view, in bytes. | |
102 */ | |
103 @JSName('byteLength') | |
104 final int lengthInBytes; | |
105 | |
106 /** | |
107 * Returns the offset in bytes into the underlying byte buffer of this view. | |
108 */ | |
109 @JSName('byteOffset') | |
110 final int offsetInBytes; | |
111 | |
112 /** | |
113 * Returns the number of bytes in the representation of each element in this | |
114 * list. | |
115 */ | |
116 @JSName('BYTES_PER_ELEMENT') | |
117 final int elementSizeInBytes; | |
118 | |
119 void _invalidIndex(int index, int length) { | |
120 if (index < 0 || index >= length) { | |
121 throw new RangeError.range(index, 0, length); | |
122 } else { | |
123 throw new ArgumentError('Invalid list index $index'); | |
124 } | |
125 } | |
126 | |
127 void _checkIndex(int index, int length) { | |
128 if (JS('bool', '(# >>> 0) !== #', index, index) || | |
129 JS('int', '#', index) >= length) { // 'int' guaranteed by above test. | |
130 _invalidIndex(index, length); | |
131 } | |
132 } | |
133 | |
134 int _checkSublistArguments(int start, int end, int length) { | |
135 // For `sublist` the [start] and [end] indices are allowed to be equal to | |
136 // [length]. However, [_checkIndex] only allows indices in the range | |
137 // 0 .. length - 1. We therefore increment the [length] argument by one | |
138 // for the [_checkIndex] checks. | |
139 _checkIndex(start, length + 1); | |
140 if (end == null) return length; | |
141 _checkIndex(end, length + 1); | |
142 if (start > end) throw new RangeError.range(start, 0, end); | |
143 return end; | |
144 } | |
145 } | |
146 | |
147 | |
148 // Validates the unnamed constructor length argument. Checking is necessary | |
149 // because passing unvalidated values to the native constructors can cause | |
150 // conversions or create views. | |
151 int _checkLength(length) { | |
152 if (length is! int) throw new ArgumentError('Invalid length $length'); | |
153 return length; | |
154 } | |
155 | |
156 // Validates `.view` constructor arguments. Checking is necessary because | |
157 // passing unvalidated values to the native constructors can cause conversions | |
158 // (e.g. String arguments) or create typed data objects that are not actually | |
159 // views of the input. | |
160 void _checkViewArguments(buffer, offsetInBytes, length) { | |
161 if (buffer is! NativeByteBuffer) { | |
162 throw new ArgumentError('Invalid view buffer'); | |
163 } | |
164 if (offsetInBytes is! int) { | |
165 throw new ArgumentError('Invalid view offsetInBytes $offsetInBytes'); | |
166 } | |
167 if (length != null && length is! int) { | |
168 throw new ArgumentError('Invalid view length $length'); | |
169 } | |
170 } | |
171 | |
172 // Ensures that [list] is a JavaScript Array or a typed array. If necessary, | |
173 // returns a copy of the list. | |
174 List _ensureNativeList(List list) { | |
175 if (list is JSIndexable) return list; | |
176 List result = new List(list.length); | |
177 for (int i = 0; i < list.length; i++) { | |
178 result[i] = list[i]; | |
179 } | |
180 return result; | |
181 } | |
182 | |
183 | |
184 class NativeByteData extends NativeTypedData implements ByteData | |
185 native "DataView" { | |
186 /** | |
187 * Creates a [ByteData] of the specified length (in elements), all of | |
188 * whose elements are initially zero. | |
189 */ | |
190 factory NativeByteData(int length) => _create1(_checkLength(length)); | |
191 | |
192 /** | |
193 * Creates an [ByteData] _view_ of the specified region in the specified | |
194 * byte buffer. Changes in the [ByteData] will be visible in the byte | |
195 * buffer and vice versa. If the [offsetInBytes] index of the region is not | |
196 * specified, it defaults to zero (the first byte in the byte buffer). | |
197 * If the length is not specified, it defaults to null, which indicates | |
198 * that the view extends to the end of the byte buffer. | |
199 * | |
200 * Throws [RangeError] if [offsetInBytes] or [length] are negative, or | |
201 * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than | |
202 * the length of [buffer]. | |
203 */ | |
204 factory NativeByteData.view(ByteBuffer buffer, | |
205 [int offsetInBytes = 0, int length]) { | |
206 _checkViewArguments(buffer, offsetInBytes, length); | |
207 return length == null | |
208 ? _create2(buffer, offsetInBytes) | |
209 : _create3(buffer, offsetInBytes, length); | |
210 } | |
211 | |
212 Type get runtimeType => ByteData; | |
213 | |
214 int get elementSizeInBytes => 1; | |
215 | |
216 /** | |
217 * Returns the floating point number represented by the four bytes at | |
218 * the specified [byteOffset] in this object, in IEEE 754 | |
219 * single-precision binary floating-point format (binary32). | |
220 * | |
221 * Throws [RangeError] if [byteOffset] is negative, or | |
222 * `byteOffset + 4` is greater than the length of this object. | |
223 */ | |
224 num getFloat32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => | |
225 _getFloat32(byteOffset, endian._littleEndian); | |
226 | |
227 @JSName('getFloat32') | |
228 @Returns('num') | |
229 num _getFloat32(int byteOffset, [bool littleEndian]) native; | |
230 | |
231 /** | |
232 * Returns the floating point number represented by the eight bytes at | |
233 * the specified [byteOffset] in this object, in IEEE 754 | |
234 * double-precision binary floating-point format (binary64). | |
235 * | |
236 * Throws [RangeError] if [byteOffset] is negative, or | |
237 * `byteOffset + 8` is greater than the length of this object. | |
238 */ | |
239 num getFloat64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => | |
240 _getFloat64(byteOffset, endian._littleEndian); | |
241 | |
242 @JSName('getFloat64') | |
243 @Returns('num') | |
244 num _getFloat64(int byteOffset, [bool littleEndian]) native; | |
245 | |
246 /** | |
247 * Returns the (possibly negative) integer represented by the two bytes at | |
248 * the specified [byteOffset] in this object, in two's complement binary | |
249 * form. | |
250 * The return value will be between 2<sup>15</sup> and 2<sup>15</sup> - 1, | |
251 * inclusive. | |
252 * | |
253 * Throws [RangeError] if [byteOffset] is negative, or | |
254 * `byteOffset + 2` is greater than the length of this object. | |
255 */ | |
256 int getInt16(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => | |
257 _getInt16(byteOffset, endian._littleEndian); | |
258 | |
259 @JSName('getInt16') | |
260 @Returns('int') | |
261 int _getInt16(int byteOffset, [bool littleEndian]) native; | |
262 | |
263 /** | |
264 * Returns the (possibly negative) integer represented by the four bytes at | |
265 * the specified [byteOffset] in this object, in two's complement binary | |
266 * form. | |
267 * The return value will be between 2<sup>31</sup> and 2<sup>31</sup> - 1, | |
268 * inclusive. | |
269 * | |
270 * Throws [RangeError] if [byteOffset] is negative, or | |
271 * `byteOffset + 4` is greater than the length of this object. | |
272 */ | |
273 int getInt32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => | |
274 _getInt32(byteOffset, endian._littleEndian); | |
275 | |
276 @JSName('getInt32') | |
277 @Returns('int') | |
278 int _getInt32(int byteOffset, [bool littleEndian]) native; | |
279 | |
280 /** | |
281 * Returns the (possibly negative) integer represented by the eight bytes at | |
282 * the specified [byteOffset] in this object, in two's complement binary | |
283 * form. | |
284 * The return value will be between 2<sup>63</sup> and 2<sup>63</sup> - 1, | |
285 * inclusive. | |
286 * | |
287 * Throws [RangeError] if [byteOffset] is negative, or | |
288 * `byteOffset + 8` is greater than the length of this object. | |
289 */ | |
290 int getInt64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) { | |
291 throw new UnsupportedError('Int64 accessor not supported by dart2js.'); | |
292 } | |
293 | |
294 /** | |
295 * Returns the (possibly negative) integer represented by the byte at the | |
296 * specified [byteOffset] in this object, in two's complement binary | |
297 * representation. The return value will be between -128 and 127, inclusive. | |
298 * | |
299 * Throws [RangeError] if [byteOffset] is negative, or | |
300 * greater than or equal to the length of this object. | |
301 */ | |
302 int getInt8(int byteOffset) native; | |
303 | |
304 /** | |
305 * Returns the positive integer represented by the two bytes starting | |
306 * at the specified [byteOffset] in this object, in unsigned binary | |
307 * form. | |
308 * The return value will be between 0 and 2<sup>16</sup> - 1, inclusive. | |
309 * | |
310 * Throws [RangeError] if [byteOffset] is negative, or | |
311 * `byteOffset + 2` is greater than the length of this object. | |
312 */ | |
313 int getUint16(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => | |
314 _getUint16(byteOffset, endian._littleEndian); | |
315 | |
316 @JSName('getUint16') | |
317 @Returns('JSUInt31') | |
318 int _getUint16(int byteOffset, [bool littleEndian]) native; | |
319 | |
320 /** | |
321 * Returns the positive integer represented by the four bytes starting | |
322 * at the specified [byteOffset] in this object, in unsigned binary | |
323 * form. | |
324 * The return value will be between 0 and 2<sup>32</sup> - 1, inclusive. | |
325 * | |
326 * Throws [RangeError] if [byteOffset] is negative, or | |
327 * `byteOffset + 4` is greater than the length of this object. | |
328 */ | |
329 int getUint32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => | |
330 _getUint32(byteOffset, endian._littleEndian); | |
331 | |
332 @JSName('getUint32') | |
333 @Returns('JSUInt32') | |
334 int _getUint32(int byteOffset, [bool littleEndian]) native; | |
335 | |
336 /** | |
337 * Returns the positive integer represented by the eight bytes starting | |
338 * at the specified [byteOffset] in this object, in unsigned binary | |
339 * form. | |
340 * The return value will be between 0 and 2<sup>64</sup> - 1, inclusive. | |
341 * | |
342 * Throws [RangeError] if [byteOffset] is negative, or | |
343 * `byteOffset + 8` is greater than the length of this object. | |
344 */ | |
345 int getUint64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) { | |
346 throw new UnsupportedError('Uint64 accessor not supported by dart2js.'); | |
347 } | |
348 | |
349 /** | |
350 * Returns the positive integer represented by the byte at the specified | |
351 * [byteOffset] in this object, in unsigned binary form. The | |
352 * return value will be between 0 and 255, inclusive. | |
353 * | |
354 * Throws [RangeError] if [byteOffset] is negative, or | |
355 * greater than or equal to the length of this object. | |
356 */ | |
357 int getUint8(int byteOffset) native; | |
358 | |
359 /** | |
360 * Sets the four bytes starting at the specified [byteOffset] in this | |
361 * object to the IEEE 754 single-precision binary floating-point | |
362 * (binary32) representation of the specified [value]. | |
363 * | |
364 * **Note that this method can lose precision.** The input [value] is | |
365 * a 64-bit floating point value, which will be converted to 32-bit | |
366 * floating point value by IEEE 754 rounding rules before it is stored. | |
367 * If [value] cannot be represented exactly as a binary32, it will be | |
368 * converted to the nearest binary32 value. If two binary32 values are | |
369 * equally close, the one whose least significant bit is zero will be used. | |
370 * Note that finite (but large) values can be converted to infinity, and | |
371 * small non-zero values can be converted to zero. | |
372 * | |
373 * Throws [RangeError] if [byteOffset] is negative, or | |
374 * `byteOffset + 4` is greater than the length of this object. | |
375 */ | |
376 void setFloat32(int byteOffset, num value, | |
377 [Endianness endian=Endianness.BIG_ENDIAN]) => | |
378 _setFloat32(byteOffset, value, endian._littleEndian); | |
379 | |
380 @JSName('setFloat32') | |
381 void _setFloat32(int byteOffset, num value, [bool littleEndian]) native; | |
382 | |
383 /** | |
384 * Sets the eight bytes starting at the specified [byteOffset] in this | |
385 * object to the IEEE 754 double-precision binary floating-point | |
386 * (binary64) representation of the specified [value]. | |
387 * | |
388 * Throws [RangeError] if [byteOffset] is negative, or | |
389 * `byteOffset + 8` is greater than the length of this object. | |
390 */ | |
391 void setFloat64(int byteOffset, num value, | |
392 [Endianness endian=Endianness.BIG_ENDIAN]) => | |
393 _setFloat64(byteOffset, value, endian._littleEndian); | |
394 | |
395 @JSName('setFloat64') | |
396 void _setFloat64(int byteOffset, num value, [bool littleEndian]) native; | |
397 | |
398 /** | |
399 * Sets the two bytes starting at the specified [byteOffset] in this | |
400 * object to the two's complement binary representation of the specified | |
401 * [value], which must fit in two bytes. In other words, [value] must lie | |
402 * between 2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive. | |
403 * | |
404 * Throws [RangeError] if [byteOffset] is negative, or | |
405 * `byteOffset + 2` is greater than the length of this object. | |
406 */ | |
407 void setInt16(int byteOffset, int value, | |
408 [Endianness endian=Endianness.BIG_ENDIAN]) => | |
409 _setInt16(byteOffset, value, endian._littleEndian); | |
410 | |
411 @JSName('setInt16') | |
412 void _setInt16(int byteOffset, int value, [bool littleEndian]) native; | |
413 | |
414 /** | |
415 * Sets the four bytes starting at the specified [byteOffset] in this | |
416 * object to the two's complement binary representation of the specified | |
417 * [value], which must fit in four bytes. In other words, [value] must lie | |
418 * between 2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive. | |
419 * | |
420 * Throws [RangeError] if [byteOffset] is negative, or | |
421 * `byteOffset + 4` is greater than the length of this object. | |
422 */ | |
423 void setInt32(int byteOffset, int value, | |
424 [Endianness endian=Endianness.BIG_ENDIAN]) => | |
425 _setInt32(byteOffset, value, endian._littleEndian); | |
426 | |
427 @JSName('setInt32') | |
428 void _setInt32(int byteOffset, int value, [bool littleEndian]) native; | |
429 | |
430 /** | |
431 * Sets the eight bytes starting at the specified [byteOffset] in this | |
432 * object to the two's complement binary representation of the specified | |
433 * [value], which must fit in eight bytes. In other words, [value] must lie | |
434 * between 2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive. | |
435 * | |
436 * Throws [RangeError] if [byteOffset] is negative, or | |
437 * `byteOffset + 8` is greater than the length of this object. | |
438 */ | |
439 void setInt64(int byteOffset, int value, | |
440 [Endianness endian=Endianness.BIG_ENDIAN]) { | |
441 throw new UnsupportedError('Int64 accessor not supported by dart2js.'); | |
442 } | |
443 | |
444 /** | |
445 * Sets the byte at the specified [byteOffset] in this object to the | |
446 * two's complement binary representation of the specified [value], which | |
447 * must fit in a single byte. In other words, [value] must be between | |
448 * -128 and 127, inclusive. | |
449 * | |
450 * Throws [RangeError] if [byteOffset] is negative, or | |
451 * greater than or equal to the length of this object. | |
452 */ | |
453 void setInt8(int byteOffset, int value) native; | |
454 | |
455 /** | |
456 * Sets the two bytes starting at the specified [byteOffset] in this object | |
457 * to the unsigned binary representation of the specified [value], | |
458 * which must fit in two bytes. in other words, [value] must be between | |
459 * 0 and 2<sup>16</sup> - 1, inclusive. | |
460 * | |
461 * Throws [RangeError] if [byteOffset] is negative, or | |
462 * `byteOffset + 2` is greater than the length of this object. | |
463 */ | |
464 void setUint16(int byteOffset, int value, | |
465 [Endianness endian=Endianness.BIG_ENDIAN]) => | |
466 _setUint16(byteOffset, value, endian._littleEndian); | |
467 | |
468 @JSName('setUint16') | |
469 void _setUint16(int byteOffset, int value, [bool littleEndian]) native; | |
470 | |
471 /** | |
472 * Sets the four bytes starting at the specified [byteOffset] in this object | |
473 * to the unsigned binary representation of the specified [value], | |
474 * which must fit in four bytes. in other words, [value] must be between | |
475 * 0 and 2<sup>32</sup> - 1, inclusive. | |
476 * | |
477 * Throws [RangeError] if [byteOffset] is negative, or | |
478 * `byteOffset + 4` is greater than the length of this object. | |
479 */ | |
480 void setUint32(int byteOffset, int value, | |
481 [Endianness endian=Endianness.BIG_ENDIAN]) => | |
482 _setUint32(byteOffset, value, endian._littleEndian); | |
483 | |
484 @JSName('setUint32') | |
485 void _setUint32(int byteOffset, int value, [bool littleEndian]) native; | |
486 | |
487 /** | |
488 * Sets the eight bytes starting at the specified [byteOffset] in this object | |
489 * to the unsigned binary representation of the specified [value], | |
490 * which must fit in eight bytes. in other words, [value] must be between | |
491 * 0 and 2<sup>64</sup> - 1, inclusive. | |
492 * | |
493 * Throws [RangeError] if [byteOffset] is negative, or | |
494 * `byteOffset + 8` is greater than the length of this object. | |
495 */ | |
496 void setUint64(int byteOffset, int value, | |
497 [Endianness endian=Endianness.BIG_ENDIAN]) { | |
498 throw new UnsupportedError('Uint64 accessor not supported by dart2js.'); | |
499 } | |
500 | |
501 /** | |
502 * Sets the byte at the specified [byteOffset] in this object to the | |
503 * unsigned binary representation of the specified [value], which must fit | |
504 * in a single byte. in other words, [value] must be between 0 and 255, | |
505 * inclusive. | |
506 * | |
507 * Throws [RangeError] if [byteOffset] is negative, | |
508 * or greater than or equal to the length of this object. | |
509 */ | |
510 void setUint8(int byteOffset, int value) native; | |
511 | |
512 static NativeByteData _create1(arg) => | |
513 JS('NativeByteData', 'new DataView(new ArrayBuffer(#))', arg); | |
514 | |
515 static NativeByteData _create2(arg1, arg2) => | |
516 JS('NativeByteData', 'new DataView(#, #)', arg1, arg2); | |
517 | |
518 static NativeByteData _create3(arg1, arg2, arg3) => | |
519 JS('NativeByteData', 'new DataView(#, #, #)', arg1, arg2, arg3); | |
520 } | |
521 | |
522 | |
523 abstract class NativeTypedArray extends NativeTypedData | |
524 implements JavaScriptIndexingBehavior { | |
525 int get length => JS('JSUInt32', '#.length', this); | |
526 | |
527 bool _setRangeFast(int start, int end, | |
528 NativeTypedArray source, int skipCount) { | |
529 int targetLength = this.length; | |
530 _checkIndex(start, targetLength + 1); | |
531 _checkIndex(end, targetLength + 1); | |
532 if (start > end) throw new RangeError.range(start, 0, end); | |
533 int count = end - start; | |
534 | |
535 if (skipCount < 0) throw new ArgumentError(skipCount); | |
536 | |
537 int sourceLength = source.length; | |
538 if (sourceLength - skipCount < count) { | |
539 throw new StateError('Not enough elements'); | |
540 } | |
541 | |
542 if (skipCount != 0 || sourceLength != count) { | |
543 // Create a view of the exact subrange that is copied from the source. | |
544 source = JS('', '#.subarray(#, #)', | |
545 source, skipCount, skipCount + count); | |
546 } | |
547 JS('void', '#.set(#, #)', this, source, start); | |
548 } | |
549 } | |
550 | |
551 abstract class NativeTypedArrayOfDouble | |
552 extends NativeTypedArray | |
553 with ListMixin<double>, FixedLengthListMixin<double> | |
554 implements List<double> { | |
555 | |
556 num operator[](int index) { | |
557 _checkIndex(index, length); | |
558 return JS('num', '#[#]', this, index); | |
559 } | |
560 | |
561 void operator[]=(int index, num value) { | |
562 _checkIndex(index, length); | |
563 JS('void', '#[#] = #', this, index, value); | |
564 } | |
565 | |
566 void setRange(int start, int end, Iterable<double> iterable, | |
567 [int skipCount = 0]) { | |
568 if (iterable is NativeTypedArrayOfDouble) { | |
569 _setRangeFast(start, end, iterable, skipCount); | |
570 return; | |
571 } | |
572 super.setRange(start, end, iterable, skipCount); | |
573 } | |
574 } | |
575 | |
576 abstract class NativeTypedArrayOfInt | |
577 extends NativeTypedArray | |
578 with ListMixin<int>, FixedLengthListMixin<int> | |
579 implements List<int> { | |
580 | |
581 // operator[]() is not here since different versions have different return | |
582 // types | |
583 | |
584 void operator[]=(int index, int value) { | |
585 _checkIndex(index, length); | |
586 JS('void', '#[#] = #', this, index, value); | |
587 } | |
588 | |
589 void setRange(int start, int end, Iterable<int> iterable, | |
590 [int skipCount = 0]) { | |
591 if (iterable is NativeTypedArrayOfInt) { | |
592 _setRangeFast(start, end, iterable, skipCount); | |
593 return; | |
594 } | |
595 super.setRange(start, end, iterable, skipCount); | |
596 } | |
597 } | |
598 | |
599 | |
600 class NativeFloat32List | |
601 extends NativeTypedArrayOfDouble | |
602 implements Float32List | |
603 native "Float32Array" { | |
604 | |
605 factory NativeFloat32List(int length) => _create1(_checkLength(length)); | |
606 | |
607 factory NativeFloat32List.fromList(List<double> elements) => | |
608 _create1(_ensureNativeList(elements)); | |
609 | |
610 factory NativeFloat32List.view(ByteBuffer buffer, | |
611 int offsetInBytes, int length) { | |
612 _checkViewArguments(buffer, offsetInBytes, length); | |
613 return length == null | |
614 ? _create2(buffer, offsetInBytes) | |
615 : _create3(buffer, offsetInBytes, length); | |
616 } | |
617 | |
618 Type get runtimeType => Float32List; | |
619 | |
620 List<double> sublist(int start, [int end]) { | |
621 end = _checkSublistArguments(start, end, length); | |
622 var source = JS('NativeFloat32List', '#.subarray(#, #)', this, start, end); | |
623 return _create1(source); | |
624 } | |
625 | |
626 static NativeFloat32List _create1(arg) => | |
627 JS('NativeFloat32List', 'new Float32Array(#)', arg); | |
628 | |
629 static NativeFloat32List _create2(arg1, arg2) => | |
630 JS('NativeFloat32List', 'new Float32Array(#, #)', arg1, arg2); | |
631 | |
632 static NativeFloat32List _create3(arg1, arg2, arg3) => | |
633 JS('NativeFloat32List', 'new Float32Array(#, #, #)', arg1, arg2, arg3); | |
634 } | |
635 | |
636 | |
637 class NativeFloat64List | |
638 extends NativeTypedArrayOfDouble | |
639 implements Float64List | |
640 native "Float64Array" { | |
641 | |
642 factory NativeFloat64List(int length) => _create1(_checkLength(length)); | |
643 | |
644 factory NativeFloat64List.fromList(List<double> elements) => | |
645 _create1(_ensureNativeList(elements)); | |
646 | |
647 factory NativeFloat64List.view(ByteBuffer buffer, | |
648 int offsetInBytes, int length) { | |
649 _checkViewArguments(buffer, offsetInBytes, length); | |
650 return length == null | |
651 ? _create2(buffer, offsetInBytes) | |
652 : _create3(buffer, offsetInBytes, length); | |
653 } | |
654 | |
655 Type get runtimeType => Float64List; | |
656 | |
657 List<double> sublist(int start, [int end]) { | |
658 end = _checkSublistArguments(start, end, length); | |
659 var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, end); | |
660 return _create1(source); | |
661 } | |
662 | |
663 static NativeFloat64List _create1(arg) => | |
664 JS('NativeFloat64List', 'new Float64Array(#)', arg); | |
665 | |
666 static NativeFloat64List _create2(arg1, arg2) => | |
667 JS('NativeFloat64List', 'new Float64Array(#, #)', arg1, arg2); | |
668 | |
669 static NativeFloat64List _create3(arg1, arg2, arg3) => | |
670 JS('NativeFloat64List', 'new Float64Array(#, #, #)', arg1, arg2, arg3); | |
671 } | |
672 | |
673 | |
674 class NativeInt16List | |
675 extends NativeTypedArrayOfInt | |
676 implements Int16List | |
677 native "Int16Array" { | |
678 | |
679 factory NativeInt16List(int length) => _create1(_checkLength(length)); | |
680 | |
681 factory NativeInt16List.fromList(List<int> elements) => | |
682 _create1(_ensureNativeList(elements)); | |
683 | |
684 factory NativeInt16List.view(ByteBuffer buffer, | |
685 [int offsetInBytes = 0, int length]) { | |
686 _checkViewArguments(buffer, offsetInBytes, length); | |
687 return length == null | |
688 ? _create2(buffer, offsetInBytes) | |
689 : _create3(buffer, offsetInBytes, length); | |
690 } | |
691 | |
692 Type get runtimeType => Int16List; | |
693 | |
694 int operator[](int index) { | |
695 _checkIndex(index, length); | |
696 return JS('int', '#[#]', this, index); | |
697 } | |
698 | |
699 List<int> sublist(int start, [int end]) { | |
700 end = _checkSublistArguments(start, end, length); | |
701 var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, end); | |
702 return _create1(source); | |
703 } | |
704 | |
705 static NativeInt16List _create1(arg) => | |
706 JS('NativeInt16List', 'new Int16Array(#)', arg); | |
707 | |
708 static NativeInt16List _create2(arg1, arg2) => | |
709 JS('NativeInt16List', 'new Int16Array(#, #)', arg1, arg2); | |
710 | |
711 static NativeInt16List _create3(arg1, arg2, arg3) => | |
712 JS('NativeInt16List', 'new Int16Array(#, #, #)', arg1, arg2, arg3); | |
713 } | |
714 | |
715 | |
716 class NativeInt32List | |
717 extends NativeTypedArrayOfInt | |
718 implements Int32List | |
719 native "Int32Array" { | |
720 | |
721 factory NativeInt32List(int length) => _create1(_checkLength(length)); | |
722 | |
723 factory NativeInt32List.fromList(List<int> elements) => | |
724 _create1(_ensureNativeList(elements)); | |
725 | |
726 factory NativeInt32List.view(ByteBuffer buffer, | |
727 int offsetInBytes, int length) { | |
728 _checkViewArguments(buffer, offsetInBytes, length); | |
729 return length == null | |
730 ? _create2(buffer, offsetInBytes) | |
731 : _create3(buffer, offsetInBytes, length); | |
732 } | |
733 | |
734 Type get runtimeType => Int32List; | |
735 | |
736 int operator[](int index) { | |
737 _checkIndex(index, length); | |
738 return JS('int', '#[#]', this, index); | |
739 } | |
740 | |
741 List<int> sublist(int start, [int end]) { | |
742 end = _checkSublistArguments(start, end, length); | |
743 var source = JS('NativeInt32List', '#.subarray(#, #)', this, start, end); | |
744 return _create1(source); | |
745 } | |
746 | |
747 static NativeInt32List _create1(arg) => | |
748 JS('NativeInt32List', 'new Int32Array(#)', arg); | |
749 | |
750 static NativeInt32List _create2(arg1, arg2) => | |
751 JS('NativeInt32List', 'new Int32Array(#, #)', arg1, arg2); | |
752 | |
753 static NativeInt32List _create3(arg1, arg2, arg3) => | |
754 JS('NativeInt32List', 'new Int32Array(#, #, #)', arg1, arg2, arg3); | |
755 } | |
756 | |
757 | |
758 class NativeInt8List | |
759 extends NativeTypedArrayOfInt | |
760 implements Int8List | |
761 native "Int8Array" { | |
762 | |
763 factory NativeInt8List(int length) => _create1(_checkLength(length)); | |
764 | |
765 factory NativeInt8List.fromList(List<int> elements) => | |
766 _create1(_ensureNativeList(elements)); | |
767 | |
768 factory NativeInt8List.view(ByteBuffer buffer, | |
769 int offsetInBytes, int length) { | |
770 _checkViewArguments(buffer, offsetInBytes, length); | |
771 return length == null | |
772 ? _create2(buffer, offsetInBytes) | |
773 : _create3(buffer, offsetInBytes, length); | |
774 } | |
775 | |
776 Type get runtimeType => Int8List; | |
777 | |
778 int operator[](int index) { | |
779 _checkIndex(index, length); | |
780 return JS('int', '#[#]', this, index); | |
781 } | |
782 | |
783 List<int> sublist(int start, [int end]) { | |
784 end = _checkSublistArguments(start, end, length); | |
785 var source = JS('NativeInt8List', '#.subarray(#, #)', this, start, end); | |
786 return _create1(source); | |
787 } | |
788 | |
789 static NativeInt8List _create1(arg) => | |
790 JS('NativeInt8List', 'new Int8Array(#)', arg); | |
791 | |
792 static NativeInt8List _create2(arg1, arg2) => | |
793 JS('NativeInt8List', 'new Int8Array(#, #)', arg1, arg2); | |
794 | |
795 static Int8List _create3(arg1, arg2, arg3) => | |
796 JS('NativeInt8List', 'new Int8Array(#, #, #)', arg1, arg2, arg3); | |
797 } | |
798 | |
799 | |
800 class NativeUint16List | |
801 extends NativeTypedArrayOfInt | |
802 implements Uint16List | |
803 native "Uint16Array" { | |
804 | |
805 factory NativeUint16List(int length) => _create1(_checkLength(length)); | |
806 | |
807 factory NativeUint16List.fromList(List<int> list) => | |
808 _create1(_ensureNativeList(list)); | |
809 | |
810 factory NativeUint16List.view(ByteBuffer buffer, | |
811 int offsetInBytes, int length) { | |
812 _checkViewArguments(buffer, offsetInBytes, length); | |
813 return length == null | |
814 ? _create2(buffer, offsetInBytes) | |
815 : _create3(buffer, offsetInBytes, length); | |
816 } | |
817 | |
818 Type get runtimeType => Uint16List; | |
819 | |
820 int operator[](int index) { | |
821 _checkIndex(index, length); | |
822 return JS('JSUInt31', '#[#]', this, index); | |
823 } | |
824 | |
825 List<int> sublist(int start, [int end]) { | |
826 end = _checkSublistArguments(start, end, length); | |
827 var source = JS('NativeUint16List', '#.subarray(#, #)', this, start, end); | |
828 return _create1(source); | |
829 } | |
830 | |
831 static NativeUint16List _create1(arg) => | |
832 JS('NativeUint16List', 'new Uint16Array(#)', arg); | |
833 | |
834 static NativeUint16List _create2(arg1, arg2) => | |
835 JS('NativeUint16List', 'new Uint16Array(#, #)', arg1, arg2); | |
836 | |
837 static NativeUint16List _create3(arg1, arg2, arg3) => | |
838 JS('NativeUint16List', 'new Uint16Array(#, #, #)', arg1, arg2, arg3); | |
839 } | |
840 | |
841 | |
842 class NativeUint32List | |
843 extends NativeTypedArrayOfInt | |
844 implements Uint32List | |
845 native "Uint32Array" { | |
846 | |
847 factory NativeUint32List(int length) => _create1(_checkLength(length)); | |
848 | |
849 factory NativeUint32List.fromList(List<int> elements) => | |
850 _create1(_ensureNativeList(elements)); | |
851 | |
852 factory NativeUint32List.view(ByteBuffer buffer, | |
853 int offsetInBytes, int length) { | |
854 _checkViewArguments(buffer, offsetInBytes, length); | |
855 return length == null | |
856 ? _create2(buffer, offsetInBytes) | |
857 : _create3(buffer, offsetInBytes, length); | |
858 } | |
859 | |
860 Type get runtimeType => Uint32List; | |
861 | |
862 int operator[](int index) { | |
863 _checkIndex(index, length); | |
864 return JS('JSUInt32', '#[#]', this, index); | |
865 } | |
866 | |
867 List<int> sublist(int start, [int end]) { | |
868 end = _checkSublistArguments(start, end, length); | |
869 var source = JS('NativeUint32List', '#.subarray(#, #)', this, start, end); | |
870 return _create1(source); | |
871 } | |
872 | |
873 static NativeUint32List _create1(arg) => | |
874 JS('NativeUint32List', 'new Uint32Array(#)', arg); | |
875 | |
876 static NativeUint32List _create2(arg1, arg2) => | |
877 JS('NativeUint32List', 'new Uint32Array(#, #)', arg1, arg2); | |
878 | |
879 static NativeUint32List _create3(arg1, arg2, arg3) => | |
880 JS('NativeUint32List', 'new Uint32Array(#, #, #)', arg1, arg2, arg3); | |
881 } | |
882 | |
883 | |
884 class NativeUint8ClampedList | |
885 extends NativeTypedArrayOfInt | |
886 implements Uint8ClampedList | |
887 native "Uint8ClampedArray,CanvasPixelArray" { | |
888 | |
889 factory NativeUint8ClampedList(int length) => _create1(_checkLength(length)); | |
890 | |
891 factory NativeUint8ClampedList.fromList(List<int> elements) => | |
892 _create1(_ensureNativeList(elements)); | |
893 | |
894 factory NativeUint8ClampedList.view(ByteBuffer buffer, | |
895 int offsetInBytes, int length) { | |
896 _checkViewArguments(buffer, offsetInBytes, length); | |
897 return length == null | |
898 ? _create2(buffer, offsetInBytes) | |
899 : _create3(buffer, offsetInBytes, length); | |
900 } | |
901 | |
902 Type get runtimeType => Uint8ClampedList; | |
903 | |
904 int get length => JS('JSUInt32', '#.length', this); | |
905 | |
906 int operator[](int index) { | |
907 _checkIndex(index, length); | |
908 return JS('JSUInt31', '#[#]', this, index); | |
909 } | |
910 | |
911 List<int> sublist(int start, [int end]) { | |
912 end = _checkSublistArguments(start, end, length); | |
913 var source = JS('NativeUint8ClampedList', '#.subarray(#, #)', | |
914 this, start, end); | |
915 return _create1(source); | |
916 } | |
917 | |
918 static NativeUint8ClampedList _create1(arg) => | |
919 JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#)', arg); | |
920 | |
921 static NativeUint8ClampedList _create2(arg1, arg2) => | |
922 JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#, #)', arg1, arg2); | |
923 | |
924 static NativeUint8ClampedList _create3(arg1, arg2, arg3) => | |
925 JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#, #, #)', | |
926 arg1, arg2, arg3); | |
927 } | |
928 | |
929 | |
930 class NativeUint8List | |
931 extends NativeTypedArrayOfInt | |
932 implements Uint8List | |
933 // On some browsers Uint8ClampedArray is a subtype of Uint8Array. Marking | |
934 // Uint8List as !nonleaf ensures that the native dispatch correctly handles | |
935 // the potential for Uint8ClampedArray to 'accidentally' pick up the | |
936 // dispatch record for Uint8List. | |
937 native "Uint8Array,!nonleaf" { | |
938 | |
939 factory NativeUint8List(int length) => _create1(_checkLength(length)); | |
940 | |
941 factory NativeUint8List.fromList(List<int> elements) => | |
942 _create1(_ensureNativeList(elements)); | |
943 | |
944 factory NativeUint8List.view(ByteBuffer buffer, | |
945 int offsetInBytes, int length) { | |
946 _checkViewArguments(buffer, offsetInBytes, length); | |
947 return length == null | |
948 ? _create2(buffer, offsetInBytes) | |
949 : _create3(buffer, offsetInBytes, length); | |
950 } | |
951 | |
952 Type get runtimeType => Uint8List; | |
953 | |
954 int get length => JS('JSUInt32', '#.length', this); | |
955 | |
956 int operator[](int index) { | |
957 _checkIndex(index, length); | |
958 return JS('JSUInt31', '#[#]', this, index); | |
959 } | |
960 | |
961 List<int> sublist(int start, [int end]) { | |
962 end = _checkSublistArguments(start, end, length); | |
963 var source = JS('NativeUint8List', '#.subarray(#, #)', this, start, end); | |
964 return _create1(source); | |
965 } | |
966 | |
967 static NativeUint8List _create1(arg) => | |
968 JS('NativeUint8List', 'new Uint8Array(#)', arg); | |
969 | |
970 static NativeUint8List _create2(arg1, arg2) => | |
971 JS('NativeUint8List', 'new Uint8Array(#, #)', arg1, arg2); | |
972 | |
973 static NativeUint8List _create3(arg1, arg2, arg3) => | |
974 JS('NativeUint8List', 'new Uint8Array(#, #, #)', arg1, arg2, arg3); | |
975 } | |
OLD | NEW |