1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.nio; 19 20 import libcore.io.SizeOf; 21 import libcore.io.Memory; 22 23 /** 24 * HeapByteBuffer, ReadWriteHeapByteBuffer and ReadOnlyHeapByteBuffer compose 25 * the implementation of array based byte buffers. 26 * <p> 27 * HeapByteBuffer implements all the shared readonly methods and is extended by 28 * the other two classes. 29 * </p> 30 * <p> 31 * All methods are marked final for runtime performance. 32 * </p> 33 * 34 */ 35 abstract class HeapByteBuffer extends BaseByteBuffer { 36 37 /** 38 * These fields are non-private for NioUtils.unsafeArray. 39 */ 40 final byte[] backingArray; 41 final int offset; 42 43 HeapByteBuffer(byte[] backingArray) { 44 this(backingArray, backingArray.length, 0); 45 } 46 47 HeapByteBuffer(int capacity) { 48 this(new byte[capacity], capacity, 0); 49 } 50 51 HeapByteBuffer(byte[] backingArray, int capacity, int offset) { 52 super(capacity, null); 53 this.backingArray = backingArray; 54 this.offset = offset; 55 if (offset + capacity > backingArray.length) { 56 throw new IndexOutOfBoundsException("backingArray.length=" + backingArray.length + 57 ", capacity=" + capacity + ", offset=" + offset); 58 } 59 } 60 61 @Override 62 public final ByteBuffer get(byte[] dst, int dstOffset, int byteCount) { 63 checkGetBounds(1, dst.length, dstOffset, byteCount); 64 System.arraycopy(backingArray, offset + position, dst, dstOffset, byteCount); 65 position += byteCount; 66 return this; 67 } 68 69 final void get(char[] dst, int dstOffset, int charCount) { 70 int byteCount = checkGetBounds(SizeOf.CHAR, dst.length, dstOffset, charCount); 71 Memory.unsafeBulkGet(dst, dstOffset, byteCount, backingArray, offset + position, SizeOf.CHAR, order.needsSwap); 72 position += byteCount; 73 } 74 75 final void get(double[] dst, int dstOffset, int doubleCount) { 76 int byteCount = checkGetBounds(SizeOf.DOUBLE, dst.length, dstOffset, doubleCount); 77 Memory.unsafeBulkGet(dst, dstOffset, byteCount, backingArray, offset + position, SizeOf.DOUBLE, order.needsSwap); 78 position += byteCount; 79 } 80 81 final void get(float[] dst, int dstOffset, int floatCount) { 82 int byteCount = checkGetBounds(SizeOf.FLOAT, dst.length, dstOffset, floatCount); 83 Memory.unsafeBulkGet(dst, dstOffset, byteCount, backingArray, offset + position, SizeOf.FLOAT, order.needsSwap); 84 position += byteCount; 85 } 86 87 final void get(int[] dst, int dstOffset, int intCount) { 88 int byteCount = checkGetBounds(SizeOf.INT, dst.length, dstOffset, intCount); 89 Memory.unsafeBulkGet(dst, dstOffset, byteCount, backingArray, offset + position, SizeOf.INT, order.needsSwap); 90 position += byteCount; 91 } 92 93 final void get(long[] dst, int dstOffset, int longCount) { 94 int byteCount = checkGetBounds(SizeOf.LONG, dst.length, dstOffset, longCount); 95 Memory.unsafeBulkGet(dst, dstOffset, byteCount, backingArray, offset + position, SizeOf.LONG, order.needsSwap); 96 position += byteCount; 97 } 98 99 final void get(short[] dst, int dstOffset, int shortCount) { 100 int byteCount = checkGetBounds(SizeOf.SHORT, dst.length, dstOffset, shortCount); 101 Memory.unsafeBulkGet(dst, dstOffset, byteCount, backingArray, offset + position, SizeOf.SHORT, order.needsSwap); 102 position += byteCount; 103 } 104 105 @Override 106 public final byte get() { 107 if (position == limit) { 108 throw new BufferUnderflowException(); 109 } 110 return backingArray[offset + position++]; 111 } 112 113 @Override 114 public final byte get(int index) { 115 checkIndex(index); 116 return backingArray[offset + index]; 117 } 118 119 @Override 120 public final char getChar() { 121 int newPosition = position + SizeOf.CHAR; 122 if (newPosition > limit) { 123 throw new BufferUnderflowException(); 124 } 125 char result = (char) Memory.peekShort(backingArray, offset + position, order); 126 position = newPosition; 127 return result; 128 } 129 130 @Override 131 public final char getChar(int index) { 132 checkIndex(index, SizeOf.CHAR); 133 return (char) Memory.peekShort(backingArray, offset + index, order); 134 } 135 136 @Override 137 public final double getDouble() { 138 return Double.longBitsToDouble(getLong()); 139 } 140 141 @Override 142 public final double getDouble(int index) { 143 return Double.longBitsToDouble(getLong(index)); 144 } 145 146 @Override 147 public final float getFloat() { 148 return Float.intBitsToFloat(getInt()); 149 } 150 151 @Override 152 public final float getFloat(int index) { 153 return Float.intBitsToFloat(getInt(index)); 154 } 155 156 @Override 157 public final int getInt() { 158 int newPosition = position + SizeOf.INT; 159 if (newPosition > limit) { 160 throw new BufferUnderflowException(); 161 } 162 int result = Memory.peekInt(backingArray, offset + position, order); 163 position = newPosition; 164 return result; 165 } 166 167 @Override 168 public final int getInt(int index) { 169 checkIndex(index, SizeOf.INT); 170 return Memory.peekInt(backingArray, offset + index, order); 171 } 172 173 @Override 174 public final long getLong() { 175 int newPosition = position + SizeOf.LONG; 176 if (newPosition > limit) { 177 throw new BufferUnderflowException(); 178 } 179 long result = Memory.peekLong(backingArray, offset + position, order); 180 position = newPosition; 181 return result; 182 } 183 184 @Override 185 public final long getLong(int index) { 186 checkIndex(index, SizeOf.LONG); 187 return Memory.peekLong(backingArray, offset + index, order); 188 } 189 190 @Override 191 public final short getShort() { 192 int newPosition = position + SizeOf.SHORT; 193 if (newPosition > limit) { 194 throw new BufferUnderflowException(); 195 } 196 short result = Memory.peekShort(backingArray, offset + position, order); 197 position = newPosition; 198 return result; 199 } 200 201 @Override 202 public final short getShort(int index) { 203 checkIndex(index, SizeOf.SHORT); 204 return Memory.peekShort(backingArray, offset + index, order); 205 } 206 207 @Override 208 public final boolean isDirect() { 209 return false; 210 } 211 } 212