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