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 18package java.nio; 19 20/** 21 * A buffer of shorts. 22 * <p> 23 * A short buffer can be created in either of the following ways: 24 * <ul> 25 * <li>{@link #allocate(int) Allocate} a new short array and create a buffer 26 * based on it;</li> 27 * <li>{@link #wrap(short[]) Wrap} an existing short array to create a new 28 * buffer;</li> 29 * <li>Use {@link java.nio.ByteBuffer#asShortBuffer() ByteBuffer.asShortBuffer} 30 * to create a short buffer based on a byte buffer.</li> 31 * </ul> 32 */ 33public abstract class ShortBuffer extends Buffer implements 34 Comparable<ShortBuffer> { 35 36 /** 37 * Creates a short buffer based on a newly allocated short array. 38 * 39 * @param capacity 40 * the capacity of the new buffer. 41 * @return the created short buffer. 42 * @throws IllegalArgumentException 43 * if {@code capacity} is less than zero. 44 */ 45 public static ShortBuffer allocate(int capacity) { 46 if (capacity < 0) { 47 throw new IllegalArgumentException(); 48 } 49 return BufferFactory.newShortBuffer(capacity); 50 } 51 52 /** 53 * Creates a new short buffer by wrapping the given short 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 short array which the new buffer will be based on. 60 * @return the created short buffer. 61 */ 62 public static ShortBuffer wrap(short[] array) { 63 return wrap(array, 0, array.length); 64 } 65 66 /** 67 * Creates a new short buffer by wrapping the given short array. 68 * <p> 69 * The new buffer's position will be {@code start}, limit will be 70 * {@code start + len}, capacity will be the length of the array. 71 * 72 * @param array 73 * the short 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 len 78 * the length, must not be negative and not greater than 79 * {@code array.length - start}. 80 * @return the created short buffer. 81 * @exception IndexOutOfBoundsException 82 * if either {@code start} or {@code len} is invalid. 83 */ 84 public static ShortBuffer wrap(short[] array, int start, int len) { 85 if (array == null) { 86 throw new NullPointerException(); 87 } 88 if (start < 0 || len < 0 || (long) start + (long) len > array.length) { 89 throw new IndexOutOfBoundsException(); 90 } 91 92 ShortBuffer buf = BufferFactory.newShortBuffer(array); 93 buf.position = start; 94 buf.limit = start + len; 95 96 return buf; 97 } 98 99 /** 100 * Constructs a {@code ShortBuffer} with given capacity. 101 * 102 * @param capacity 103 * The capacity of the buffer 104 */ 105 ShortBuffer(int capacity) { 106 super(capacity); 107 // BEGIN android-added 108 _elementSizeShift = 1; 109 // END android-added 110 } 111 112 /** 113 * Returns the short array which this buffer is based on, if there is one. 114 * 115 * @return the short array which this buffer is based on. 116 * @exception ReadOnlyBufferException 117 * if this buffer is based on an array, but it is read-only. 118 * @exception UnsupportedOperationException 119 * if this buffer is not based on an array. 120 */ 121 public final short[] array() { 122 return protectedArray(); 123 } 124 125 /** 126 * Returns the offset of the short array which this buffer is based on, if 127 * there is one. 128 * <p> 129 * The offset is the index of the array corresponding to the zero position 130 * of the buffer. 131 * 132 * @return the offset of the short array which this buffer is based on. 133 * @exception ReadOnlyBufferException 134 * if this buffer is based on an array, but it is read-only. 135 * @exception UnsupportedOperationException 136 * if this buffer is not based on an array. 137 */ 138 public final int arrayOffset() { 139 return protectedArrayOffset(); 140 } 141 142 // BEGIN android-added 143 @Override Object _array() { 144 if (hasArray()) { 145 return array(); 146 } 147 return null; 148 } 149 150 @Override int _arrayOffset() { 151 if (hasArray()) { 152 return arrayOffset(); 153 } 154 return 0; 155 } 156 // END android-added 157 158 /** 159 * Returns a read-only buffer that shares its content with this buffer. 160 * <p> 161 * The returned buffer is guaranteed to be a new instance, even if this 162 * buffer is read-only itself. The new buffer's position, limit, capacity 163 * and mark are the same as this buffer's. 164 * <p> 165 * The new buffer shares its content with this buffer, which means this 166 * buffer's change of content will be visible to the new buffer. The two 167 * buffer's position, limit and mark are independent. 168 * 169 * @return a read-only version of this buffer. 170 */ 171 public abstract ShortBuffer asReadOnlyBuffer(); 172 173 /** 174 * Compacts this short buffer. 175 * <p> 176 * The remaining shorts will be moved to the head of the buffer, starting 177 * from position zero. Then the position is set to {@code remaining()}; the 178 * limit is set to capacity; the mark is cleared. 179 * 180 * @return this buffer. 181 * @exception ReadOnlyBufferException 182 * if no changes may be made to the contents of this buffer. 183 */ 184 public abstract ShortBuffer compact(); 185 186 /** 187 * Compare the remaining shorts of this buffer to another short buffer's 188 * remaining shorts. 189 * 190 * @param otherBuffer 191 * another short buffer. 192 * @return a negative value if this is less than {@code otherBuffer}; 0 if 193 * this equals to {@code otherBuffer}; a positive value if this is 194 * greater than {@code otherBuffer}. 195 * @exception ClassCastException 196 * if {@code otherBuffer} is not a short buffer. 197 */ 198 public int compareTo(ShortBuffer otherBuffer) { 199 int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining() 200 : otherBuffer.remaining(); 201 int thisPos = position; 202 int otherPos = otherBuffer.position; 203 short thisByte, otherByte; 204 while (compareRemaining > 0) { 205 thisByte = get(thisPos); 206 otherByte = otherBuffer.get(otherPos); 207 if (thisByte != otherByte) { 208 return thisByte < otherByte ? -1 : 1; 209 } 210 thisPos++; 211 otherPos++; 212 compareRemaining--; 213 } 214 return remaining() - otherBuffer.remaining(); 215 } 216 217 /** 218 * Returns a duplicated buffer that shares its content with this buffer. 219 * <p> 220 * The duplicated buffer's position, limit, capacity and mark are the same 221 * as this buffer. The duplicated buffer's read-only property and byte order 222 * are the same as this buffer's. 223 * <p> 224 * The new buffer shares its content with this buffer, which means either 225 * buffer's change of content will be visible to the other. The two buffer's 226 * position, limit and mark are independent. 227 * 228 * @return a duplicated buffer that shares its content with this buffer. 229 */ 230 public abstract ShortBuffer duplicate(); 231 232 /** 233 * Checks whether this short buffer is equal to another object. 234 * <p> 235 * If {@code other} is not a short buffer then {@code false} is returned. 236 * Two short buffers are equal if and only if their remaining shorts are 237 * exactly the same. Position, limit, capacity and mark are not considered. 238 * 239 * @param other 240 * the object to compare with this short buffer. 241 * @return {@code true} if this short buffer is equal to {@code other}, 242 * {@code false} otherwise. 243 */ 244 @Override 245 public boolean equals(Object other) { 246 if (!(other instanceof ShortBuffer)) { 247 return false; 248 } 249 ShortBuffer otherBuffer = (ShortBuffer) other; 250 251 if (remaining() != otherBuffer.remaining()) { 252 return false; 253 } 254 255 int myPosition = position; 256 int otherPosition = otherBuffer.position; 257 boolean equalSoFar = true; 258 while (equalSoFar && (myPosition < limit)) { 259 equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++); 260 } 261 262 return equalSoFar; 263 } 264 265 /** 266 * Returns the short at the current position and increases the position by 267 * 1. 268 * 269 * @return the short at the current position. 270 * @exception BufferUnderflowException 271 * if the position is equal or greater than limit. 272 */ 273 public abstract short get(); 274 275 /** 276 * Reads shorts from the current position into the specified short array and 277 * increases the position by the number of shorts read. 278 * <p> 279 * Calling this method has the same effect as 280 * {@code get(dest, 0, dest.length)}. 281 * 282 * @param dest 283 * the destination short array. 284 * @return this buffer. 285 * @exception BufferUnderflowException 286 * if {@code dest.length} is greater than {@code remaining()}. 287 */ 288 public ShortBuffer get(short[] dest) { 289 return get(dest, 0, dest.length); 290 } 291 292 /** 293 * Reads shorts from the current position into the specified short array, 294 * starting from the specified offset, and increases the position by the 295 * number of shorts read. 296 * 297 * @param dest 298 * the target short array. 299 * @param off 300 * the offset of the short array, must not be negative and not 301 * greater than {@code dest.length}. 302 * @param len 303 * the number of shorts to read, must be no less than zero and 304 * not greater than {@code dest.length - off}. 305 * @return this buffer. 306 * @exception IndexOutOfBoundsException 307 * if either {@code off} or {@code len} is invalid. 308 * @exception BufferUnderflowException 309 * if {@code len} is greater than {@code remaining()}. 310 */ 311 public ShortBuffer get(short[] dest, int off, int len) { 312 int length = dest.length; 313 if (off < 0 || len < 0 || (long) off + (long) len > length) { 314 throw new IndexOutOfBoundsException(); 315 } 316 if (len > remaining()) { 317 throw new BufferUnderflowException(); 318 } 319 for (int i = off; i < off + len; i++) { 320 dest[i] = get(); 321 } 322 return this; 323 } 324 325 /** 326 * Returns the short at the specified index; the position is not changed. 327 * 328 * @param index 329 * the index, must not be negative and less than limit. 330 * @return a short at the specified index. 331 * @exception IndexOutOfBoundsException 332 * if index is invalid. 333 */ 334 public abstract short get(int index); 335 336 /** 337 * Indicates whether this buffer is based on a short array and is 338 * read/write. 339 * 340 * @return {@code true} if this buffer is based on a short array and 341 * provides read/write access, {@code false} otherwise. 342 */ 343 public final boolean hasArray() { 344 return protectedHasArray(); 345 } 346 347 /** 348 * Calculates this buffer's hash code from the remaining chars. The 349 * position, limit, capacity and mark don't affect the hash code. 350 * 351 * @return the hash code calculated from the remaining shorts. 352 */ 353 @Override 354 public int hashCode() { 355 int myPosition = position; 356 int hash = 0; 357 while (myPosition < limit) { 358 hash = hash + get(myPosition++); 359 } 360 return hash; 361 } 362 363 /** 364 * Indicates whether this buffer is direct. A direct buffer will try its 365 * best to take advantage of native memory APIs and it may not stay in the 366 * Java heap, so it is not affected by garbage collection. 367 * <p> 368 * A short buffer is direct if it is based on a byte buffer and the byte 369 * buffer is direct. 370 * 371 * @return {@code true} if this buffer is direct, {@code false} otherwise. 372 */ 373 public abstract boolean isDirect(); 374 375 /** 376 * Returns the byte order used by this buffer when converting shorts from/to 377 * bytes. 378 * <p> 379 * If this buffer is not based on a byte buffer, then always return the 380 * platform's native byte order. 381 * 382 * @return the byte order used by this buffer when converting shorts from/to 383 * bytes. 384 */ 385 public abstract ByteOrder order(); 386 387 /** 388 * Child class implements this method to realize {@code array()}. 389 * 390 * @return see {@code array()} 391 */ 392 abstract short[] protectedArray(); 393 394 /** 395 * Child class implements this method to realize {@code arrayOffset()}. 396 * 397 * @return see {@code arrayOffset()} 398 */ 399 abstract int protectedArrayOffset(); 400 401 /** 402 * Child class implements this method to realize {@code hasArray()}. 403 * 404 * @return see {@code hasArray()} 405 */ 406 abstract boolean protectedHasArray(); 407 408 /** 409 * Writes the given short to the current position and increases the position 410 * by 1. 411 * 412 * @param s 413 * the short to write. 414 * @return this buffer. 415 * @exception BufferOverflowException 416 * if position is equal or greater than limit. 417 * @exception ReadOnlyBufferException 418 * if no changes may be made to the contents of this buffer. 419 */ 420 public abstract ShortBuffer put(short s); 421 422 /** 423 * Writes shorts from the given short array to the current position and 424 * increases the position by the number of shorts written. 425 * <p> 426 * Calling this method has the same effect as 427 * {@code put(src, 0, src.length)}. 428 * 429 * @param src 430 * the source short array. 431 * @return this buffer. 432 * @exception BufferOverflowException 433 * if {@code remaining()} is less than {@code src.length}. 434 * @exception ReadOnlyBufferException 435 * if no changes may be made to the contents of this buffer. 436 */ 437 public final ShortBuffer put(short[] src) { 438 return put(src, 0, src.length); 439 } 440 441 /** 442 * Writes shorts from the given short array, starting from the specified 443 * offset, to the current position and increases the position by the number 444 * of shorts written. 445 * 446 * @param src 447 * the source short array. 448 * @param off 449 * the offset of short array, must not be negative and not 450 * greater than {@code src.length}. 451 * @param len 452 * the number of shorts to write, must be no less than zero and 453 * not greater than {@code src.length - off}. 454 * @return this buffer. 455 * @exception BufferOverflowException 456 * if {@code remaining()} is less than {@code len}. 457 * @exception IndexOutOfBoundsException 458 * if either {@code off} or {@code len} is invalid. 459 * @exception ReadOnlyBufferException 460 * if no changes may be made to the contents of this buffer. 461 */ 462 public ShortBuffer put(short[] src, int off, int len) { 463 int length = src.length; 464 if (off < 0 || len < 0 || (long) off + (long) len > length) { 465 throw new IndexOutOfBoundsException(); 466 } 467 468 if (len > remaining()) { 469 throw new BufferOverflowException(); 470 } 471 for (int i = off; i < off + len; i++) { 472 put(src[i]); 473 } 474 return this; 475 } 476 477 /** 478 * Writes all the remaining shorts of the {@code src} short buffer to this 479 * buffer's current position, and increases both buffers' position by the 480 * number of shorts copied. 481 * 482 * @param src 483 * the source short buffer. 484 * @return this buffer. 485 * @exception BufferOverflowException 486 * if {@code src.remaining()} is greater than this buffer's 487 * {@code remaining()}. 488 * @exception IllegalArgumentException 489 * if {@code src} is this buffer. 490 * @exception ReadOnlyBufferException 491 * if no changes may be made to the contents of this buffer. 492 */ 493 public ShortBuffer put(ShortBuffer src) { 494 if (src == this) { 495 throw new IllegalArgumentException(); 496 } 497 if (src.remaining() > remaining()) { 498 throw new BufferOverflowException(); 499 } 500 short[] contents = new short[src.remaining()]; 501 src.get(contents); 502 put(contents); 503 return this; 504 } 505 506 /** 507 * Writes a short to the specified index of this buffer; the position is not 508 * changed. 509 * 510 * @param index 511 * the index, must not be negative and less than the limit. 512 * @param s 513 * the short to write. 514 * @return this buffer. 515 * @exception IndexOutOfBoundsException 516 * if index is invalid. 517 * @exception ReadOnlyBufferException 518 * if no changes may be made to the contents of this buffer. 519 */ 520 public abstract ShortBuffer put(int index, short s); 521 522 /** 523 * Returns a sliced buffer that shares its content with this buffer. 524 * <p> 525 * The sliced buffer's capacity will be this buffer's {@code remaining()}, 526 * and its zero position will correspond to this buffer's current position. 527 * The new buffer's position will be 0, limit will be its capacity, and its 528 * mark is cleared. The new buffer's read-only property and byte order are 529 * same as this buffer's. 530 * <p> 531 * The new buffer shares its content with this buffer, which means either 532 * buffer's change of content will be visible to the other. The two buffer's 533 * position, limit and mark are independent. 534 * 535 * @return a sliced buffer that shares its content with this buffer. 536 */ 537 public abstract ShortBuffer slice(); 538 539 /** 540 * Returns a string representing the state of this short buffer. 541 * 542 * @return a string representing the state of this short buffer. 543 */ 544 @Override 545 public String toString() { 546 StringBuilder buf = new StringBuilder(); 547 buf.append(getClass().getName()); 548 buf.append(", status: capacity="); //$NON-NLS-1$ 549 buf.append(capacity()); 550 buf.append(" position="); //$NON-NLS-1$ 551 buf.append(position()); 552 buf.append(" limit="); //$NON-NLS-1$ 553 buf.append(limit()); 554 return buf.toString(); 555 } 556} 557