1 /*
   2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #warn This file is preprocessed before being compiled
  27 
  28 package java.nio;
  29 
  30 /**
  31 #if[rw]
  32  * A read/write Heap$Type$Buffer.
  33 #else[rw]
  34  * A read-only Heap$Type$Buffer.  This class extends the corresponding
  35  * read/write class, overriding the mutation methods to throw a {@link
  36  * ReadOnlyBufferException} and overriding the view-buffer methods to return an
  37  * instance of this class rather than of the superclass.
  38 #end[rw]
  39  */
  40 
  41 import java.util.Objects;
  42 
  43 class Heap$Type$Buffer$RW$
  44     extends {#if[ro]?Heap}$Type$Buffer
  45 {
  46     // Cached array base offset
  47     private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
  48 
  49     // Cached array base offset
  50     private static final long ARRAY_INDEX_SCALE = UNSAFE.arrayIndexScale($type$[].class);
  51 
  52     // For speed these fields are actually declared in X-Buffer;
  53     // these declarations are here as documentation
  54     /*
  55 #if[rw]
  56     protected final $type$[] hb;
  57     protected final int offset;
  58 #end[rw]
  59     */
  60 
  61     Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
  62 #if[rw]
  63         super(-1, 0, lim, cap, new $type$[cap], 0);
  64         /*
  65         hb = new $type$[cap];
  66         offset = 0;
  67         */
  68         this.address = ARRAY_BASE_OFFSET;
  69 #else[rw]
  70         super(cap, lim);
  71         this.isReadOnly = true;
  72 #end[rw]
  73     }
  74 
  75     Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
  76 #if[rw]
  77         super(-1, off, off + len, buf.length, buf, 0);
  78         /*
  79         hb = buf;
  80         offset = 0;
  81         */
  82         this.address = ARRAY_BASE_OFFSET;
  83 #else[rw]
  84         super(buf, off, len);
  85         this.isReadOnly = true;
  86 #end[rw]
  87     }
  88 
  89     protected Heap$Type$Buffer$RW$($type$[] buf,
  90                                    int mark, int pos, int lim, int cap,
  91                                    int off)
  92     {
  93 #if[rw]
  94         super(mark, pos, lim, cap, buf, off);
  95         /*
  96         hb = buf;
  97         offset = off;
  98         */
  99         this.address = ARRAY_BASE_OFFSET + off * ARRAY_INDEX_SCALE;
 100 #else[rw]
 101         super(buf, mark, pos, lim, cap, off);
 102         this.isReadOnly = true;
 103 #end[rw]
 104     }
 105 
 106     public $Type$Buffer slice() {
 107         return new Heap$Type$Buffer$RW$(hb,
 108                                         -1,
 109                                         0,
 110                                         this.remaining(),
 111                                         this.remaining(),
 112                                         this.position() + offset);
 113     }
 114 
 115 #if[byte]
 116     $Type$Buffer slice(int pos, int lim) {
 117         assert (pos >= 0);
 118         assert (pos <= lim);
 119         int rem = lim - pos;
 120         return new Heap$Type$Buffer$RW$(hb,
 121                                         -1,
 122                                         0,
 123                                         rem,
 124                                         rem,
 125                                         pos + offset);
 126     }
 127 #end[byte]
 128 
 129     public $Type$Buffer duplicate() {
 130         return new Heap$Type$Buffer$RW$(hb,
 131                                         this.markValue(),
 132                                         this.position(),
 133                                         this.limit(),
 134                                         this.capacity(),
 135                                         offset);
 136     }
 137 
 138     public $Type$Buffer asReadOnlyBuffer() {
 139 #if[rw]
 140         return new Heap$Type$BufferR(hb,
 141                                      this.markValue(),
 142                                      this.position(),
 143                                      this.limit(),
 144                                      this.capacity(),
 145                                      offset);
 146 #else[rw]
 147         return duplicate();
 148 #end[rw]
 149     }
 150 
 151 #if[rw]
 152 
 153     protected int ix(int i) {
 154         return i + offset;
 155     }
 156 
 157 #if[byte]
 158     private long byteOffset(long i) {
 159         return address + i;
 160     }
 161 #end[byte]
 162 
 163     public $type$ get() {
 164         return hb[ix(nextGetIndex())];
 165     }
 166 
 167     public $type$ get(int i) {
 168         return hb[ix(checkIndex(i))];
 169     }
 170 
 171 #if[streamableType]
 172     $type$ getUnchecked(int i) {
 173         return hb[ix(i)];
 174     }
 175 #end[streamableType]
 176 
 177     public $Type$Buffer get($type$[] dst, int offset, int length) {
 178         checkBounds(offset, length, dst.length);
 179         if (length > remaining())
 180             throw new BufferUnderflowException();
 181         System.arraycopy(hb, ix(position()), dst, offset, length);
 182         position(position() + length);
 183         return this;
 184     }
 185 
 186     public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
 187         //System.out.println("Heap absolute bulk get");
 188         Objects.checkFromIndexSize(index, length, limit());
 189         Objects.checkFromIndexSize(offset, length, dst.length);
 190         System.arraycopy(hb, ix(index), dst, offset, length);
 191         return this;
 192     }
 193 
 194     public boolean isDirect() {
 195         return false;
 196     }
 197 
 198 #end[rw]
 199 
 200     public boolean isReadOnly() {
 201         return {#if[rw]?false:true};
 202     }
 203 
 204     public $Type$Buffer put($type$ x) {
 205 #if[rw]
 206         hb[ix(nextPutIndex())] = x;
 207         return this;
 208 #else[rw]
 209         throw new ReadOnlyBufferException();
 210 #end[rw]
 211     }
 212 
 213     public $Type$Buffer put(int i, $type$ x) {
 214 #if[rw]
 215         hb[ix(checkIndex(i))] = x;
 216         return this;
 217 #else[rw]
 218         throw new ReadOnlyBufferException();
 219 #end[rw]
 220     }
 221 
 222     public $Type$Buffer put($type$[] src, int offset, int length) {
 223 #if[rw]
 224         checkBounds(offset, length, src.length);
 225         if (length > remaining())
 226             throw new BufferOverflowException();
 227         System.arraycopy(src, offset, hb, ix(position()), length);
 228         position(position() + length);
 229         return this;
 230 #else[rw]
 231         throw new ReadOnlyBufferException();
 232 #end[rw]
 233     }
 234 
 235     public $Type$Buffer put($Type$Buffer src) {
 236 #if[rw]
 237         if (src instanceof Heap$Type$Buffer) {
 238             if (src == this)
 239                 throw createSameBufferException();
 240             Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
 241             int n = sb.remaining();
 242             if (n > remaining())
 243                 throw new BufferOverflowException();
 244             System.arraycopy(sb.hb, sb.ix(sb.position()),
 245                              hb, ix(position()), n);
 246             sb.position(sb.position() + n);
 247             position(position() + n);
 248         } else if (src.isDirect()) {
 249             int n = src.remaining();
 250             if (n > remaining())
 251                 throw new BufferOverflowException();
 252             src.get(hb, ix(position()), n);
 253             position(position() + n);
 254         } else {
 255             super.put(src);
 256         }
 257         return this;
 258 #else[rw]
 259         throw new ReadOnlyBufferException();
 260 #end[rw]
 261     }
 262 
 263     public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
 264         //System.out.println("Heap absolute bulk put array");
 265 #if[rw]
 266         Objects.checkFromIndexSize(index, length, limit());
 267         Objects.checkFromIndexSize(offset, length, src.length);
 268         System.arraycopy(src, offset, hb, ix(index), length);
 269         return this;
 270 #else[rw]
 271         throw new ReadOnlyBufferException();
 272 #end[rw]
 273     }
 274 
 275     public $Type$Buffer put(int index, $Type$Buffer src, int offset,
 276         int length) {
 277         //System.out.println("Heap absolute bulk put buffer");
 278 #if[rw]
 279         if (src instanceof Heap$Type$Buffer) {
 280             if (index < 0)
 281                 throw new IndexOutOfBoundsException("Index negative: " + index);
 282             Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
 283             Objects.checkFromIndexSize(index, length, limit());
 284             Objects.checkFromIndexSize(offset, length, sb.limit());
 285             System.arraycopy(sb.hb, sb.ix(offset),
 286                              hb, ix(index), length);
 287         } else if (src.isDirect()) {
 288             if (index < 0)
 289                 throw new IndexOutOfBoundsException("Index negative: " + index);
 290             Objects.checkFromIndexSize(index, length, limit());
 291             Objects.checkFromIndexSize(offset, length, src.limit());
 292             src.get(offset, hb, ix(index), length);
 293         } else {
 294             super.put(index, src, offset, length);
 295         }
 296         return this;
 297 #else[rw]
 298         throw new ReadOnlyBufferException();
 299 #end[rw]
 300     }
 301 
 302     public $Type$Buffer compact() {
 303 #if[rw]
 304         System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
 305         position(remaining());
 306         limit(capacity());
 307         discardMark();
 308         return this;
 309 #else[rw]
 310         throw new ReadOnlyBufferException();
 311 #end[rw]
 312     }
 313 
 314 
 315 
 316 #if[byte]
 317 
 318     byte _get(int i) {                          // package-private
 319         return hb[i];
 320     }
 321 
 322     void _put(int i, byte b) {                  // package-private
 323 #if[rw]
 324         hb[i] = b;
 325 #else[rw]
 326         throw new ReadOnlyBufferException();
 327 #end[rw]
 328     }
 329 
 330     // char
 331 
 332 #if[rw]
 333 
 334     public char getChar() {
 335         return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 336     }
 337 
 338     public char getChar(int i) {
 339         return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 340     }
 341 
 342 #end[rw]
 343 
 344     public $Type$Buffer putChar(char x) {
 345 #if[rw]
 346         UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 347         return this;
 348 #else[rw]
 349         throw new ReadOnlyBufferException();
 350 #end[rw]
 351     }
 352 
 353     public $Type$Buffer putChar(int i, char x) {
 354 #if[rw]
 355         UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 356         return this;
 357 #else[rw]
 358         throw new ReadOnlyBufferException();
 359 #end[rw]
 360     }
 361 
 362     public CharBuffer asCharBuffer() {
 363         int size = this.remaining() >> 1;
 364         long addr = address + position();
 365         return (bigEndian
 366                 ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
 367                                                                -1,
 368                                                                0,
 369                                                                size,
 370                                                                size,
 371                                                                addr))
 372                 : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
 373                                                                -1,
 374                                                                0,
 375                                                                size,
 376                                                                size,
 377                                                                addr)));
 378     }
 379 
 380 
 381     // short
 382 
 383 #if[rw]
 384 
 385     public short getShort() {
 386         return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 387     }
 388 
 389     public short getShort(int i) {
 390         return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 391     }
 392 
 393 #end[rw]
 394 
 395     public $Type$Buffer putShort(short x) {
 396 #if[rw]
 397         UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 398         return this;
 399 #else[rw]
 400         throw new ReadOnlyBufferException();
 401 #end[rw]
 402     }
 403 
 404     public $Type$Buffer putShort(int i, short x) {
 405 #if[rw]
 406         UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 407         return this;
 408 #else[rw]
 409         throw new ReadOnlyBufferException();
 410 #end[rw]
 411     }
 412 
 413     public ShortBuffer asShortBuffer() {
 414         int size = this.remaining() >> 1;
 415         long addr = address + position();
 416         return (bigEndian
 417                 ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
 418                                                                  -1,
 419                                                                  0,
 420                                                                  size,
 421                                                                  size,
 422                                                                  addr))
 423                 : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
 424                                                                  -1,
 425                                                                  0,
 426                                                                  size,
 427                                                                  size,
 428                                                                  addr)));
 429     }
 430 
 431 
 432     // int
 433 
 434 #if[rw]
 435 
 436     public int getInt() {
 437         return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 438     }
 439 
 440     public int getInt(int i) {
 441         return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 442     }
 443 
 444 #end[rw]
 445 
 446     public $Type$Buffer putInt(int x) {
 447 #if[rw]
 448         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
 449         return this;
 450 #else[rw]
 451         throw new ReadOnlyBufferException();
 452 #end[rw]
 453     }
 454 
 455     public $Type$Buffer putInt(int i, int x) {
 456 #if[rw]
 457         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
 458         return this;
 459 #else[rw]
 460         throw new ReadOnlyBufferException();
 461 #end[rw]
 462     }
 463 
 464     public IntBuffer asIntBuffer() {
 465         int size = this.remaining() >> 2;
 466         long addr = address + position();
 467         return (bigEndian
 468                 ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
 469                                                              -1,
 470                                                              0,
 471                                                              size,
 472                                                              size,
 473                                                              addr))
 474                 : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
 475                                                              -1,
 476                                                              0,
 477                                                              size,
 478                                                              size,
 479                                                              addr)));
 480     }
 481 
 482 
 483     // long
 484 
 485 #if[rw]
 486 
 487     public long getLong() {
 488         return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 489     }
 490 
 491     public long getLong(int i) {
 492         return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 493     }
 494 
 495 #end[rw]
 496 
 497     public $Type$Buffer putLong(long x) {
 498 #if[rw]
 499         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
 500         return this;
 501 #else[rw]
 502         throw new ReadOnlyBufferException();
 503 #end[rw]
 504     }
 505 
 506     public $Type$Buffer putLong(int i, long x) {
 507 #if[rw]
 508         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
 509         return this;
 510 #else[rw]
 511         throw new ReadOnlyBufferException();
 512 #end[rw]
 513     }
 514 
 515     public LongBuffer asLongBuffer() {
 516         int size = this.remaining() >> 3;
 517         long addr = address + position();
 518         return (bigEndian
 519                 ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
 520                                                                -1,
 521                                                                0,
 522                                                                size,
 523                                                                size,
 524                                                                addr))
 525                 : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
 526                                                                -1,
 527                                                                0,
 528                                                                size,
 529                                                                size,
 530                                                                addr)));
 531     }
 532 
 533 
 534     // float
 535 
 536 #if[rw]
 537 
 538     public float getFloat() {
 539         int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 540         return Float.intBitsToFloat(x);
 541     }
 542 
 543     public float getFloat(int i) {
 544         int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 545         return Float.intBitsToFloat(x);
 546     }
 547 
 548 #end[rw]
 549 
 550     public $Type$Buffer putFloat(float x) {
 551 #if[rw]
 552         int y = Float.floatToRawIntBits(x);
 553         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
 554         return this;
 555 #else[rw]
 556         throw new ReadOnlyBufferException();
 557 #end[rw]
 558     }
 559 
 560     public $Type$Buffer putFloat(int i, float x) {
 561 #if[rw]
 562         int y = Float.floatToRawIntBits(x);
 563         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
 564         return this;
 565 #else[rw]
 566         throw new ReadOnlyBufferException();
 567 #end[rw]
 568     }
 569 
 570     public FloatBuffer asFloatBuffer() {
 571         int size = this.remaining() >> 2;
 572         long addr = address + position();
 573         return (bigEndian
 574                 ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
 575                                                                  -1,
 576                                                                  0,
 577                                                                  size,
 578                                                                  size,
 579                                                                  addr))
 580                 : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
 581                                                                  -1,
 582                                                                  0,
 583                                                                  size,
 584                                                                  size,
 585                                                                  addr)));
 586     }
 587 
 588 
 589     // double
 590 
 591 #if[rw]
 592 
 593     public double getDouble() {
 594         long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 595         return Double.longBitsToDouble(x);
 596     }
 597 
 598     public double getDouble(int i) {
 599         long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 600         return Double.longBitsToDouble(x);
 601     }
 602 
 603 #end[rw]
 604 
 605     public $Type$Buffer putDouble(double x) {
 606 #if[rw]
 607         long y = Double.doubleToRawLongBits(x);
 608         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
 609         return this;
 610 #else[rw]
 611         throw new ReadOnlyBufferException();
 612 #end[rw]
 613     }
 614 
 615     public $Type$Buffer putDouble(int i, double x) {
 616 #if[rw]
 617         long y = Double.doubleToRawLongBits(x);
 618         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
 619         return this;
 620 #else[rw]
 621         throw new ReadOnlyBufferException();
 622 #end[rw]
 623     }
 624 
 625     public DoubleBuffer asDoubleBuffer() {
 626         int size = this.remaining() >> 3;
 627         long addr = address + position();
 628         return (bigEndian
 629                 ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
 630                                                                    -1,
 631                                                                    0,
 632                                                                    size,
 633                                                                    size,
 634                                                                    addr))
 635                 : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
 636                                                                    -1,
 637                                                                    0,
 638                                                                    size,
 639                                                                    size,
 640                                                                    addr)));
 641     }
 642 
 643 
 644 #end[byte]
 645 
 646 
 647 #if[char]
 648 
 649     String toString(int start, int end) {               // package-private
 650         try {
 651             return new String(hb, start + offset, end - start);
 652         } catch (StringIndexOutOfBoundsException x) {
 653             throw new IndexOutOfBoundsException();
 654         }
 655     }
 656 
 657 
 658     // --- Methods to support CharSequence ---
 659 
 660     public CharBuffer subSequence(int start, int end) {
 661         if ((start < 0)
 662             || (end > length())
 663             || (start > end))
 664             throw new IndexOutOfBoundsException();
 665         int pos = position();
 666         return new HeapCharBuffer$RW$(hb,
 667                                       -1,
 668                                       pos + start,
 669                                       pos + end,
 670                                       capacity(),
 671                                       offset);
 672     }
 673 
 674 #end[char]
 675 
 676 
 677 #if[!byte]
 678 
 679     public ByteOrder order() {
 680         return ByteOrder.nativeOrder();
 681     }
 682 #end[!byte]
 683 #if[char]
 684 
 685     ByteOrder charRegionOrder() {
 686         return order();
 687     }
 688 #end[char]
 689 }