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