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 ByteBufferAsCharBuffer(ByteBuffer bb, int mark, int pos, int lim, int cap, int off, ByteOrder order)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; 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.order = order; 53 offset = off; 54 } 55 slice()56 public CharBuffer slice() { 57 int pos = this.position(); 58 int lim = this.limit(); 59 assert (pos <= lim); 60 int rem = (pos <= lim ? lim - pos : 0); 61 int off = (pos << 1) + offset; 62 assert (off >= 0); 63 return new ByteBufferAsCharBuffer(bb, -1, 0, rem, rem, off, order); 64 } 65 duplicate()66 public CharBuffer duplicate() { 67 return new ByteBufferAsCharBuffer(bb, 68 markValue(), 69 position(), 70 limit(), 71 capacity(), 72 offset, 73 order); 74 } 75 asReadOnlyBuffer()76 public CharBuffer asReadOnlyBuffer() { 77 return new ByteBufferAsCharBuffer(bb.asReadOnlyBuffer(), 78 markValue(), 79 position(), 80 limit(), 81 capacity(), 82 offset, 83 order); 84 } 85 ix(int i)86 protected int ix(int i) { 87 return (i << 1) + offset; 88 } 89 get()90 public char get() { 91 return get(nextGetIndex()); 92 } 93 get(int i)94 public char get(int i) { 95 return bb.getCharUnchecked(ix(checkIndex(i))); 96 } 97 get(char[] dst, int offset, int length)98 public CharBuffer get(char[] dst, int offset, int length) { 99 checkBounds(offset, length, dst.length); 100 if (length > remaining()) 101 throw new BufferUnderflowException(); 102 bb.getUnchecked(ix(position), dst, offset, length); 103 position += length; 104 return this; 105 } 106 getUnchecked(int i)107 char getUnchecked(int i) { 108 return bb.getCharUnchecked(ix(i)); 109 } 110 put(char x)111 public CharBuffer put(char x) { 112 put(nextPutIndex(), x); 113 return this; 114 } 115 put(int i, char x)116 public CharBuffer put(int i, char x) { 117 if (isReadOnly) { 118 throw new ReadOnlyBufferException(); 119 } 120 bb.putCharUnchecked(ix(checkIndex(i)), x); 121 return this; 122 } 123 put(char[] src, int offset, int length)124 public CharBuffer put(char[] src, int offset, int length) { 125 checkBounds(offset, length, src.length); 126 if (length > remaining()) 127 throw new BufferOverflowException(); 128 bb.putUnchecked(ix(position), src, offset, length); 129 position += length; 130 return this; 131 } 132 compact()133 public CharBuffer compact() { 134 if (isReadOnly) { 135 throw new ReadOnlyBufferException(); 136 } 137 int pos = position(); 138 int lim = limit(); 139 assert (pos <= lim); 140 int rem = (pos <= lim ? lim - pos : 0); 141 if (!(bb instanceof DirectByteBuffer)) { 142 System.arraycopy(bb.array(), ix(pos), bb.array(), ix(0), rem << 1); 143 } else { 144 Memory.memmove(this, ix(0), this, ix(pos), rem << 1); 145 } 146 position(rem); 147 limit(capacity()); 148 discardMark(); 149 return this; 150 } 151 isDirect()152 public boolean isDirect() { 153 return bb.isDirect(); 154 } 155 isReadOnly()156 public boolean isReadOnly() { 157 return isReadOnly; 158 } 159 toString(int start, int end)160 public String toString(int start, int end) { 161 if ((end > limit()) || (start > end)) 162 throw new IndexOutOfBoundsException(); 163 try { 164 int len = end - start; 165 char[] ca = new char[len]; 166 CharBuffer cb = CharBuffer.wrap(ca); 167 CharBuffer db = this.duplicate(); 168 db.position(start); 169 db.limit(end); 170 cb.put(db); 171 return new String(ca); 172 } catch (StringIndexOutOfBoundsException x) { 173 throw new IndexOutOfBoundsException(); 174 } 175 } 176 177 // --- Methods to support CharSequence --- 178 subSequence(int start, int end)179 public CharBuffer subSequence(int start, int end) { 180 int pos = position(); 181 int lim = limit(); 182 assert (pos <= lim); 183 pos = (pos <= lim ? pos : lim); 184 int len = lim - pos; 185 186 if ((start < 0) || (end > len) || (start > end)) 187 throw new IndexOutOfBoundsException(); 188 return new ByteBufferAsCharBuffer(bb, 189 -1, 190 pos + start, 191 pos + end, 192 capacity(), 193 offset, 194 order); 195 } 196 order()197 public ByteOrder order() { 198 return order; 199 } 200 } 201