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