1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.  Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27
28package java.nio;
29
30
31import libcore.io.Memory;
32
33/**
34 * A read/write HeapByteBuffer.
35 */
36
37class HeapByteBuffer extends ByteBuffer {
38
39    // For speed these fields are actually declared in X-Buffer;
40    // these declarations are here as documentation
41    /*
42
43      protected final byte[] hb;
44      protected final int offset;
45
46    */
47
48    HeapByteBuffer(int cap, int lim) {            // packag-private
49        this(cap, lim, false);
50    }
51
52
53    HeapByteBuffer(int cap, int lim, boolean isReadOnly) {            // package-private
54        super(-1, 0, lim, cap, new byte[cap], 0);
55        this.isReadOnly = isReadOnly;
56    }
57
58    HeapByteBuffer(byte[] buf, int off, int len) { // package-private
59        this(buf, off, len, false);
60    }
61
62    HeapByteBuffer(byte[] buf, int off, int len, boolean isReadOnly) { // package-private
63        super(-1, off, off + len, buf.length, buf, 0);
64        this.isReadOnly = isReadOnly;
65    }
66
67    protected HeapByteBuffer(byte[] buf,
68                             int mark, int pos, int lim, int cap,
69                             int off) {
70        this(buf, mark, pos, lim, cap, off, false);
71    }
72
73    protected HeapByteBuffer(byte[] buf,
74                             int mark, int pos, int lim, int cap,
75                             int off, boolean isReadOnly) {
76        super(mark, pos, lim, cap, buf, off);
77        this.isReadOnly = isReadOnly;
78    }
79
80    public ByteBuffer slice() {
81        return new HeapByteBuffer(hb,
82                -1,
83                0,
84                remaining(),
85                remaining(),
86                position() + offset,
87                isReadOnly);
88    }
89
90    public ByteBuffer duplicate() {
91        return new HeapByteBuffer(hb,
92                markValue(),
93                position(),
94                limit(),
95                capacity(),
96                offset,
97                isReadOnly);
98    }
99
100    public ByteBuffer asReadOnlyBuffer() {
101        return new HeapByteBuffer(hb,
102                this.markValue(),
103                this.position(),
104                this.limit(),
105                this.capacity(),
106                offset, true);
107    }
108
109    protected int ix(int i) {
110        return i + offset;
111    }
112
113    public byte get() {
114        return hb[ix(nextGetIndex())];
115    }
116
117    public byte get(int i) {
118        return hb[ix(checkIndex(i))];
119    }
120
121    public ByteBuffer get(byte[] dst, int offset, int length) {
122        checkBounds(offset, length, dst.length);
123        if (length > remaining())
124            throw new BufferUnderflowException();
125        System.arraycopy(hb, ix(position()), dst, offset, length);
126        position(position() + length);
127        return this;
128    }
129
130    public boolean isDirect() {
131        return false;
132    }
133
134    public boolean isReadOnly() {
135        return isReadOnly;
136    }
137
138    public ByteBuffer put(byte x) {
139        if (isReadOnly) {
140            throw new ReadOnlyBufferException();
141        }
142        hb[ix(nextPutIndex())] = x;
143        return this;
144    }
145
146    public ByteBuffer put(int i, byte x) {
147        if (isReadOnly) {
148            throw new ReadOnlyBufferException();
149        }
150        hb[ix(checkIndex(i))] = x;
151        return this;
152    }
153
154    public ByteBuffer put(byte[] src, int offset, int length) {
155        if (isReadOnly) {
156            throw new ReadOnlyBufferException();
157        }
158        checkBounds(offset, length, src.length);
159        if (length > remaining())
160            throw new BufferOverflowException();
161        System.arraycopy(src, offset, hb, ix(position()), length);
162        position(position() + length);
163        return this;
164    }
165
166    public ByteBuffer compact() {
167        if (isReadOnly) {
168            throw new ReadOnlyBufferException();
169        }
170        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
171        position(remaining());
172        limit(capacity());
173        discardMark();
174        return this;
175    }
176
177    byte _get(int i) {                          // package-private
178        return hb[i];
179    }
180
181    void _put(int i, byte b) {                  // package-private
182        if (isReadOnly) {
183            throw new ReadOnlyBufferException();
184        }
185        hb[i] = b;
186    }
187
188    public char getChar() {
189        return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
190    }
191
192    public char getChar(int i) {
193        return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
194    }
195
196    char getCharUnchecked(int i) {
197        return Bits.getChar(this, ix(i), bigEndian);
198    }
199
200    void getUnchecked(int pos, char[] dst, int dstOffset, int length) {
201        Memory.unsafeBulkGet(dst, dstOffset, length * 2, hb, ix(pos), 2, !nativeByteOrder);
202    }
203
204    public ByteBuffer putChar(char x) {
205        if (isReadOnly) {
206            throw new ReadOnlyBufferException();
207        }
208        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
209        return this;
210    }
211
212    public ByteBuffer putChar(int i, char x) {
213        if (isReadOnly) {
214            throw new ReadOnlyBufferException();
215        }
216        Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian);
217        return this;
218    }
219
220    void putCharUnchecked(int i, char x) {
221        Bits.putChar(this, ix(i), x, bigEndian);
222    }
223
224    void putUnchecked(int pos, char[] src, int srcOffset, int length) {
225        Memory.unsafeBulkPut(hb, ix(pos), length * 2, src, srcOffset, 2, !nativeByteOrder);
226    }
227
228    public CharBuffer asCharBuffer() {
229        int size = this.remaining() >> 1;
230        int off = position();
231        return (CharBuffer) (new ByteBufferAsCharBuffer(this,
232                -1,
233                0,
234                size,
235                size,
236                off,
237                order()));
238    }
239
240    public short getShort() {
241        return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
242    }
243
244    public short getShort(int i) {
245        return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
246    }
247
248    short getShortUnchecked(int i) {
249        return Bits.getShort(this, ix(i), bigEndian);
250    }
251
252    void getUnchecked(int pos, short[] dst, int dstOffset, int length) {
253        Memory.unsafeBulkGet(dst, dstOffset, length * 2, hb, ix(pos), 2, !nativeByteOrder);
254    }
255
256    public ByteBuffer putShort(short x) {
257        if (isReadOnly) {
258            throw new ReadOnlyBufferException();
259        }
260        Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian);
261        return this;
262    }
263
264    public ByteBuffer putShort(int i, short x) {
265        if (isReadOnly) {
266            throw new ReadOnlyBufferException();
267        }
268        Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian);
269        return this;
270    }
271
272    void putShortUnchecked(int i, short x) {
273        Bits.putShort(this, ix(i), x, bigEndian);
274    }
275
276    void putUnchecked(int pos, short[] src, int srcOffset, int length) {
277        Memory.unsafeBulkPut(hb, ix(pos), length * 2, src, srcOffset, 2, !nativeByteOrder);
278    }
279
280    public ShortBuffer asShortBuffer() {
281        int size = this.remaining() >> 1;
282        int off = position();
283        return new ByteBufferAsShortBuffer(this,
284                -1,
285                0,
286                size,
287                size,
288                off,
289                order());
290    }
291
292    public int getInt() {
293        return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
294    }
295
296    public int getInt(int i) {
297        return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
298    }
299
300    int getIntUnchecked(int i) {
301        return Bits.getInt(this, ix(i), bigEndian);
302    }
303
304    void getUnchecked(int pos, int[] dst, int dstOffset, int length) {
305        Memory.unsafeBulkGet(dst, dstOffset, length * 4, hb, ix(pos), 4, !nativeByteOrder);
306    }
307
308    public ByteBuffer putInt(int x) {
309        if (isReadOnly) {
310            throw new ReadOnlyBufferException();
311        }
312        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
313        return this;
314    }
315
316    public ByteBuffer putInt(int i, int x) {
317        if (isReadOnly) {
318            throw new ReadOnlyBufferException();
319        }
320        Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian);
321        return this;
322    }
323
324    void putIntUnchecked(int i, int x) {
325        Bits.putInt(this, ix(i), x, bigEndian);
326    }
327
328    void putUnchecked(int pos, int[] src, int srcOffset, int length) {
329        Memory.unsafeBulkPut(hb, ix(pos), length * 4, src, srcOffset, 4, !nativeByteOrder);
330    }
331
332    public IntBuffer asIntBuffer() {
333        int size = this.remaining() >> 2;
334        int off = position();
335
336        return (IntBuffer) (new ByteBufferAsIntBuffer(this,
337                -1,
338                0,
339                size,
340                size,
341                off,
342                order()));
343    }
344
345    public long getLong() {
346        return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
347    }
348
349    public long getLong(int i) {
350        return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
351    }
352
353    long getLongUnchecked(int i) {
354        return Bits.getLong(this, ix(i), bigEndian);
355    }
356
357    void getUnchecked(int pos, long[] dst, int dstOffset, int length) {
358        Memory.unsafeBulkGet(dst, dstOffset, length * 8, hb, ix(pos), 8, !nativeByteOrder);
359    }
360
361    public ByteBuffer putLong(long x) {
362        if (isReadOnly) {
363            throw new ReadOnlyBufferException();
364        }
365        Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian);
366        return this;
367    }
368
369    public ByteBuffer putLong(int i, long x) {
370        if (isReadOnly) {
371            throw new ReadOnlyBufferException();
372        }
373        Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian);
374        return this;
375    }
376
377    void putLongUnchecked(int i, long x) {
378        Bits.putLong(this, ix(i), x, bigEndian);
379    }
380
381    void putUnchecked(int pos, long[] src, int srcOffset, int length) {
382        Memory.unsafeBulkPut(hb, ix(pos), length * 8, src, srcOffset, 8, !nativeByteOrder);
383    }
384
385    public LongBuffer asLongBuffer() {
386        int size = this.remaining() >> 3;
387        int off = position();
388        return (LongBuffer) (new ByteBufferAsLongBuffer(this,
389                -1,
390                0,
391                size,
392                size,
393                off,
394                order()));
395    }
396
397    public float getFloat() {
398        return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
399    }
400
401    public float getFloat(int i) {
402        return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
403    }
404
405    float getFloatUnchecked(int i) {
406        return Bits.getFloat(this, ix(i), bigEndian);
407    }
408
409    void getUnchecked(int pos, float[] dst, int dstOffset, int length) {
410        Memory.unsafeBulkGet(dst, dstOffset, length * 4, hb, ix(pos), 4, !nativeByteOrder);
411    }
412
413    public ByteBuffer putFloat(float x) {
414        if (isReadOnly) {
415            throw new ReadOnlyBufferException();
416        }
417        Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian);
418        return this;
419    }
420
421    public ByteBuffer putFloat(int i, float x) {
422        if (isReadOnly) {
423            throw new ReadOnlyBufferException();
424        }
425        Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian);
426        return this;
427    }
428
429    void putFloatUnchecked(int i, float x) {
430        Bits.putFloat(this, ix(i), x, bigEndian);
431    }
432
433    void putUnchecked(int pos, float[] src, int srcOffset, int length) {
434        Memory.unsafeBulkPut(hb, ix(pos), length * 4, src, srcOffset, 4, !nativeByteOrder);
435    }
436
437    public FloatBuffer asFloatBuffer() {
438        int size = this.remaining() >> 2;
439        int off = position();
440        return (FloatBuffer) (new ByteBufferAsFloatBuffer(this,
441                -1,
442                0,
443                size,
444                size,
445                off,
446                order()));
447    }
448
449    public double getDouble() {
450        return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
451    }
452
453    public double getDouble(int i) {
454        return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
455    }
456
457    double getDoubleUnchecked(int i) {
458        return Bits.getDouble(this, ix(i), bigEndian);
459    }
460
461    void getUnchecked(int pos, double[] dst, int dstOffset, int length) {
462        Memory.unsafeBulkGet(dst, dstOffset, length * 8, hb, ix(pos), 8, !nativeByteOrder);
463    }
464
465    public ByteBuffer putDouble(double x) {
466        if (isReadOnly) {
467            throw new ReadOnlyBufferException();
468        }
469        Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian);
470        return this;
471    }
472
473    public ByteBuffer putDouble(int i, double x) {
474        if (isReadOnly) {
475            throw new ReadOnlyBufferException();
476        }
477        Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian);
478        return this;
479    }
480
481    void putDoubleUnchecked(int i, double x) {
482        Bits.putDouble(this, ix(i), x, bigEndian);
483    }
484
485    void putUnchecked(int pos, double[] src, int srcOffset, int length) {
486        Memory.unsafeBulkPut(hb, ix(pos), length * 8, src, srcOffset, 8, !nativeByteOrder);
487    }
488
489    public DoubleBuffer asDoubleBuffer() {
490        int size = this.remaining() >> 3;
491        int off = position();
492        return (DoubleBuffer) (new ByteBufferAsDoubleBuffer(this,
493                -1,
494                0,
495                size,
496                size,
497                off,
498                order()));
499    }
500}
501