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 18package java.nio; 19 20import libcore.io.SizeOf; 21 22abstract class DirectByteBuffer extends BaseByteBuffer { 23 // This is the offset into {@code Buffer.block} at which this buffer logically starts. 24 // TODO: rewrite this so we set 'block' to an OffsetMemoryBlock? 25 protected final int offset; 26 27 protected DirectByteBuffer(MemoryBlock block, int capacity, int offset) { 28 super(capacity, block); 29 30 long baseSize = block.getSize(); 31 if (baseSize >= 0 && (capacity + offset) > baseSize) { 32 throw new IllegalArgumentException("capacity + offset > baseSize"); 33 } 34 35 this.offset = offset; 36 this.effectiveDirectAddress = block.toInt() + offset; 37 } 38 39 @Override 40 public final ByteBuffer get(byte[] dst, int dstOffset, int byteCount) { 41 checkGetBounds(1, dst.length, dstOffset, byteCount); 42 this.block.peekByteArray(offset + position, dst, dstOffset, byteCount); 43 position += byteCount; 44 return this; 45 } 46 47 final void get(char[] dst, int dstOffset, int charCount) { 48 int byteCount = checkGetBounds(SizeOf.CHAR, dst.length, dstOffset, charCount); 49 this.block.peekCharArray(offset + position, dst, dstOffset, charCount, order.needsSwap); 50 position += byteCount; 51 } 52 53 final void get(double[] dst, int dstOffset, int doubleCount) { 54 int byteCount = checkGetBounds(SizeOf.DOUBLE, dst.length, dstOffset, doubleCount); 55 this.block.peekDoubleArray(offset + position, dst, dstOffset, doubleCount, order.needsSwap); 56 position += byteCount; 57 } 58 59 final void get(float[] dst, int dstOffset, int floatCount) { 60 int byteCount = checkGetBounds(SizeOf.FLOAT, dst.length, dstOffset, floatCount); 61 this.block.peekFloatArray(offset + position, dst, dstOffset, floatCount, order.needsSwap); 62 position += byteCount; 63 } 64 65 final void get(int[] dst, int dstOffset, int intCount) { 66 int byteCount = checkGetBounds(SizeOf.INT, dst.length, dstOffset, intCount); 67 this.block.peekIntArray(offset + position, dst, dstOffset, intCount, order.needsSwap); 68 position += byteCount; 69 } 70 71 final void get(long[] dst, int dstOffset, int longCount) { 72 int byteCount = checkGetBounds(SizeOf.LONG, dst.length, dstOffset, longCount); 73 this.block.peekLongArray(offset + position, dst, dstOffset, longCount, order.needsSwap); 74 position += byteCount; 75 } 76 77 final void get(short[] dst, int dstOffset, int shortCount) { 78 int byteCount = checkGetBounds(SizeOf.SHORT, dst.length, dstOffset, shortCount); 79 this.block.peekShortArray(offset + position, dst, dstOffset, shortCount, order.needsSwap); 80 position += byteCount; 81 } 82 83 @Override 84 public final byte get() { 85 if (position == limit) { 86 throw new BufferUnderflowException(); 87 } 88 return this.block.peekByte(offset + position++); 89 } 90 91 @Override 92 public final byte get(int index) { 93 checkIndex(index); 94 return this.block.peekByte(offset + index); 95 } 96 97 @Override 98 public final char getChar() { 99 int newPosition = position + SizeOf.CHAR; 100 if (newPosition > limit) { 101 throw new BufferUnderflowException(); 102 } 103 char result = (char) this.block.peekShort(offset + position, order); 104 position = newPosition; 105 return result; 106 } 107 108 @Override 109 public final char getChar(int index) { 110 checkIndex(index, SizeOf.CHAR); 111 return (char) this.block.peekShort(offset + index, order); 112 } 113 114 @Override 115 public final double getDouble() { 116 int newPosition = position + SizeOf.DOUBLE; 117 if (newPosition > limit) { 118 throw new BufferUnderflowException(); 119 } 120 double result = Double.longBitsToDouble(this.block.peekLong(offset + position, order)); 121 position = newPosition; 122 return result; 123 } 124 125 @Override 126 public final double getDouble(int index) { 127 checkIndex(index, SizeOf.DOUBLE); 128 return Double.longBitsToDouble(this.block.peekLong(offset + index, order)); 129 } 130 131 @Override 132 public final float getFloat() { 133 int newPosition = position + SizeOf.FLOAT; 134 if (newPosition > limit) { 135 throw new BufferUnderflowException(); 136 } 137 float result = Float.intBitsToFloat(this.block.peekInt(offset + position, order)); 138 position = newPosition; 139 return result; 140 } 141 142 @Override 143 public final float getFloat(int index) { 144 checkIndex(index, SizeOf.FLOAT); 145 return Float.intBitsToFloat(this.block.peekInt(offset + index, order)); 146 } 147 148 @Override 149 public final int getInt() { 150 int newPosition = position + SizeOf.INT; 151 if (newPosition > limit) { 152 throw new BufferUnderflowException(); 153 } 154 int result = this.block.peekInt(offset + position, order); 155 position = newPosition; 156 return result; 157 } 158 159 @Override 160 public final int getInt(int index) { 161 checkIndex(index, SizeOf.INT); 162 return this.block.peekInt(offset + index, order); 163 } 164 165 @Override 166 public final long getLong() { 167 int newPosition = position + SizeOf.LONG; 168 if (newPosition > limit) { 169 throw new BufferUnderflowException(); 170 } 171 long result = this.block.peekLong(offset + position, order); 172 position = newPosition; 173 return result; 174 } 175 176 @Override 177 public final long getLong(int index) { 178 checkIndex(index, SizeOf.LONG); 179 return this.block.peekLong(offset + index, order); 180 } 181 182 @Override 183 public final short getShort() { 184 int newPosition = position + SizeOf.SHORT; 185 if (newPosition > limit) { 186 throw new BufferUnderflowException(); 187 } 188 short result = this.block.peekShort(offset + position, order); 189 position = newPosition; 190 return result; 191 } 192 193 @Override 194 public final short getShort(int index) { 195 checkIndex(index, SizeOf.SHORT); 196 return this.block.peekShort(offset + index, order); 197 } 198 199 @Override 200 public final boolean isDirect() { 201 return true; 202 } 203 204 public final void free() { 205 block.free(); 206 } 207 208 @Override byte[] protectedArray() { 209 byte[] array = this.block.array(); 210 if (array == null) { 211 throw new UnsupportedOperationException(); 212 } 213 return array; 214 } 215 216 @Override int protectedArrayOffset() { 217 protectedArray(); // Throw if we don't have an array. 218 return offset; 219 } 220 221 @Override boolean protectedHasArray() { 222 return this.block.array() != null; 223 } 224} 225