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         int pos = this.position();
 106         int lim = this.limit();
 107         int rem = (pos <= lim ? lim - pos : 0);
 108         return new Heap$Type$Buffer$RW$(hb,
 109                                         -1,
 110                                         0,
 111                                         rem,
 112                                         rem,
 113                                         pos + offset);
 114     }
 115 
 116 #if[byte]
 117     $Type$Buffer slice(int pos, int lim) {
 118         assert (pos >= 0);
 119         assert (pos <= lim);
 120         int rem = lim - pos;
 121         return new Heap$Type$Buffer$RW$(hb,
 122                                         -1,
 123                                         0,
 124                                         rem,
 125                                         rem,
 126                                         pos + offset);
 127     }
 128 #end[byte]
 129 
 130     public $Type$Buffer duplicate() {
 131         return new Heap$Type$Buffer$RW$(hb,
 132                                         this.markValue(),
 133                                         this.position(),
 134                                         this.limit(),
 135                                         this.capacity(),
 136                                         offset);
 137     }
 138 
 139     public $Type$Buffer asReadOnlyBuffer() {
 140 #if[rw]
 141         return new Heap$Type$BufferR(hb,
 142                                      this.markValue(),
 143                                      this.position(),
 144                                      this.limit(),
 145                                      this.capacity(),
 146                                      offset);
 147 #else[rw]
 148         return duplicate();
 149 #end[rw]
 150     }
 151 
 152 #if[rw]
 153 
 154     protected int ix(int i) {
 155         return i + offset;
 156     }
 157 
 158 #if[byte]
 159     private long byteOffset(long i) {
 160         return address + i;
 161     }
 162 #end[byte]
 163 
 164     public $type$ get() {
 165         return hb[ix(nextGetIndex())];
 166     }
 167 
 168     public $type$ get(int i) {
 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         checkBounds(offset, length, dst.length);
 180         int pos = position();
 181         if (length > limit() - pos)
 182             throw new BufferUnderflowException();
 183         System.arraycopy(hb, ix(pos), dst, offset, length);
 184         position(pos + length);
 185         return this;
 186     }
 187 
 188     public boolean isDirect() {
 189         return false;
 190     }
 191 
 192 #end[rw]
 193 
 194     public boolean isReadOnly() {
 195         return {#if[rw]?false:true};
 196     }
 197 
 198     public $Type$Buffer put($type$ x) {
 199 #if[rw]
 200         hb[ix(nextPutIndex())] = x;
 201         return this;
 202 #else[rw]
 203         throw new ReadOnlyBufferException();
 204 #end[rw]
 205     }
 206 
 207     public $Type$Buffer put(int i, $type$ x) {
 208 #if[rw]
 209         hb[ix(checkIndex(i))] = x;
 210         return this;
 211 #else[rw]
 212         throw new ReadOnlyBufferException();
 213 #end[rw]
 214     }
 215 
 216     public $Type$Buffer put($type$[] src, int offset, int length) {
 217 #if[rw]
 218         checkBounds(offset, length, src.length);
 219         int pos = position();
 220         if (length > limit() - pos)
 221             throw new BufferOverflowException();
 222         System.arraycopy(src, offset, hb, ix(pos), length);
 223         position(pos + length);
 224         return this;
 225 #else[rw]
 226         throw new ReadOnlyBufferException();
 227 #end[rw]
 228     }
 229 
 230     public $Type$Buffer put($Type$Buffer src) {
 231 #if[rw]
 232         if (src instanceof Heap$Type$Buffer) {
 233             if (src == this)
 234                 throw createSameBufferException();
 235             Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
 236             int pos = position();
 237             int sbpos = sb.position();
 238             int n = sb.limit() - sbpos;
 239             if (n > limit() - pos)
 240                 throw new BufferOverflowException();
 241             System.arraycopy(sb.hb, sb.ix(sbpos),
 242                              hb, ix(pos), n);
 243             sb.position(sbpos + n);
 244             position(pos + n);
 245         } else if (src.isDirect()) {
 246             int n = src.remaining();
 247             int pos = position();
 248             if (n > limit() - pos)
 249                 throw new BufferOverflowException();
 250             src.get(hb, ix(pos), n);
 251             position(pos + n);
 252         } else {
 253             super.put(src);
 254         }
 255         return this;
 256 #else[rw]
 257         throw new ReadOnlyBufferException();
 258 #end[rw]
 259     }
 260 
 261     public $Type$Buffer compact() {
 262 #if[rw]
 263         int pos = position();
 264         int rem = limit() - pos;
 265         System.arraycopy(hb, ix(pos), hb, ix(0), rem);
 266         position(rem);
 267         limit(capacity());
 268         discardMark();
 269         return this;
 270 #else[rw]
 271         throw new ReadOnlyBufferException();
 272 #end[rw]
 273     }
 274 
 275 
 276 
 277 #if[byte]
 278 
 279     byte _get(int i) {                          // package-private
 280         return hb[i];
 281     }
 282 
 283     void _put(int i, byte b) {                  // package-private
 284 #if[rw]
 285         hb[i] = b;
 286 #else[rw]
 287         throw new ReadOnlyBufferException();
 288 #end[rw]
 289     }
 290 
 291     // char
 292 
 293 #if[rw]
 294 
 295     public char getChar() {
 296         return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 297     }
 298 
 299     public char getChar(int i) {
 300         return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 301     }
 302 
 303 #end[rw]
 304 
 305     public $Type$Buffer putChar(char x) {
 306 #if[rw]
 307         UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 308         return this;
 309 #else[rw]
 310         throw new ReadOnlyBufferException();
 311 #end[rw]
 312     }
 313 
 314     public $Type$Buffer putChar(int i, char x) {
 315 #if[rw]
 316         UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 317         return this;
 318 #else[rw]
 319         throw new ReadOnlyBufferException();
 320 #end[rw]
 321     }
 322 
 323     public CharBuffer asCharBuffer() {
 324         int pos = position();
 325         int size = (limit() - pos) >> 1;
 326         long addr = address + pos;
 327         return (bigEndian
 328                 ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
 329                                                                -1,
 330                                                                0,
 331                                                                size,
 332                                                                size,
 333                                                                addr))
 334                 : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
 335                                                                -1,
 336                                                                0,
 337                                                                size,
 338                                                                size,
 339                                                                addr)));
 340     }
 341 
 342 
 343     // short
 344 
 345 #if[rw]
 346 
 347     public short getShort() {
 348         return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
 349     }
 350 
 351     public short getShort(int i) {
 352         return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
 353     }
 354 
 355 #end[rw]
 356 
 357     public $Type$Buffer putShort(short x) {
 358 #if[rw]
 359         UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
 360         return this;
 361 #else[rw]
 362         throw new ReadOnlyBufferException();
 363 #end[rw]
 364     }
 365 
 366     public $Type$Buffer putShort(int i, short x) {
 367 #if[rw]
 368         UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
 369         return this;
 370 #else[rw]
 371         throw new ReadOnlyBufferException();
 372 #end[rw]
 373     }
 374 
 375     public ShortBuffer asShortBuffer() {
 376         int pos = position();
 377         int size = (limit() - pos) >> 1;
 378         long addr = address + pos;
 379         return (bigEndian
 380                 ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
 381                                                                  -1,
 382                                                                  0,
 383                                                                  size,
 384                                                                  size,
 385                                                                  addr))
 386                 : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
 387                                                                  -1,
 388                                                                  0,
 389                                                                  size,
 390                                                                  size,
 391                                                                  addr)));
 392     }
 393 
 394 
 395     // int
 396 
 397 #if[rw]
 398 
 399     public int getInt() {
 400         return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 401     }
 402 
 403     public int getInt(int i) {
 404         return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 405     }
 406 
 407 #end[rw]
 408 
 409     public $Type$Buffer putInt(int x) {
 410 #if[rw]
 411         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
 412         return this;
 413 #else[rw]
 414         throw new ReadOnlyBufferException();
 415 #end[rw]
 416     }
 417 
 418     public $Type$Buffer putInt(int i, int x) {
 419 #if[rw]
 420         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
 421         return this;
 422 #else[rw]
 423         throw new ReadOnlyBufferException();
 424 #end[rw]
 425     }
 426 
 427     public IntBuffer asIntBuffer() {
 428         int pos = position();
 429         int size = (limit() - pos) >> 2;
 430         long addr = address + pos;
 431         return (bigEndian
 432                 ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
 433                                                              -1,
 434                                                              0,
 435                                                              size,
 436                                                              size,
 437                                                              addr))
 438                 : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
 439                                                              -1,
 440                                                              0,
 441                                                              size,
 442                                                              size,
 443                                                              addr)));
 444     }
 445 
 446 
 447     // long
 448 
 449 #if[rw]
 450 
 451     public long getLong() {
 452         return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 453     }
 454 
 455     public long getLong(int i) {
 456         return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 457     }
 458 
 459 #end[rw]
 460 
 461     public $Type$Buffer putLong(long x) {
 462 #if[rw]
 463         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
 464         return this;
 465 #else[rw]
 466         throw new ReadOnlyBufferException();
 467 #end[rw]
 468     }
 469 
 470     public $Type$Buffer putLong(int i, long x) {
 471 #if[rw]
 472         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
 473         return this;
 474 #else[rw]
 475         throw new ReadOnlyBufferException();
 476 #end[rw]
 477     }
 478 
 479     public LongBuffer asLongBuffer() {
 480         int pos = position();
 481         int size = (limit() - pos) >> 3;
 482         long addr = address + pos;
 483         return (bigEndian
 484                 ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
 485                                                                -1,
 486                                                                0,
 487                                                                size,
 488                                                                size,
 489                                                                addr))
 490                 : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
 491                                                                -1,
 492                                                                0,
 493                                                                size,
 494                                                                size,
 495                                                                addr)));
 496     }
 497 
 498 
 499     // float
 500 
 501 #if[rw]
 502 
 503     public float getFloat() {
 504         int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
 505         return Float.intBitsToFloat(x);
 506     }
 507 
 508     public float getFloat(int i) {
 509         int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
 510         return Float.intBitsToFloat(x);
 511     }
 512 
 513 #end[rw]
 514 
 515     public $Type$Buffer putFloat(float x) {
 516 #if[rw]
 517         int y = Float.floatToRawIntBits(x);
 518         UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
 519         return this;
 520 #else[rw]
 521         throw new ReadOnlyBufferException();
 522 #end[rw]
 523     }
 524 
 525     public $Type$Buffer putFloat(int i, float x) {
 526 #if[rw]
 527         int y = Float.floatToRawIntBits(x);
 528         UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
 529         return this;
 530 #else[rw]
 531         throw new ReadOnlyBufferException();
 532 #end[rw]
 533     }
 534 
 535     public FloatBuffer asFloatBuffer() {
 536         int pos = position();
 537         int size = (limit() - pos) >> 2;
 538         long addr = address + pos;
 539         return (bigEndian
 540                 ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
 541                                                                  -1,
 542                                                                  0,
 543                                                                  size,
 544                                                                  size,
 545                                                                  addr))
 546                 : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
 547                                                                  -1,
 548                                                                  0,
 549                                                                  size,
 550                                                                  size,
 551                                                                  addr)));
 552     }
 553 
 554 
 555     // double
 556 
 557 #if[rw]
 558 
 559     public double getDouble() {
 560         long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
 561         return Double.longBitsToDouble(x);
 562     }
 563 
 564     public double getDouble(int i) {
 565         long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
 566         return Double.longBitsToDouble(x);
 567     }
 568 
 569 #end[rw]
 570 
 571     public $Type$Buffer putDouble(double x) {
 572 #if[rw]
 573         long y = Double.doubleToRawLongBits(x);
 574         UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
 575         return this;
 576 #else[rw]
 577         throw new ReadOnlyBufferException();
 578 #end[rw]
 579     }
 580 
 581     public $Type$Buffer putDouble(int i, double x) {
 582 #if[rw]
 583         long y = Double.doubleToRawLongBits(x);
 584         UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
 585         return this;
 586 #else[rw]
 587         throw new ReadOnlyBufferException();
 588 #end[rw]
 589     }
 590 
 591     public DoubleBuffer asDoubleBuffer() {
 592         int pos = position();
 593         int size = (limit() - pos) >> 3;
 594         long addr = address + pos;
 595         return (bigEndian
 596                 ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
 597                                                                    -1,
 598                                                                    0,
 599                                                                    size,
 600                                                                    size,
 601                                                                    addr))
 602                 : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
 603                                                                    -1,
 604                                                                    0,
 605                                                                    size,
 606                                                                    size,
 607                                                                    addr)));
 608     }
 609 
 610 
 611 #end[byte]
 612 
 613 
 614 #if[char]
 615 
 616     String toString(int start, int end) {               // package-private
 617         try {
 618             return new String(hb, start + offset, end - start);
 619         } catch (StringIndexOutOfBoundsException x) {
 620             throw new IndexOutOfBoundsException();
 621         }
 622     }
 623 
 624 
 625     // --- Methods to support CharSequence ---
 626 
 627     public CharBuffer subSequence(int start, int end) {
 628         if ((start < 0)
 629             || (end > length())
 630             || (start > end))
 631             throw new IndexOutOfBoundsException();
 632         int pos = position();
 633         return new HeapCharBuffer$RW$(hb,
 634                                       -1,
 635                                       pos + start,
 636                                       pos + end,
 637                                       capacity(),
 638                                       offset);
 639     }
 640 
 641 #end[char]
 642 
 643 
 644 #if[!byte]
 645 
 646     public ByteOrder order() {
 647         return ByteOrder.nativeOrder();
 648     }
 649 #end[!byte]
 650 #if[char]
 651 
 652     ByteOrder charRegionOrder() {
 653         return order();
 654     }
 655 #end[char]
 656 }