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 srcIndex,
 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(srcIndex, length, sb.limit());
 285             System.arraycopy(sb.hb, sb.ix(srcIndex),
 286                              hb, ix(index), length);
 287         } else if (src.isDirect()) {
 288             Objects.checkFromIndexSize(index, length, limit());
 289             Objects.checkFromIndexSize(srcIndex, length, src.limit());
 290             src.get(srcIndex, hb, ix(index), length);
 291         } else {
 292             super.put(index, src, srcIndex, length);
 293         }
 294         return this;
 295 #else[rw]
 296         throw new ReadOnlyBufferException();
 297 #end[rw]
 298     }
 299 
 300     public $Type$Buffer compact() {
 301 #if[rw]
 302         System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
 303         position(remaining());
 304         limit(capacity());
 305         discardMark();
 306         return this;
 307 #else[rw]
 308         throw new ReadOnlyBufferException();
 309 #end[rw]
 310     }
 311 
 312 
 313 
 314 #if[byte]
 315 
 316     byte _get(int i) {                          // package-private
 317         return hb[i];
 318     }
 319 
 320     void _put(int i, byte b) {                  // package-private
 321 #if[rw]
 322         hb[i] = b;
 323 #else[rw]
 324         throw new ReadOnlyBufferException();
 325 #end[rw]
 326     }
 327 
 328     // char
 329 
 330 #if[rw]
 331 
 332     public char getChar() {
 333         return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 334     }
 335 
 336     public char getChar(int i) {
 337         return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 338     }
 339 
 340 #end[rw]
 341 
 342     public $Type$Buffer putChar(char x) {
 343 #if[rw]
 344         UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 345         return this;
 346 #else[rw]
 347         throw new ReadOnlyBufferException();
 348 #end[rw]
 349     }
 350 
 351     public $Type$Buffer putChar(int i, char x) {
 352 #if[rw]
 353         UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 354         return this;
 355 #else[rw]
 356         throw new ReadOnlyBufferException();
 357 #end[rw]
 358     }
 359 
 360     public CharBuffer asCharBuffer() {
 361         int size = this.remaining() >> 1;
 362         long addr = address + position();
 363         return (bigEndian
 364                 ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
 365                                                                -1,
 366                                                                0,
 367                                                                size,
 368                                                                size,
 369                                                                addr))
 370                 : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
 371                                                                -1,
 372                                                                0,
 373                                                                size,
 374                                                                size,
 375                                                                addr)));
 376     }
 377 
 378 
 379     // short
 380 
 381 #if[rw]
 382 
 383     public short getShort() {
 384         return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 385     }
 386 
 387     public short getShort(int i) {
 388         return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 389     }
 390 
 391 #end[rw]
 392 
 393     public $Type$Buffer putShort(short x) {
 394 #if[rw]
 395         UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 396         return this;
 397 #else[rw]
 398         throw new ReadOnlyBufferException();
 399 #end[rw]
 400     }
 401 
 402     public $Type$Buffer putShort(int i, short x) {
 403 #if[rw]
 404         UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 405         return this;
 406 #else[rw]
 407         throw new ReadOnlyBufferException();
 408 #end[rw]
 409     }
 410 
 411     public ShortBuffer asShortBuffer() {
 412         int size = this.remaining() >> 1;
 413         long addr = address + position();
 414         return (bigEndian
 415                 ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
 416                                                                  -1,
 417                                                                  0,
 418                                                                  size,
 419                                                                  size,
 420                                                                  addr))
 421                 : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
 422                                                                  -1,
 423                                                                  0,
 424                                                                  size,
 425                                                                  size,
 426                                                                  addr)));
 427     }
 428 
 429 
 430     // int
 431 
 432 #if[rw]
 433 
 434     public int getInt() {
 435         return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 436     }
 437 
 438     public int getInt(int i) {
 439         return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 440     }
 441 
 442 #end[rw]
 443 
 444     public $Type$Buffer putInt(int x) {
 445 #if[rw]
 446         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
 447         return this;
 448 #else[rw]
 449         throw new ReadOnlyBufferException();
 450 #end[rw]
 451     }
 452 
 453     public $Type$Buffer putInt(int i, int x) {
 454 #if[rw]
 455         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
 456         return this;
 457 #else[rw]
 458         throw new ReadOnlyBufferException();
 459 #end[rw]
 460     }
 461 
 462     public IntBuffer asIntBuffer() {
 463         int size = this.remaining() >> 2;
 464         long addr = address + position();
 465         return (bigEndian
 466                 ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
 467                                                              -1,
 468                                                              0,
 469                                                              size,
 470                                                              size,
 471                                                              addr))
 472                 : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
 473                                                              -1,
 474                                                              0,
 475                                                              size,
 476                                                              size,
 477                                                              addr)));
 478     }
 479 
 480 
 481     // long
 482 
 483 #if[rw]
 484 
 485     public long getLong() {
 486         return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 487     }
 488 
 489     public long getLong(int i) {
 490         return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 491     }
 492 
 493 #end[rw]
 494 
 495     public $Type$Buffer putLong(long x) {
 496 #if[rw]
 497         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
 498         return this;
 499 #else[rw]
 500         throw new ReadOnlyBufferException();
 501 #end[rw]
 502     }
 503 
 504     public $Type$Buffer putLong(int i, long x) {
 505 #if[rw]
 506         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
 507         return this;
 508 #else[rw]
 509         throw new ReadOnlyBufferException();
 510 #end[rw]
 511     }
 512 
 513     public LongBuffer asLongBuffer() {
 514         int size = this.remaining() >> 3;
 515         long addr = address + position();
 516         return (bigEndian
 517                 ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
 518                                                                -1,
 519                                                                0,
 520                                                                size,
 521                                                                size,
 522                                                                addr))
 523                 : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
 524                                                                -1,
 525                                                                0,
 526                                                                size,
 527                                                                size,
 528                                                                addr)));
 529     }
 530 
 531 
 532     // float
 533 
 534 #if[rw]
 535 
 536     public float getFloat() {
 537         int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 538         return Float.intBitsToFloat(x);
 539     }
 540 
 541     public float getFloat(int i) {
 542         int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 543         return Float.intBitsToFloat(x);
 544     }
 545 
 546 #end[rw]
 547 
 548     public $Type$Buffer putFloat(float x) {
 549 #if[rw]
 550         int y = Float.floatToRawIntBits(x);
 551         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
 552         return this;
 553 #else[rw]
 554         throw new ReadOnlyBufferException();
 555 #end[rw]
 556     }
 557 
 558     public $Type$Buffer putFloat(int i, float x) {
 559 #if[rw]
 560         int y = Float.floatToRawIntBits(x);
 561         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
 562         return this;
 563 #else[rw]
 564         throw new ReadOnlyBufferException();
 565 #end[rw]
 566     }
 567 
 568     public FloatBuffer asFloatBuffer() {
 569         int size = this.remaining() >> 2;
 570         long addr = address + position();
 571         return (bigEndian
 572                 ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
 573                                                                  -1,
 574                                                                  0,
 575                                                                  size,
 576                                                                  size,
 577                                                                  addr))
 578                 : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
 579                                                                  -1,
 580                                                                  0,
 581                                                                  size,
 582                                                                  size,
 583                                                                  addr)));
 584     }
 585 
 586 
 587     // double
 588 
 589 #if[rw]
 590 
 591     public double getDouble() {
 592         long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 593         return Double.longBitsToDouble(x);
 594     }
 595 
 596     public double getDouble(int i) {
 597         long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 598         return Double.longBitsToDouble(x);
 599     }
 600 
 601 #end[rw]
 602 
 603     public $Type$Buffer putDouble(double x) {
 604 #if[rw]
 605         long y = Double.doubleToRawLongBits(x);
 606         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
 607         return this;
 608 #else[rw]
 609         throw new ReadOnlyBufferException();
 610 #end[rw]
 611     }
 612 
 613     public $Type$Buffer putDouble(int i, double x) {
 614 #if[rw]
 615         long y = Double.doubleToRawLongBits(x);
 616         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
 617         return this;
 618 #else[rw]
 619         throw new ReadOnlyBufferException();
 620 #end[rw]
 621     }
 622 
 623     public DoubleBuffer asDoubleBuffer() {
 624         int size = this.remaining() >> 3;
 625         long addr = address + position();
 626         return (bigEndian
 627                 ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
 628                                                                    -1,
 629                                                                    0,
 630                                                                    size,
 631                                                                    size,
 632                                                                    addr))
 633                 : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
 634                                                                    -1,
 635                                                                    0,
 636                                                                    size,
 637                                                                    size,
 638                                                                    addr)));
 639     }
 640 
 641 
 642 #end[byte]
 643 
 644 
 645 #if[char]
 646 
 647     String toString(int start, int end) {               // package-private
 648         try {
 649             return new String(hb, start + offset, end - start);
 650         } catch (StringIndexOutOfBoundsException x) {
 651             throw new IndexOutOfBoundsException();
 652         }
 653     }
 654 
 655 
 656     // --- Methods to support CharSequence ---
 657 
 658     public CharBuffer subSequence(int start, int end) {
 659         if ((start < 0)
 660             || (end > length())
 661             || (start > end))
 662             throw new IndexOutOfBoundsException();
 663         int pos = position();
 664         return new HeapCharBuffer$RW$(hb,
 665                                       -1,
 666                                       pos + start,
 667                                       pos + end,
 668                                       capacity(),
 669                                       offset);
 670     }
 671 
 672 #end[char]
 673 
 674 
 675 #if[!byte]
 676 
 677     public ByteOrder order() {
 678         return ByteOrder.nativeOrder();
 679     }
 680 #end[!byte]
 681 #if[char]
 682 
 683     ByteOrder charRegionOrder() {
 684         return order();
 685     }
 686 #end[char]
 687 }