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