/*
 * Copyright (C) 2014 The Android Open Source Project
 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.nio;

import java.io.FileDescriptor;

import dalvik.system.VMRuntime;
import libcore.io.Memory;
import libcore.io.SizeOf;
import sun.misc.Cleaner;
import sun.nio.ch.DirectBuffer;

/** @hide */
public class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer {

    /**
     * Stores the details of the memory backing a DirectByteBuffer. This could be a pointer
     * (passed through from JNI or resulting from a mapping) or a non-movable byte array allocated
     * from Java. Each MemoryRef also has an isAccessible associated with it, which determines
     * whether the underlying memory is "accessible". The notion of "accessibility" is usually
     * defined by the allocator of the reference, and is separate from the accessibility of the
     * memory as defined by the underlying system.
     *
     * A single MemoryRef instance is shared across all slices and duplicates of a given buffer.
     */
    static class MemoryRef {
        byte[] buffer;
        long allocatedAddress;
        final int offset;
        boolean isAccessible;

        MemoryRef(int capacity) {
            VMRuntime runtime = VMRuntime.getRuntime();
            buffer = (byte[]) runtime.newNonMovableArray(byte.class, capacity + 7);
            allocatedAddress = runtime.addressOf(buffer);
            // Offset is set to handle the alignment: http://b/16449607
            offset = (int) (((allocatedAddress + 7) & ~(long) 7) - allocatedAddress);
            isAccessible = true;
        }

        MemoryRef(long allocatedAddress) {
            buffer = null;
            this.allocatedAddress = allocatedAddress;
            this.offset = 0;
            isAccessible = true;
        }

        void free() {
            buffer = null;
            allocatedAddress = 0;
            isAccessible = false;
        }
    }

    final Cleaner cleaner;
    final MemoryRef memoryRef;

    DirectByteBuffer(int capacity, MemoryRef memoryRef) {
        super(-1, 0, capacity, capacity, memoryRef.buffer, memoryRef.offset);
        // Only have references to java objects, no need for a cleaner since the GC will do all
        // the work.
        this.memoryRef = memoryRef;
        this.address = memoryRef.allocatedAddress + memoryRef.offset;
        cleaner = null;
        this.isReadOnly = false;
    }

    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
    //
    private DirectByteBuffer(long addr, int cap) {
        super(-1, 0, cap, cap);
        memoryRef = new MemoryRef(addr);
        address = addr;
        cleaner = null;
    }

    /** @hide */
    public DirectByteBuffer(int cap, long addr,
                            FileDescriptor fd,
                            Runnable unmapper,
                            boolean isReadOnly) {
        super(-1, 0, cap, cap, fd);
        this.isReadOnly = isReadOnly;
        memoryRef = new MemoryRef(addr);
        address = addr;
        cleaner = Cleaner.create(memoryRef, unmapper);
    }

    // For duplicates and slices
    //
    DirectByteBuffer(MemoryRef memoryRef,         // package-private
                     int mark, int pos, int lim, int cap,
                     int off) {
        this(memoryRef, mark, pos, lim, cap, off, false);
    }

    DirectByteBuffer(MemoryRef memoryRef,         // package-private
                     int mark, int pos, int lim, int cap,
                     int off, boolean isReadOnly) {
        super(mark, pos, lim, cap, memoryRef.buffer, off);
        this.isReadOnly = isReadOnly;
        this.memoryRef = memoryRef;
        address = memoryRef.allocatedAddress + off;
        cleaner = null;
    }

    @Override
    public Object attachment() {
        return memoryRef;
    }

    @Override
    public Cleaner cleaner() {
        return cleaner;
    }

    public ByteBuffer slice() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int pos = position();
        int lim = limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
        int off = pos + offset;
        assert (off >= 0);
        return new DirectByteBuffer(memoryRef, -1, 0, rem, rem, off, isReadOnly);
    }

    public ByteBuffer duplicate() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return new DirectByteBuffer(memoryRef,
                this.markValue(),
                this.position(),
                this.limit(),
                this.capacity(),
                offset,
                isReadOnly);
    }

    public ByteBuffer asReadOnlyBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return new DirectByteBuffer(memoryRef,
                this.markValue(),
                this.position(),
                this.limit(),
                this.capacity(),
                offset,
                true);
    }

    @Override
    public long address() {
        return address;
    }

    private long ix(int i) {
        return address + i;
    }

    private byte get(long a) {
        return Memory.peekByte(a);
    }

    public byte get() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return get(ix(nextGetIndex()));
    }

    public byte get(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return get(ix(checkIndex(i)));
    }

    public ByteBuffer get(byte[] dst, int dstOffset, int length) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        checkBounds(dstOffset, length, dst.length);
        int pos = position();
        int lim = limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
        if (length > rem)
            throw new BufferUnderflowException();
        Memory.peekByteArray(ix(pos),
                dst, dstOffset, length);
        position = pos + length;
        return this;
    }

    public ByteBuffer put(long a, byte x) {
        Memory.pokeByte(a, x);
        return this;
    }

    public ByteBuffer put(byte x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        put(ix(nextPutIndex()), x);
        return this;
    }

    public ByteBuffer put(int i, byte x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        put(ix(checkIndex(i)), x);
        return this;
    }

    public ByteBuffer put(byte[] src, int srcOffset, int length) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        checkBounds(srcOffset, length, src.length);
        int pos = position();
        int lim = limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
        if (length > rem)
            throw new BufferOverflowException();
        Memory.pokeByteArray(ix(pos),
                src, srcOffset, length);
        position = pos + length;
        return this;
    }

    public ByteBuffer compact() {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int pos = position();
        int lim = limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
        System.arraycopy(hb, position + offset, hb, offset, remaining());
        position(rem);
        limit(capacity());
        discardMark();
        return this;
    }

    public boolean isDirect() {
        return true;
    }

    public boolean isReadOnly() {
        return isReadOnly;
    }

    byte _get(int i) {                          // package-private
        return get(i);
    }

    void _put(int i, byte b) {                  // package-private
        put(i, b);
    }

    private char getChar(long a) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return (char) Memory.peekShort(position, !nativeByteOrder);
    }

    public char getChar() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int newPosition = position + SizeOf.CHAR;
        if (newPosition > limit()) {
            throw new BufferUnderflowException();
        }
        char x = (char) Memory.peekShort(ix(position), !nativeByteOrder);
        position = newPosition;
        return x;
    }

    public char getChar(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        checkIndex(i, SizeOf.CHAR);
        char x = (char) Memory.peekShort(ix(i), !nativeByteOrder);
        return x;
    }

    char getCharUnchecked(int i) {
        return (char) Memory.peekShort(ix(i), !nativeByteOrder);
    }

    void getUnchecked(int pos, char[] dst, int dstOffset, int length) {
        Memory.peekCharArray(ix(pos),
                dst, dstOffset, length, !nativeByteOrder);
    }


    private ByteBuffer putChar(long a, char x) {
        Memory.pokeShort(a, (short) x, !nativeByteOrder);
        return this;
    }

    public ByteBuffer putChar(char x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putChar(ix(nextPutIndex(SizeOf.CHAR)), x);
        return this;
    }

    public ByteBuffer putChar(int i, char x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putChar(ix(checkIndex(i, SizeOf.CHAR)), x);
        return this;
    }

    void putCharUnchecked(int i, char x) {
        putChar(ix(i), x);
    }

    void putUnchecked(int pos, char[] src, int srcOffset, int length) {
        Memory.pokeCharArray(ix(pos),
                src, srcOffset, length, !nativeByteOrder);
    }

    public CharBuffer asCharBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int off = this.position();
        int lim = this.limit();
        assert (off <= lim);
        int rem = (off <= lim ? lim - off : 0);
        int size = rem >> 1;
        return (CharBuffer) (new ByteBufferAsCharBuffer(this,
                -1,
                0,
                size,
                size,
                off,
                order()));
    }

    private short getShort(long a) {
        return Memory.peekShort(a, !nativeByteOrder);
    }

    public short getShort() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getShort(ix(nextGetIndex(SizeOf.SHORT)));
    }

    public short getShort(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getShort(ix(checkIndex(i, SizeOf.SHORT)));
    }

    short getShortUnchecked(int i) {
        return getShort(ix(i));
    }

    void getUnchecked(int pos, short[] dst, int dstOffset, int length) {
        Memory.peekShortArray(ix(pos),
                dst, dstOffset, length, !nativeByteOrder);
    }


    private ByteBuffer putShort(long a, short x) {
        Memory.pokeShort(a, x, !nativeByteOrder);
        return this;
    }

    public ByteBuffer putShort(short x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putShort(ix(nextPutIndex(SizeOf.SHORT)), x);
        return this;
    }

    public ByteBuffer putShort(int i, short x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putShort(ix(checkIndex(i, SizeOf.SHORT)), x);
        return this;
    }

    void putShortUnchecked(int i, short x) {
        putShort(ix(i), x);
    }

    void putUnchecked(int pos, short[] src, int srcOffset, int length) {
        Memory.pokeShortArray(ix(pos),
                src, srcOffset, length, !nativeByteOrder);
    }

    public ShortBuffer asShortBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int off = this.position();
        int lim = this.limit();
        assert (off <= lim);
        int rem = (off <= lim ? lim - off : 0);
        int size = rem >> 1;
        return (ShortBuffer) (new ByteBufferAsShortBuffer(this,
                -1,
                0,
                size,
                size,
                off,
                order()));
    }

    private int getInt(long a) {
        return Memory.peekInt(a, !nativeByteOrder);
    }

    public int getInt() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getInt(ix(nextGetIndex(SizeOf.INT)));
    }

    public int getInt(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getInt(ix(checkIndex(i, (SizeOf.INT))));
    }

    int getIntUnchecked(int i) {
        return getInt(ix(i));
    }

    void getUnchecked(int pos, int[] dst, int dstOffset, int length) {
        Memory.peekIntArray(ix(pos),
                dst, dstOffset, length, !nativeByteOrder);
    }

    private ByteBuffer putInt(long a, int x) {
        Memory.pokeInt(a, x, !nativeByteOrder);
        return this;
    }

    public ByteBuffer putInt(int x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putInt(ix(nextPutIndex(SizeOf.INT)), x);
        return this;
    }

    public ByteBuffer putInt(int i, int x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putInt(ix(checkIndex(i, SizeOf.INT)), x);
        return this;
    }

    void putIntUnchecked(int i, int x) {
        putInt(ix(i), x);
    }

    void putUnchecked(int pos, int[] src, int srcOffset, int length) {
        Memory.pokeIntArray(ix(pos),
                src, srcOffset, length, !nativeByteOrder);
    }


    public IntBuffer asIntBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int off = this.position();
        int lim = this.limit();
        assert (off <= lim);
        int rem = (off <= lim ? lim - off : 0);
        int size = rem >> 2;
        return (IntBuffer) (new ByteBufferAsIntBuffer(this,
                -1,
                0,
                size,
                size,
                off,
                order()));
    }

    private long getLong(long a) {
        return Memory.peekLong(a, !nativeByteOrder);
    }

    public long getLong() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getLong(ix(nextGetIndex(SizeOf.LONG)));
    }

    public long getLong(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getLong(ix(checkIndex(i, SizeOf.LONG)));
    }

    long getLongUnchecked(int i) {
        return getLong(ix(i));
    }

    void getUnchecked(int pos, long[] dst, int dstOffset, int length) {
        Memory.peekLongArray(ix(pos),
                dst, dstOffset, length, !nativeByteOrder);
    }

    private ByteBuffer putLong(long a, long x) {
        Memory.pokeLong(a, x, !nativeByteOrder);
        return this;
    }

    public ByteBuffer putLong(long x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putLong(ix(nextPutIndex(SizeOf.LONG)), x);
        return this;
    }

    public ByteBuffer putLong(int i, long x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putLong(ix(checkIndex(i, SizeOf.LONG)), x);
        return this;
    }

    void putLongUnchecked(int i, long x) {
        putLong(ix(i), x);
    }

    void putUnchecked(int pos, long[] src, int srcOffset, int length) {
        Memory.pokeLongArray(ix(pos),
                src, srcOffset, length, !nativeByteOrder);
    }


    public LongBuffer asLongBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int off = this.position();
        int lim = this.limit();
        assert (off <= lim);
        int rem = (off <= lim ? lim - off : 0);
        int size = rem >> 3;
        return (LongBuffer) (new ByteBufferAsLongBuffer(this,
                -1,
                0,
                size,
                size,
                off,
                order()));
    }

    private float getFloat(long a) {
        int x = Memory.peekInt(a, !nativeByteOrder);
        return Float.intBitsToFloat(x);
    }

    public float getFloat() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getFloat(ix(nextGetIndex(SizeOf.FLOAT)));
    }

    public float getFloat(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getFloat(ix(checkIndex(i, SizeOf.FLOAT)));
    }

    float getFloatUnchecked(int i) {
        return getFloat(ix(i));
    }

    void getUnchecked(int pos, float[] dst, int dstOffset, int length) {
        Memory.peekFloatArray(ix(pos),
                dst, dstOffset, length, !nativeByteOrder);
    }

    private ByteBuffer putFloat(long a, float x) {
        int y = Float.floatToRawIntBits(x);
        Memory.pokeInt(a, y, !nativeByteOrder);
        return this;
    }

    public ByteBuffer putFloat(float x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putFloat(ix(nextPutIndex(SizeOf.FLOAT)), x);
        return this;
    }

    public ByteBuffer putFloat(int i, float x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putFloat(ix(checkIndex(i, SizeOf.FLOAT)), x);
        return this;
    }

    void putFloatUnchecked(int i, float x) {
        putFloat(ix(i), x);
    }

    void putUnchecked(int pos, float[] src, int srcOffset, int length) {
        Memory.pokeFloatArray(ix(pos),
                src, srcOffset, length, !nativeByteOrder);
    }

    public FloatBuffer asFloatBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int off = this.position();
        int lim = this.limit();
        assert (off <= lim);
        int rem = (off <= lim ? lim - off : 0);
        int size = rem >> 2;
        return (FloatBuffer) (new ByteBufferAsFloatBuffer(this,
                -1,
                0,
                size,
                size,
                off,
                order()));
    }

    private double getDouble(long a) {
        long x = Memory.peekLong(a, !nativeByteOrder);
        return Double.longBitsToDouble(x);
    }

    public double getDouble() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getDouble(ix(nextGetIndex(SizeOf.DOUBLE)));
    }

    public double getDouble(int i) {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        return getDouble(ix(checkIndex(i, SizeOf.DOUBLE)));
    }

    double getDoubleUnchecked(int i) {
        return getDouble(ix(i));
    }

    void getUnchecked(int pos, double[] dst, int dstOffset, int length) {
        Memory.peekDoubleArray(ix(pos),
                dst, dstOffset, length, !nativeByteOrder);
    }

    private ByteBuffer putDouble(long a, double x) {
        long y = Double.doubleToRawLongBits(x);
        Memory.pokeLong(a, y, !nativeByteOrder);
        return this;
    }

    public ByteBuffer putDouble(double x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putDouble(ix(nextPutIndex(SizeOf.DOUBLE)), x);
        return this;
    }

    public ByteBuffer putDouble(int i, double x) {
        if (isReadOnly) {
            throw new ReadOnlyBufferException();
        }
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        putDouble(ix(checkIndex(i, SizeOf.DOUBLE)), x);
        return this;
    }

    void putDoubleUnchecked(int i, double x) {
        putDouble(ix(i), x);
    }

    void putUnchecked(int pos, double[] src, int srcOffset, int length) {
        Memory.pokeDoubleArray(ix(pos),
                src, srcOffset, length, !nativeByteOrder);
    }

    public DoubleBuffer asDoubleBuffer() {
        if (!memoryRef.isAccessible) {
            throw new IllegalStateException("buffer is inaccessible");
        }
        int off = this.position();
        int lim = this.limit();
        assert (off <= lim);
        int rem = (off <= lim ? lim - off : 0);

        int size = rem >> 3;
        return (DoubleBuffer) (new ByteBufferAsDoubleBuffer(this,
                -1,
                0,
                size,
                size,
                off,
                order()));
    }

    public boolean isAccessible() {
        return memoryRef.isAccessible;
    }

    public void setAccessible(boolean value) {
        memoryRef.isAccessible = value;
    }
}
