NativeArrayBuffer.java revision 1090:4df3417e1a6e
1169689Skan/* 2169689Skan * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3169689Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4169689Skan * 5169689Skan * This code is free software; you can redistribute it and/or modify it 6169689Skan * under the terms of the GNU General Public License version 2 only, as 7169689Skan * published by the Free Software Foundation. Oracle designates this 8169689Skan * particular file as subject to the "Classpath" exception as provided 9169689Skan * by Oracle in the LICENSE file that accompanied this code. 10169689Skan * 11169689Skan * This code is distributed in the hope that it will be useful, but WITHOUT 12169689Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13169689Skan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14169689Skan * version 2 for more details (a copy is included in the LICENSE file that 15169689Skan * accompanied this code). 16169689Skan * 17169689Skan * You should have received a copy of the GNU General Public License version 18169689Skan * 2 along with this work; if not, write to the Free Software Foundation, 19169689Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20169689Skan * 21169689Skan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22169689Skan * or visit www.oracle.com if you need additional information or have any 23169689Skan * questions. 24169689Skan */ 25169689Skan 26169689Skanpackage jdk.nashorn.internal.objects; 27169689Skan 28169689Skanimport static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 29169689Skanimport java.nio.ByteBuffer; 30169689Skanimport jdk.nashorn.internal.objects.annotations.Attribute; 31169689Skanimport jdk.nashorn.internal.objects.annotations.Constructor; 32169689Skanimport jdk.nashorn.internal.objects.annotations.Function; 33169689Skanimport jdk.nashorn.internal.objects.annotations.Getter; 34169689Skanimport jdk.nashorn.internal.objects.annotations.ScriptClass; 35169689Skanimport jdk.nashorn.internal.objects.annotations.SpecializedFunction; 36169689Skanimport jdk.nashorn.internal.objects.annotations.Where; 37169689Skanimport jdk.nashorn.internal.runtime.JSType; 38169689Skanimport jdk.nashorn.internal.runtime.PropertyMap; 39169689Skanimport jdk.nashorn.internal.runtime.ScriptObject; 40169689Skanimport jdk.nashorn.internal.runtime.ScriptRuntime; 41169689Skan 42169689Skan/** 43169689Skan * NativeArrayBuffer - ArrayBuffer as described in the JS typed 44169689Skan * array spec 45169689Skan */ 46169689Skan@ScriptClass("ArrayBuffer") 47169689Skanpublic final class NativeArrayBuffer extends ScriptObject { 48169689Skan private final ByteBuffer nb; 49169689Skan 50169689Skan // initialized by nasgen 51169689Skan private static PropertyMap $nasgenmap$; 52169689Skan 53169689Skan /** 54169689Skan * Constructor 55169689Skan * @param nb native byte buffer to wrap 56169689Skan * @param global global instance 57169689Skan */ 58169689Skan protected NativeArrayBuffer(final ByteBuffer nb, final Global global) { 59169689Skan super(global.getArrayBufferPrototype(), $nasgenmap$); 60169689Skan this.nb = nb; 61169689Skan } 62169689Skan 63169689Skan /** 64169689Skan * Constructor 65169689Skan * @param nb native byte buffer to wrap 66169689Skan */ 67169689Skan protected NativeArrayBuffer(final ByteBuffer nb) { 68169689Skan this(nb, Global.instance()); 69169689Skan } 70169689Skan 71169689Skan /** 72169689Skan * Constructor 73169689Skan * @param byteLength byteLength for buffer 74169689Skan */ 75169689Skan protected NativeArrayBuffer(final int byteLength) { 76169689Skan this(ByteBuffer.allocateDirect(byteLength)); 77169689Skan } 78169689Skan 79169689Skan /** 80169689Skan * Clone constructor 81169689Skan * Used only for slice 82169689Skan * @param other original buffer 83169689Skan * @param begin begin byte index 84169689Skan * @param end end byte index 85169689Skan */ 86169689Skan protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) { 87169689Skan this(cloneBuffer(other.getNioBuffer(), begin, end)); 88169689Skan } 89169689Skan 90169689Skan /** 91169689Skan * Constructor 92169689Skan * @param newObj is this invoked with new 93169689Skan * @param self self reference 94169689Skan * @param args arguments to constructor 95169689Skan * @return new NativeArrayBuffer 96169689Skan */ 97169689Skan @Constructor(arity = 1) 98169689Skan public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) { 99169689Skan if (!newObj) { 100169689Skan throw typeError("constructor.requires.new", "ArrayBuffer"); 101169689Skan } 102169689Skan 103169689Skan if (args.length == 0) { 104169689Skan throw new RuntimeException("missing length argument"); 105169689Skan } 106169689Skan 107169689Skan return new NativeArrayBuffer(JSType.toInt32(args[0])); 108169689Skan } 109169689Skan 110169689Skan private static ByteBuffer cloneBuffer(final ByteBuffer original, final int begin, final int end) { 111169689Skan final ByteBuffer clone = ByteBuffer.allocateDirect(original.capacity()); 112169689Skan original.rewind();//copy from the beginning 113169689Skan clone.put(original); 114169689Skan original.rewind(); 115169689Skan clone.flip(); 116169689Skan clone.position(begin); 117169689Skan clone.limit(end); 118169689Skan return clone.slice(); 119169689Skan } 120169689Skan 121169689Skan ByteBuffer getNioBuffer() { 122169689Skan return nb; 123169689Skan } 124169689Skan 125169689Skan @Override 126169689Skan public String getClassName() { 127169689Skan return "ArrayBuffer"; 128169689Skan } 129169689Skan 130169689Skan /** 131169689Skan * Byte length for native array buffer 132169689Skan * @param self native array buffer 133169689Skan * @return byte length 134169689Skan */ 135169689Skan @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) 136169689Skan public static int byteLength(final Object self) { 137169689Skan return ((NativeArrayBuffer)self).getByteLength(); 138169689Skan } 139169689Skan 140169689Skan /** 141169689Skan * Returns true if an object is an ArrayBufferView 142169689Skan * 143169689Skan * @param self self 144169689Skan * @param obj object to check 145169689Skan * 146169689Skan * @return true if obj is an ArrayBufferView 147169689Skan */ 148169689Skan @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 149169689Skan public static boolean isView(final Object self, final Object obj) { 150169689Skan return obj instanceof ArrayBufferView; 151169689Skan } 152169689Skan 153169689Skan /** 154169689Skan * Slice function 155169689Skan * @param self native array buffer 156169689Skan * @param begin0 start byte index 157169689Skan * @param end0 end byte index 158169689Skan * @return new array buffer, sliced 159169689Skan */ 160169689Skan @Function(attributes = Attribute.NOT_ENUMERABLE) 161169689Skan public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) { 162169689Skan final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self; 163169689Skan final int byteLength = arrayBuffer.getByteLength(); 164169689Skan final int begin = adjustIndex(JSType.toInt32(begin0), byteLength); 165169689Skan final int end = adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : byteLength, byteLength); 166169689Skan return new NativeArrayBuffer(arrayBuffer, begin, Math.max(end, begin)); 167169689Skan } 168169689Skan 169169689Skan /** 170169689Skan * Specialized slice function 171169689Skan * @param self native array buffer 172169689Skan * @param begin start byte index 173169689Skan * @param end end byte index 174169689Skan * @return new array buffer, sliced 175169689Skan */ 176169689Skan @SpecializedFunction 177169689Skan public static Object slice(final Object self, final int begin, final int end) { 178169689Skan final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self; 179169689Skan final int byteLength = arrayBuffer.getByteLength(); 180169689Skan return new NativeArrayBuffer(arrayBuffer, adjustIndex(begin, byteLength), Math.max(adjustIndex(end, byteLength), begin)); 181169689Skan } 182169689Skan 183169689Skan /** 184169689Skan * Specialized slice function 185169689Skan * @param self native array buffer 186169689Skan * @param begin start byte index 187169689Skan * @return new array buffer, sliced 188169689Skan */ 189169689Skan @SpecializedFunction 190169689Skan public static Object slice(final Object self, final int begin) { 191169689Skan return slice(self, begin, ((NativeArrayBuffer)self).getByteLength()); 192169689Skan } 193169689Skan 194169689Skan /** 195169689Skan * If index is negative, it refers to an index from the end of the array, as 196169689Skan * opposed to from the beginning. The index is clamped to the valid index 197169689Skan * range for the array. 198169689Skan * 199169689Skan * @param index The index. 200169689Skan * @param length The length of the array. 201169689Skan * @return valid index index in the range [0, length). 202169689Skan */ 203169689Skan static int adjustIndex(final int index, final int length) { 204169689Skan return index < 0 ? clamp(index + length, length) : clamp(index, length); 205169689Skan } 206169689Skan 207169689Skan /** 208169689Skan * Clamp index into the range [0, length). 209169689Skan */ 210169689Skan private static int clamp(final int index, final int length) { 211169689Skan if (index < 0) { 212169689Skan return 0; 213169689Skan } else if (index > length) { 214169689Skan return length; 215169689Skan } 216169689Skan return index; 217169689Skan } 218169689Skan 219169689Skan int getByteLength() { 220169689Skan return nb.limit(); 221169689Skan } 222169689Skan 223169689Skan ByteBuffer getBuffer() { 224169689Skan return nb; 225169689Skan } 226169689Skan 227169689Skan ByteBuffer getBuffer(final int offset) { 228169689Skan return (ByteBuffer)nb.duplicate().position(offset); 229169689Skan } 230169689Skan 231169689Skan ByteBuffer getBuffer(final int offset, final int length) { 232169689Skan return (ByteBuffer)getBuffer(offset).limit(length); 233169689Skan } 234169689Skan} 235169689Skan