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