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