1 /*
   2  * Copyright (c) 2000, 2016, 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 class Heap$Type$Buffer$RW$
  42     extends {#if[ro]?Heap}$Type$Buffer
  43 {
  44     // Cached array base offset
  45     private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
  46 
  47     // Cached array base offset
  48     private static final long ARRAY_INDEX_SCALE = UNSAFE.arrayIndexScale($type$[].class);
  49 
  50     // For speed these fields are actually declared in X-Buffer;
  51     // these declarations are here as documentation
  52     /*
  53 #if[rw]
  54     protected final $type$[] hb;
  55     protected final int offset;
  56 #end[rw]
  57     */
  58 
  59     Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
  60 #if[rw]
  61         super(-1, 0, lim, cap, new $type$[cap], 0);
  62         /*
  63         hb = new $type$[cap];
  64         offset = 0;
  65         */
  66         this.address = ARRAY_BASE_OFFSET;
  67 #else[rw]
  68         super(cap, lim);
  69         this.isReadOnly = true;
  70 #end[rw]
  71     }
  72 
  73     Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
  74 #if[rw]
  75         super(-1, off, off + len, buf.length, buf, 0);
  76         /*
  77         hb = buf;
  78         offset = 0;
  79         */
  80         this.address = ARRAY_BASE_OFFSET;
  81 #else[rw]
  82         super(buf, off, len);
  83         this.isReadOnly = true;
  84 #end[rw]
  85     }
  86 
  87     protected Heap$Type$Buffer$RW$($type$[] buf,
  88                                    int mark, int pos, int lim, int cap,
  89                                    int off)
  90     {
  91 #if[rw]
  92         super(mark, pos, lim, cap, buf, off);
  93         /*
  94         hb = buf;
  95         offset = off;
  96         */
  97         this.address = ARRAY_BASE_OFFSET + off * ARRAY_INDEX_SCALE;
  98 #else[rw]
  99         super(buf, mark, pos, lim, cap, off);
 100         this.isReadOnly = true;
 101 #end[rw]
 102     }
 103 
 104     public $Type$Buffer slice() {
 105         return new Heap$Type$Buffer$RW$(hb,
 106                                         -1,
 107                                         0,
 108                                         this.remaining(),
 109                                         this.remaining(),
 110                                         this.position() + offset);
 111     }
 112 
 113 #if[byte]
 114     $Type$Buffer slice(int pos, int lim) {
 115         assert (pos >= 0);
 116         assert (pos <= lim);
 117         int rem = lim - pos;
 118         return new Heap$Type$Buffer$RW$(hb,
 119                                         -1,
 120                                         0,
 121                                         rem,
 122                                         rem,
 123                                         pos + offset);
 124     }
 125 #end[byte]
 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         checkBounds(offset, length, dst.length);
 177         if (length > remaining())
 178             throw new BufferUnderflowException();
 179         System.arraycopy(hb, ix(position()), dst, offset, length);
 180         position(position() + length);
 181         return this;
 182     }
 183 
 184     public boolean isDirect() {
 185         return false;
 186     }
 187 
 188 #end[rw]
 189 
 190     public boolean isReadOnly() {
 191         return {#if[rw]?false:true};
 192     }
 193 
 194     public $Type$Buffer put($type$ x) {
 195 #if[rw]
 196         hb[ix(nextPutIndex())] = x;
 197         return this;
 198 #else[rw]
 199         throw new ReadOnlyBufferException();
 200 #end[rw]
 201     }
 202 
 203     public $Type$Buffer put(int i, $type$ x) {
 204 #if[rw]
 205         hb[ix(checkIndex(i))] = x;
 206         return this;
 207 #else[rw]
 208         throw new ReadOnlyBufferException();
 209 #end[rw]
 210     }
 211 
 212     public $Type$Buffer put($type$[] src, int offset, int length) {
 213 #if[rw]
 214         checkBounds(offset, length, src.length);
 215         if (length > remaining())
 216             throw new BufferOverflowException();
 217         System.arraycopy(src, offset, hb, ix(position()), length);
 218         position(position() + length);
 219         return this;
 220 #else[rw]
 221         throw new ReadOnlyBufferException();
 222 #end[rw]
 223     }
 224 
 225     public $Type$Buffer put($Type$Buffer src) {
 226 #if[rw]
 227         if (src instanceof Heap$Type$Buffer) {
 228             if (src == this)
 229                 throw createSameBufferException();
 230             Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
 231             int n = sb.remaining();
 232             if (n > remaining())
 233                 throw new BufferOverflowException();
 234             System.arraycopy(sb.hb, sb.ix(sb.position()),
 235                              hb, ix(position()), n);
 236             sb.position(sb.position() + n);
 237             position(position() + n);
 238         } else if (src.isDirect()) {
 239             int n = src.remaining();
 240             if (n > remaining())
 241                 throw new BufferOverflowException();
 242             src.get(hb, ix(position()), n);
 243             position(position() + n);
 244         } else {
 245             super.put(src);
 246         }
 247         return this;
 248 #else[rw]
 249         throw new ReadOnlyBufferException();
 250 #end[rw]
 251     }
 252 
 253     public $Type$Buffer compact() {
 254 #if[rw]
 255         System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
 256         position(remaining());
 257         limit(capacity());
 258         discardMark();
 259         return this;
 260 #else[rw]
 261         throw new ReadOnlyBufferException();
 262 #end[rw]
 263     }
 264 
 265 
 266 
 267 #if[byte]
 268 
 269     byte _get(int i) {                          // package-private
 270         return hb[i];
 271     }
 272 
 273     void _put(int i, byte b) {                  // package-private
 274 #if[rw]
 275         hb[i] = b;
 276 #else[rw]
 277         throw new ReadOnlyBufferException();
 278 #end[rw]
 279     }
 280 
 281     // char
 282 
 283 #if[rw]
 284 
 285     public char getChar() {
 286         return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 287     }
 288 
 289     public char getChar(int i) {
 290         return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 291     }
 292 
 293 #end[rw]
 294 
 295     public $Type$Buffer putChar(char x) {
 296 #if[rw]
 297         UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 298         return this;
 299 #else[rw]
 300         throw new ReadOnlyBufferException();
 301 #end[rw]
 302     }
 303 
 304     public $Type$Buffer putChar(int i, char x) {
 305 #if[rw]
 306         UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 307         return this;
 308 #else[rw]
 309         throw new ReadOnlyBufferException();
 310 #end[rw]
 311     }
 312 
 313     public CharBuffer asCharBuffer() {
 314         int size = this.remaining() >> 1;
 315         long addr = address + position();
 316         return (bigEndian
 317                 ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
 318                                                                -1,
 319                                                                0,
 320                                                                size,
 321                                                                size,
 322                                                                addr))
 323                 : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
 324                                                                -1,
 325                                                                0,
 326                                                                size,
 327                                                                size,
 328                                                                addr)));
 329     }
 330 
 331 
 332     // short
 333 
 334 #if[rw]
 335 
 336     public short getShort() {
 337         return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 338     }
 339 
 340     public short getShort(int i) {
 341         return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 342     }
 343 
 344 #end[rw]
 345 
 346     public $Type$Buffer putShort(short x) {
 347 #if[rw]
 348         UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 349         return this;
 350 #else[rw]
 351         throw new ReadOnlyBufferException();
 352 #end[rw]
 353     }
 354 
 355     public $Type$Buffer putShort(int i, short x) {
 356 #if[rw]
 357         UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 358         return this;
 359 #else[rw]
 360         throw new ReadOnlyBufferException();
 361 #end[rw]
 362     }
 363 
 364     public ShortBuffer asShortBuffer() {
 365         int size = this.remaining() >> 1;
 366         long addr = address + position();
 367         return (bigEndian
 368                 ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
 369                                                                  -1,
 370                                                                  0,
 371                                                                  size,
 372                                                                  size,
 373                                                                  addr))
 374                 : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
 375                                                                  -1,
 376                                                                  0,
 377                                                                  size,
 378                                                                  size,
 379                                                                  addr)));
 380     }
 381 
 382 
 383     // int
 384 
 385 #if[rw]
 386 
 387     public int getInt() {
 388         return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 389     }
 390 
 391     public int getInt(int i) {
 392         return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 393     }
 394 
 395 #end[rw]
 396 
 397     public $Type$Buffer putInt(int x) {
 398 #if[rw]
 399         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
 400         return this;
 401 #else[rw]
 402         throw new ReadOnlyBufferException();
 403 #end[rw]
 404     }
 405 
 406     public $Type$Buffer putInt(int i, int x) {
 407 #if[rw]
 408         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
 409         return this;
 410 #else[rw]
 411         throw new ReadOnlyBufferException();
 412 #end[rw]
 413     }
 414 
 415     public IntBuffer asIntBuffer() {
 416         int size = this.remaining() >> 2;
 417         long addr = address + position();
 418         return (bigEndian
 419                 ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
 420                                                              -1,
 421                                                              0,
 422                                                              size,
 423                                                              size,
 424                                                              addr))
 425                 : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
 426                                                              -1,
 427                                                              0,
 428                                                              size,
 429                                                              size,
 430                                                              addr)));
 431     }
 432 
 433 
 434     // long
 435 
 436 #if[rw]
 437 
 438     public long getLong() {
 439         return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 440     }
 441 
 442     public long getLong(int i) {
 443         return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 444     }
 445 
 446 #end[rw]
 447 
 448     public $Type$Buffer putLong(long x) {
 449 #if[rw]
 450         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
 451         return this;
 452 #else[rw]
 453         throw new ReadOnlyBufferException();
 454 #end[rw]
 455     }
 456 
 457     public $Type$Buffer putLong(int i, long x) {
 458 #if[rw]
 459         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
 460         return this;
 461 #else[rw]
 462         throw new ReadOnlyBufferException();
 463 #end[rw]
 464     }
 465 
 466     public LongBuffer asLongBuffer() {
 467         int size = this.remaining() >> 3;
 468         long addr = address + position();
 469         return (bigEndian
 470                 ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
 471                                                                -1,
 472                                                                0,
 473                                                                size,
 474                                                                size,
 475                                                                addr))
 476                 : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
 477                                                                -1,
 478                                                                0,
 479                                                                size,
 480                                                                size,
 481                                                                addr)));
 482     }
 483 
 484 
 485     // float
 486 
 487 #if[rw]
 488 
 489     public float getFloat() {
 490         int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 491         return Float.intBitsToFloat(x);
 492     }
 493 
 494     public float getFloat(int i) {
 495         int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 496         return Float.intBitsToFloat(x);
 497     }
 498 
 499 #end[rw]
 500 
 501     public $Type$Buffer putFloat(float x) {
 502 #if[rw]
 503         int y = Float.floatToRawIntBits(x);
 504         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
 505         return this;
 506 #else[rw]
 507         throw new ReadOnlyBufferException();
 508 #end[rw]
 509     }
 510 
 511     public $Type$Buffer putFloat(int i, float x) {
 512 #if[rw]
 513         int y = Float.floatToRawIntBits(x);
 514         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
 515         return this;
 516 #else[rw]
 517         throw new ReadOnlyBufferException();
 518 #end[rw]
 519     }
 520 
 521     public FloatBuffer asFloatBuffer() {
 522         int size = this.remaining() >> 2;
 523         long addr = address + position();
 524         return (bigEndian
 525                 ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
 526                                                                  -1,
 527                                                                  0,
 528                                                                  size,
 529                                                                  size,
 530                                                                  addr))
 531                 : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
 532                                                                  -1,
 533                                                                  0,
 534                                                                  size,
 535                                                                  size,
 536                                                                  addr)));
 537     }
 538 
 539 
 540     // double
 541 
 542 #if[rw]
 543 
 544     public double getDouble() {
 545         long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 546         return Double.longBitsToDouble(x);
 547     }
 548 
 549     public double getDouble(int i) {
 550         long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 551         return Double.longBitsToDouble(x);
 552     }
 553 
 554 #end[rw]
 555 
 556     public $Type$Buffer putDouble(double x) {
 557 #if[rw]
 558         long y = Double.doubleToRawLongBits(x);
 559         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
 560         return this;
 561 #else[rw]
 562         throw new ReadOnlyBufferException();
 563 #end[rw]
 564     }
 565 
 566     public $Type$Buffer putDouble(int i, double x) {
 567 #if[rw]
 568         long y = Double.doubleToRawLongBits(x);
 569         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
 570         return this;
 571 #else[rw]
 572         throw new ReadOnlyBufferException();
 573 #end[rw]
 574     }
 575 
 576     public DoubleBuffer asDoubleBuffer() {
 577         int size = this.remaining() >> 3;
 578         long addr = address + position();
 579         return (bigEndian
 580                 ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
 581                                                                    -1,
 582                                                                    0,
 583                                                                    size,
 584                                                                    size,
 585                                                                    addr))
 586                 : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
 587                                                                    -1,
 588                                                                    0,
 589                                                                    size,
 590                                                                    size,
 591                                                                    addr)));
 592     }
 593 
 594 
 595 #end[byte]
 596 
 597 
 598 #if[char]
 599 
 600     String toString(int start, int end) {               // package-private
 601         try {
 602             return new String(hb, start + offset, end - start);
 603         } catch (StringIndexOutOfBoundsException x) {
 604             throw new IndexOutOfBoundsException();
 605         }
 606     }
 607 
 608 
 609     // --- Methods to support CharSequence ---
 610 
 611     public CharBuffer subSequence(int start, int end) {
 612         if ((start < 0)
 613             || (end > length())
 614             || (start > end))
 615             throw new IndexOutOfBoundsException();
 616         int pos = position();
 617         return new HeapCharBuffer$RW$(hb,
 618                                       -1,
 619                                       pos + start,
 620                                       pos + end,
 621                                       capacity(),
 622                                       offset);
 623     }
 624 
 625 #end[char]
 626 
 627 
 628 #if[!byte]
 629 
 630     public ByteOrder order() {
 631         return ByteOrder.nativeOrder();
 632     }
 633 #end[!byte]
 634 #if[char]
 635 
 636     ByteOrder charRegionOrder() {
 637         return order();
 638     }
 639 #end[char]
 640 }