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