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 short 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 */
33final class ByteBufferAsShortBuffer extends ShortBuffer {
34
35    private final ByteBuffer byteBuffer;
36
37    static ShortBuffer asShortBuffer(ByteBuffer byteBuffer) {
38        ByteBuffer slice = byteBuffer.slice();
39        slice.order(byteBuffer.order());
40        return new ByteBufferAsShortBuffer(slice);
41    }
42
43    private ByteBufferAsShortBuffer(ByteBuffer byteBuffer) {
44        super(byteBuffer.capacity() / SizeOf.SHORT);
45        this.byteBuffer = byteBuffer;
46        this.byteBuffer.clear();
47        this.effectiveDirectAddress = byteBuffer.effectiveDirectAddress;
48    }
49
50    @Override
51    public ShortBuffer asReadOnlyBuffer() {
52        ByteBufferAsShortBuffer buf = new ByteBufferAsShortBuffer(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 ShortBuffer compact() {
62        if (byteBuffer.isReadOnly()) {
63            throw new ReadOnlyBufferException();
64        }
65        byteBuffer.limit(limit * SizeOf.SHORT);
66        byteBuffer.position(position * SizeOf.SHORT);
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 ShortBuffer duplicate() {
77        ByteBuffer bb = byteBuffer.duplicate().order(byteBuffer.order());
78        ByteBufferAsShortBuffer buf = new ByteBufferAsShortBuffer(bb);
79        buf.limit = limit;
80        buf.position = position;
81        buf.mark = mark;
82        return buf;
83    }
84
85    @Override
86    public short get() {
87        if (position == limit) {
88            throw new BufferUnderflowException();
89        }
90        return byteBuffer.getShort(position++ * SizeOf.SHORT);
91    }
92
93    @Override
94    public short get(int index) {
95        checkIndex(index);
96        return byteBuffer.getShort(index * SizeOf.SHORT);
97    }
98
99    @Override
100    public ShortBuffer get(short[] dst, int dstOffset, int shortCount) {
101        byteBuffer.limit(limit * SizeOf.SHORT);
102        byteBuffer.position(position * SizeOf.SHORT);
103        if (byteBuffer instanceof DirectByteBuffer) {
104            ((DirectByteBuffer) byteBuffer).get(dst, dstOffset, shortCount);
105        } else {
106            ((ByteArrayBuffer) byteBuffer).get(dst, dstOffset, shortCount);
107        }
108        this.position += shortCount;
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 short[] 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 ShortBuffer put(short c) {
141        if (position == limit) {
142            throw new BufferOverflowException();
143        }
144        byteBuffer.putShort(position++ * SizeOf.SHORT, c);
145        return this;
146    }
147
148    @Override
149    public ShortBuffer put(int index, short c) {
150        checkIndex(index);
151        byteBuffer.putShort(index * SizeOf.SHORT, c);
152        return this;
153    }
154
155    @Override
156    public ShortBuffer put(short[] src, int srcOffset, int shortCount) {
157        byteBuffer.limit(limit * SizeOf.SHORT);
158        byteBuffer.position(position * SizeOf.SHORT);
159        if (byteBuffer instanceof DirectByteBuffer) {
160            ((DirectByteBuffer) byteBuffer).put(src, srcOffset, shortCount);
161        } else {
162            ((ByteArrayBuffer) byteBuffer).put(src, srcOffset, shortCount);
163        }
164        this.position += shortCount;
165        return this;
166    }
167
168    @Override
169    public ShortBuffer slice() {
170        byteBuffer.limit(limit * SizeOf.SHORT);
171        byteBuffer.position(position * SizeOf.SHORT);
172        ByteBuffer bb = byteBuffer.slice().order(byteBuffer.order());
173        ShortBuffer result = new ByteBufferAsShortBuffer(bb);
174        byteBuffer.clear();
175        return result;
176    }
177
178}
179