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