1/*
2 * Copyright (c) 2000, 2021, 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#if[rw]
276        checkScope();
277        int length = end - start;
278        Objects.checkFromIndexSize(start, length, src.length());
279        int pos = position();
280        int lim = limit();
281        int rem = (pos <= lim) ? lim - pos : 0;
282        if (length > rem)
283            throw new BufferOverflowException();
284        src.getChars(start, end, hb, ix(pos));
285        position(pos + length);
286        return this;
287#else[rw]
288        throw new ReadOnlyBufferException();
289#end[rw]
290    }
291
292#end[char]
293
294    public $Type$Buffer compact() {
295#if[rw]
296        int pos = position();
297        int lim = limit();
298        assert (pos <= lim);
299        int rem = (pos <= lim ? lim - pos : 0);
300        System.arraycopy(hb, ix(pos), hb, ix(0), rem);
301        position(rem);
302        limit(capacity());
303        discardMark();
304        return this;
305#else[rw]
306        throw new ReadOnlyBufferException();
307#end[rw]
308    }
309
310
311
312#if[byte]
313
314    byte _get(int i) {                          // package-private
315        return hb[i];
316    }
317
318    void _put(int i, byte b) {                  // package-private
319#if[rw]
320        hb[i] = b;
321#else[rw]
322        throw new ReadOnlyBufferException();
323#end[rw]
324    }
325
326    // char
327
328#if[rw]
329
330    public char getChar() {
331        return SCOPED_MEMORY_ACCESS.getCharUnaligned(scope(), hb, byteOffset(nextGetIndex(2)), bigEndian);
332    }
333
334    public char getChar(int i) {
335        return SCOPED_MEMORY_ACCESS.getCharUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), bigEndian);
336    }
337
338#end[rw]
339
340    public $Type$Buffer putChar(char x) {
341#if[rw]
342        SCOPED_MEMORY_ACCESS.putCharUnaligned(scope(), hb, byteOffset(nextPutIndex(2)), x, bigEndian);
343        return this;
344#else[rw]
345        throw new ReadOnlyBufferException();
346#end[rw]
347    }
348
349    public $Type$Buffer putChar(int i, char x) {
350#if[rw]
351        SCOPED_MEMORY_ACCESS.putCharUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
352        return this;
353#else[rw]
354        throw new ReadOnlyBufferException();
355#end[rw]
356    }
357
358    public CharBuffer asCharBuffer() {
359        int pos = position();
360        int size = (limit() - pos) >> 1;
361        long addr = address + pos;
362        return (bigEndian
363                ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
364                                                               -1,
365                                                               0,
366                                                               size,
367                                                               size,
368                                                               addr, segment))
369                : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
370                                                               -1,
371                                                               0,
372                                                               size,
373                                                               size,
374                                                               addr, segment)));
375    }
376
377
378    // short
379
380#if[rw]
381
382    public short getShort() {
383        return SCOPED_MEMORY_ACCESS.getShortUnaligned(scope(), hb, byteOffset(nextGetIndex(2)), bigEndian);
384    }
385
386    public short getShort(int i) {
387        return SCOPED_MEMORY_ACCESS.getShortUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), bigEndian);
388    }
389
390#end[rw]
391
392    public $Type$Buffer putShort(short x) {
393#if[rw]
394        SCOPED_MEMORY_ACCESS.putShortUnaligned(scope(), hb, byteOffset(nextPutIndex(2)), x, bigEndian);
395        return this;
396#else[rw]
397        throw new ReadOnlyBufferException();
398#end[rw]
399    }
400
401    public $Type$Buffer putShort(int i, short x) {
402#if[rw]
403        SCOPED_MEMORY_ACCESS.putShortUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
404        return this;
405#else[rw]
406        throw new ReadOnlyBufferException();
407#end[rw]
408    }
409
410    public ShortBuffer asShortBuffer() {
411        int pos = position();
412        int size = (limit() - pos) >> 1;
413        long addr = address + pos;
414        return (bigEndian
415                ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
416                                                                 -1,
417                                                                 0,
418                                                                 size,
419                                                                 size,
420                                                                 addr, segment))
421                : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
422                                                                 -1,
423                                                                 0,
424                                                                 size,
425                                                                 size,
426                                                                 addr, segment)));
427    }
428
429
430    // int
431
432#if[rw]
433
434    public int getInt() {
435        return SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(nextGetIndex(4)), bigEndian);
436    }
437
438    public int getInt(int i) {
439        return SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), bigEndian);
440    }
441
442#end[rw]
443
444    public $Type$Buffer putInt(int x) {
445#if[rw]
446        SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(nextPutIndex(4)), x, bigEndian);
447        return this;
448#else[rw]
449        throw new ReadOnlyBufferException();
450#end[rw]
451    }
452
453    public $Type$Buffer putInt(int i, int x) {
454#if[rw]
455        SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
456        return this;
457#else[rw]
458        throw new ReadOnlyBufferException();
459#end[rw]
460    }
461
462    public IntBuffer asIntBuffer() {
463        int pos = position();
464        int size = (limit() - pos) >> 2;
465        long addr = address + pos;
466        return (bigEndian
467                ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
468                                                             -1,
469                                                             0,
470                                                             size,
471                                                             size,
472                                                             addr, segment))
473                : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
474                                                             -1,
475                                                             0,
476                                                             size,
477                                                             size,
478                                                             addr, segment)));
479    }
480
481
482    // long
483
484#if[rw]
485
486    public long getLong() {
487        return SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(nextGetIndex(8)), bigEndian);
488    }
489
490    public long getLong(int i) {
491        return SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), bigEndian);
492    }
493
494#end[rw]
495
496    public $Type$Buffer putLong(long x) {
497#if[rw]
498        SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(nextPutIndex(8)), x, bigEndian);
499        return this;
500#else[rw]
501        throw new ReadOnlyBufferException();
502#end[rw]
503    }
504
505    public $Type$Buffer putLong(int i, long x) {
506#if[rw]
507        SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
508        return this;
509#else[rw]
510        throw new ReadOnlyBufferException();
511#end[rw]
512    }
513
514    public LongBuffer asLongBuffer() {
515        int pos = position();
516        int size = (limit() - pos) >> 3;
517        long addr = address + pos;
518        return (bigEndian
519                ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
520                                                               -1,
521                                                               0,
522                                                               size,
523                                                               size,
524                                                               addr, segment))
525                : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
526                                                               -1,
527                                                               0,
528                                                               size,
529                                                               size,
530                                                               addr, segment)));
531    }
532
533
534    // float
535
536#if[rw]
537
538    public float getFloat() {
539        int x = SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(nextGetIndex(4)), bigEndian);
540        return Float.intBitsToFloat(x);
541    }
542
543    public float getFloat(int i) {
544        int x = SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), bigEndian);
545        return Float.intBitsToFloat(x);
546    }
547
548#end[rw]
549
550    public $Type$Buffer putFloat(float x) {
551#if[rw]
552        int y = Float.floatToRawIntBits(x);
553        SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(nextPutIndex(4)), y, bigEndian);
554        return this;
555#else[rw]
556        throw new ReadOnlyBufferException();
557#end[rw]
558    }
559
560    public $Type$Buffer putFloat(int i, float x) {
561#if[rw]
562        int y = Float.floatToRawIntBits(x);
563        SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
564        return this;
565#else[rw]
566        throw new ReadOnlyBufferException();
567#end[rw]
568    }
569
570    public FloatBuffer asFloatBuffer() {
571        int pos = position();
572        int size = (limit() - pos) >> 2;
573        long addr = address + pos;
574        return (bigEndian
575                ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
576                                                                 -1,
577                                                                 0,
578                                                                 size,
579                                                                 size,
580                                                                 addr, segment))
581                : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
582                                                                 -1,
583                                                                 0,
584                                                                 size,
585                                                                 size,
586                                                                 addr, segment)));
587    }
588
589
590    // double
591
592#if[rw]
593
594    public double getDouble() {
595        long x = SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(nextGetIndex(8)), bigEndian);
596        return Double.longBitsToDouble(x);
597    }
598
599    public double getDouble(int i) {
600        long x = SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), bigEndian);
601        return Double.longBitsToDouble(x);
602    }
603
604#end[rw]
605
606    public $Type$Buffer putDouble(double x) {
607#if[rw]
608        long y = Double.doubleToRawLongBits(x);
609        SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(nextPutIndex(8)), y, bigEndian);
610        return this;
611#else[rw]
612        throw new ReadOnlyBufferException();
613#end[rw]
614    }
615
616    public $Type$Buffer putDouble(int i, double x) {
617#if[rw]
618        long y = Double.doubleToRawLongBits(x);
619        SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
620        return this;
621#else[rw]
622        throw new ReadOnlyBufferException();
623#end[rw]
624    }
625
626    public DoubleBuffer asDoubleBuffer() {
627        int pos = position();
628        int size = (limit() - pos) >> 3;
629        long addr = address + pos;
630        return (bigEndian
631                ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
632                                                                   -1,
633                                                                   0,
634                                                                   size,
635                                                                   size,
636                                                                   addr, segment))
637                : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
638                                                                   -1,
639                                                                   0,
640                                                                   size,
641                                                                   size,
642                                                                   addr, segment)));
643    }
644
645
646#end[byte]
647
648
649#if[char]
650
651    String toString(int start, int end) {               // package-private
652        try {
653            return new String(hb, start + offset, end - start);
654        } catch (StringIndexOutOfBoundsException x) {
655            throw new IndexOutOfBoundsException();
656        }
657    }
658
659
660    // --- Methods to support CharSequence ---
661
662    public CharBuffer subSequence(int start, int end) {
663        int pos = position();
664        Objects.checkFromToIndex(start, end, limit() - pos);
665        return new HeapCharBuffer$RW$(hb,
666                                      -1,
667                                      pos + start,
668                                      pos + end,
669                                      capacity(),
670                                      offset, segment);
671    }
672
673#end[char]
674
675
676#if[!byte]
677
678    public ByteOrder order() {
679        return ByteOrder.nativeOrder();
680    }
681#end[!byte]
682#if[char]
683
684    ByteOrder charRegionOrder() {
685        return order();
686    }
687#end[char]
688}
689