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 byte[] protectedArray() { 81 return backingArray; 82 } 83 84 @Override int protectedArrayOffset() { 85 return offset; 86 } 87 88 @Override boolean protectedHasArray() { 89 return true; 90 } 91 92 @Override 93 public ByteBuffer put(byte b) { 94 if (position == limit) { 95 throw new BufferOverflowException(); 96 } 97 backingArray[offset + position++] = b; 98 return this; 99 } 100 101 @Override 102 public ByteBuffer put(int index, byte b) { 103 checkIndex(index); 104 backingArray[offset + index] = b; 105 return this; 106 } 107 108 @Override 109 public ByteBuffer put(byte[] src, int srcOffset, int byteCount) { 110 checkPutBounds(1, src.length, srcOffset, byteCount); 111 System.arraycopy(src, srcOffset, backingArray, offset + position, byteCount); 112 position += byteCount; 113 return this; 114 } 115 116 final void put(char[] src, int srcOffset, int charCount) { 117 int byteCount = checkPutBounds(SizeOf.CHAR, src.length, srcOffset, charCount); 118 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.CHAR, order.needsSwap); 119 position += byteCount; 120 } 121 122 final void put(double[] src, int srcOffset, int doubleCount) { 123 int byteCount = checkPutBounds(SizeOf.DOUBLE, src.length, srcOffset, doubleCount); 124 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.DOUBLE, order.needsSwap); 125 position += byteCount; 126 } 127 128 final void put(float[] src, int srcOffset, int floatCount) { 129 int byteCount = checkPutBounds(SizeOf.FLOAT, src.length, srcOffset, floatCount); 130 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.FLOAT, order.needsSwap); 131 position += byteCount; 132 } 133 134 final void put(int[] src, int srcOffset, int intCount) { 135 int byteCount = checkPutBounds(SizeOf.INT, src.length, srcOffset, intCount); 136 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.INT, order.needsSwap); 137 position += byteCount; 138 } 139 140 final void put(long[] src, int srcOffset, int longCount) { 141 int byteCount = checkPutBounds(SizeOf.LONG, src.length, srcOffset, longCount); 142 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.LONG, order.needsSwap); 143 position += byteCount; 144 } 145 146 final void put(short[] src, int srcOffset, int shortCount) { 147 int byteCount = checkPutBounds(SizeOf.SHORT, src.length, srcOffset, shortCount); 148 Memory.unsafeBulkPut(backingArray, offset + position, byteCount, src, srcOffset, SizeOf.SHORT, order.needsSwap); 149 position += byteCount; 150 } 151 152 @Override 153 public ByteBuffer putChar(int index, char value) { 154 checkIndex(index, SizeOf.CHAR); 155 Memory.pokeShort(backingArray, offset + index, (short) value, order); 156 return this; 157 } 158 159 @Override 160 public ByteBuffer putChar(char value) { 161 int newPosition = position + SizeOf.CHAR; 162 if (newPosition > limit) { 163 throw new BufferOverflowException(); 164 } 165 Memory.pokeShort(backingArray, offset + position, (short) value, order); 166 position = newPosition; 167 return this; 168 } 169 170 @Override 171 public ByteBuffer putDouble(double value) { 172 return putLong(Double.doubleToRawLongBits(value)); 173 } 174 175 @Override 176 public ByteBuffer putDouble(int index, double value) { 177 return putLong(index, Double.doubleToRawLongBits(value)); 178 } 179 180 @Override 181 public ByteBuffer putFloat(float value) { 182 return putInt(Float.floatToRawIntBits(value)); 183 } 184 185 @Override 186 public ByteBuffer putFloat(int index, float value) { 187 return putInt(index, Float.floatToRawIntBits(value)); 188 } 189 190 @Override 191 public ByteBuffer putInt(int value) { 192 int newPosition = position + SizeOf.INT; 193 if (newPosition > limit) { 194 throw new BufferOverflowException(); 195 } 196 Memory.pokeInt(backingArray, offset + position, value, order); 197 position = newPosition; 198 return this; 199 } 200 201 @Override 202 public ByteBuffer putInt(int index, int value) { 203 checkIndex(index, SizeOf.INT); 204 Memory.pokeInt(backingArray, offset + index, value, order); 205 return this; 206 } 207 208 @Override 209 public ByteBuffer putLong(int index, long value) { 210 checkIndex(index, SizeOf.LONG); 211 Memory.pokeLong(backingArray, offset + index, value, order); 212 return this; 213 } 214 215 @Override 216 public ByteBuffer putLong(long value) { 217 int newPosition = position + SizeOf.LONG; 218 if (newPosition > limit) { 219 throw new BufferOverflowException(); 220 } 221 Memory.pokeLong(backingArray, offset + position, value, order); 222 position = newPosition; 223 return this; 224 } 225 226 @Override 227 public ByteBuffer putShort(int index, short value) { 228 checkIndex(index, SizeOf.SHORT); 229 Memory.pokeShort(backingArray, offset + index, value, order); 230 return this; 231 } 232 233 @Override 234 public ByteBuffer putShort(short value) { 235 int newPosition = position + SizeOf.SHORT; 236 if (newPosition > limit) { 237 throw new BufferOverflowException(); 238 } 239 Memory.pokeShort(backingArray, offset + position, value, order); 240 position = newPosition; 241 return this; 242 } 243 244 @Override 245 public ByteBuffer slice() { 246 return new ReadWriteHeapByteBuffer(backingArray, remaining(), offset + position); 247 } 248 } 249