1/*
2 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.nio;
27
28import libcore.io.Memory;
29
30class ByteBufferAsDoubleBuffer
31        extends DoubleBuffer {            // package-private
32
33    protected final ByteBuffer bb;
34    protected final int offset;
35    private final ByteOrder order;
36
37    ByteBufferAsDoubleBuffer(ByteBuffer bb,
38                             int mark, int pos, int lim, int cap,
39                             int off, ByteOrder order) {
40        super(mark, pos, lim, cap);
41        this.bb = bb.duplicate();
42        this.isReadOnly = bb.isReadOnly;
43        // There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
44        // HeapByteBuffer. We only have to initialize the field when bb is an instance of
45        // DirectByteBuffer.
46        // The address field is used by NIOAccess#getBasePointer and GetDirectBufferAddress method
47        // in art which return the address of the first usable byte of the underlying memory, i.e,
48        // the position of parent buffer. Therefore, value of "off" will be equal to parent buffer's
49        // position when the method is called from either HeapByteBuffer or DirectByteBuffer.
50        if (bb instanceof DirectByteBuffer) {
51            this.address = bb.address + off;
52        }
53        this.bb.order(order);
54        this.order = order;
55        offset = off;
56    }
57
58    public DoubleBuffer slice() {
59        int pos = this.position();
60        int lim = this.limit();
61        assert (pos <= lim);
62        int rem = (pos <= lim ? lim - pos : 0);
63        int off = (pos << 3) + offset;
64        assert (off >= 0);
65        return new ByteBufferAsDoubleBuffer(bb, -1, 0, rem, rem, off, order);
66    }
67
68    public DoubleBuffer duplicate() {
69        return new ByteBufferAsDoubleBuffer(bb,
70                markValue(),
71                position(),
72                limit(),
73                capacity(),
74                offset,
75                order);
76    }
77
78    public DoubleBuffer asReadOnlyBuffer() {
79        return new ByteBufferAsDoubleBuffer(bb.asReadOnlyBuffer(),
80                markValue(),
81                position(),
82                limit(),
83                capacity(),
84                offset,
85                order);
86    }
87
88    protected int ix(int i) {
89        return (i << 3) + offset;
90    }
91
92    public double get() {
93        return get(nextGetIndex());
94    }
95
96    public double get(int i) {
97        return bb.getDoubleUnchecked(ix(checkIndex(i)));
98    }
99
100    public DoubleBuffer get(double[] dst, int offset, int length) {
101        checkBounds(offset, length, dst.length);
102        if (length > remaining())
103            throw new BufferUnderflowException();
104        bb.getUnchecked(ix(position), dst, offset, length);
105        position += length;
106        return this;
107    }
108
109    public DoubleBuffer put(double x) {
110        put(nextPutIndex(), x);
111        return this;
112    }
113
114    public DoubleBuffer put(int i, double x) {
115        if (isReadOnly) {
116            throw new ReadOnlyBufferException();
117        }
118        bb.putDoubleUnchecked(ix(checkIndex(i)), x);
119        return this;
120    }
121
122    public DoubleBuffer put(double[] src, int offset, int length) {
123        checkBounds(offset, length, src.length);
124        if (length > remaining())
125            throw new BufferOverflowException();
126        bb.putUnchecked(ix(position), src, offset, length);
127        position += length;
128        return this;
129    }
130
131    public DoubleBuffer compact() {
132        if (isReadOnly) {
133            throw new ReadOnlyBufferException();
134        }
135        int pos = position();
136        int lim = limit();
137        assert (pos <= lim);
138        int rem = (pos <= lim ? lim - pos : 0);
139        if (!(bb instanceof DirectByteBuffer)) {
140            System.arraycopy(bb.array(), ix(pos), bb.array(), ix(0), rem << 3);
141        } else {
142            Memory.memmove(this, ix(0), this, ix(pos), rem << 3);
143        }
144        position(rem);
145        limit(capacity());
146        discardMark();
147        return this;
148    }
149
150    public boolean isDirect() {
151        return bb.isDirect();
152    }
153
154    public boolean isReadOnly() {
155        return isReadOnly;
156    }
157
158    public ByteOrder order() {
159        return order;
160    }
161}
162