1/*
2 * Copyright (c) 2000, 2019, 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// Android-note: This file is generated by ojluni/src/tools/gensrc_android.sh.
28
29package java.nio;
30
31import java.util.Objects;
32
33import libcore.io.Memory;
34
35class ByteBufferAs$Type$Buffer                  // package-private
36    extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
37{
38
39#if[rw]
40
41    protected final ByteBuffer bb;
42
43#end[rw]
44    // Android-added: Added offset as address can be zero on Android.
45    /**
46      * The offset from the Bytebuffer at the position 0 (in addition to bb.offset) in the
47      * number of bytes.
48      */
49    protected final int byteOffset;
50    // Android-added: Merge with little- and big-endian classes.
51    private final ByteOrder order;
52
53    // Android-changed: Added ByteOrder and removed MemorySegmentProxy to be supported yet.
54    ByteBufferAs$Type$Buffer(ByteBuffer bb,
55                                     int mark, int pos, int lim, int cap,
56                                     int off, ByteOrder order)
57    {
58#if[rw]
59        // Android-removed: Android duplicates the buffer, and merges with the read-only buffer.
60        // super(mark, pos, lim, cap, segment);
61        // this.bb = bb;
62        // address = addr;
63        // assert address >= bb.address;
64        super(mark, pos, lim, cap);
65        this.bb = bb.duplicate();
66        this.isReadOnly = bb.isReadOnly;
67        // There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
68        // HeapByteBuffer. We only have to initialize the field when bb is an instance of
69        // DirectByteBuffer.
70        // The address field is used by NIOAccess#getBasePointer and GetDirectBufferAddress method
71        // in art which return the address of the first usable byte of the underlying memory, i.e,
72        // the position of parent buffer. Therefore, value of "off" will be equal to parent buffer's
73        // position when the method is called from either HeapByteBuffer or DirectByteBuffer.
74        if (bb instanceof DirectByteBuffer) {
75            this.address = bb.address + off;
76        }
77        this.bb.order(order);
78        this.order = order;
79        byteOffset = off;
80#else[rw]
81        super(bb, mark, pos, lim, cap, addr, segment);
82#end[rw]
83    }
84
85    @Override
86    Object base() {
87        // Android-changed: DirectByteBuffer allocated directly assigns both hb and address field.
88        // return bb.hb;
89        return bb.base();
90    }
91
92    @Override
93    public $Type$Buffer slice() {
94        int pos = this.position();
95        int lim = this.limit();
96        int rem = (pos <= lim ? lim - pos : 0);
97        // Android-changed: Added ByteOrder and removed MemorySegmentProxy to be supported yet.
98        // long addr = byteOffset(pos);
99        // return new ByteBufferAs$Type$Buffer(bb, -1, 0, rem, rem, addr, order);
100        return new ByteBufferAs$Type$Buffer(bb, -1, 0, rem, rem, ix(pos), order);
101    }
102
103    @Override
104    public $Type$Buffer slice(int index, int length) {
105        Objects.checkFromIndexSize(index, length, limit());
106        return new ByteBufferAs$Type$Buffer(bb,
107                                                    -1,
108                                                    0,
109                                                    length,
110                                                    length,
111        // Android-changed: Added ByteOrder and removed MemorySegmentProxy to be supported yet.
112                                                    ix(index), order);
113    }
114
115    @Override
116    public $Type$Buffer duplicate() {
117        return new ByteBufferAs$Type$Buffer(bb,
118                                                    this.markValue(),
119                                                    this.position(),
120                                                    this.limit(),
121                                                    this.capacity(),
122        // Android-changed: Added ByteOrder and removed MemorySegmentProxy to be supported yet.
123                                                    byteOffset, order);
124    }
125
126    @Override
127    public $Type$Buffer asReadOnlyBuffer() {
128#if[rw]
129        return new ByteBufferAs$Type$Buffer(bb.asReadOnlyBuffer(),
130                                                 this.markValue(),
131                                                 this.position(),
132                                                 this.limit(),
133                                                 this.capacity(),
134        // Android-changed: Added ByteOrder and removed MemorySegmentProxy to be supported yet.
135                                                 byteOffset, order);
136#else[rw]
137        return duplicate();
138#end[rw]
139    }
140
141#if[rw]
142
143    private int ix(int i) {
144        // Android-changed: address can be zero on Android.
145        // int off = (int) (address - bb.address);
146        // return (i << $LG_BYTES_PER_VALUE$) + off;
147        return (i << $LG_BYTES_PER_VALUE$) + byteOffset;
148    }
149
150    // Android-removed: Removed unused byteOffset(long).
151    /*
152    protected long byteOffset(long i) {
153        return (i << $LG_BYTES_PER_VALUE$) + address;
154    }
155    */
156
157    @Override
158    public $type$ get() {
159        // Android-changed: Removed MemorySegmentProxy to be supported yet.
160        // $memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(scope(), bb.hb, byteOffset(nextGetIndex()),
161        //     {#if[boB]?true:false});
162        // return $fromBits$(x);
163        return get(nextGetIndex());
164    }
165
166    @Override
167    public $type$ get(int i) {
168        // Android-changed: Removed MemorySegmentProxy to be supported yet.
169        // $memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(scope(), bb.hb, byteOffset(checkIndex(i)),
170        //    {#if[boB]?true:false});
171        // return $fromBits$(x);
172        return bb.get$Type$Unchecked(ix(checkIndex(i)));
173    }
174
175    // BEGIN Android-added: Improve the efficiency of get().
176    @Override
177    public $Type$Buffer get($type$[] dst, int off, int length) {
178        Objects.checkFromIndexSize(off, length, dst.length);
179        if (length > remaining())
180            throw new BufferUnderflowException();
181        bb.getUnchecked(ix(position), dst, off, length);
182        position += length;
183        return this;
184    }
185
186    @Override
187    public $Type$Buffer get(int index, $type$[] dst, int off, int length) {
188        Objects.checkFromIndexSize(index, length, limit());
189        Objects.checkFromIndexSize(off, length, dst.length);
190        bb.getUnchecked(ix(index), dst, off, length);
191        return this;
192    }
193    // END Android-added: Improve the efficiency of get().
194
195#if[streamableType]
196    @Override
197    $type$ getUnchecked(int i) {
198        // Android-changed: Removed MemorySegmentProxy to be supported yet.
199        // $memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(null, bb.hb, byteOffset(i),
200        //     {#if[boB]?true:false});
201        // return $fromBits$(x);
202        return bb.get$Type$Unchecked(ix(i));
203    }
204#end[streamableType]
205
206#end[rw]
207
208    @Override
209    public $Type$Buffer put($type$ x) {
210#if[rw]
211        // Android-added: Merge the Read-only buffer class with this Read-Write buffer class.
212        throwIfReadOnly();
213        // Android-changed: Removed MemorySegmentProxy to be supported yet.
214        // $memtype$ y = $toBits$(x);
215        // SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(scope(), bb.hb, byteOffset(nextPutIndex()), y,
216        //     {#if[boB]?true:false});
217        put(nextPutIndex(), x);
218        return this;
219#else[rw]
220        throw new ReadOnlyBufferException();
221#end[rw]
222    }
223
224    @Override
225    public $Type$Buffer put(int i, $type$ x) {
226#if[rw]
227        // Android-added: Merge the Read-only buffer class with this Read-Write buffer class.
228        throwIfReadOnly();
229        // Android-changed: Removed MemorySegmentProxy to be supported yet.
230        // $memtype$ y = $toBits$(x);
231        // SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(scope(), bb.hb, byteOffset(checkIndex(i)), y,
232        //     {#if[boB]?true:false});
233        bb.put$Type$Unchecked(ix(checkIndex(i)), x);
234        return this;
235#else[rw]
236        throw new ReadOnlyBufferException();
237#end[rw]
238    }
239
240    // BEGIN Android-added: Improve the efficiency of put(type$[]).
241    @Override
242    public $Type$Buffer put($type$[] src, int off, int length) {
243        throwIfReadOnly();
244        Objects.checkFromIndexSize(off, length, src.length);
245        if (length > remaining())
246            throw new BufferOverflowException();
247        bb.putUnchecked(ix(position), src, off, length);
248        position += length;
249        return this;
250    }
251
252    @Override
253    public $Type$Buffer put(int index, $type$[] src, int off, int length) {
254        throwIfReadOnly();
255        Objects.checkFromIndexSize(index, length, limit());
256        Objects.checkFromIndexSize(off, length, src.length);
257        putUnchecked(index, src, off, length);
258        return this;
259    }
260
261    private void putUnchecked(int index, $type$[] src, int off, int length) {
262        bb.putUnchecked(ix(index), src, off, length);
263    }
264
265    @Override
266    void putBuffer(int pos, $Type$Buffer src, int srcPos, int n) {
267        if (src.hb != null) {
268            // this and src don't share the same backed char[].
269            putUnchecked(pos, src.hb, srcPos + src.offset, n);
270            return;
271        }
272        if (order() == src.order() &&
273              src instanceof ByteBufferAs$Type$Buffer asSrc) { // always true if src.hb == null
274            this.bb.putBuffer(ix(pos), asSrc.bb, asSrc.ix(srcPos), n << $LG_BYTES_PER_VALUE$);
275            return;
276        }
277
278        // Fallback to the slow path until memmove with bswap is implemented
279        super.putBuffer(pos, src, srcPos, n);
280    }
281    // END Android-added: Improve the efficiency of put(type$[]).
282
283    @Override
284    public $Type$Buffer compact() {
285#if[rw]
286        // Android-added: Merge the Read-only buffer class with this Read-Write buffer class.
287        throwIfReadOnly();
288        int pos = position();
289        int lim = limit();
290        int rem = (pos <= lim ? lim - pos : 0);
291        // Android-changed: Improve the efficiency.
292        /*
293        ByteBuffer db = bb.duplicate();
294        db.limit(ix(lim));
295        db.position(ix(0));
296        ByteBuffer sb = db.slice();
297        sb.position(pos << $LG_BYTES_PER_VALUE$);
298        sb.compact();
299        */
300        if (!(bb instanceof DirectByteBuffer)) {
301            System.arraycopy(bb.array(), ix(pos), bb.array(), ix(0), rem << $LG_BYTES_PER_VALUE$);
302        } else {
303            // Use pos << $LG_BYTES_PER_VALUE$ instead of ix(pos) to avoid double counting of the offset
304            // because this.address == bb.address + offset;
305            Memory.memmove(this, 0, this, pos << $LG_BYTES_PER_VALUE$, rem << $LG_BYTES_PER_VALUE$);
306        }
307        position(rem);
308        limit(capacity());
309        discardMark();
310        return this;
311#else[rw]
312        throw new ReadOnlyBufferException();
313#end[rw]
314    }
315
316    @Override
317    public boolean isDirect() {
318        return bb.isDirect();
319    }
320
321    @Override
322    public boolean isReadOnly() {
323        return isReadOnly;
324    }
325
326#if[char]
327
328    @Override
329    public String toString(int start, int end) {
330        Objects.checkFromToIndex(start, end, limit());
331        try {
332            int len = end - start;
333            char[] ca = new char[len];
334            CharBuffer cb = CharBuffer.wrap(ca);
335            CharBuffer db = this.duplicate();
336            db.position(start);
337            db.limit(end);
338            cb.put(db);
339            return new String(ca);
340        } catch (StringIndexOutOfBoundsException x) {
341            throw new IndexOutOfBoundsException();
342        }
343    }
344
345
346    // --- Methods to support CharSequence ---
347
348    @Override
349    public CharBuffer subSequence(int start, int end) {
350        int pos = position();
351        int lim = limit();
352        pos = (pos <= lim ? pos : lim);
353        int len = lim - pos;
354
355        Objects.checkFromToIndex(start, end, len);
356        return new ByteBufferAsCharBuffer(bb,
357                                                  -1,
358                                                  pos + start,
359                                                  pos + end,
360                                                  capacity(),
361        // Android-changed: Added ByteOrder and removed MemorySegmentProxy to be supported yet.
362                                                  byteOffset, order);
363    }
364
365#end[char]
366
367
368    @Override
369    public ByteOrder order() {
370        return order;
371    }
372
373#if[char]
374    @Override
375    ByteOrder charRegionOrder() {
376        return order();
377    }
378#end[char]
379
380    // Android-added: Merge the Read-only buffer class with this Read-Write buffer class.
381    private void throwIfReadOnly() {
382        if (isReadOnly) {
383            throw new ReadOnlyBufferException();
384        }
385    }
386}
387