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 
28 package java.nio;
29 
30 
31 import libcore.io.Memory;
32 
33 /**
34  * A read/write HeapByteBuffer.
35  */
36 
37 final 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 
HeapByteBuffer(int cap, int lim)48     HeapByteBuffer(int cap, int lim) {            // packag-private
49         this(cap, lim, false);
50     }
51 
52 
HeapByteBuffer(int cap, int lim, boolean isReadOnly)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 
HeapByteBuffer(byte[] buf, int off, int len)58     HeapByteBuffer(byte[] buf, int off, int len) { // package-private
59         this(buf, off, len, false);
60     }
61 
HeapByteBuffer(byte[] buf, int off, int len, boolean isReadOnly)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 
HeapByteBuffer(byte[] buf, int mark, int pos, int lim, int cap, int off, boolean isReadOnly)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
slice()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
duplicate()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
asReadOnlyBuffer()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 
ix(int i)105     protected int ix(int i) {
106         return i + offset;
107     }
108 
109     @Override
get()110     public byte get() {
111         return hb[ix(nextGetIndex())];
112     }
113 
114     @Override
get(int i)115     public byte get(int i) {
116         return hb[ix(checkIndex(i))];
117     }
118 
119     @Override
get(byte[] dst, int offset, int length)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
isDirect()130     public boolean isDirect() {
131         return false;
132     }
133 
134     @Override
isReadOnly()135     public boolean isReadOnly() {
136         return isReadOnly;
137     }
138 
139     @Override
put(byte x)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
put(int i, byte x)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
put(byte[] src, int offset, int length)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
compact()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
_get(int i)183     byte _get(int i) {                          // package-private
184         return hb[i];
185     }
186 
187     @Override
_put(int i, byte b)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
getChar()196     public char getChar() {
197         return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
198     }
199 
200     @Override
getChar(int i)201     public char getChar(int i) {
202         return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
203     }
204 
205     @Override
getCharUnchecked(int i)206     char getCharUnchecked(int i) {
207         return Bits.getChar(this, ix(i), bigEndian);
208     }
209 
210     @Override
getUnchecked(int pos, char[] dst, int dstOffset, int length)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
putChar(char x)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
putChar(int i, char x)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
putCharUnchecked(int i, char x)234     void putCharUnchecked(int i, char x) {
235         Bits.putChar(this, ix(i), x, bigEndian);
236     }
237 
238     @Override
putUnchecked(int pos, char[] src, int srcOffset, int length)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
asCharBuffer()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
getShort()257     public short getShort() {
258         return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
259     }
260 
261     @Override
getShort(int i)262     public short getShort(int i) {
263         return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
264     }
265 
266     @Override
getShortUnchecked(int i)267     short getShortUnchecked(int i) {
268         return Bits.getShort(this, ix(i), bigEndian);
269     }
270 
271     @Override
getUnchecked(int pos, short[] dst, int dstOffset, int length)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
putShort(short x)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
putShort(int i, short x)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
putShortUnchecked(int i, short x)295     void putShortUnchecked(int i, short x) {
296         Bits.putShort(this, ix(i), x, bigEndian);
297     }
298 
299     @Override
putUnchecked(int pos, short[] src, int srcOffset, int length)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
asShortBuffer()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
getInt()318     public int getInt() {
319         return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
320     }
321 
322     @Override
getInt(int i)323     public int getInt(int i) {
324         return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
325     }
326 
327     @Override
getIntUnchecked(int i)328     int getIntUnchecked(int i) {
329         return Bits.getInt(this, ix(i), bigEndian);
330     }
331 
332     @Override
getUnchecked(int pos, int[] dst, int dstOffset, int length)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
putInt(int x)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
putInt(int i, int x)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
putIntUnchecked(int i, int x)356     void putIntUnchecked(int i, int x) {
357         Bits.putInt(this, ix(i), x, bigEndian);
358     }
359 
360     @Override
putUnchecked(int pos, int[] src, int srcOffset, int length)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
asIntBuffer()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
getLong()380     public long getLong() {
381         return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
382     }
383 
384     @Override
getLong(int i)385     public long getLong(int i) {
386         return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
387     }
388 
389     @Override
getLongUnchecked(int i)390     long getLongUnchecked(int i) {
391         return Bits.getLong(this, ix(i), bigEndian);
392     }
393 
394     @Override
getUnchecked(int pos, long[] dst, int dstOffset, int length)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
putLong(long x)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
putLong(int i, long x)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
putLongUnchecked(int i, long x)418     void putLongUnchecked(int i, long x) {
419         Bits.putLong(this, ix(i), x, bigEndian);
420     }
421 
422     @Override
putUnchecked(int pos, long[] src, int srcOffset, int length)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
asLongBuffer()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
getFloat()441     public float getFloat() {
442         return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
443     }
444 
445     @Override
getFloat(int i)446     public float getFloat(int i) {
447         return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
448     }
449 
450     @Override
getFloatUnchecked(int i)451     float getFloatUnchecked(int i) {
452         return Bits.getFloat(this, ix(i), bigEndian);
453     }
454 
455     @Override
getUnchecked(int pos, float[] dst, int dstOffset, int length)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
putFloat(float x)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
putFloat(int i, float x)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
putFloatUnchecked(int i, float x)479     void putFloatUnchecked(int i, float x) {
480         Bits.putFloat(this, ix(i), x, bigEndian);
481     }
482 
483     @Override
putUnchecked(int pos, float[] src, int srcOffset, int length)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
asFloatBuffer()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
getDouble()502     public double getDouble() {
503         return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
504     }
505 
506     @Override
getDouble(int i)507     public double getDouble(int i) {
508         return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
509     }
510 
511     @Override
getDoubleUnchecked(int i)512     double getDoubleUnchecked(int i) {
513         return Bits.getDouble(this, ix(i), bigEndian);
514     }
515 
516     @Override
getUnchecked(int pos, double[] dst, int dstOffset, int length)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
putDouble(double x)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
putDouble(int i, double x)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
putDoubleUnchecked(int i, double x)540     void putDoubleUnchecked(int i, double x) {
541         Bits.putDouble(this, ix(i), x, bigEndian);
542     }
543 
544     @Override
putUnchecked(int pos, double[] src, int srcOffset, int length)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
asDoubleBuffer()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