1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 28package java.nio; 29 30 31import libcore.io.Memory; 32 33/** 34 * A read/write HeapByteBuffer. 35 */ 36 37class HeapByteBuffer extends ByteBuffer { 38 39 // For speed these fields are actually declared in X-Buffer; 40 // these declarations are here as documentation 41 /* 42 43 protected final byte[] hb; 44 protected final int offset; 45 46 */ 47 48 HeapByteBuffer(int cap, int lim) { // packag-private 49 this(cap, lim, false); 50 } 51 52 53 HeapByteBuffer(int cap, int lim, boolean isReadOnly) { // package-private 54 super(-1, 0, lim, cap, new byte[cap], 0); 55 this.isReadOnly = isReadOnly; 56 } 57 58 HeapByteBuffer(byte[] buf, int off, int len) { // package-private 59 this(buf, off, len, false); 60 } 61 62 HeapByteBuffer(byte[] buf, int off, int len, boolean isReadOnly) { // package-private 63 super(-1, off, off + len, buf.length, buf, 0); 64 this.isReadOnly = isReadOnly; 65 } 66 67 protected HeapByteBuffer(byte[] buf, 68 int mark, int pos, int lim, int cap, 69 int off) { 70 this(buf, mark, pos, lim, cap, off, false); 71 } 72 73 protected HeapByteBuffer(byte[] buf, 74 int mark, int pos, int lim, int cap, 75 int off, boolean isReadOnly) { 76 super(mark, pos, lim, cap, buf, off); 77 this.isReadOnly = isReadOnly; 78 } 79 80 public ByteBuffer slice() { 81 return new HeapByteBuffer(hb, 82 -1, 83 0, 84 remaining(), 85 remaining(), 86 position() + offset, 87 isReadOnly); 88 } 89 90 public ByteBuffer duplicate() { 91 return new HeapByteBuffer(hb, 92 markValue(), 93 position(), 94 limit(), 95 capacity(), 96 offset, 97 isReadOnly); 98 } 99 100 public ByteBuffer asReadOnlyBuffer() { 101 return new HeapByteBuffer(hb, 102 this.markValue(), 103 this.position(), 104 this.limit(), 105 this.capacity(), 106 offset, true); 107 } 108 109 protected int ix(int i) { 110 return i + offset; 111 } 112 113 public byte get() { 114 return hb[ix(nextGetIndex())]; 115 } 116 117 public byte get(int i) { 118 return hb[ix(checkIndex(i))]; 119 } 120 121 public ByteBuffer get(byte[] dst, int offset, int length) { 122 checkBounds(offset, length, dst.length); 123 if (length > remaining()) 124 throw new BufferUnderflowException(); 125 System.arraycopy(hb, ix(position()), dst, offset, length); 126 position(position() + length); 127 return this; 128 } 129 130 public boolean isDirect() { 131 return false; 132 } 133 134 public boolean isReadOnly() { 135 return isReadOnly; 136 } 137 138 public ByteBuffer put(byte x) { 139 if (isReadOnly) { 140 throw new ReadOnlyBufferException(); 141 } 142 hb[ix(nextPutIndex())] = x; 143 return this; 144 } 145 146 public ByteBuffer put(int i, byte x) { 147 if (isReadOnly) { 148 throw new ReadOnlyBufferException(); 149 } 150 hb[ix(checkIndex(i))] = x; 151 return this; 152 } 153 154 public ByteBuffer put(byte[] src, int offset, int length) { 155 if (isReadOnly) { 156 throw new ReadOnlyBufferException(); 157 } 158 checkBounds(offset, length, src.length); 159 if (length > remaining()) 160 throw new BufferOverflowException(); 161 System.arraycopy(src, offset, hb, ix(position()), length); 162 position(position() + length); 163 return this; 164 } 165 166 public ByteBuffer compact() { 167 if (isReadOnly) { 168 throw new ReadOnlyBufferException(); 169 } 170 System.arraycopy(hb, ix(position()), hb, ix(0), remaining()); 171 position(remaining()); 172 limit(capacity()); 173 discardMark(); 174 return this; 175 } 176 177 byte _get(int i) { // package-private 178 return hb[i]; 179 } 180 181 void _put(int i, byte b) { // package-private 182 if (isReadOnly) { 183 throw new ReadOnlyBufferException(); 184 } 185 hb[i] = b; 186 } 187 188 public char getChar() { 189 return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian); 190 } 191 192 public char getChar(int i) { 193 return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian); 194 } 195 196 char getCharUnchecked(int i) { 197 return Bits.getChar(this, ix(i), bigEndian); 198 } 199 200 void getUnchecked(int pos, char[] dst, int dstOffset, int length) { 201 Memory.unsafeBulkGet(dst, dstOffset, length * 2, hb, ix(pos), 2, !nativeByteOrder); 202 } 203 204 public ByteBuffer putChar(char x) { 205 if (isReadOnly) { 206 throw new ReadOnlyBufferException(); 207 } 208 Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian); 209 return this; 210 } 211 212 public ByteBuffer putChar(int i, char x) { 213 if (isReadOnly) { 214 throw new ReadOnlyBufferException(); 215 } 216 Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian); 217 return this; 218 } 219 220 void putCharUnchecked(int i, char x) { 221 Bits.putChar(this, ix(i), x, bigEndian); 222 } 223 224 void putUnchecked(int pos, char[] src, int srcOffset, int length) { 225 Memory.unsafeBulkPut(hb, ix(pos), length * 2, src, srcOffset, 2, !nativeByteOrder); 226 } 227 228 public CharBuffer asCharBuffer() { 229 int size = this.remaining() >> 1; 230 int off = position(); 231 return (CharBuffer) (new ByteBufferAsCharBuffer(this, 232 -1, 233 0, 234 size, 235 size, 236 off, 237 order())); 238 } 239 240 public short getShort() { 241 return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian); 242 } 243 244 public short getShort(int i) { 245 return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian); 246 } 247 248 short getShortUnchecked(int i) { 249 return Bits.getShort(this, ix(i), bigEndian); 250 } 251 252 void getUnchecked(int pos, short[] dst, int dstOffset, int length) { 253 Memory.unsafeBulkGet(dst, dstOffset, length * 2, hb, ix(pos), 2, !nativeByteOrder); 254 } 255 256 public ByteBuffer putShort(short x) { 257 if (isReadOnly) { 258 throw new ReadOnlyBufferException(); 259 } 260 Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian); 261 return this; 262 } 263 264 public ByteBuffer putShort(int i, short x) { 265 if (isReadOnly) { 266 throw new ReadOnlyBufferException(); 267 } 268 Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian); 269 return this; 270 } 271 272 void putShortUnchecked(int i, short x) { 273 Bits.putShort(this, ix(i), x, bigEndian); 274 } 275 276 void putUnchecked(int pos, short[] src, int srcOffset, int length) { 277 Memory.unsafeBulkPut(hb, ix(pos), length * 2, src, srcOffset, 2, !nativeByteOrder); 278 } 279 280 public ShortBuffer asShortBuffer() { 281 int size = this.remaining() >> 1; 282 int off = position(); 283 return new ByteBufferAsShortBuffer(this, 284 -1, 285 0, 286 size, 287 size, 288 off, 289 order()); 290 } 291 292 public int getInt() { 293 return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian); 294 } 295 296 public int getInt(int i) { 297 return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian); 298 } 299 300 int getIntUnchecked(int i) { 301 return Bits.getInt(this, ix(i), bigEndian); 302 } 303 304 void getUnchecked(int pos, int[] dst, int dstOffset, int length) { 305 Memory.unsafeBulkGet(dst, dstOffset, length * 4, hb, ix(pos), 4, !nativeByteOrder); 306 } 307 308 public ByteBuffer putInt(int x) { 309 if (isReadOnly) { 310 throw new ReadOnlyBufferException(); 311 } 312 Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian); 313 return this; 314 } 315 316 public ByteBuffer putInt(int i, int x) { 317 if (isReadOnly) { 318 throw new ReadOnlyBufferException(); 319 } 320 Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian); 321 return this; 322 } 323 324 void putIntUnchecked(int i, int x) { 325 Bits.putInt(this, ix(i), x, bigEndian); 326 } 327 328 void putUnchecked(int pos, int[] src, int srcOffset, int length) { 329 Memory.unsafeBulkPut(hb, ix(pos), length * 4, src, srcOffset, 4, !nativeByteOrder); 330 } 331 332 public IntBuffer asIntBuffer() { 333 int size = this.remaining() >> 2; 334 int off = position(); 335 336 return (IntBuffer) (new ByteBufferAsIntBuffer(this, 337 -1, 338 0, 339 size, 340 size, 341 off, 342 order())); 343 } 344 345 public long getLong() { 346 return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian); 347 } 348 349 public long getLong(int i) { 350 return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian); 351 } 352 353 long getLongUnchecked(int i) { 354 return Bits.getLong(this, ix(i), bigEndian); 355 } 356 357 void getUnchecked(int pos, long[] dst, int dstOffset, int length) { 358 Memory.unsafeBulkGet(dst, dstOffset, length * 8, hb, ix(pos), 8, !nativeByteOrder); 359 } 360 361 public ByteBuffer putLong(long x) { 362 if (isReadOnly) { 363 throw new ReadOnlyBufferException(); 364 } 365 Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian); 366 return this; 367 } 368 369 public ByteBuffer putLong(int i, long x) { 370 if (isReadOnly) { 371 throw new ReadOnlyBufferException(); 372 } 373 Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian); 374 return this; 375 } 376 377 void putLongUnchecked(int i, long x) { 378 Bits.putLong(this, ix(i), x, bigEndian); 379 } 380 381 void putUnchecked(int pos, long[] src, int srcOffset, int length) { 382 Memory.unsafeBulkPut(hb, ix(pos), length * 8, src, srcOffset, 8, !nativeByteOrder); 383 } 384 385 public LongBuffer asLongBuffer() { 386 int size = this.remaining() >> 3; 387 int off = position(); 388 return (LongBuffer) (new ByteBufferAsLongBuffer(this, 389 -1, 390 0, 391 size, 392 size, 393 off, 394 order())); 395 } 396 397 public float getFloat() { 398 return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian); 399 } 400 401 public float getFloat(int i) { 402 return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian); 403 } 404 405 float getFloatUnchecked(int i) { 406 return Bits.getFloat(this, ix(i), bigEndian); 407 } 408 409 void getUnchecked(int pos, float[] dst, int dstOffset, int length) { 410 Memory.unsafeBulkGet(dst, dstOffset, length * 4, hb, ix(pos), 4, !nativeByteOrder); 411 } 412 413 public ByteBuffer putFloat(float x) { 414 if (isReadOnly) { 415 throw new ReadOnlyBufferException(); 416 } 417 Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian); 418 return this; 419 } 420 421 public ByteBuffer putFloat(int i, float x) { 422 if (isReadOnly) { 423 throw new ReadOnlyBufferException(); 424 } 425 Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian); 426 return this; 427 } 428 429 void putFloatUnchecked(int i, float x) { 430 Bits.putFloat(this, ix(i), x, bigEndian); 431 } 432 433 void putUnchecked(int pos, float[] src, int srcOffset, int length) { 434 Memory.unsafeBulkPut(hb, ix(pos), length * 4, src, srcOffset, 4, !nativeByteOrder); 435 } 436 437 public FloatBuffer asFloatBuffer() { 438 int size = this.remaining() >> 2; 439 int off = position(); 440 return (FloatBuffer) (new ByteBufferAsFloatBuffer(this, 441 -1, 442 0, 443 size, 444 size, 445 off, 446 order())); 447 } 448 449 public double getDouble() { 450 return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian); 451 } 452 453 public double getDouble(int i) { 454 return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian); 455 } 456 457 double getDoubleUnchecked(int i) { 458 return Bits.getDouble(this, ix(i), bigEndian); 459 } 460 461 void getUnchecked(int pos, double[] dst, int dstOffset, int length) { 462 Memory.unsafeBulkGet(dst, dstOffset, length * 8, hb, ix(pos), 8, !nativeByteOrder); 463 } 464 465 public ByteBuffer putDouble(double x) { 466 if (isReadOnly) { 467 throw new ReadOnlyBufferException(); 468 } 469 Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian); 470 return this; 471 } 472 473 public ByteBuffer putDouble(int i, double x) { 474 if (isReadOnly) { 475 throw new ReadOnlyBufferException(); 476 } 477 Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian); 478 return this; 479 } 480 481 void putDoubleUnchecked(int i, double x) { 482 Bits.putDouble(this, ix(i), x, bigEndian); 483 } 484 485 void putUnchecked(int pos, double[] src, int srcOffset, int length) { 486 Memory.unsafeBulkPut(hb, ix(pos), length * 8, src, srcOffset, 8, !nativeByteOrder); 487 } 488 489 public DoubleBuffer asDoubleBuffer() { 490 int size = this.remaining() >> 3; 491 int off = position(); 492 return (DoubleBuffer) (new ByteBufferAsDoubleBuffer(this, 493 -1, 494 0, 495 size, 496 size, 497 off, 498 order())); 499 } 500} 501