Home | History | Annotate | Download | only in nio
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.nio;
     19 
     20 import libcore.io.SizeOf;
     21 import libcore.io.Memory;
     22 
     23 /**
     24  * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
     25  * compose the implementation of platform memory based byte buffers.
     26  * <p>
     27  * ReadWriteDirectByteBuffer extends DirectByteBuffer with all the write
     28  * methods.
     29  * </p>
     30  * <p>
     31  * This class is marked final for runtime performance.
     32  * </p>
     33  */
     34 final class ReadWriteDirectByteBuffer extends DirectByteBuffer {
     35     static ReadWriteDirectByteBuffer copy(DirectByteBuffer other, int markOfOther) {
     36         ReadWriteDirectByteBuffer buf =
     37                 new ReadWriteDirectByteBuffer(other.block, other.capacity(), other.offset);
     38         buf.limit = other.limit;
     39         buf.position = other.position();
     40         buf.mark = markOfOther;
     41         return buf;
     42     }
     43 
     44     // Used by ByteBuffer.allocateDirect.
     45     ReadWriteDirectByteBuffer(int capacity) {
     46         super(MemoryBlock.allocate(capacity), capacity, 0);
     47     }
     48 
     49     // Used by the JNI NewDirectByteBuffer function.
     50     ReadWriteDirectByteBuffer(int address, int capacity) {
     51         super(MemoryBlock.wrapFromJni(address, capacity), capacity, 0);
     52     }
     53 
     54     ReadWriteDirectByteBuffer(MemoryBlock block, int capacity, int offset) {
     55         super(block, capacity, offset);
     56     }
     57 
     58     @Override
     59     public ByteBuffer asReadOnlyBuffer() {
     60         return ReadOnlyDirectByteBuffer.copy(this, mark);
     61     }
     62 
     63     @Override
     64     public ByteBuffer compact() {
     65         Memory.memmove(this, 0, this, position, remaining());
     66         position = limit - position;
     67         limit = capacity;
     68         mark = UNSET_MARK;
     69         return this;
     70     }
     71 
     72     @Override
     73     public ByteBuffer duplicate() {
     74         return copy(this, mark);
     75     }
     76 
     77     @Override
     78     public boolean isReadOnly() {
     79         return false;
     80     }
     81 
     82     @Override
     83     public ByteBuffer put(byte value) {
     84         if (position == limit) {
     85             throw new BufferOverflowException();
     86         }
     87         this.block.pokeByte(offset + position++, value);
     88         return this;
     89     }
     90 
     91     @Override
     92     public ByteBuffer put(int index, byte value) {
     93         checkIndex(index);
     94         this.block.pokeByte(offset + index, value);
     95         return this;
     96     }
     97 
     98     @Override
     99     public ByteBuffer put(byte[] src, int srcOffset, int byteCount) {
    100         checkPutBounds(1, src.length, srcOffset, byteCount);
    101         this.block.pokeByteArray(offset + position, src, srcOffset, byteCount);
    102         position += byteCount;
    103         return this;
    104     }
    105 
    106     final void put(char[] src, int srcOffset, int charCount) {
    107         int byteCount = checkPutBounds(SizeOf.CHAR, src.length, srcOffset, charCount);
    108         this.block.pokeCharArray(offset + position, src, srcOffset, charCount, order.needsSwap);
    109         position += byteCount;
    110     }
    111 
    112     final void put(double[] src, int srcOffset, int doubleCount) {
    113         int byteCount = checkPutBounds(SizeOf.DOUBLE, src.length, srcOffset, doubleCount);
    114         this.block.pokeDoubleArray(offset + position, src, srcOffset, doubleCount, order.needsSwap);
    115         position += byteCount;
    116     }
    117 
    118     final void put(float[] src, int srcOffset, int floatCount) {
    119         int byteCount = checkPutBounds(SizeOf.FLOAT, src.length, srcOffset, floatCount);
    120         this.block.pokeFloatArray(offset + position, src, srcOffset, floatCount, order.needsSwap);
    121         position += byteCount;
    122     }
    123 
    124     final void put(int[] src, int srcOffset, int intCount) {
    125         int byteCount = checkPutBounds(SizeOf.INT, src.length, srcOffset, intCount);
    126         this.block.pokeIntArray(offset + position, src, srcOffset, intCount, order.needsSwap);
    127         position += byteCount;
    128     }
    129 
    130     final void put(long[] src, int srcOffset, int longCount) {
    131         int byteCount = checkPutBounds(SizeOf.LONG, src.length, srcOffset, longCount);
    132         this.block.pokeLongArray(offset + position, src, srcOffset, longCount, order.needsSwap);
    133         position += byteCount;
    134     }
    135 
    136     final void put(short[] src, int srcOffset, int shortCount) {
    137         int byteCount = checkPutBounds(SizeOf.SHORT, src.length, srcOffset, shortCount);
    138         this.block.pokeShortArray(offset + position, src, srcOffset, shortCount, order.needsSwap);
    139         position += byteCount;
    140     }
    141 
    142     @Override
    143     public ByteBuffer putChar(char value) {
    144         int newPosition = position + SizeOf.CHAR;
    145         if (newPosition > limit) {
    146             throw new BufferOverflowException();
    147         }
    148         this.block.pokeShort(offset + position, (short) value, order);
    149         position = newPosition;
    150         return this;
    151     }
    152 
    153     @Override
    154     public ByteBuffer putChar(int index, char value) {
    155         checkIndex(index, SizeOf.CHAR);
    156         this.block.pokeShort(offset + index, (short) value, order);
    157         return this;
    158     }
    159 
    160     @Override
    161     public ByteBuffer putDouble(double value) {
    162         int newPosition = position + SizeOf.DOUBLE;
    163         if (newPosition > limit) {
    164             throw new BufferOverflowException();
    165         }
    166         this.block.pokeLong(offset + position, Double.doubleToRawLongBits(value), order);
    167         position = newPosition;
    168         return this;
    169     }
    170 
    171     @Override
    172     public ByteBuffer putDouble(int index, double value) {
    173         checkIndex(index, SizeOf.DOUBLE);
    174         this.block.pokeLong(offset + index, Double.doubleToRawLongBits(value), order);
    175         return this;
    176     }
    177 
    178     @Override
    179     public ByteBuffer putFloat(float value) {
    180         int newPosition = position + SizeOf.FLOAT;
    181         if (newPosition > limit) {
    182             throw new BufferOverflowException();
    183         }
    184         this.block.pokeInt(offset + position, Float.floatToRawIntBits(value), order);
    185         position = newPosition;
    186         return this;
    187     }
    188 
    189     @Override
    190     public ByteBuffer putFloat(int index, float value) {
    191         checkIndex(index, SizeOf.FLOAT);
    192         this.block.pokeInt(offset + index, Float.floatToRawIntBits(value), order);
    193         return this;
    194     }
    195 
    196     @Override
    197     public ByteBuffer putInt(int value) {
    198         int newPosition = position + SizeOf.INT;
    199         if (newPosition > limit) {
    200             throw new BufferOverflowException();
    201         }
    202         this.block.pokeInt(offset + position, value, order);
    203         position = newPosition;
    204         return this;
    205     }
    206 
    207     @Override
    208     public ByteBuffer putInt(int index, int value) {
    209         checkIndex(index, SizeOf.INT);
    210         this.block.pokeInt(offset + index, value, order);
    211         return this;
    212     }
    213 
    214     @Override
    215     public ByteBuffer putLong(long value) {
    216         int newPosition = position + SizeOf.LONG;
    217         if (newPosition > limit) {
    218             throw new BufferOverflowException();
    219         }
    220         this.block.pokeLong(offset + position, value, order);
    221         position = newPosition;
    222         return this;
    223     }
    224 
    225     @Override
    226     public ByteBuffer putLong(int index, long value) {
    227         checkIndex(index, SizeOf.LONG);
    228         this.block.pokeLong(offset + index, value, order);
    229         return this;
    230     }
    231 
    232     @Override
    233     public ByteBuffer putShort(short value) {
    234         int newPosition = position + SizeOf.SHORT;
    235         if (newPosition > limit) {
    236             throw new BufferOverflowException();
    237         }
    238         this.block.pokeShort(offset + position, value, order);
    239         position = newPosition;
    240         return this;
    241     }
    242 
    243     @Override
    244     public ByteBuffer putShort(int index, short value) {
    245         checkIndex(index, SizeOf.SHORT);
    246         this.block.pokeShort(offset + index, value, order);
    247         return this;
    248     }
    249 
    250     @Override
    251     public ByteBuffer slice() {
    252         return new ReadWriteDirectByteBuffer(block, remaining(), offset + position);
    253     }
    254 
    255 }
    256