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
37final class 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    private HeapByteBuffer(int cap, int lim, boolean isReadOnly) {
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    private HeapByteBuffer(byte[] buf, int off, int len, boolean isReadOnly) {
63        super(-1, off, off + len, buf.length, buf, 0);
64        this.isReadOnly = isReadOnly;
65    }
66
67    private HeapByteBuffer(byte[] buf, int mark, int pos, int lim, int cap, int off,
68            boolean isReadOnly) {
69        super(mark, pos, lim, cap, buf, off);
70        this.isReadOnly = isReadOnly;
71    }
72
73    @Override
74    public ByteBuffer slice() {
75        return new HeapByteBuffer(hb,
76                -1,
77                0,
78                remaining(),
79                remaining(),
80                position() + offset,
81                isReadOnly);
82    }
83
84    @Override
85    public ByteBuffer duplicate() {
86        return new HeapByteBuffer(hb,
87                markValue(),
88                position(),
89                limit(),
90                capacity(),
91                offset,
92                isReadOnly);
93    }
94
95    @Override
96    public ByteBuffer asReadOnlyBuffer() {
97        return new HeapByteBuffer(hb,
98                this.markValue(),
99                this.position(),
100                this.limit(),
101                this.capacity(),
102                offset, true);
103    }
104
105    protected int ix(int i) {
106        return i + offset;
107    }
108
109    @Override
110    public byte get() {
111        return hb[ix(nextGetIndex())];
112    }
113
114    @Override
115    public byte get(int i) {
116        return hb[ix(checkIndex(i))];
117    }
118
119    @Override
120    public ByteBuffer get(byte[] dst, int offset, int length) {
121        checkBounds(offset, length, dst.length);
122        if (length > remaining())
123            throw new BufferUnderflowException();
124        System.arraycopy(hb, ix(position()), dst, offset, length);
125        position(position() + length);
126        return this;
127    }
128
129    @Override
130    public boolean isDirect() {
131        return false;
132    }
133
134    @Override
135    public boolean isReadOnly() {
136        return isReadOnly;
137    }
138
139    @Override
140    public ByteBuffer put(byte x) {
141        if (isReadOnly) {
142            throw new ReadOnlyBufferException();
143        }
144        hb[ix(nextPutIndex())] = x;
145        return this;
146    }
147
148    @Override
149    public ByteBuffer put(int i, byte x) {
150        if (isReadOnly) {
151            throw new ReadOnlyBufferException();
152        }
153        hb[ix(checkIndex(i))] = x;
154        return this;
155    }
156
157    @Override
158    public ByteBuffer put(byte[] src, int offset, int length) {
159        if (isReadOnly) {
160            throw new ReadOnlyBufferException();
161        }
162        checkBounds(offset, length, src.length);
163        if (length > remaining())
164            throw new BufferOverflowException();
165        System.arraycopy(src, offset, hb, ix(position()), length);
166        position(position() + length);
167        return this;
168    }
169
170    @Override
171    public ByteBuffer compact() {
172        if (isReadOnly) {
173            throw new ReadOnlyBufferException();
174        }
175        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
176        position(remaining());
177        limit(capacity());
178        discardMark();
179        return this;
180    }
181
182    @Override
183    byte _get(int i) {                          // package-private
184        return hb[i];
185    }
186
187    @Override
188    void _put(int i, byte b) {                  // package-private
189        if (isReadOnly) {
190            throw new ReadOnlyBufferException();
191        }
192        hb[i] = b;
193    }
194
195    @Override
196    public char getChar() {
197        return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
198    }
199
200    @Override
201    public char getChar(int i) {
202        return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
203    }
204
205    @Override
206    char getCharUnchecked(int i) {
207        return Bits.getChar(this, ix(i), bigEndian);
208    }
209
210    @Override
211    void getUnchecked(int pos, char[] dst, int dstOffset, int length) {
212        Memory.unsafeBulkGet(dst, dstOffset, length * 2, hb, ix(pos), 2, !nativeByteOrder);
213    }
214
215    @Override
216    public ByteBuffer putChar(char x) {
217        if (isReadOnly) {
218            throw new ReadOnlyBufferException();
219        }
220        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
221        return this;
222    }
223
224    @Override
225    public ByteBuffer putChar(int i, char x) {
226        if (isReadOnly) {
227            throw new ReadOnlyBufferException();
228        }
229        Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian);
230        return this;
231    }
232
233    @Override
234    void putCharUnchecked(int i, char x) {
235        Bits.putChar(this, ix(i), x, bigEndian);
236    }
237
238    @Override
239    void putUnchecked(int pos, char[] src, int srcOffset, int length) {
240        Memory.unsafeBulkPut(hb, ix(pos), length * 2, src, srcOffset, 2, !nativeByteOrder);
241    }
242
243    @Override
244    public CharBuffer asCharBuffer() {
245        int size = this.remaining() >> 1;
246        int off = position();
247        return new ByteBufferAsCharBuffer(this,
248                -1,
249                0,
250                size,
251                size,
252                off,
253                order());
254    }
255
256    @Override
257    public short getShort() {
258        return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
259    }
260
261    @Override
262    public short getShort(int i) {
263        return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
264    }
265
266    @Override
267    short getShortUnchecked(int i) {
268        return Bits.getShort(this, ix(i), bigEndian);
269    }
270
271    @Override
272    void getUnchecked(int pos, short[] dst, int dstOffset, int length) {
273        Memory.unsafeBulkGet(dst, dstOffset, length * 2, hb, ix(pos), 2, !nativeByteOrder);
274    }
275
276    @Override
277    public ByteBuffer putShort(short x) {
278        if (isReadOnly) {
279            throw new ReadOnlyBufferException();
280        }
281        Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian);
282        return this;
283    }
284
285    @Override
286    public ByteBuffer putShort(int i, short x) {
287        if (isReadOnly) {
288            throw new ReadOnlyBufferException();
289        }
290        Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian);
291        return this;
292    }
293
294    @Override
295    void putShortUnchecked(int i, short x) {
296        Bits.putShort(this, ix(i), x, bigEndian);
297    }
298
299    @Override
300    void putUnchecked(int pos, short[] src, int srcOffset, int length) {
301        Memory.unsafeBulkPut(hb, ix(pos), length * 2, src, srcOffset, 2, !nativeByteOrder);
302    }
303
304    @Override
305    public ShortBuffer asShortBuffer() {
306        int size = this.remaining() >> 1;
307        int off = position();
308        return new ByteBufferAsShortBuffer(this,
309                -1,
310                0,
311                size,
312                size,
313                off,
314                order());
315    }
316
317    @Override
318    public int getInt() {
319        return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
320    }
321
322    @Override
323    public int getInt(int i) {
324        return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
325    }
326
327    @Override
328    int getIntUnchecked(int i) {
329        return Bits.getInt(this, ix(i), bigEndian);
330    }
331
332    @Override
333    void getUnchecked(int pos, int[] dst, int dstOffset, int length) {
334        Memory.unsafeBulkGet(dst, dstOffset, length * 4, hb, ix(pos), 4, !nativeByteOrder);
335    }
336
337    @Override
338    public ByteBuffer putInt(int x) {
339        if (isReadOnly) {
340            throw new ReadOnlyBufferException();
341        }
342        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
343        return this;
344    }
345
346    @Override
347    public ByteBuffer putInt(int i, int x) {
348        if (isReadOnly) {
349            throw new ReadOnlyBufferException();
350        }
351        Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian);
352        return this;
353    }
354
355    @Override
356    void putIntUnchecked(int i, int x) {
357        Bits.putInt(this, ix(i), x, bigEndian);
358    }
359
360    @Override
361    void putUnchecked(int pos, int[] src, int srcOffset, int length) {
362        Memory.unsafeBulkPut(hb, ix(pos), length * 4, src, srcOffset, 4, !nativeByteOrder);
363    }
364
365    @Override
366    public IntBuffer asIntBuffer() {
367        int size = this.remaining() >> 2;
368        int off = position();
369
370        return new ByteBufferAsIntBuffer(this,
371                -1,
372                0,
373                size,
374                size,
375                off,
376                order());
377    }
378
379    @Override
380    public long getLong() {
381        return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
382    }
383
384    @Override
385    public long getLong(int i) {
386        return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
387    }
388
389    @Override
390    long getLongUnchecked(int i) {
391        return Bits.getLong(this, ix(i), bigEndian);
392    }
393
394    @Override
395    void getUnchecked(int pos, long[] dst, int dstOffset, int length) {
396        Memory.unsafeBulkGet(dst, dstOffset, length * 8, hb, ix(pos), 8, !nativeByteOrder);
397    }
398
399    @Override
400    public ByteBuffer putLong(long x) {
401        if (isReadOnly) {
402            throw new ReadOnlyBufferException();
403        }
404        Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian);
405        return this;
406    }
407
408    @Override
409    public ByteBuffer putLong(int i, long x) {
410        if (isReadOnly) {
411            throw new ReadOnlyBufferException();
412        }
413        Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian);
414        return this;
415    }
416
417    @Override
418    void putLongUnchecked(int i, long x) {
419        Bits.putLong(this, ix(i), x, bigEndian);
420    }
421
422    @Override
423    void putUnchecked(int pos, long[] src, int srcOffset, int length) {
424        Memory.unsafeBulkPut(hb, ix(pos), length * 8, src, srcOffset, 8, !nativeByteOrder);
425    }
426
427    @Override
428    public LongBuffer asLongBuffer() {
429        int size = this.remaining() >> 3;
430        int off = position();
431        return new ByteBufferAsLongBuffer(this,
432                -1,
433                0,
434                size,
435                size,
436                off,
437                order());
438    }
439
440    @Override
441    public float getFloat() {
442        return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
443    }
444
445    @Override
446    public float getFloat(int i) {
447        return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
448    }
449
450    @Override
451    float getFloatUnchecked(int i) {
452        return Bits.getFloat(this, ix(i), bigEndian);
453    }
454
455    @Override
456    void getUnchecked(int pos, float[] dst, int dstOffset, int length) {
457        Memory.unsafeBulkGet(dst, dstOffset, length * 4, hb, ix(pos), 4, !nativeByteOrder);
458    }
459
460    @Override
461    public ByteBuffer putFloat(float x) {
462        if (isReadOnly) {
463            throw new ReadOnlyBufferException();
464        }
465        Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian);
466        return this;
467    }
468
469    @Override
470    public ByteBuffer putFloat(int i, float x) {
471        if (isReadOnly) {
472            throw new ReadOnlyBufferException();
473        }
474        Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian);
475        return this;
476    }
477
478    @Override
479    void putFloatUnchecked(int i, float x) {
480        Bits.putFloat(this, ix(i), x, bigEndian);
481    }
482
483    @Override
484    void putUnchecked(int pos, float[] src, int srcOffset, int length) {
485        Memory.unsafeBulkPut(hb, ix(pos), length * 4, src, srcOffset, 4, !nativeByteOrder);
486    }
487
488    @Override
489    public FloatBuffer asFloatBuffer() {
490        int size = this.remaining() >> 2;
491        int off = position();
492        return new ByteBufferAsFloatBuffer(this,
493                -1,
494                0,
495                size,
496                size,
497                off,
498                order());
499    }
500
501    @Override
502    public double getDouble() {
503        return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
504    }
505
506    @Override
507    public double getDouble(int i) {
508        return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
509    }
510
511    @Override
512    double getDoubleUnchecked(int i) {
513        return Bits.getDouble(this, ix(i), bigEndian);
514    }
515
516    @Override
517    void getUnchecked(int pos, double[] dst, int dstOffset, int length) {
518        Memory.unsafeBulkGet(dst, dstOffset, length * 8, hb, ix(pos), 8, !nativeByteOrder);
519    }
520
521    @Override
522    public ByteBuffer putDouble(double x) {
523        if (isReadOnly) {
524            throw new ReadOnlyBufferException();
525        }
526        Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian);
527        return this;
528    }
529
530    @Override
531    public ByteBuffer putDouble(int i, double x) {
532        if (isReadOnly) {
533            throw new ReadOnlyBufferException();
534        }
535        Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian);
536        return this;
537    }
538
539    @Override
540    void putDoubleUnchecked(int i, double x) {
541        Bits.putDouble(this, ix(i), x, bigEndian);
542    }
543
544    @Override
545    void putUnchecked(int pos, double[] src, int srcOffset, int length) {
546        Memory.unsafeBulkPut(hb, ix(pos), length * 8, src, srcOffset, 8, !nativeByteOrder);
547    }
548
549    @Override
550    public DoubleBuffer asDoubleBuffer() {
551        int size = this.remaining() >> 3;
552        int off = position();
553        return new ByteBufferAsDoubleBuffer(this,
554                -1,
555                0,
556                size,
557                size,
558                off,
559                order());
560    }
561}
562