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