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