1 /* 2 * Copyright (c) 2010, 2013, 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 */ 25 26 package jdk.nashorn.internal.objects; 27 28 import java.nio.ByteBuffer; 29 import java.util.Arrays; 30 import jdk.nashorn.internal.objects.annotations.Attribute; 31 import jdk.nashorn.internal.objects.annotations.Constructor; 32 import jdk.nashorn.internal.objects.annotations.Function; 33 import jdk.nashorn.internal.objects.annotations.Getter; 34 import jdk.nashorn.internal.objects.annotations.ScriptClass; 35 import jdk.nashorn.internal.runtime.JSType; 36 import jdk.nashorn.internal.runtime.PropertyMap; 37 import jdk.nashorn.internal.runtime.ScriptObject; 38 import jdk.nashorn.internal.runtime.ScriptRuntime; 39 40 @ScriptClass("ArrayBuffer") 41 final class NativeArrayBuffer extends ScriptObject { 42 private final byte[] buffer; 43 44 // initialized by nasgen 45 private static PropertyMap $nasgenmap$; 46 47 static PropertyMap getInitialMap() { 48 return $nasgenmap$; 49 } 50 51 @Constructor(arity = 1) 52 public static Object constructor(final boolean newObj, final Object self, final Object... args) { 53 if (args.length == 0) { 54 throw new RuntimeException("missing length argument"); 55 } 56 57 return new NativeArrayBuffer(JSType.toInt32(args[0])); 58 } 59 60 protected NativeArrayBuffer(final byte[] byteArray, final Global global) { 61 super(global.getArrayBufferPrototype(), getInitialMap()); 62 this.buffer = byteArray; 63 } 64 65 protected NativeArrayBuffer(final byte[] byteArray) { 66 this(byteArray, Global.instance()); 67 } 68 69 protected NativeArrayBuffer(final int byteLength) { 70 this(new byte[byteLength]); 71 } 72 73 protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) { 74 this(Arrays.copyOfRange(other.buffer, begin, end)); 75 } 76 77 @Override 78 public String getClassName() { 79 return "ArrayBuffer"; 80 } 81 82 @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) 83 public static Object byteLength(final Object self) { 84 return ((NativeArrayBuffer)self).buffer.length; 85 } 86 87 @Function(attributes = Attribute.NOT_ENUMERABLE) 88 public static Object slice(final Object self, final Object begin0, final Object end0) { 89 final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self; 90 int begin = JSType.toInt32(begin0); 91 int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength(); 92 begin = adjustIndex(begin, arrayBuffer.getByteLength()); 93 end = adjustIndex(end, arrayBuffer.getByteLength()); 94 return new NativeArrayBuffer((NativeArrayBuffer) self, begin, Math.max(end, begin)); 95 } 96 97 /** 98 * If index is negative, it refers to an index from the end of the array, as 99 * opposed to from the beginning. The index is clamped to the valid index 100 * range for the array. 101 * 102 * @param index The index. 103 * @param length The length of the array. 104 * @return valid index index in the range [0, length). 105 */ 106 static int adjustIndex(final int index, final int length) { 107 if (index < 0) { 108 return clamp(index + length, length); 109 } 110 return clamp(index, length); 111 } 112 113 /** 114 * Clamp index into the range [0, length). 115 */ 116 private static int clamp(final int index, final int length) { 117 if (index < 0) { 118 return 0; 119 } else if (index > length) { 120 return length; 121 } 122 return index; 123 } 124 125 public byte[] getByteArray() { 126 return buffer; 127 } 128 129 public int getByteLength() { 130 return buffer.length; 131 } 132 133 ByteBuffer getBuffer() { 134 return ByteBuffer.wrap(buffer); 135 } 136 137 ByteBuffer getBuffer(final int offset) { 138 return ByteBuffer.wrap(buffer, offset, buffer.length - offset); 139 } 140 141 ByteBuffer getBuffer(final int offset, final int length) { 142 return ByteBuffer.wrap(buffer, offset, length); 143 } 144 }