Buffer.java revision 29dbfe19b113a13b712be2bc762ef1c81cd06c47
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 19/** 20 * A buffer is a list of elements of a specific primitive type. 21 * <p> 22 * A buffer can be described by the following properties: 23 * <ul> 24 * <li>Capacity: the number of elements a buffer can hold. Capacity may not be 25 * negative and never changes.</li> 26 * <li>Position: a cursor of this buffer. Elements are read or written at the 27 * position if you do not specify an index explicitly. Position may not be 28 * negative and not greater than the limit.</li> 29 * <li>Limit: controls the scope of accessible elements. You can only read or 30 * write elements from index zero to <code>limit - 1</code>. Accessing 31 * elements out of the scope will cause an exception. Limit may not be negative 32 * and not greater than capacity.</li> 33 * <li>Mark: used to remember the current position, so that you can reset the 34 * position later. Mark may not be negative and no greater than position.</li> 35 * <li>A buffer can be read-only or read-write. Trying to modify the elements 36 * of a read-only buffer will cause a <code>ReadOnlyBufferException</code>, 37 * while changing the position, limit and mark of a read-only buffer is OK.</li> 38 * <li>A buffer can be direct or indirect. A direct buffer will try its best to 39 * take advantage of native memory APIs and it may not stay in the Java heap, 40 * thus it is not affected by garbage collection.</li> 41 * </ul> 42 * <p> 43 * Buffers are not thread-safe. If concurrent access to a buffer instance is 44 * required, then the callers are responsible to take care of the 45 * synchronization issues. 46 */ 47public abstract class Buffer { 48 49 static final int SIZEOF_CHAR = 2; 50 static final int SIZEOF_DOUBLE = 8; 51 static final int SIZEOF_FLOAT = 4; 52 static final int SIZEOF_INT = 4; 53 static final int SIZEOF_LONG = 8; 54 static final int SIZEOF_SHORT = 2; 55 56 /** 57 * <code>UNSET_MARK</code> means the mark has not been set. 58 */ 59 final static int UNSET_MARK = -1; 60 61 /** 62 * The capacity of this buffer, which never changes. 63 */ 64 final int capacity; 65 66 /** 67 * <code>limit - 1</code> is the last element that can be read or written. 68 * Limit must be no less than zero and no greater than <code>capacity</code>. 69 */ 70 int limit; 71 72 /** 73 * Mark is where position will be set when <code>reset()</code> is called. 74 * Mark is not set by default. Mark is always no less than zero and no 75 * greater than <code>position</code>. 76 */ 77 int mark = UNSET_MARK; 78 79 /** 80 * The current position of this buffer. Position is always no less than zero 81 * and no greater than <code>limit</code>. 82 */ 83 int position = 0; 84 85 // BEGIN android-added 86 /** 87 * The log base 2 of the element size of this buffer. Each typed subclass 88 * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this 89 * value. The value is used by JNI code in frameworks/base/ to avoid the 90 * need for costly 'instanceof' tests. 91 */ 92 int _elementSizeShift; 93 94 /** 95 * For direct buffers, the effective address of the data. This is set 96 * on first use. If the field is zero, this is either not a direct 97 * buffer or the field has not been initialized, and you need to issue 98 * the getEffectiveAddress() call and use the result of that. 99 * 100 * This is an optimization used by the GetDirectBufferAddress JNI call. 101 */ 102 int effectiveDirectAddress = 0; 103 // END android-added 104 105 /** 106 * Construct a buffer with the specified capacity. 107 * 108 * @param capacity 109 * The capacity of this buffer 110 */ 111 Buffer(int capacity) { 112 super(); 113 if (capacity < 0) { 114 throw new IllegalArgumentException(); 115 } 116 this.capacity = this.limit = capacity; 117 } 118 119 /** 120 * Returns the array that backs this buffer (optional operation). 121 * The returned value is the actual array, not a copy, so modifications 122 * to the array write through to the buffer. 123 * 124 * <p>Subclasses should override this method with a covariant return type 125 * to provide the exact type of the array. 126 * 127 * <p>Use {@code hasArray} to ensure this method won't throw. 128 * (A separate call to {@code isReadOnly} is not necessary.) 129 * 130 * @return the array 131 * @throws ReadOnlyBufferException if the buffer is read-only 132 * UnsupportedOperationException if the buffer does not expose an array 133 * @since 1.6 134 */ 135 public abstract Object array(); 136 137 /** 138 * Returns the offset into the array returned by {@code array} of the first 139 * element of the buffer (optional operation). The backing array (if there is one) 140 * is not necessarily the same size as the buffer, and position 0 in the buffer is 141 * not necessarily the 0th element in the array. Use 142 * {@code buffer.array()[offset + buffer.arrayOffset()} to access element {@code offset} 143 * in {@code buffer}. 144 * 145 * <p>Use {@code hasArray} to ensure this method won't throw. 146 * (A separate call to {@code isReadOnly} is not necessary.) 147 * 148 * @return the offset 149 * @throws ReadOnlyBufferException if the buffer is read-only 150 * UnsupportedOperationException if the buffer does not expose an array 151 * @since 1.6 152 */ 153 public abstract int arrayOffset(); 154 155 /** 156 * Returns the capacity of this buffer. 157 * 158 * @return the number of elements that are contained in this buffer. 159 */ 160 public final int capacity() { 161 return capacity; 162 } 163 164 /** 165 * Clears this buffer. 166 * <p> 167 * While the content of this buffer is not changed, the following internal 168 * changes take place: the current position is reset back to the start of 169 * the buffer, the value of the buffer limit is made equal to the capacity 170 * and mark is cleared. 171 * 172 * @return this buffer. 173 */ 174 public final Buffer clear() { 175 position = 0; 176 mark = UNSET_MARK; 177 limit = capacity; 178 return this; 179 } 180 181 /** 182 * Flips this buffer. 183 * <p> 184 * The limit is set to the current position, then the position is set to 185 * zero, and the mark is cleared. 186 * <p> 187 * The content of this buffer is not changed. 188 * 189 * @return this buffer. 190 */ 191 public final Buffer flip() { 192 limit = position; 193 position = 0; 194 mark = UNSET_MARK; 195 return this; 196 } 197 198 /** 199 * Returns true if {@code array} and {@code arrayOffset} won't throw. This method does not 200 * return true for buffers not backed by arrays because the other methods would throw 201 * {@code UnsupportedOperationException}, nor does it return true for buffers backed by 202 * read-only arrays, because the other methods would throw {@code ReadOnlyBufferException}. 203 * @since 1.6 204 */ 205 public abstract boolean hasArray(); 206 207 /** 208 * Indicates if there are elements remaining in this buffer, that is if 209 * {@code position < limit}. 210 * 211 * @return {@code true} if there are elements remaining in this buffer, 212 * {@code false} otherwise. 213 */ 214 public final boolean hasRemaining() { 215 return position < limit; 216 } 217 218 /** 219 * Returns true if this is a direct buffer. 220 * @since 1.6 221 */ 222 public abstract boolean isDirect(); 223 224 /** 225 * Indicates whether this buffer is read-only. 226 * 227 * @return {@code true} if this buffer is read-only, {@code false} 228 * otherwise. 229 */ 230 public abstract boolean isReadOnly(); 231 232 /** 233 * Returns the limit of this buffer. 234 * 235 * @return the limit of this buffer. 236 */ 237 public final int limit() { 238 return limit; 239 } 240 241 /** 242 * Sets the limit of this buffer. 243 * <p> 244 * If the current position in the buffer is in excess of 245 * <code>newLimit</code> then, on returning from this call, it will have 246 * been adjusted to be equivalent to <code>newLimit</code>. If the mark 247 * is set and is greater than the new limit, then it is cleared. 248 * 249 * @param newLimit 250 * the new limit, must not be negative and not greater than 251 * capacity. 252 * @return this buffer. 253 * @exception IllegalArgumentException 254 * if <code>newLimit</code> is invalid. 255 */ 256 public final Buffer limit(int newLimit) { 257 if (newLimit < 0 || newLimit > capacity) { 258 throw new IllegalArgumentException(); 259 } 260 261 limit = newLimit; 262 if (position > newLimit) { 263 position = newLimit; 264 } 265 if ((mark != UNSET_MARK) && (mark > newLimit)) { 266 mark = UNSET_MARK; 267 } 268 return this; 269 } 270 271 /** 272 * Marks the current position, so that the position may return to this point 273 * later by calling <code>reset()</code>. 274 * 275 * @return this buffer. 276 */ 277 public final Buffer mark() { 278 mark = position; 279 return this; 280 } 281 282 /** 283 * Returns the position of this buffer. 284 * 285 * @return the value of this buffer's current position. 286 */ 287 public final int position() { 288 return position; 289 } 290 291 /** 292 * Sets the position of this buffer. 293 * <p> 294 * If the mark is set and it is greater than the new position, then it is 295 * cleared. 296 * 297 * @param newPosition 298 * the new position, must be not negative and not greater than 299 * limit. 300 * @return this buffer. 301 * @exception IllegalArgumentException 302 * if <code>newPosition</code> is invalid. 303 */ 304 public final Buffer position(int newPosition) { 305 if (newPosition < 0 || newPosition > limit) { 306 throw new IllegalArgumentException(); 307 } 308 309 position = newPosition; 310 if ((mark != UNSET_MARK) && (mark > position)) { 311 mark = UNSET_MARK; 312 } 313 return this; 314 } 315 316 /** 317 * Returns the number of remaining elements in this buffer, that is 318 * {@code limit - position}. 319 * 320 * @return the number of remaining elements in this buffer. 321 */ 322 public final int remaining() { 323 return limit - position; 324 } 325 326 /** 327 * Resets the position of this buffer to the <code>mark</code>. 328 * 329 * @return this buffer. 330 * @exception InvalidMarkException 331 * if the mark is not set. 332 */ 333 public final Buffer reset() { 334 if (mark == UNSET_MARK) { 335 throw new InvalidMarkException(); 336 } 337 position = mark; 338 return this; 339 } 340 341 /** 342 * Rewinds this buffer. 343 * <p> 344 * The position is set to zero, and the mark is cleared. The content of this 345 * buffer is not changed. 346 * 347 * @return this buffer. 348 */ 349 public final Buffer rewind() { 350 position = 0; 351 mark = UNSET_MARK; 352 return this; 353 } 354} 355