NativeDataView.java revision 1119:e033e2c32122
1/* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25package jdk.nashorn.internal.objects; 26 27import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 28import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 29import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 30 31import java.nio.ByteBuffer; 32import java.nio.ByteOrder; 33import jdk.nashorn.internal.objects.annotations.Attribute; 34import jdk.nashorn.internal.objects.annotations.Constructor; 35import jdk.nashorn.internal.objects.annotations.Function; 36import jdk.nashorn.internal.objects.annotations.Property; 37import jdk.nashorn.internal.objects.annotations.ScriptClass; 38import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 39import jdk.nashorn.internal.runtime.JSType; 40import jdk.nashorn.internal.runtime.PropertyMap; 41import jdk.nashorn.internal.runtime.ScriptObject; 42import jdk.nashorn.internal.runtime.ScriptRuntime; 43 44/** 45 * <p> 46 * DataView builtin constructor. Based on the specification here: 47 * http://www.khronos.org/registry/typedarray/specs/latest/#8 48 * </p> 49 * <p> 50 * An ArrayBuffer is a useful object for representing an arbitrary chunk of data. 51 * In many cases, such data will be read from disk or from the network, and will 52 * not follow the alignment restrictions that are imposed on the typed array views 53 * described earlier. In addition, the data will often be heterogeneous in nature 54 * and have a defined byte order. The DataView view provides a low-level interface 55 * for reading such data from and writing it to an ArrayBuffer. 56 * </p> 57 * <p> 58 * Regardless of the host computer's endianness, DataView reads or writes values 59 * to or from main memory with a specified endianness: big or little. 60 * </p> 61 */ 62@ScriptClass("DataView") 63public class NativeDataView extends ScriptObject { 64 // initialized by nasgen 65 private static PropertyMap $nasgenmap$; 66 67 // inherited ArrayBufferView properties 68 69 /** 70 * Underlying ArrayBuffer storage object 71 */ 72 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 73 public final Object buffer; 74 75 /** 76 * The offset in bytes from the start of the ArrayBuffer 77 */ 78 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 79 public final int byteOffset; 80 81 /** 82 * The number of bytes from the offset that this DataView will reference 83 */ 84 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 85 public final int byteLength; 86 87 // underlying ByteBuffer 88 private final ByteBuffer buf; 89 90 private NativeDataView(final NativeArrayBuffer arrBuf) { 91 this(arrBuf, arrBuf.getBuffer(), 0); 92 } 93 94 private NativeDataView(final NativeArrayBuffer arrBuf, final int offset) { 95 this(arrBuf, bufferFrom(arrBuf, offset), offset); 96 } 97 98 private NativeDataView(final NativeArrayBuffer arrBuf, final int offset, final int length) { 99 this(arrBuf, bufferFrom(arrBuf, offset, length), offset, length); 100 } 101 102 private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset) { 103 this(arrBuf, buf, offset, buf.capacity() - offset); 104 } 105 106 private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset, final int length) { 107 super(Global.instance().getDataViewPrototype(), $nasgenmap$); 108 this.buffer = arrBuf; 109 this.byteOffset = offset; 110 this.byteLength = length; 111 this.buf = buf; 112 } 113 114 /** 115 * Create a new DataView object using the passed ArrayBuffer for its 116 * storage. Optional byteOffset and byteLength can be used to limit the 117 * section of the buffer referenced. The byteOffset indicates the offset in 118 * bytes from the start of the ArrayBuffer, and the byteLength is the number 119 * of bytes from the offset that this DataView will reference. If both 120 * byteOffset and byteLength are omitted, the DataView spans the entire 121 * ArrayBuffer range. If the byteLength is omitted, the DataView extends from 122 * the given byteOffset until the end of the ArrayBuffer. 123 * 124 * If the given byteOffset and byteLength references an area beyond the end 125 * of the ArrayBuffer an exception is raised. 126 127 * @param newObj if this constructor was invoked with 'new' or not 128 * @param self constructor function object 129 * @param args arguments to the constructor 130 * @return newly constructed DataView object 131 */ 132 @Constructor(arity = 1) 133 public static NativeDataView constructor(final boolean newObj, final Object self, final Object... args) { 134 if (args.length == 0 || !(args[0] instanceof NativeArrayBuffer)) { 135 throw typeError("not.an.arraybuffer.in.dataview"); 136 } 137 138 final NativeArrayBuffer arrBuf = (NativeArrayBuffer)args[0]; 139 switch (args.length) { 140 case 1: 141 return new NativeDataView(arrBuf); 142 case 2: 143 return new NativeDataView(arrBuf, JSType.toInt32(args[1])); 144 default: 145 return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2])); 146 } 147 } 148 149 /** 150 * Specialized version of DataView constructor 151 * 152 * @param newObj if this constructor was invoked with 'new' or not 153 * @param self constructor function object 154 * @param arrBuf underlying ArrayBuffer storage object 155 * @param offset offset in bytes from the start of the ArrayBuffer 156 * @return newly constructed DataView object 157 */ 158 @SpecializedFunction(isConstructor=true) 159 public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) { 160 if (!(arrBuf instanceof NativeArrayBuffer)) { 161 throw typeError("not.an.arraybuffer.in.dataview"); 162 } 163 return new NativeDataView((NativeArrayBuffer) arrBuf, offset); 164 } 165 166 /** 167 * Specialized version of DataView constructor 168 * 169 * @param newObj if this constructor was invoked with 'new' or not 170 * @param self constructor function object 171 * @param arrBuf underlying ArrayBuffer storage object 172 * @param offset in bytes from the start of the ArrayBuffer 173 * @param length is the number of bytes from the offset that this DataView will reference 174 * @return newly constructed DataView object 175 */ 176 @SpecializedFunction(isConstructor=true) 177 public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) { 178 if (!(arrBuf instanceof NativeArrayBuffer)) { 179 throw typeError("not.an.arraybuffer.in.dataview"); 180 } 181 return new NativeDataView((NativeArrayBuffer) arrBuf, offset, length); 182 } 183 184 // Gets the value of the given type at the specified byte offset 185 // from the start of the view. There is no alignment constraint; 186 // multi-byte values may be fetched from any offset. 187 // 188 // For multi-byte values, the optional littleEndian argument 189 // indicates whether a big-endian or little-endian value should be 190 // read. If false or undefined, a big-endian value is read. 191 // 192 // These methods raise an exception if they would read 193 // beyond the end of the view. 194 195 /** 196 * Get 8-bit signed int from given byteOffset 197 * 198 * @param self DataView object 199 * @param byteOffset byte offset to read from 200 * @return 8-bit signed int value at the byteOffset 201 */ 202 @Function(attributes = Attribute.NOT_ENUMERABLE) 203 public static int getInt8(final Object self, final Object byteOffset) { 204 try { 205 return getBuffer(self).get(JSType.toInt32(byteOffset)); 206 } catch (final IllegalArgumentException iae) { 207 throw rangeError(iae, "dataview.offset"); 208 } 209 } 210 211 /** 212 * Get 8-bit signed int from given byteOffset 213 * 214 * @param self DataView object 215 * @param byteOffset byte offset to read from 216 * @return 8-bit signed int value at the byteOffset 217 */ 218 @SpecializedFunction 219 public static int getInt8(final Object self, final int byteOffset) { 220 try { 221 return getBuffer(self).get(byteOffset); 222 } catch (final IllegalArgumentException iae) { 223 throw rangeError(iae, "dataview.offset"); 224 } 225 } 226 227 /** 228 * Get 8-bit unsigned int from given byteOffset 229 * 230 * @param self DataView object 231 * @param byteOffset byte offset to read from 232 * @return 8-bit unsigned int value at the byteOffset 233 */ 234 @Function(attributes = Attribute.NOT_ENUMERABLE) 235 public static int getUint8(final Object self, final Object byteOffset) { 236 try { 237 return 0xFF & getBuffer(self).get(JSType.toInt32(byteOffset)); 238 } catch (final IllegalArgumentException iae) { 239 throw rangeError(iae, "dataview.offset"); 240 } 241 } 242 243 /** 244 * Get 8-bit unsigned int from given byteOffset 245 * 246 * @param self DataView object 247 * @param byteOffset byte offset to read from 248 * @return 8-bit unsigned int value at the byteOffset 249 */ 250 @SpecializedFunction 251 public static int getUint8(final Object self, final int byteOffset) { 252 try { 253 return 0xFF & getBuffer(self).get(byteOffset); 254 } catch (final IllegalArgumentException iae) { 255 throw rangeError(iae, "dataview.offset"); 256 } 257 } 258 259 /** 260 * Get 16-bit signed int from given byteOffset 261 * 262 * @param self DataView object 263 * @param byteOffset byte offset to read from 264 * @param littleEndian (optional) flag indicating whether to read in little endian order 265 * @return 16-bit signed int value at the byteOffset 266 */ 267 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 268 public static int getInt16(final Object self, final Object byteOffset, final Object littleEndian) { 269 try { 270 return getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)); 271 } catch (final IllegalArgumentException iae) { 272 throw rangeError(iae, "dataview.offset"); 273 } 274 } 275 276 /** 277 * Get 16-bit signed int from given byteOffset 278 * 279 * @param self DataView object 280 * @param byteOffset byte offset to read from 281 * @return 16-bit signed int value at the byteOffset 282 */ 283 @SpecializedFunction 284 public static int getInt16(final Object self, final int byteOffset) { 285 try { 286 return getBuffer(self, false).getShort(byteOffset); 287 } catch (final IllegalArgumentException iae) { 288 throw rangeError(iae, "dataview.offset"); 289 } 290 } 291 292 /** 293 * Get 16-bit signed int from given byteOffset 294 * 295 * @param self DataView object 296 * @param byteOffset byte offset to read from 297 * @param littleEndian (optional) flag indicating whether to read in little endian order 298 * @return 16-bit signed int value at the byteOffset 299 */ 300 @SpecializedFunction 301 public static int getInt16(final Object self, final int byteOffset, final boolean littleEndian) { 302 try { 303 return getBuffer(self, littleEndian).getShort(byteOffset); 304 } catch (final IllegalArgumentException iae) { 305 throw rangeError(iae, "dataview.offset"); 306 } 307 } 308 309 /** 310 * Get 16-bit unsigned int from given byteOffset 311 * 312 * @param self DataView object 313 * @param byteOffset byte offset to read from 314 * @param littleEndian (optional) flag indicating whether to read in little endian order 315 * @return 16-bit unsigned int value at the byteOffset 316 */ 317 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 318 public static int getUint16(final Object self, final Object byteOffset, final Object littleEndian) { 319 try { 320 return 0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)); 321 } catch (final IllegalArgumentException iae) { 322 throw rangeError(iae, "dataview.offset"); 323 } 324 } 325 326 /** 327 * Get 16-bit unsigned int from given byteOffset 328 * 329 * @param self DataView object 330 * @param byteOffset byte offset to read from 331 * @return 16-bit unsigned int value at the byteOffset 332 */ 333 @SpecializedFunction 334 public static int getUint16(final Object self, final int byteOffset) { 335 try { 336 return 0xFFFF & getBuffer(self, false).getShort(byteOffset); 337 } catch (final IllegalArgumentException iae) { 338 throw rangeError(iae, "dataview.offset"); 339 } 340 } 341 342 /** 343 * Get 16-bit unsigned int from given byteOffset 344 * 345 * @param self DataView object 346 * @param byteOffset byte offset to read from 347 * @param littleEndian (optional) flag indicating whether to read in little endian order 348 * @return 16-bit unsigned int value at the byteOffset 349 */ 350 @SpecializedFunction 351 public static int getUint16(final Object self, final int byteOffset, final boolean littleEndian) { 352 try { 353 return 0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset); 354 } catch (final IllegalArgumentException iae) { 355 throw rangeError(iae, "dataview.offset"); 356 } 357 } 358 359 /** 360 * Get 32-bit signed int from given byteOffset 361 * 362 * @param self DataView object 363 * @param byteOffset byte offset to read from 364 * @param littleEndian (optional) flag indicating whether to read in little endian order 365 * @return 32-bit signed int value at the byteOffset 366 */ 367 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 368 public static int getInt32(final Object self, final Object byteOffset, final Object littleEndian) { 369 try { 370 return getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)); 371 } catch (final IllegalArgumentException iae) { 372 throw rangeError(iae, "dataview.offset"); 373 } 374 } 375 376 /** 377 * Get 32-bit signed int from given byteOffset 378 * 379 * @param self DataView object 380 * @param byteOffset byte offset to read from 381 * @return 32-bit signed int value at the byteOffset 382 */ 383 @SpecializedFunction 384 public static int getInt32(final Object self, final int byteOffset) { 385 try { 386 return getBuffer(self, false).getInt(byteOffset); 387 } catch (final IllegalArgumentException iae) { 388 throw rangeError(iae, "dataview.offset"); 389 } 390 } 391 392 /** 393 * Get 32-bit signed int from given byteOffset 394 * 395 * @param self DataView object 396 * @param byteOffset byte offset to read from 397 * @param littleEndian (optional) flag indicating whether to read in little endian order 398 * @return 32-bit signed int value at the byteOffset 399 */ 400 @SpecializedFunction 401 public static int getInt32(final Object self, final int byteOffset, final boolean littleEndian) { 402 try { 403 return getBuffer(self, littleEndian).getInt(byteOffset); 404 } catch (final IllegalArgumentException iae) { 405 throw rangeError(iae, "dataview.offset"); 406 } 407 } 408 409 /** 410 * Get 32-bit unsigned int from given byteOffset 411 * 412 * @param self DataView object 413 * @param byteOffset byte offset to read from 414 * @param littleEndian (optional) flag indicating whether to read in little endian order 415 * @return 32-bit unsigned int value at the byteOffset 416 */ 417 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 418 public static long getUint32(final Object self, final Object byteOffset, final Object littleEndian) { 419 try { 420 return 0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)); 421 } catch (final IllegalArgumentException iae) { 422 throw rangeError(iae, "dataview.offset"); 423 } 424 } 425 426 /** 427 * Get 32-bit unsigned int from given byteOffset 428 * 429 * @param self DataView object 430 * @param byteOffset byte offset to read from 431 * @return 32-bit unsigned int value at the byteOffset 432 */ 433 @SpecializedFunction 434 public static long getUint32(final Object self, final int byteOffset) { 435 try { 436 return JSType.toUint32(getBuffer(self, false).getInt(JSType.toInt32(byteOffset))); 437 } catch (final IllegalArgumentException iae) { 438 throw rangeError(iae, "dataview.offset"); 439 } 440 } 441 442 /** 443 * Get 32-bit unsigned int from given byteOffset 444 * 445 * @param self DataView object 446 * @param byteOffset byte offset to read from 447 * @param littleEndian (optional) flag indicating whether to read in little endian order 448 * @return 32-bit unsigned int value at the byteOffset 449 */ 450 @SpecializedFunction 451 public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) { 452 try { 453 return JSType.toUint32(getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset))); 454 } catch (final IllegalArgumentException iae) { 455 throw rangeError(iae, "dataview.offset"); 456 } 457 } 458 459 /** 460 * Get 32-bit float value from given byteOffset 461 * 462 * @param self DataView object 463 * @param byteOffset byte offset to read from 464 * @param littleEndian (optional) flag indicating whether to read in little endian order 465 * @return 32-bit float value at the byteOffset 466 */ 467 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 468 public static double getFloat32(final Object self, final Object byteOffset, final Object littleEndian) { 469 try { 470 return getBuffer(self, littleEndian).getFloat(JSType.toInt32(byteOffset)); 471 } catch (final IllegalArgumentException iae) { 472 throw rangeError(iae, "dataview.offset"); 473 } 474 } 475 476 /** 477 * Get 32-bit float value from given byteOffset 478 * 479 * @param self DataView object 480 * @param byteOffset byte offset to read from 481 * @return 32-bit float value at the byteOffset 482 */ 483 @SpecializedFunction 484 public static double getFloat32(final Object self, final int byteOffset) { 485 try { 486 return getBuffer(self, false).getFloat(byteOffset); 487 } catch (final IllegalArgumentException iae) { 488 throw rangeError(iae, "dataview.offset"); 489 } 490 } 491 492 /** 493 * Get 32-bit float value from given byteOffset 494 * 495 * @param self DataView object 496 * @param byteOffset byte offset to read from 497 * @param littleEndian (optional) flag indicating whether to read in little endian order 498 * @return 32-bit float value at the byteOffset 499 */ 500 @SpecializedFunction 501 public static double getFloat32(final Object self, final int byteOffset, final boolean littleEndian) { 502 try { 503 return getBuffer(self, littleEndian).getFloat(byteOffset); 504 } catch (final IllegalArgumentException iae) { 505 throw rangeError(iae, "dataview.offset"); 506 } 507 } 508 509 /** 510 * Get 64-bit float value from given byteOffset 511 * 512 * @param self DataView object 513 * @param byteOffset byte offset to read from 514 * @param littleEndian (optional) flag indicating whether to read in little endian order 515 * @return 64-bit float value at the byteOffset 516 */ 517 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 518 public static double getFloat64(final Object self, final Object byteOffset, final Object littleEndian) { 519 try { 520 return getBuffer(self, littleEndian).getDouble(JSType.toInt32(byteOffset)); 521 } catch (final IllegalArgumentException iae) { 522 throw rangeError(iae, "dataview.offset"); 523 } 524 } 525 526 /** 527 * Get 64-bit float value from given byteOffset 528 * 529 * @param self DataView object 530 * @param byteOffset byte offset to read from 531 * @return 64-bit float value at the byteOffset 532 */ 533 @SpecializedFunction 534 public static double getFloat64(final Object self, final int byteOffset) { 535 try { 536 return getBuffer(self, false).getDouble(byteOffset); 537 } catch (final IllegalArgumentException iae) { 538 throw rangeError(iae, "dataview.offset"); 539 } 540 } 541 542 /** 543 * Get 64-bit float value from given byteOffset 544 * 545 * @param self DataView object 546 * @param byteOffset byte offset to read from 547 * @param littleEndian (optional) flag indicating whether to read in little endian order 548 * @return 64-bit float value at the byteOffset 549 */ 550 @SpecializedFunction 551 public static double getFloat64(final Object self, final int byteOffset, final boolean littleEndian) { 552 try { 553 return getBuffer(self, littleEndian).getDouble(byteOffset); 554 } catch (final IllegalArgumentException iae) { 555 throw rangeError(iae, "dataview.offset"); 556 } 557 } 558 559 // Stores a value of the given type at the specified byte offset 560 // from the start of the view. There is no alignment constraint; 561 // multi-byte values may be stored at any offset. 562 // 563 // For multi-byte values, the optional littleEndian argument 564 // indicates whether the value should be stored in big-endian or 565 // little-endian byte order. If false or undefined, the value is 566 // stored in big-endian byte order. 567 // 568 // These methods raise an exception if they would write 569 // beyond the end of the view. 570 571 /** 572 * Set 8-bit signed int at the given byteOffset 573 * 574 * @param self DataView object 575 * @param byteOffset byte offset to read from 576 * @param value byte value to set 577 * @return undefined 578 */ 579 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 580 public static Object setInt8(final Object self, final Object byteOffset, final Object value) { 581 try { 582 getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value)); 583 return UNDEFINED; 584 } catch (final IllegalArgumentException iae) { 585 throw rangeError(iae, "dataview.offset"); 586 } 587 } 588 589 /** 590 * Set 8-bit signed int at the given byteOffset 591 * 592 * @param self DataView object 593 * @param byteOffset byte offset to read from 594 * @param value byte value to set 595 * @return undefined 596 */ 597 @SpecializedFunction 598 public static Object setInt8(final Object self, final int byteOffset, final int value) { 599 try { 600 getBuffer(self).put(byteOffset, (byte)value); 601 return UNDEFINED; 602 } catch (final IllegalArgumentException iae) { 603 throw rangeError(iae, "dataview.offset"); 604 } 605 } 606 607 /** 608 * Set 8-bit unsigned int at the given byteOffset 609 * 610 * @param self DataView object 611 * @param byteOffset byte offset to write at 612 * @param value byte value to set 613 * @return undefined 614 */ 615 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 616 public static Object setUint8(final Object self, final Object byteOffset, final Object value) { 617 try { 618 getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value)); 619 return UNDEFINED; 620 } catch (final IllegalArgumentException iae) { 621 throw rangeError(iae, "dataview.offset"); 622 } 623 } 624 625 /** 626 * Set 8-bit unsigned int at the given byteOffset 627 * 628 * @param self DataView object 629 * @param byteOffset byte offset to write at 630 * @param value byte value to set 631 * @return undefined 632 */ 633 @SpecializedFunction 634 public static Object setUint8(final Object self, final int byteOffset, final int value) { 635 try { 636 getBuffer(self).put(byteOffset, (byte)value); 637 return UNDEFINED; 638 } catch (final IllegalArgumentException iae) { 639 throw rangeError(iae, "dataview.offset"); 640 } 641 } 642 643 /** 644 * Set 16-bit signed int at the given byteOffset 645 * 646 * @param self DataView object 647 * @param byteOffset byte offset to write at 648 * @param value short value to set 649 * @param littleEndian (optional) flag indicating whether to write in little endian order 650 * @return undefined 651 */ 652 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 653 public static Object setInt16(final Object self, final Object byteOffset, final Object value, final Object littleEndian) { 654 try { 655 getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value)); 656 return UNDEFINED; 657 } catch (final IllegalArgumentException iae) { 658 throw rangeError(iae, "dataview.offset"); 659 } 660 } 661 662 /** 663 * Set 16-bit signed int at the given byteOffset 664 * 665 * @param self DataView object 666 * @param byteOffset byte offset to write at 667 * @param value short value to set 668 * @return undefined 669 */ 670 @SpecializedFunction 671 public static Object setInt16(final Object self, final int byteOffset, final int value) { 672 try { 673 getBuffer(self, false).putShort(byteOffset, (short)value); 674 return UNDEFINED; 675 } catch (final IllegalArgumentException iae) { 676 throw rangeError(iae, "dataview.offset"); 677 } 678 } 679 680 /** 681 * Set 16-bit signed int at the given byteOffset 682 * 683 * @param self DataView object 684 * @param byteOffset byte offset to write at 685 * @param value short value to set 686 * @param littleEndian (optional) flag indicating whether to write in little endian order 687 * @return undefined 688 */ 689 @SpecializedFunction 690 public static Object setInt16(final Object self, final int byteOffset, final int value, final boolean littleEndian) { 691 try { 692 getBuffer(self, littleEndian).putShort(byteOffset, (short)value); 693 return UNDEFINED; 694 } catch (final IllegalArgumentException iae) { 695 throw rangeError(iae, "dataview.offset"); 696 } 697 } 698 699 /** 700 * Set 16-bit unsigned int at the given byteOffset 701 * 702 * @param self DataView object 703 * @param byteOffset byte offset to write at 704 * @param value short value to set 705 * @param littleEndian (optional) flag indicating whether to write in little endian order 706 * @return undefined 707 */ 708 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 709 public static Object setUint16(final Object self, final Object byteOffset, final Object value, final Object littleEndian) { 710 try { 711 getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value)); 712 return UNDEFINED; 713 } catch (final IllegalArgumentException iae) { 714 throw rangeError(iae, "dataview.offset"); 715 } 716 } 717 718 /** 719 * Set 16-bit unsigned int at the given byteOffset 720 * 721 * @param self DataView object 722 * @param byteOffset byte offset to write at 723 * @param value short value to set 724 * @return undefined 725 */ 726 @SpecializedFunction 727 public static Object setUint16(final Object self, final int byteOffset, final int value) { 728 try { 729 getBuffer(self, false).putShort(byteOffset, (short)value); 730 return UNDEFINED; 731 } catch (final IllegalArgumentException iae) { 732 throw rangeError(iae, "dataview.offset"); 733 } 734 } 735 736 /** 737 * Set 16-bit unsigned int at the given byteOffset 738 * 739 * @param self DataView object 740 * @param byteOffset byte offset to write at 741 * @param value short value to set 742 * @param littleEndian (optional) flag indicating whether to write in little endian order 743 * @return undefined 744 */ 745 @SpecializedFunction 746 public static Object setUint16(final Object self, final int byteOffset, final int value, final boolean littleEndian) { 747 try { 748 getBuffer(self, littleEndian).putShort(byteOffset, (short)value); 749 return UNDEFINED; 750 } catch (final IllegalArgumentException iae) { 751 throw rangeError(iae, "dataview.offset"); 752 } 753 } 754 755 /** 756 * Set 32-bit signed int at the given byteOffset 757 * 758 * @param self DataView object 759 * @param byteOffset byte offset to write at 760 * @param value int value to set 761 * @param littleEndian (optional) flag indicating whether to write in little endian order 762 * @return undefined 763 */ 764 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 765 public static Object setInt32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) { 766 try { 767 getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), JSType.toInt32(value)); 768 return UNDEFINED; 769 } catch (final IllegalArgumentException iae) { 770 throw rangeError(iae, "dataview.offset"); 771 } 772 } 773 774 /** 775 * Set 32-bit signed int at the given byteOffset 776 * 777 * @param self DataView object 778 * @param byteOffset byte offset to write at 779 * @param value int value to set 780 * @return undefined 781 */ 782 @SpecializedFunction 783 public static Object setInt32(final Object self, final int byteOffset, final int value) { 784 try { 785 getBuffer(self, false).putInt(byteOffset, value); 786 return UNDEFINED; 787 } catch (final IllegalArgumentException iae) { 788 throw rangeError(iae, "dataview.offset"); 789 } 790 } 791 792 /** 793 * Set 32-bit signed int at the given byteOffset 794 * 795 * @param self DataView object 796 * @param byteOffset byte offset to write at 797 * @param value int value to set 798 * @param littleEndian (optional) flag indicating whether to write in little endian order 799 * @return undefined 800 */ 801 @SpecializedFunction 802 public static Object setInt32(final Object self, final int byteOffset, final int value, final boolean littleEndian) { 803 try { 804 getBuffer(self, littleEndian).putInt(byteOffset, value); 805 return UNDEFINED; 806 } catch (final IllegalArgumentException iae) { 807 throw rangeError(iae, "dataview.offset"); 808 } 809 } 810 811 /** 812 * Set 32-bit unsigned int at the given byteOffset 813 * 814 * @param self DataView object 815 * @param byteOffset byte offset to write at 816 * @param value int value to set 817 * @param littleEndian (optional) flag indicating whether to write in little endian order 818 * @return undefined 819 */ 820 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 821 public static Object setUint32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) { 822 try { 823 getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toUint32(value)); 824 return UNDEFINED; 825 } catch (final IllegalArgumentException iae) { 826 throw rangeError(iae, "dataview.offset"); 827 } 828 } 829 830 /** 831 * Set 32-bit unsigned int at the given byteOffset 832 * 833 * @param self DataView object 834 * @param byteOffset byte offset to write at 835 * @param value int value to set 836 * @return undefined 837 */ 838 @SpecializedFunction 839 public static Object setUint32(final Object self, final int byteOffset, final long value) { 840 try { 841 getBuffer(self, false).putInt(byteOffset, (int)value); 842 return UNDEFINED; 843 } catch (final IllegalArgumentException iae) { 844 throw rangeError(iae, "dataview.offset"); 845 } 846 } 847 848 /** 849 * Set 32-bit unsigned int at the given byteOffset 850 * 851 * @param self DataView object 852 * @param byteOffset byte offset to write at 853 * @param value int value to set 854 * @param littleEndian (optional) flag indicating whether to write in little endian order 855 * @return undefined 856 */ 857 @SpecializedFunction 858 public static Object setUint32(final Object self, final int byteOffset, final long value, final boolean littleEndian) { 859 try { 860 getBuffer(self, littleEndian).putInt(byteOffset, (int)value); 861 return UNDEFINED; 862 } catch (final IllegalArgumentException iae) { 863 throw rangeError(iae, "dataview.offset"); 864 } 865 } 866 867 /** 868 * Set 32-bit float at the given byteOffset 869 * 870 * @param self DataView object 871 * @param byteOffset byte offset to write at 872 * @param value float value to set 873 * @param littleEndian (optional) flag indicating whether to write in little endian order 874 * @return undefined 875 */ 876 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 877 public static Object setFloat32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) { 878 try { 879 getBuffer(self, littleEndian).putFloat((int)JSType.toUint32(byteOffset), (float)JSType.toNumber(value)); 880 return UNDEFINED; 881 } catch (final IllegalArgumentException iae) { 882 throw rangeError(iae, "dataview.offset"); 883 } 884 } 885 886 /** 887 * Set 32-bit float at the given byteOffset 888 * 889 * @param self DataView object 890 * @param byteOffset byte offset to write at 891 * @param value float value to set 892 * @return undefined 893 */ 894 @SpecializedFunction 895 public static Object setFloat32(final Object self, final int byteOffset, final double value) { 896 try { 897 getBuffer(self, false).putFloat(byteOffset, (float)value); 898 return UNDEFINED; 899 } catch (final IllegalArgumentException iae) { 900 throw rangeError(iae, "dataview.offset"); 901 } 902 } 903 904 /** 905 * Set 32-bit float at the given byteOffset 906 * 907 * @param self DataView object 908 * @param byteOffset byte offset to write at 909 * @param value float value to set 910 * @param littleEndian (optional) flag indicating whether to write in little endian order 911 * @return undefined 912 */ 913 @SpecializedFunction 914 public static Object setFloat32(final Object self, final int byteOffset, final double value, final boolean littleEndian) { 915 try { 916 getBuffer(self, littleEndian).putFloat(byteOffset, (float)value); 917 return UNDEFINED; 918 } catch (final IllegalArgumentException iae) { 919 throw rangeError(iae, "dataview.offset"); 920 } 921 } 922 923 /** 924 * Set 64-bit float at the given byteOffset 925 * 926 * @param self DataView object 927 * @param byteOffset byte offset to write at 928 * @param value double value to set 929 * @param littleEndian (optional) flag indicating whether to write in little endian order 930 * @return undefined 931 */ 932 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2) 933 public static Object setFloat64(final Object self, final Object byteOffset, final Object value, final Object littleEndian) { 934 try { 935 getBuffer(self, littleEndian).putDouble((int)JSType.toUint32(byteOffset), JSType.toNumber(value)); 936 return UNDEFINED; 937 } catch (final IllegalArgumentException iae) { 938 throw rangeError(iae, "dataview.offset"); 939 } 940 } 941 942 /** 943 * Set 64-bit float at the given byteOffset 944 * 945 * @param self DataView object 946 * @param byteOffset byte offset to write at 947 * @param value double value to set 948 * @return undefined 949 */ 950 @SpecializedFunction 951 public static Object setFloat64(final Object self, final int byteOffset, final double value) { 952 try { 953 getBuffer(self, false).putDouble(byteOffset, value); 954 return UNDEFINED; 955 } catch (final IllegalArgumentException iae) { 956 throw rangeError(iae, "dataview.offset"); 957 } 958 } 959 960 /** 961 * Set 64-bit float at the given byteOffset 962 * 963 * @param self DataView object 964 * @param byteOffset byte offset to write at 965 * @param value double value to set 966 * @param littleEndian (optional) flag indicating whether to write in little endian order 967 * @return undefined 968 */ 969 @SpecializedFunction 970 public static Object setFloat64(final Object self, final int byteOffset, final double value, final boolean littleEndian) { 971 try { 972 getBuffer(self, littleEndian).putDouble(byteOffset, value); 973 return UNDEFINED; 974 } catch (final IllegalArgumentException iae) { 975 throw rangeError(iae, "dataview.offset"); 976 } 977 } 978 979 // internals only below this point 980 private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset) { 981 try { 982 return nab.getBuffer(offset); 983 } catch (final IllegalArgumentException iae) { 984 throw rangeError(iae, "dataview.constructor.offset"); 985 } 986 } 987 988 private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset, final int length) { 989 try { 990 return nab.getBuffer(offset, length); 991 } catch (final IllegalArgumentException iae) { 992 throw rangeError(iae, "dataview.constructor.offset"); 993 } 994 } 995 996 private static NativeDataView checkSelf(final Object self) { 997 if (!(self instanceof NativeDataView)) { 998 throw typeError("not.an.arraybuffer.in.dataview", ScriptRuntime.safeToString(self)); 999 } 1000 return (NativeDataView)self; 1001 } 1002 1003 private static ByteBuffer getBuffer(final Object self) { 1004 return checkSelf(self).buf; 1005 } 1006 1007 private static ByteBuffer getBuffer(final Object self, final Object littleEndian) { 1008 return getBuffer(self, JSType.toBoolean(littleEndian)); 1009 } 1010 1011 private static ByteBuffer getBuffer(final Object self, final boolean littleEndian) { 1012 return getBuffer(self).order(littleEndian? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 1013 } 1014} 1015