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 DoubleToByteBufferAdapter 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 DoubleToByteBufferAdapter(slice);
42    }
43
44    private DoubleToByteBufferAdapter(ByteBuffer byteBuffer) {
45        super(byteBuffer.capacity() / SizeOf.DOUBLE);
46        this.byteBuffer = byteBuffer;
47        this.byteBuffer.clear();
48        this.effectiveDirectAddress = byteBuffer.effectiveDirectAddress;
49    }
50
51    @Override
52    public DoubleBuffer asReadOnlyBuffer() {
53        DoubleToByteBufferAdapter buf = new DoubleToByteBufferAdapter(byteBuffer.asReadOnlyBuffer());
54        buf.limit = limit;
55        buf.position = position;
56        buf.mark = mark;
57        buf.byteBuffer.order = byteBuffer.order;
58        return buf;
59    }
60
61    @Override
62    public DoubleBuffer compact() {
63        if (byteBuffer.isReadOnly()) {
64            throw new ReadOnlyBufferException();
65        }
66        byteBuffer.limit(limit * SizeOf.DOUBLE);
67        byteBuffer.position(position * SizeOf.DOUBLE);
68        byteBuffer.compact();
69        byteBuffer.clear();
70        position = limit - position;
71        limit = capacity;
72        mark = UNSET_MARK;
73        return this;
74    }
75
76    @Override
77    public DoubleBuffer duplicate() {
78        ByteBuffer bb = byteBuffer.duplicate().order(byteBuffer.order());
79        DoubleToByteBufferAdapter buf = new DoubleToByteBufferAdapter(bb);
80        buf.limit = limit;
81        buf.position = position;
82        buf.mark = mark;
83        return buf;
84    }
85
86    @Override
87    public double get() {
88        if (position == limit) {
89            throw new BufferUnderflowException();
90        }
91        return byteBuffer.getDouble(position++ * SizeOf.DOUBLE);
92    }
93
94    @Override
95    public double get(int index) {
96        checkIndex(index);
97        return byteBuffer.getDouble(index * SizeOf.DOUBLE);
98    }
99
100    @Override
101    public DoubleBuffer get(double[] dst, int dstOffset, int doubleCount) {
102        byteBuffer.limit(limit * SizeOf.DOUBLE);
103        byteBuffer.position(position * SizeOf.DOUBLE);
104        if (byteBuffer instanceof DirectByteBuffer) {
105            ((DirectByteBuffer) byteBuffer).get(dst, dstOffset, doubleCount);
106        } else {
107            ((HeapByteBuffer) byteBuffer).get(dst, dstOffset, doubleCount);
108        }
109        this.position += doubleCount;
110        return this;
111    }
112
113    @Override
114    public boolean isDirect() {
115        return byteBuffer.isDirect();
116    }
117
118    @Override
119    public boolean isReadOnly() {
120        return byteBuffer.isReadOnly();
121    }
122
123    @Override
124    public ByteOrder order() {
125        return byteBuffer.order();
126    }
127
128    @Override double[] protectedArray() {
129        throw new UnsupportedOperationException();
130    }
131
132    @Override int protectedArrayOffset() {
133        throw new UnsupportedOperationException();
134    }
135
136    @Override boolean protectedHasArray() {
137        return false;
138    }
139
140    @Override
141    public DoubleBuffer put(double c) {
142        if (position == limit) {
143            throw new BufferOverflowException();
144        }
145        byteBuffer.putDouble(position++ * SizeOf.DOUBLE, c);
146        return this;
147    }
148
149    @Override
150    public DoubleBuffer put(int index, double c) {
151        checkIndex(index);
152        byteBuffer.putDouble(index * SizeOf.DOUBLE, c);
153        return this;
154    }
155
156    @Override
157    public DoubleBuffer put(double[] src, int srcOffset, int doubleCount) {
158        byteBuffer.limit(limit * SizeOf.DOUBLE);
159        byteBuffer.position(position * SizeOf.DOUBLE);
160        if (byteBuffer instanceof ReadWriteDirectByteBuffer) {
161            ((ReadWriteDirectByteBuffer) byteBuffer).put(src, srcOffset, doubleCount);
162        } else {
163            ((ReadWriteHeapByteBuffer) byteBuffer).put(src, srcOffset, doubleCount);
164        }
165        this.position += doubleCount;
166        return this;
167    }
168
169    @Override
170    public DoubleBuffer slice() {
171        byteBuffer.limit(limit * SizeOf.DOUBLE);
172        byteBuffer.position(position * SizeOf.DOUBLE);
173        ByteBuffer bb = byteBuffer.slice().order(byteBuffer.order());
174        DoubleBuffer result = new DoubleToByteBufferAdapter(bb);
175        byteBuffer.clear();
176        return result;
177    }
178
179}
180