1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package java.nio; 18 19 import libcore.io.Memory; 20 import libcore.io.SizeOf; 21 22 /** 23 * HeapByteBuffer, ReadWriteHeapByteBuffer and ReadOnlyHeapByteBuffer compose 24 * the implementation of array based byte buffers. 25 * <p> 26 * ReadWriteHeapByteBuffer extends HeapByteBuffer with all the write methods. 27 * </p> 28 * <p> 29 * This class is marked final for runtime performance. 30 * </p> 31 * 32 */ 33 final class ReadWriteHeapByteBuffer extends HeapByteBuffer { 34 35 static ReadWriteHeapByteBuffer copy(HeapByteBuffer other, int markOfOther) { 36 ReadWriteHeapByteBuffer buf = 37 new ReadWriteHeapByteBuffer(other.backingArray, other.capacity(), other.offset); 38 buf.limit = other.limit; 39 buf.position = other.position(); 40 buf.mark = markOfOther; 41 return buf; 42 } 43 44 ReadWriteHeapByteBuffer(byte[] backingArray) { 45 super(backingArray); 46 } 47 48 ReadWriteHeapByteBuffer(int capacity) { 49 super(capacity); 50 } 51 52 ReadWriteHeapByteBuffer(byte[] backingArray, int capacity, int arrayOffset) { 53 super(backingArray, capacity, arrayOffset); 54 } 55 56 @Override 57 public ByteBuffer asReadOnlyBuffer() { 58 return ReadOnlyHeapByteBuffer.copy(this, mark); 59 } 60 61 @Override 62 public ByteBuffer compact() { 63 System.arraycopy(backingArray, position + offset, backingArray, offset, remaining()); 64 position = limit - position; 65 limit = capacity; 66 mark = UNSET_MARK; 67 return this; 68 } 69 70 @Override 71 public ByteBuffer duplicate() { 72 return copy(this, mark); 73 } 74 75 @Override 76 public boolean isReadOnly() { 77 return false; 78 } 79 80 @Override 81 protected byte[] protectedArray() { 82 return backingArray; 83 } 84 85 @Override 86 protected int protectedArrayOffset() { 87 return offset; 88 } 89 90 @Override 91 protected boolean protectedHasArray() { 92 return true; 93 } 94 95 @Override 96 public ByteBuffer put(byte b) { 97 if (position == limit) { 98 throw new BufferOverflowException(); 99 } 100 backingArray[offset + position++] = b; 101 return this; 102 } 103 104 @Override 105 public ByteBuffer put(int index, byte b) { 106 checkIndex(index); 107 backingArray[offset + index] = b; 108 return this; 109 } 110 111 @Override 112 public ByteBuffer put(byte[] src, int srcOffset, int byteCount) { 113 checkPutBounds(1, src.length, srcOffset, byteCount); 114 System.arraycopy(src, srcOffset, backingArray, offset + position, byteCount); 115 position += byteCount; 116 return this; 117 } 118 119 final void put(char[] src, int srcOffset, int charCount) { 120 int byteCount = checkPutBounds(SizeOf.CHAR, src.length, srcOffset, charCount); 121 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.CHAR, order.needsSwap); 122 position += byteCount; 123 } 124 125 final void put(double[] src, int srcOffset, int doubleCount) { 126 int byteCount = checkPutBounds(SizeOf.DOUBLE, src.length, srcOffset, doubleCount); 127 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.DOUBLE, order.needsSwap); 128 position += byteCount; 129 } 130 131 final void put(float[] src, int srcOffset, int floatCount) { 132 int byteCount = checkPutBounds(SizeOf.FLOAT, src.length, srcOffset, floatCount); 133 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.FLOAT, order.needsSwap); 134 position += byteCount; 135 } 136 137 final void put(int[] src, int srcOffset, int intCount) { 138 int byteCount = checkPutBounds(SizeOf.INT, src.length, srcOffset, intCount); 139 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.INT, order.needsSwap); 140 position += byteCount; 141 } 142 143 final void put(long[] src, int srcOffset, int longCount) { 144 int byteCount = checkPutBounds(SizeOf.LONG, src.length, srcOffset, longCount); 145 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.LONG, order.needsSwap); 146 position += byteCount; 147 } 148 149 final void put(short[] src, int srcOffset, int shortCount) { 150 int byteCount = checkPutBounds(SizeOf.SHORT, src.length, srcOffset, shortCount); 151 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.SHORT, order.needsSwap); 152 position += byteCount; 153 } 154 155 @Override 156 public ByteBuffer putChar(int index, char value) { 157 checkIndex(index, SizeOf.CHAR); 158 Memory.pokeShort(backingArray, offset + index, (short) value, order); 159 return this; 160 } 161 162 @Override 163 public ByteBuffer putChar(char value) { 164 int newPosition = position + SizeOf.CHAR; 165 if (newPosition > limit) { 166 throw new BufferOverflowException(); 167 } 168 Memory.pokeShort(backingArray, offset + position, (short) value, order); 169 position = newPosition; 170 return this; 171 } 172 173 @Override 174 public ByteBuffer putDouble(double value) { 175 return putLong(Double.doubleToRawLongBits(value)); 176 } 177 178 @Override 179 public ByteBuffer putDouble(int index, double value) { 180 return putLong(index, Double.doubleToRawLongBits(value)); 181 } 182 183 @Override 184 public ByteBuffer putFloat(float value) { 185 return putInt(Float.floatToRawIntBits(value)); 186 } 187 188 @Override 189 public ByteBuffer putFloat(int index, float value) { 190 return putInt(index, Float.floatToRawIntBits(value)); 191 } 192 193 @Override 194 public ByteBuffer putInt(int value) { 195 int newPosition = position + SizeOf.INT; 196 if (newPosition > limit) { 197 throw new BufferOverflowException(); 198 } 199 Memory.pokeInt(backingArray, offset + position, value, order); 200 position = newPosition; 201 return this; 202 } 203 204 @Override 205 public ByteBuffer putInt(int index, int value) { 206 checkIndex(index, SizeOf.INT); 207 Memory.pokeInt(backingArray, offset + index, value, order); 208 return this; 209 } 210 211 @Override 212 public ByteBuffer putLong(int index, long value) { 213 checkIndex(index, SizeOf.LONG); 214 Memory.pokeLong(backingArray, offset + index, value, order); 215 return this; 216 } 217 218 @Override 219 public ByteBuffer putLong(long value) { 220 int newPosition = position + SizeOf.LONG; 221 if (newPosition > limit) { 222 throw new BufferOverflowException(); 223 } 224 Memory.pokeLong(backingArray, offset + position, value, order); 225 position = newPosition; 226 return this; 227 } 228 229 @Override 230 public ByteBuffer putShort(int index, short value) { 231 checkIndex(index, SizeOf.SHORT); 232 Memory.pokeShort(backingArray, offset + index, value, order); 233 return this; 234 } 235 236 @Override 237 public ByteBuffer putShort(short value) { 238 int newPosition = position + SizeOf.SHORT; 239 if (newPosition > limit) { 240 throw new BufferOverflowException(); 241 } 242 Memory.pokeShort(backingArray, offset + position, value, order); 243 position = newPosition; 244 return this; 245 } 246 247 @Override 248 public ByteBuffer slice() { 249 return new ReadWriteHeapByteBuffer(backingArray, remaining(), offset + position); 250 } 251 } 252