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 import java.util.Objects;
  31 
  32 /**
  33 #if[rw]
  34  * A read/write Heap$Type$Buffer.
  35 #else[rw]
  36  * A read-only Heap$Type$Buffer.  This class extends the corresponding
  37  * read/write class, overriding the mutation methods to throw a {@link
  38  * ReadOnlyBufferException} and overriding the view-buffer methods to return an
  39  * instance of this class rather than of the superclass.
  40 #end[rw]
  41  */
  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         int rem = this.remaining();
 108         return new Heap$Type$Buffer$RW$(hb,
 109                                         -1,
 110                                         0,
 111                                         rem,
 112                                         rem,
 113                                         this.position() + offset);
 114     }
 115 
 116     @Override
 117     public $Type$Buffer slice(int index, int length) {
 118         Objects.checkFromIndexSize(index, length, limit());
 119         return new Heap$Type$Buffer$RW$(hb,
 120                                         -1,
 121                                         0,
 122                                         length,
 123                                         length,
 124                                         index + offset);
 125     }
 126 
 127     public $Type$Buffer duplicate() {
 128         return new Heap$Type$Buffer$RW$(hb,
 129                                         this.markValue(),
 130                                         this.position(),
 131                                         this.limit(),
 132                                         this.capacity(),
 133                                         offset);
 134     }
 135 
 136     public $Type$Buffer asReadOnlyBuffer() {
 137 #if[rw]
 138         return new Heap$Type$BufferR(hb,
 139                                      this.markValue(),
 140                                      this.position(),
 141                                      this.limit(),
 142                                      this.capacity(),
 143                                      offset);
 144 #else[rw]
 145         return duplicate();
 146 #end[rw]
 147     }
 148 
 149 #if[rw]
 150 
 151     protected int ix(int i) {
 152         return i + offset;
 153     }
 154 
 155 #if[byte]
 156     private long byteOffset(long i) {
 157         return address + i;
 158     }
 159 #end[byte]
 160 
 161     public $type$ get() {
 162         return hb[ix(nextGetIndex())];
 163     }
 164 
 165     public $type$ get(int i) {
 166         return hb[ix(checkIndex(i))];
 167     }
 168 
 169 #if[streamableType]
 170     $type$ getUnchecked(int i) {
 171         return hb[ix(i)];
 172     }
 173 #end[streamableType]
 174 
 175     public $Type$Buffer get($type$[] dst, int offset, int length) {
 176         Objects.checkFromIndexSize(offset, length, dst.length);
 177         int pos = position();
 178         if (length > limit() - pos)
 179             throw new BufferUnderflowException();
 180         System.arraycopy(hb, ix(pos), dst, offset, length);
 181         position(pos + length);
 182         return this;
 183     }
 184 
 185     public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
 186         Objects.checkFromIndexSize(index, length, limit());
 187         Objects.checkFromIndexSize(offset, length, dst.length);
 188         System.arraycopy(hb, ix(index), dst, offset, length);
 189         return this;
 190     }
 191 
 192     public boolean isDirect() {
 193         return false;
 194     }
 195 
 196 #end[rw]
 197 
 198     public boolean isReadOnly() {
 199         return {#if[rw]?false:true};
 200     }
 201 
 202     public $Type$Buffer put($type$ x) {
 203 #if[rw]
 204         hb[ix(nextPutIndex())] = x;
 205         return this;
 206 #else[rw]
 207         throw new ReadOnlyBufferException();
 208 #end[rw]
 209     }
 210 
 211     public $Type$Buffer put(int i, $type$ x) {
 212 #if[rw]
 213         hb[ix(checkIndex(i))] = x;
 214         return this;
 215 #else[rw]
 216         throw new ReadOnlyBufferException();
 217 #end[rw]
 218     }
 219 
 220     public $Type$Buffer put($type$[] src, int offset, int length) {
 221 #if[rw]
 222         Objects.checkFromIndexSize(offset, length, src.length);
 223         int pos = position();
 224         if (length > limit() - pos)
 225             throw new BufferOverflowException();
 226         System.arraycopy(src, offset, hb, ix(pos), length);
 227         position(pos + length);
 228         return this;
 229 #else[rw]
 230         throw new ReadOnlyBufferException();
 231 #end[rw]
 232     }
 233 
 234     public $Type$Buffer put($Type$Buffer src) {
 235 #if[rw]
 236         if (src instanceof Heap$Type$Buffer) {
 237             if (src == this)
 238                 throw createSameBufferException();
 239             Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
 240             int pos = position();
 241             int sbpos = sb.position();
 242             int n = sb.limit() - sbpos;
 243             if (n > limit() - pos)
 244                 throw new BufferOverflowException();
 245             System.arraycopy(sb.hb, sb.ix(sbpos),
 246                              hb, ix(pos), n);
 247             sb.position(sbpos + n);
 248             position(pos + n);
 249         } else if (src.isDirect()) {
 250             int n = src.remaining();
 251             int pos = position();
 252             if (n > limit() - pos)
 253                 throw new BufferOverflowException();
 254             src.get(hb, ix(pos), n);
 255             position(pos + n);
 256         } else {
 257             super.put(src);
 258         }
 259         return this;
 260 #else[rw]
 261         throw new ReadOnlyBufferException();
 262 #end[rw]
 263     }
 264 
 265     public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
 266 #if[rw]
 267         Objects.checkFromIndexSize(index, length, limit());
 268         Objects.checkFromIndexSize(offset, length, src.length);
 269         System.arraycopy(src, offset, hb, ix(index), length);
 270         return this;
 271 #else[rw]
 272         throw new ReadOnlyBufferException();
 273 #end[rw]
 274     }
 275 
 276 #if[char]
 277 
 278     public $Type$Buffer put(String src, int start, int end) {
 279         int length = end - start;
 280         Objects.checkFromIndexSize(start, length, src.length());
 281         if (isReadOnly())
 282             throw new ReadOnlyBufferException();
 283         int pos = position();
 284         int lim = limit();
 285         int rem = (pos <= lim) ? lim - pos : 0;
 286         if (length > rem)
 287             throw new BufferOverflowException();
 288         src.getChars(start, end, hb, ix(pos));
 289         position(pos + length);
 290         return this;
 291     }
 292 
 293 #end[char]
 294 
 295     public $Type$Buffer compact() {
 296 #if[rw]
 297         int pos = position();
 298         int rem = limit() - pos;
 299         System.arraycopy(hb, ix(pos), hb, ix(0), rem);
 300         position(rem);
 301         limit(capacity());
 302         discardMark();
 303         return this;
 304 #else[rw]
 305         throw new ReadOnlyBufferException();
 306 #end[rw]
 307     }
 308 
 309 
 310 
 311 #if[byte]
 312 
 313     byte _get(int i) {                          // package-private
 314         return hb[i];
 315     }
 316 
 317     void _put(int i, byte b) {                  // package-private
 318 #if[rw]
 319         hb[i] = b;
 320 #else[rw]
 321         throw new ReadOnlyBufferException();
 322 #end[rw]
 323     }
 324 
 325     // char
 326 
 327 #if[rw]
 328 
 329     public char getChar() {
 330         return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 331     }
 332 
 333     public char getChar(int i) {
 334         return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 335     }
 336 
 337 #end[rw]
 338 
 339     public $Type$Buffer putChar(char x) {
 340 #if[rw]
 341         UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 342         return this;
 343 #else[rw]
 344         throw new ReadOnlyBufferException();
 345 #end[rw]
 346     }
 347 
 348     public $Type$Buffer putChar(int i, char x) {
 349 #if[rw]
 350         UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 351         return this;
 352 #else[rw]
 353         throw new ReadOnlyBufferException();
 354 #end[rw]
 355     }
 356 
 357     public CharBuffer asCharBuffer() {
 358         int pos = position();
 359         int size = (limit() - pos) >> 1;
 360         long addr = address + pos;
 361         return (bigEndian
 362                 ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
 363                                                                -1,
 364                                                                0,
 365                                                                size,
 366                                                                size,
 367                                                                addr))
 368                 : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
 369                                                                -1,
 370                                                                0,
 371                                                                size,
 372                                                                size,
 373                                                                addr)));
 374     }
 375 
 376 
 377     // short
 378 
 379 #if[rw]
 380 
 381     public short getShort() {
 382         return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 383     }
 384 
 385     public short getShort(int i) {
 386         return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 387     }
 388 
 389 #end[rw]
 390 
 391     public $Type$Buffer putShort(short x) {
 392 #if[rw]
 393         UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 394         return this;
 395 #else[rw]
 396         throw new ReadOnlyBufferException();
 397 #end[rw]
 398     }
 399 
 400     public $Type$Buffer putShort(int i, short x) {
 401 #if[rw]
 402         UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 403         return this;
 404 #else[rw]
 405         throw new ReadOnlyBufferException();
 406 #end[rw]
 407     }
 408 
 409     public ShortBuffer asShortBuffer() {
 410         int pos = position();
 411         int size = (limit() - pos) >> 1;
 412         long addr = address + pos;
 413         return (bigEndian
 414                 ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
 415                                                                  -1,
 416                                                                  0,
 417                                                                  size,
 418                                                                  size,
 419                                                                  addr))
 420                 : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
 421                                                                  -1,
 422                                                                  0,
 423                                                                  size,
 424                                                                  size,
 425                                                                  addr)));
 426     }
 427 
 428 
 429     // int
 430 
 431 #if[rw]
 432 
 433     public int getInt() {
 434         return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 435     }
 436 
 437     public int getInt(int i) {
 438         return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 439     }
 440 
 441 #end[rw]
 442 
 443     public $Type$Buffer putInt(int x) {
 444 #if[rw]
 445         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
 446         return this;
 447 #else[rw]
 448         throw new ReadOnlyBufferException();
 449 #end[rw]
 450     }
 451 
 452     public $Type$Buffer putInt(int i, int x) {
 453 #if[rw]
 454         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
 455         return this;
 456 #else[rw]
 457         throw new ReadOnlyBufferException();
 458 #end[rw]
 459     }
 460 
 461     public IntBuffer asIntBuffer() {
 462         int pos = position();
 463         int size = (limit() - pos) >> 2;
 464         long addr = address + pos;
 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 pos = position();
 515         int size = (limit() - pos) >> 3;
 516         long addr = address + pos;
 517         return (bigEndian
 518                 ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
 519                                                                -1,
 520                                                                0,
 521                                                                size,
 522                                                                size,
 523                                                                addr))
 524                 : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
 525                                                                -1,
 526                                                                0,
 527                                                                size,
 528                                                                size,
 529                                                                addr)));
 530     }
 531 
 532 
 533     // float
 534 
 535 #if[rw]
 536 
 537     public float getFloat() {
 538         int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 539         return Float.intBitsToFloat(x);
 540     }
 541 
 542     public float getFloat(int i) {
 543         int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 544         return Float.intBitsToFloat(x);
 545     }
 546 
 547 #end[rw]
 548 
 549     public $Type$Buffer putFloat(float x) {
 550 #if[rw]
 551         int y = Float.floatToRawIntBits(x);
 552         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
 553         return this;
 554 #else[rw]
 555         throw new ReadOnlyBufferException();
 556 #end[rw]
 557     }
 558 
 559     public $Type$Buffer putFloat(int i, float x) {
 560 #if[rw]
 561         int y = Float.floatToRawIntBits(x);
 562         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
 563         return this;
 564 #else[rw]
 565         throw new ReadOnlyBufferException();
 566 #end[rw]
 567     }
 568 
 569     public FloatBuffer asFloatBuffer() {
 570         int pos = position();
 571         int size = (limit() - pos) >> 2;
 572         long addr = address + pos;
 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 pos = position();
 627         int size = (limit() - pos) >> 3;
 628         long addr = address + pos;
 629         return (bigEndian
 630                 ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
 631                                                                    -1,
 632                                                                    0,
 633                                                                    size,
 634                                                                    size,
 635                                                                    addr))
 636                 : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
 637                                                                    -1,
 638                                                                    0,
 639                                                                    size,
 640                                                                    size,
 641                                                                    addr)));
 642     }
 643 
 644 
 645 #end[byte]
 646 
 647 
 648 #if[char]
 649 
 650     String toString(int start, int end) {               // package-private
 651         try {
 652             return new String(hb, start + offset, end - start);
 653         } catch (StringIndexOutOfBoundsException x) {
 654             throw new IndexOutOfBoundsException();
 655         }
 656     }
 657 
 658 
 659     // --- Methods to support CharSequence ---
 660 
 661     public CharBuffer subSequence(int start, int end) {
 662         int pos = position();
 663         Objects.checkFromToIndex(start, end, limit() - pos);
 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 }