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 * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer 25 * compose the implementation of platform memory based byte buffers. 26 * <p> 27 * ReadWriteDirectByteBuffer extends DirectByteBuffer with all the write 28 * methods. 29 * </p> 30 * <p> 31 * This class is marked final for runtime performance. 32 * </p> 33 */ 34 final class ReadWriteDirectByteBuffer extends DirectByteBuffer { 35 static ReadWriteDirectByteBuffer copy(DirectByteBuffer other, int markOfOther) { 36 ReadWriteDirectByteBuffer buf = 37 new ReadWriteDirectByteBuffer(other.block, other.capacity(), other.offset); 38 buf.limit = other.limit; 39 buf.position = other.position(); 40 buf.mark = markOfOther; 41 return buf; 42 } 43 44 // Used by ByteBuffer.allocateDirect. 45 ReadWriteDirectByteBuffer(int capacity) { 46 super(MemoryBlock.allocate(capacity), capacity, 0); 47 } 48 49 // Used by the JNI NewDirectByteBuffer function. 50 ReadWriteDirectByteBuffer(int address, int capacity) { 51 super(MemoryBlock.wrapFromJni(address, capacity), capacity, 0); 52 } 53 54 ReadWriteDirectByteBuffer(MemoryBlock block, int capacity, int offset) { 55 super(block, capacity, offset); 56 } 57 58 @Override 59 public ByteBuffer asReadOnlyBuffer() { 60 return ReadOnlyDirectByteBuffer.copy(this, mark); 61 } 62 63 @Override 64 public ByteBuffer compact() { 65 Memory.memmove(this, 0, this, position, remaining()); 66 position = limit - position; 67 limit = capacity; 68 mark = UNSET_MARK; 69 return this; 70 } 71 72 @Override 73 public ByteBuffer duplicate() { 74 return copy(this, mark); 75 } 76 77 @Override 78 public boolean isReadOnly() { 79 return false; 80 } 81 82 @Override 83 public ByteBuffer put(byte value) { 84 if (position == limit) { 85 throw new BufferOverflowException(); 86 } 87 this.block.pokeByte(offset + position++, value); 88 return this; 89 } 90 91 @Override 92 public ByteBuffer put(int index, byte value) { 93 checkIndex(index); 94 this.block.pokeByte(offset + index, value); 95 return this; 96 } 97 98 @Override 99 public ByteBuffer put(byte[] src, int srcOffset, int byteCount) { 100 checkPutBounds(1, src.length, srcOffset, byteCount); 101 this.block.pokeByteArray(offset + position, src, srcOffset, byteCount); 102 position += byteCount; 103 return this; 104 } 105 106 final void put(char[] src, int srcOffset, int charCount) { 107 int byteCount = checkPutBounds(SizeOf.CHAR, src.length, srcOffset, charCount); 108 this.block.pokeCharArray(offset + position, src, srcOffset, charCount, order.needsSwap); 109 position += byteCount; 110 } 111 112 final void put(double[] src, int srcOffset, int doubleCount) { 113 int byteCount = checkPutBounds(SizeOf.DOUBLE, src.length, srcOffset, doubleCount); 114 this.block.pokeDoubleArray(offset + position, src, srcOffset, doubleCount, order.needsSwap); 115 position += byteCount; 116 } 117 118 final void put(float[] src, int srcOffset, int floatCount) { 119 int byteCount = checkPutBounds(SizeOf.FLOAT, src.length, srcOffset, floatCount); 120 this.block.pokeFloatArray(offset + position, src, srcOffset, floatCount, order.needsSwap); 121 position += byteCount; 122 } 123 124 final void put(int[] src, int srcOffset, int intCount) { 125 int byteCount = checkPutBounds(SizeOf.INT, src.length, srcOffset, intCount); 126 this.block.pokeIntArray(offset + position, src, srcOffset, intCount, order.needsSwap); 127 position += byteCount; 128 } 129 130 final void put(long[] src, int srcOffset, int longCount) { 131 int byteCount = checkPutBounds(SizeOf.LONG, src.length, srcOffset, longCount); 132 this.block.pokeLongArray(offset + position, src, srcOffset, longCount, order.needsSwap); 133 position += byteCount; 134 } 135 136 final void put(short[] src, int srcOffset, int shortCount) { 137 int byteCount = checkPutBounds(SizeOf.SHORT, src.length, srcOffset, shortCount); 138 this.block.pokeShortArray(offset + position, src, srcOffset, shortCount, order.needsSwap); 139 position += byteCount; 140 } 141 142 @Override 143 public ByteBuffer putChar(char value) { 144 int newPosition = position + SizeOf.CHAR; 145 if (newPosition > limit) { 146 throw new BufferOverflowException(); 147 } 148 this.block.pokeShort(offset + position, (short) value, order); 149 position = newPosition; 150 return this; 151 } 152 153 @Override 154 public ByteBuffer putChar(int index, char value) { 155 checkIndex(index, SizeOf.CHAR); 156 this.block.pokeShort(offset + index, (short) value, order); 157 return this; 158 } 159 160 @Override 161 public ByteBuffer putDouble(double value) { 162 int newPosition = position + SizeOf.DOUBLE; 163 if (newPosition > limit) { 164 throw new BufferOverflowException(); 165 } 166 this.block.pokeLong(offset + position, Double.doubleToRawLongBits(value), order); 167 position = newPosition; 168 return this; 169 } 170 171 @Override 172 public ByteBuffer putDouble(int index, double value) { 173 checkIndex(index, SizeOf.DOUBLE); 174 this.block.pokeLong(offset + index, Double.doubleToRawLongBits(value), order); 175 return this; 176 } 177 178 @Override 179 public ByteBuffer putFloat(float value) { 180 int newPosition = position + SizeOf.FLOAT; 181 if (newPosition > limit) { 182 throw new BufferOverflowException(); 183 } 184 this.block.pokeInt(offset + position, Float.floatToRawIntBits(value), order); 185 position = newPosition; 186 return this; 187 } 188 189 @Override 190 public ByteBuffer putFloat(int index, float value) { 191 checkIndex(index, SizeOf.FLOAT); 192 this.block.pokeInt(offset + index, Float.floatToRawIntBits(value), order); 193 return this; 194 } 195 196 @Override 197 public ByteBuffer putInt(int value) { 198 int newPosition = position + SizeOf.INT; 199 if (newPosition > limit) { 200 throw new BufferOverflowException(); 201 } 202 this.block.pokeInt(offset + position, value, order); 203 position = newPosition; 204 return this; 205 } 206 207 @Override 208 public ByteBuffer putInt(int index, int value) { 209 checkIndex(index, SizeOf.INT); 210 this.block.pokeInt(offset + index, value, order); 211 return this; 212 } 213 214 @Override 215 public ByteBuffer putLong(long value) { 216 int newPosition = position + SizeOf.LONG; 217 if (newPosition > limit) { 218 throw new BufferOverflowException(); 219 } 220 this.block.pokeLong(offset + position, value, order); 221 position = newPosition; 222 return this; 223 } 224 225 @Override 226 public ByteBuffer putLong(int index, long value) { 227 checkIndex(index, SizeOf.LONG); 228 this.block.pokeLong(offset + index, value, order); 229 return this; 230 } 231 232 @Override 233 public ByteBuffer putShort(short value) { 234 int newPosition = position + SizeOf.SHORT; 235 if (newPosition > limit) { 236 throw new BufferOverflowException(); 237 } 238 this.block.pokeShort(offset + position, value, order); 239 position = newPosition; 240 return this; 241 } 242 243 @Override 244 public ByteBuffer putShort(int index, short value) { 245 checkIndex(index, SizeOf.SHORT); 246 this.block.pokeShort(offset + index, value, order); 247 return this; 248 } 249 250 @Override 251 public ByteBuffer slice() { 252 return new ReadWriteDirectByteBuffer(block, remaining(), offset + position); 253 } 254 255 } 256