1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.nio; 19 20 import java.util.Arrays; 21 22 /** 23 * A buffer of ints. 24 * <p> 25 * A int buffer can be created in either of the following ways: 26 * <ul> 27 * <li>{@link #allocate(int) Allocate} a new int array and create a buffer 28 * based on it;</li> 29 * <li>{@link #wrap(int[]) Wrap} an existing int array to create a new buffer;</li> 30 * <li>Use {@link java.nio.ByteBuffer#asIntBuffer() ByteBuffer.asIntBuffer} to 31 * create a int buffer based on a byte buffer.</li> 32 * </ul> 33 */ 34 public abstract class IntBuffer extends Buffer implements Comparable<IntBuffer> { 35 36 /** 37 * Creates an int buffer based on a newly allocated int array. 38 * 39 * @param capacity 40 * the capacity of the new buffer. 41 * @return the created int buffer. 42 * @throws IllegalArgumentException 43 * if {@code capacity} is less than zero. 44 */ 45 public static IntBuffer allocate(int capacity) { 46 if (capacity < 0) { 47 throw new IllegalArgumentException("capacity < 0: " + capacity); 48 } 49 return new IntArrayBuffer(new int[capacity]); 50 } 51 52 /** 53 * Creates a new int buffer by wrapping the given int array. 54 * <p> 55 * Calling this method has the same effect as 56 * {@code wrap(array, 0, array.length)}. 57 * 58 * @param array 59 * the int array which the new buffer will be based on. 60 * @return the created int buffer. 61 */ 62 public static IntBuffer wrap(int[] array) { 63 return wrap(array, 0, array.length); 64 } 65 66 /** 67 * Creates a new int buffer by wrapping the given int array. 68 * <p> 69 * The new buffer's position will be {@code start}, limit will be 70 * {@code start + intCount}, capacity will be the length of the array. 71 * 72 * @param array 73 * the int array which the new buffer will be based on. 74 * @param start 75 * the start index, must not be negative and not greater than 76 * {@code array.length} 77 * @param intCount 78 * the length, must not be negative and not greater than 79 * {@code array.length - start}. 80 * @return the created int buffer. 81 * @throws IndexOutOfBoundsException 82 * if either {@code start} or {@code intCount} is invalid. 83 */ 84 public static IntBuffer wrap(int[] array, int start, int intCount) { 85 Arrays.checkOffsetAndCount(array.length, start, intCount); 86 IntBuffer buf = new IntArrayBuffer(array); 87 buf.position = start; 88 buf.limit = start + intCount; 89 return buf; 90 } 91 92 IntBuffer(int capacity, long effectiveDirectAddress) { 93 super(2, capacity, effectiveDirectAddress); 94 } 95 96 public final int[] array() { 97 return protectedArray(); 98 } 99 100 public final int arrayOffset() { 101 return protectedArrayOffset(); 102 } 103 104 /** 105 * Returns a read-only buffer that shares its content with this buffer. 106 * <p> 107 * The returned buffer is guaranteed to be a new instance, even this buffer 108 * is read-only itself. The new buffer's position, limit, capacity and mark 109 * are the same as this buffer's. 110 * <p> 111 * The new buffer shares its content with this buffer, which means this 112 * buffer's change of content will be visible to the new buffer. The two 113 * buffer's position, limit and mark are independent. 114 * 115 * @return a read-only version of this buffer. 116 */ 117 public abstract IntBuffer asReadOnlyBuffer(); 118 119 /** 120 * Compacts this int buffer. 121 * <p> 122 * The remaining ints will be moved to the head of the buffer, starting from 123 * position zero. Then the position is set to {@code remaining()}; the 124 * limit is set to capacity; the mark is cleared. 125 * 126 * @return this buffer. 127 * @throws ReadOnlyBufferException 128 * if no changes may be made to the contents of this buffer. 129 */ 130 public abstract IntBuffer compact(); 131 132 /** 133 * Compares the remaining ints of this buffer to another int buffer's 134 * remaining ints. 135 * 136 * @param otherBuffer 137 * another int buffer. 138 * @return a negative value if this is less than {@code other}; 0 if this 139 * equals to {@code other}; a positive value if this is greater 140 * than {@code other}. 141 * @throws ClassCastException 142 * if {@code other} is not an int buffer. 143 */ 144 public int compareTo(IntBuffer otherBuffer) { 145 int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining() 146 : otherBuffer.remaining(); 147 int thisPos = position; 148 int otherPos = otherBuffer.position; 149 int thisInt, otherInt; 150 while (compareRemaining > 0) { 151 thisInt = get(thisPos); 152 otherInt = otherBuffer.get(otherPos); 153 if (thisInt != otherInt) { 154 return thisInt < otherInt ? -1 : 1; 155 } 156 thisPos++; 157 otherPos++; 158 compareRemaining--; 159 } 160 return remaining() - otherBuffer.remaining(); 161 } 162 163 /** 164 * Returns a duplicated buffer that shares its content with this buffer. 165 * <p> 166 * The duplicated buffer's position, limit, capacity and mark are the same 167 * as this buffer. The duplicated buffer's read-only property and byte order 168 * are the same as this buffer's. 169 * <p> 170 * The new buffer shares its content with this buffer, which means either 171 * buffer's change of content will be visible to the other. The two buffers' 172 * position, limit and mark are independent. 173 */ 174 public abstract IntBuffer duplicate(); 175 176 /** 177 * Checks whether this int buffer is equal to another object. 178 * <p> 179 * If {@code other} is not a int buffer then {@code false} is returned. Two 180 * int buffers are equal if and only if their remaining ints are exactly the 181 * same. Position, limit, capacity and mark are not considered. 182 * 183 * @param other 184 * the object to compare with this int buffer. 185 * @return {@code true} if this int buffer is equal to {@code other}, 186 * {@code false} otherwise. 187 */ 188 @Override 189 public boolean equals(Object other) { 190 if (!(other instanceof IntBuffer)) { 191 return false; 192 } 193 IntBuffer otherBuffer = (IntBuffer) other; 194 195 if (remaining() != otherBuffer.remaining()) { 196 return false; 197 } 198 199 int myPosition = position; 200 int otherPosition = otherBuffer.position; 201 boolean equalSoFar = true; 202 while (equalSoFar && (myPosition < limit)) { 203 equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++); 204 } 205 206 return equalSoFar; 207 } 208 209 /** 210 * Returns the int at the current position and increases the position by 1. 211 * 212 * @return the int at the current position. 213 * @throws BufferUnderflowException 214 * if the position is equal or greater than limit. 215 */ 216 public abstract int get(); 217 218 /** 219 * Reads ints from the current position into the specified int array and 220 * increases the position by the number of ints read. 221 * <p> 222 * Calling this method has the same effect as 223 * {@code get(dst, 0, dst.length)}. 224 * 225 * @param dst 226 * the destination int array. 227 * @return this buffer. 228 * @throws BufferUnderflowException 229 * if {@code dst.length} is greater than {@code remaining()}. 230 */ 231 public IntBuffer get(int[] dst) { 232 return get(dst, 0, dst.length); 233 } 234 235 /** 236 * Reads ints from the current position into the specified int array, 237 * starting from the specified offset, and increases the position by the 238 * number of ints read. 239 * 240 * @param dst 241 * the target int array. 242 * @param dstOffset 243 * the offset of the int array, must not be negative and not 244 * greater than {@code dst.length}. 245 * @param intCount 246 * the number of ints to read, must be no less than zero and not 247 * greater than {@code dst.length - dstOffset}. 248 * @return this buffer. 249 * @throws IndexOutOfBoundsException 250 * if either {@code dstOffset} or {@code intCount} is invalid. 251 * @throws BufferUnderflowException 252 * if {@code intCount} is greater than {@code remaining()}. 253 */ 254 public IntBuffer get(int[] dst, int dstOffset, int intCount) { 255 Arrays.checkOffsetAndCount(dst.length, dstOffset, intCount); 256 if (intCount > remaining()) { 257 throw new BufferUnderflowException(); 258 } 259 for (int i = dstOffset; i < dstOffset + intCount; ++i) { 260 dst[i] = get(); 261 } 262 return this; 263 } 264 265 /** 266 * Returns an int at the specified index; the position is not changed. 267 * 268 * @param index 269 * the index, must not be negative and less than limit. 270 * @return an int at the specified index. 271 * @throws IndexOutOfBoundsException 272 * if index is invalid. 273 */ 274 public abstract int get(int index); 275 276 public final boolean hasArray() { 277 return protectedHasArray(); 278 } 279 280 /** 281 * Calculates this buffer's hash code from the remaining chars. The 282 * position, limit, capacity and mark don't affect the hash code. 283 * 284 * @return the hash code calculated from the remaining ints. 285 */ 286 @Override 287 public int hashCode() { 288 int myPosition = position; 289 int hash = 0; 290 while (myPosition < limit) { 291 hash = hash + get(myPosition++); 292 } 293 return hash; 294 } 295 296 /** 297 * Indicates whether this buffer is direct. A direct buffer will try its 298 * best to take advantage of native memory APIs and it may not stay in the 299 * Java heap, so it is not affected by garbage collection. 300 * <p> 301 * An int buffer is direct if it is based on a byte buffer and the byte 302 * buffer is direct. 303 * 304 * @return {@code true} if this buffer is direct, {@code false} otherwise. 305 */ 306 public abstract boolean isDirect(); 307 308 /** 309 * Returns the byte order used by this buffer when converting ints from/to 310 * bytes. 311 * <p> 312 * If this buffer is not based on a byte buffer, then always return the 313 * platform's native byte order. 314 * 315 * @return the byte order used by this buffer when converting ints from/to 316 * bytes. 317 */ 318 public abstract ByteOrder order(); 319 320 /** 321 * Child class implements this method to realize {@code array()}. 322 * 323 * @return see {@code array()} 324 */ 325 abstract int[] protectedArray(); 326 327 /** 328 * Child class implements this method to realize {@code arrayOffset()}. 329 * 330 * @return see {@code arrayOffset()} 331 */ 332 abstract int protectedArrayOffset(); 333 334 /** 335 * Child class implements this method to realize {@code hasArray()}. 336 * 337 * @return see {@code hasArray()} 338 */ 339 abstract boolean protectedHasArray(); 340 341 /** 342 * Writes the given int to the current position and increases the position 343 * by 1. 344 * 345 * @param i 346 * the int to write. 347 * @return this buffer. 348 * @throws BufferOverflowException 349 * if position is equal or greater than limit. 350 * @throws ReadOnlyBufferException 351 * if no changes may be made to the contents of this buffer. 352 */ 353 public abstract IntBuffer put(int i); 354 355 /** 356 * Writes ints from the given int array to the current position and 357 * increases the position by the number of ints written. 358 * <p> 359 * Calling this method has the same effect as 360 * {@code put(src, 0, src.length)}. 361 * 362 * @param src 363 * the source int array. 364 * @return this buffer. 365 * @throws BufferOverflowException 366 * if {@code remaining()} is less than {@code src.length}. 367 * @throws ReadOnlyBufferException 368 * if no changes may be made to the contents of this buffer. 369 */ 370 public final IntBuffer put(int[] src) { 371 return put(src, 0, src.length); 372 } 373 374 /** 375 * Writes ints from the given int array, starting from the specified offset, 376 * to the current position and increases the position by the number of ints 377 * written. 378 * 379 * @param src 380 * the source int array. 381 * @param srcOffset 382 * the offset of int array, must not be negative and not greater 383 * than {@code src.length}. 384 * @param intCount 385 * the number of ints to write, must be no less than zero and not 386 * greater than {@code src.length - srcOffset}. 387 * @return this buffer. 388 * @throws BufferOverflowException 389 * if {@code remaining()} is less than {@code intCount}. 390 * @throws IndexOutOfBoundsException 391 * if either {@code srcOffset} or {@code intCount} is invalid. 392 * @throws ReadOnlyBufferException 393 * if no changes may be made to the contents of this buffer. 394 */ 395 public IntBuffer put(int[] src, int srcOffset, int intCount) { 396 if (isReadOnly()) { 397 throw new ReadOnlyBufferException(); 398 } 399 Arrays.checkOffsetAndCount(src.length, srcOffset, intCount); 400 if (intCount > remaining()) { 401 throw new BufferOverflowException(); 402 } 403 for (int i = srcOffset; i < srcOffset + intCount; ++i) { 404 put(src[i]); 405 } 406 return this; 407 } 408 409 /** 410 * Writes all the remaining ints of the {@code src} int buffer to this 411 * buffer's current position, and increases both buffers' position by the 412 * number of ints copied. 413 * 414 * @param src 415 * the source int buffer. 416 * @return this buffer. 417 * @throws BufferOverflowException 418 * if {@code src.remaining()} is greater than this buffer's 419 * {@code remaining()}. 420 * @throws IllegalArgumentException 421 * if {@code src} is this buffer. 422 * @throws ReadOnlyBufferException 423 * if no changes may be made to the contents of this buffer. 424 */ 425 public IntBuffer put(IntBuffer src) { 426 if (isReadOnly()) { 427 throw new ReadOnlyBufferException(); 428 } 429 if (src == this) { 430 throw new IllegalArgumentException("src == this"); 431 } 432 if (src.remaining() > remaining()) { 433 throw new BufferOverflowException(); 434 } 435 int[] contents = new int[src.remaining()]; 436 src.get(contents); 437 put(contents); 438 return this; 439 } 440 441 /** 442 * Write a int to the specified index of this buffer; the position is not 443 * changed. 444 * 445 * @param index 446 * the index, must not be negative and less than the limit. 447 * @param i 448 * the int to write. 449 * @return this buffer. 450 * @throws IndexOutOfBoundsException 451 * if index is invalid. 452 * @throws ReadOnlyBufferException 453 * if no changes may be made to the contents of this buffer. 454 */ 455 public abstract IntBuffer put(int index, int i); 456 457 /** 458 * Returns a sliced buffer that shares its content with this buffer. 459 * <p> 460 * The sliced buffer's capacity will be this buffer's {@code remaining()}, 461 * and its zero position will correspond to this buffer's current position. 462 * The new buffer's position will be 0, limit will be its capacity, and its 463 * mark is cleared. The new buffer's read-only property and byte order are 464 * same as this buffer's. 465 * <p> 466 * The new buffer shares its content with this buffer, which means either 467 * buffer's change of content will be visible to the other. The two buffers' 468 * position, limit and mark are independent. 469 */ 470 public abstract IntBuffer slice(); 471 } 472