1 /* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.nio; 27 28 import libcore.io.Memory; 29 30 class ByteBufferAsCharBuffer extends CharBuffer { // package-private 31 32 protected final ByteBuffer bb; 33 protected final int offset; 34 private final ByteOrder order; 35 36 ByteBufferAsCharBuffer(ByteBuffer bb, 37 int mark, int pos, int lim, int cap, 38 int off, ByteOrder order) { 39 super(mark, pos, lim, cap); 40 this.bb = bb.duplicate(); 41 this.isReadOnly = bb.isReadOnly; 42 // There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and 43 // HeapByteBuffer. We only have to initialize the field when bb is an instance of 44 // DirectByteBuffer. 45 // The address field is used by NIOAccess#getBasePointer and GetDirectBufferAddress method 46 // in art which return the address of the first usable byte of the underlying memory, i.e, 47 // the position of parent buffer. Therefore, value of "off" will be equal to parent buffer's 48 // position when the method is called from either HeapByteBuffer or DirectByteBuffer. 49 if (bb instanceof DirectByteBuffer) { 50 this.address = bb.address + off; 51 } 52 this.bb.order(order); 53 this.order = order; 54 offset = off; 55 } 56 57 public CharBuffer slice() { 58 int pos = this.position(); 59 int lim = this.limit(); 60 assert (pos <= lim); 61 int rem = (pos <= lim ? lim - pos : 0); 62 int off = (pos << 1) + offset; 63 assert (off >= 0); 64 return new ByteBufferAsCharBuffer(bb, -1, 0, rem, rem, off, order); 65 } 66 67 public CharBuffer duplicate() { 68 return new ByteBufferAsCharBuffer(bb, 69 markValue(), 70 position(), 71 limit(), 72 capacity(), 73 offset, 74 order); 75 } 76 77 public CharBuffer asReadOnlyBuffer() { 78 return new ByteBufferAsCharBuffer(bb.asReadOnlyBuffer(), 79 markValue(), 80 position(), 81 limit(), 82 capacity(), 83 offset, 84 order); 85 } 86 87 protected int ix(int i) { 88 return (i << 1) + offset; 89 } 90 91 public char get() { 92 return get(nextGetIndex()); 93 } 94 95 public char get(int i) { 96 return bb.getCharUnchecked(ix(checkIndex(i))); 97 } 98 99 public CharBuffer get(char[] dst, int offset, int length) { 100 checkBounds(offset, length, dst.length); 101 if (length > remaining()) 102 throw new BufferUnderflowException(); 103 bb.getUnchecked(ix(position), dst, offset, length); 104 position += length; 105 return this; 106 } 107 108 char getUnchecked(int i) { 109 return bb.getCharUnchecked(ix(i)); 110 } 111 112 public CharBuffer put(char x) { 113 put(nextPutIndex(), x); 114 return this; 115 } 116 117 public CharBuffer put(int i, char x) { 118 if (isReadOnly) { 119 throw new ReadOnlyBufferException(); 120 } 121 bb.putCharUnchecked(ix(checkIndex(i)), x); 122 return this; 123 } 124 125 public CharBuffer put(char[] src, int offset, int length) { 126 checkBounds(offset, length, src.length); 127 if (length > remaining()) 128 throw new BufferOverflowException(); 129 bb.putUnchecked(ix(position), src, offset, length); 130 position += length; 131 return this; 132 } 133 134 public CharBuffer compact() { 135 if (isReadOnly) { 136 throw new ReadOnlyBufferException(); 137 } 138 int pos = position(); 139 int lim = limit(); 140 assert (pos <= lim); 141 int rem = (pos <= lim ? lim - pos : 0); 142 if (!(bb instanceof DirectByteBuffer)) { 143 System.arraycopy(bb.array(), ix(pos), bb.array(), ix(0), rem << 1); 144 } else { 145 Memory.memmove(this, ix(0), this, ix(pos), rem << 1); 146 } 147 position(rem); 148 limit(capacity()); 149 discardMark(); 150 return this; 151 } 152 153 public boolean isDirect() { 154 return bb.isDirect(); 155 } 156 157 public boolean isReadOnly() { 158 return isReadOnly; 159 } 160 161 public String toString(int start, int end) { 162 if ((end > limit()) || (start > end)) 163 throw new IndexOutOfBoundsException(); 164 try { 165 int len = end - start; 166 char[] ca = new char[len]; 167 CharBuffer cb = CharBuffer.wrap(ca); 168 CharBuffer db = this.duplicate(); 169 db.position(start); 170 db.limit(end); 171 cb.put(db); 172 return new String(ca); 173 } catch (StringIndexOutOfBoundsException x) { 174 throw new IndexOutOfBoundsException(); 175 } 176 } 177 178 // --- Methods to support CharSequence --- 179 180 public CharBuffer subSequence(int start, int end) { 181 int pos = position(); 182 int lim = limit(); 183 assert (pos <= lim); 184 pos = (pos <= lim ? pos : lim); 185 int len = lim - pos; 186 187 if ((start < 0) || (end > len) || (start > end)) 188 throw new IndexOutOfBoundsException(); 189 return new ByteBufferAsCharBuffer(bb, 190 -1, 191 pos + start, 192 pos + end, 193 capacity(), 194 offset, 195 order); 196 } 197 198 public ByteOrder order() { 199 return order; 200 } 201 } 202