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