1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership.
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License.  You may obtain a copy of the License at
7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.nio;
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1943a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughesimport libcore.io.SizeOf;
2043a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class wraps a byte buffer to be a char buffer.
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Implementation notice:
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul>
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>After a byte buffer instance is wrapped, it becomes privately owned by
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the adapter. It must NOT be accessed outside the adapter any more.</li>
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>The byte buffer's position and limit are NOT linked with the adapter.
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The adapter extends Buffer, thus has its own position and limit.</li>
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul>
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </p>
32f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
340440837fd0013373ba3476283151299e7be9e5a3Elliott Hughesfinal class CharToByteBufferAdapter extends CharBuffer {
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final ByteBuffer byteBuffer;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
3817b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes    static CharBuffer asCharBuffer(ByteBuffer byteBuffer) {
3917b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes        ByteBuffer slice = byteBuffer.slice();
4017b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes        slice.order(byteBuffer.order());
4117b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes        return new CharToByteBufferAdapter(slice);
4217b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes    }
4317b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes
4417b2f493468764dc1f237c02d94747d122dbd101Elliott Hughes    private CharToByteBufferAdapter(ByteBuffer byteBuffer) {
4543a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        super(byteBuffer.capacity() / SizeOf.CHAR);
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.byteBuffer = byteBuffer;
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.byteBuffer.clear();
480440837fd0013373ba3476283151299e7be9e5a3Elliott Hughes        this.effectiveDirectAddress = byteBuffer.effectiveDirectAddress;
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
50eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson
51eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharBuffer asReadOnlyBuffer() {
53f46d2ce4d4c92d16e2574f57f70fc5477dc12697Elliott Hughes        CharToByteBufferAdapter buf = new CharToByteBufferAdapter(byteBuffer.asReadOnlyBuffer());
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf.limit = limit;
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf.position = position;
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf.mark = mark;
570c0934430f2cdd830b54eacf518355057f3567f3Elliott Hughes        buf.byteBuffer.order = byteBuffer.order;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return buf;
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
61eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharBuffer compact() {
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (byteBuffer.isReadOnly()) {
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new ReadOnlyBufferException();
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6643a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.limit(limit * SizeOf.CHAR);
6743a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.position(position * SizeOf.CHAR);
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byteBuffer.compact();
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byteBuffer.clear();
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        position = limit - position;
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        limit = capacity;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        mark = UNSET_MARK;
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
76eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharBuffer duplicate() {
78eebf863ca5c8a7497f92602fe9ea3d1282c8bdedElliott Hughes        ByteBuffer bb = byteBuffer.duplicate().order(byteBuffer.order());
79eebf863ca5c8a7497f92602fe9ea3d1282c8bdedElliott Hughes        CharToByteBufferAdapter buf = new CharToByteBufferAdapter(bb);
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf.limit = limit;
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf.position = position;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf.mark = mark;
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return buf;
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
86eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public char get() {
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (position == limit) {
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new BufferUnderflowException();
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
9143a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        return byteBuffer.getChar(position++ * SizeOf.CHAR);
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
94eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public char get(int index) {
9686f5f3e0e2bd808e4c85b0563ae50f17b7d48309Elliott Hughes        checkIndex(index);
9743a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        return byteBuffer.getChar(index * SizeOf.CHAR);
98961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes    }
99961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes
100961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes    @Override
101961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes    public CharBuffer get(char[] dst, int dstOffset, int charCount) {
10243a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.limit(limit * SizeOf.CHAR);
10343a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.position(position * SizeOf.CHAR);
104961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes        if (byteBuffer instanceof DirectByteBuffer) {
105961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes            ((DirectByteBuffer) byteBuffer).get(dst, dstOffset, charCount);
106961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes        } else {
1076944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes            ((HeapByteBuffer) byteBuffer).get(dst, dstOffset, charCount);
108961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes        }
1096944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes        this.position += charCount;
1106944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes        return this;
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
113eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isDirect() {
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return byteBuffer.isDirect();
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
118eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isReadOnly() {
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return byteBuffer.isReadOnly();
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
123eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public ByteOrder order() {
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return byteBuffer.order();
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
128bdd17cde8cf675f5d5703aad4dfb565932fb4c50Elliott Hughes    @Override char[] protectedArray() {
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new UnsupportedOperationException();
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
132bdd17cde8cf675f5d5703aad4dfb565932fb4c50Elliott Hughes    @Override int protectedArrayOffset() {
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new UnsupportedOperationException();
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
136bdd17cde8cf675f5d5703aad4dfb565932fb4c50Elliott Hughes    @Override boolean protectedHasArray() {
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
140eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharBuffer put(char c) {
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (position == limit) {
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new BufferOverflowException();
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
14543a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.putChar(position++ * SizeOf.CHAR, c);
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
149eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharBuffer put(int index, char c) {
151a1603838fe9e865575c87982e32c6343740e464cElliott Hughes        checkIndex(index);
15243a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.putChar(index * SizeOf.CHAR, c);
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
156eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
1570e1b748ecabf720065a632f28330f5d4d037d5aeElliott Hughes    public CharBuffer put(char[] src, int srcOffset, int charCount) {
15843a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.limit(limit * SizeOf.CHAR);
15943a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.position(position * SizeOf.CHAR);
160692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes        if (byteBuffer instanceof ReadWriteDirectByteBuffer) {
1610e1b748ecabf720065a632f28330f5d4d037d5aeElliott Hughes            ((ReadWriteDirectByteBuffer) byteBuffer).put(src, srcOffset, charCount);
162692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes        } else {
1638fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes            ((ReadWriteHeapByteBuffer) byteBuffer).put(src, srcOffset, charCount);
164692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes        }
1658fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        this.position += charCount;
1668fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        return this;
167692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes    }
168692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
169692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes    @Override
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharBuffer slice() {
17143a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.limit(limit * SizeOf.CHAR);
17243a9f774d075e0e441d8b996e3f6c81ea483ec89Elliott Hughes        byteBuffer.position(position * SizeOf.CHAR);
173eebf863ca5c8a7497f92602fe9ea3d1282c8bdedElliott Hughes        ByteBuffer bb = byteBuffer.slice().order(byteBuffer.order());
174eebf863ca5c8a7497f92602fe9ea3d1282c8bdedElliott Hughes        CharBuffer result = new CharToByteBufferAdapter(bb);
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byteBuffer.clear();
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
179eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CharSequence subSequence(int start, int end) {
181a1603838fe9e865575c87982e32c6343740e464cElliott Hughes        checkStartEndRemaining(start, end);
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        CharBuffer result = duplicate();
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        result.limit(position + end);
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        result.position(position + start);
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
188