1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package java.nio;
18
19import libcore.io.SizeOf;
20
21/**
22 * This class wraps a byte buffer to be a double buffer.
23 * <p>
24 * Implementation notice:
25 * <ul>
26 * <li>After a byte buffer instance is wrapped, it becomes privately owned by
27 * the adapter. It must NOT be accessed outside the adapter any more.</li>
28 * <li>The byte buffer's position and limit are NOT linked with the adapter.
29 * The adapter extends Buffer, thus has its own position and limit.</li>
30 * </ul>
31 * </p>
32 *
33 */
34final class ByteBufferAsDoubleBuffer extends DoubleBuffer {
35
36    private final ByteBuffer byteBuffer;
37
38    static DoubleBuffer asDoubleBuffer(ByteBuffer byteBuffer) {
39        ByteBuffer slice = byteBuffer.slice();
40        slice.order(byteBuffer.order());
41        return new ByteBufferAsDoubleBuffer(slice);
42    }
43
44    private ByteBufferAsDoubleBuffer(ByteBuffer byteBuffer) {
45        super(byteBuffer.capacity() / SizeOf.DOUBLE, byteBuffer.effectiveDirectAddress);
46        this.byteBuffer = byteBuffer;
47        this.byteBuffer.clear();
48    }
49
50    @Override
51    public DoubleBuffer asReadOnlyBuffer() {
52        ByteBufferAsDoubleBuffer buf = new ByteBufferAsDoubleBuffer(byteBuffer.asReadOnlyBuffer());
53        buf.limit = limit;
54        buf.position = position;
55        buf.mark = mark;
56        buf.byteBuffer.order = byteBuffer.order;
57        return buf;
58    }
59
60    @Override
61    public DoubleBuffer compact() {
62        if (byteBuffer.isReadOnly()) {
63            throw new ReadOnlyBufferException();
64        }
65        byteBuffer.limit(limit * SizeOf.DOUBLE);
66        byteBuffer.position(position * SizeOf.DOUBLE);
67        byteBuffer.compact();
68        byteBuffer.clear();
69        position = limit - position;
70        limit = capacity;
71        mark = UNSET_MARK;
72        return this;
73    }
74
75    @Override
76    public DoubleBuffer duplicate() {
77        ByteBuffer bb = byteBuffer.duplicate().order(byteBuffer.order());
78        ByteBufferAsDoubleBuffer buf = new ByteBufferAsDoubleBuffer(bb);
79        buf.limit = limit;
80        buf.position = position;
81        buf.mark = mark;
82        return buf;
83    }
84
85    @Override
86    public double get() {
87        if (position == limit) {
88            throw new BufferUnderflowException();
89        }
90        return byteBuffer.getDouble(position++ * SizeOf.DOUBLE);
91    }
92
93    @Override
94    public double get(int index) {
95        checkIndex(index);
96        return byteBuffer.getDouble(index * SizeOf.DOUBLE);
97    }
98
99    @Override
100    public DoubleBuffer get(double[] dst, int dstOffset, int doubleCount) {
101        byteBuffer.limit(limit * SizeOf.DOUBLE);
102        byteBuffer.position(position * SizeOf.DOUBLE);
103        if (byteBuffer instanceof DirectByteBuffer) {
104            ((DirectByteBuffer) byteBuffer).get(dst, dstOffset, doubleCount);
105        } else {
106            ((ByteArrayBuffer) byteBuffer).get(dst, dstOffset, doubleCount);
107        }
108        this.position += doubleCount;
109        return this;
110    }
111
112    @Override
113    public boolean isDirect() {
114        return byteBuffer.isDirect();
115    }
116
117    @Override
118    public boolean isReadOnly() {
119        return byteBuffer.isReadOnly();
120    }
121
122    @Override
123    public ByteOrder order() {
124        return byteBuffer.order();
125    }
126
127    @Override double[] protectedArray() {
128        throw new UnsupportedOperationException();
129    }
130
131    @Override int protectedArrayOffset() {
132        throw new UnsupportedOperationException();
133    }
134
135    @Override boolean protectedHasArray() {
136        return false;
137    }
138
139    @Override
140    public DoubleBuffer put(double c) {
141        if (position == limit) {
142            throw new BufferOverflowException();
143        }
144        byteBuffer.putDouble(position++ * SizeOf.DOUBLE, c);
145        return this;
146    }
147
148    @Override
149    public DoubleBuffer put(int index, double c) {
150        checkIndex(index);
151        byteBuffer.putDouble(index * SizeOf.DOUBLE, c);
152        return this;
153    }
154
155    @Override
156    public DoubleBuffer put(double[] src, int srcOffset, int doubleCount) {
157        byteBuffer.limit(limit * SizeOf.DOUBLE);
158        byteBuffer.position(position * SizeOf.DOUBLE);
159        if (byteBuffer instanceof DirectByteBuffer) {
160            ((DirectByteBuffer) byteBuffer).put(src, srcOffset, doubleCount);
161        } else {
162            ((ByteArrayBuffer) byteBuffer).put(src, srcOffset, doubleCount);
163        }
164        this.position += doubleCount;
165        return this;
166    }
167
168    @Override
169    public DoubleBuffer slice() {
170        byteBuffer.limit(limit * SizeOf.DOUBLE);
171        byteBuffer.position(position * SizeOf.DOUBLE);
172        ByteBuffer bb = byteBuffer.slice().order(byteBuffer.order());
173        DoubleBuffer result = new ByteBufferAsDoubleBuffer(bb);
174        byteBuffer.clear();
175        return result;
176    }
177
178}
179