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 */ 47 public static LongBuffer allocate(int capacity) { 48 if (capacity < 0) { 49 throw new IllegalArgumentException("capacity < 0: " + capacity); 50 } 51 return new LongArrayBuffer(new long[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 */ 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 * @throws IndexOutOfBoundsException 84 * if either {@code start} or {@code longCount} is invalid. 85 */ 86 public static LongBuffer wrap(long[] array, int start, int longCount) { 87 Arrays.checkOffsetAndCount(array.length, start, longCount); 88 LongBuffer buf = new LongArrayBuffer(array); 89 buf.position = start; 90 buf.limit = start + longCount; 91 return buf; 92 } 93 94 LongBuffer(int capacity, long effectiveDirectAddress) { 95 super(3, capacity, effectiveDirectAddress); 96 } 97 98 public final long[] 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 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 * @throws ReadOnlyBufferException 130 * if no changes may be made to the contents of this buffer. 131 */ 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 * @throws ClassCastException 144 * if {@code otherBuffer} is not a long buffer. 145 */ 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 buffers' 174 * position, limit and mark are independent. 175 */ 176 public abstract LongBuffer duplicate(); 177 178 /** 179 * Checks whether this long buffer is equal to another object. 180 * <p> 181 * If {@code other} is not a long buffer then {@code false} is returned. Two 182 * long buffers are equal if and only if their remaining longs are exactly 183 * the same. Position, limit, capacity and mark are not considered. 184 * 185 * @param other 186 * the object to compare with this long buffer. 187 * @return {@code true} if this long buffer is equal to {@code other}, 188 * {@code false} otherwise. 189 */ 190 @Override 191 public boolean equals(Object other) { 192 if (!(other instanceof LongBuffer)) { 193 return false; 194 } 195 LongBuffer otherBuffer = (LongBuffer) 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 long at the current position and increase the position by 1. 213 * 214 * @return the long at the current position. 215 * @throws BufferUnderflowException 216 * if the position is equal or greater than limit. 217 */ 218 public abstract long get(); 219 220 /** 221 * Reads longs from the current position into the specified long array and 222 * increases the position by the number of longs read. 223 * <p> 224 * Calling this method has the same effect as 225 * {@code get(dst, 0, dst.length)}. 226 * 227 * @param dst 228 * the destination long array. 229 * @return this buffer. 230 * @throws BufferUnderflowException 231 * if {@code dst.length} is greater than {@code remaining()}. 232 */ 233 public LongBuffer get(long[] dst) { 234 return get(dst, 0, dst.length); 235 } 236 237 /** 238 * Reads longs from the current position into the specified long array, 239 * starting from the specified offset, and increase the position by the 240 * number of longs read. 241 * 242 * @param dst 243 * the target long array. 244 * @param dstOffset 245 * the offset of the long array, must not be negative and not 246 * greater than {@code dst.length}. 247 * @param longCount 248 * the number of longs to read, must be no less than zero and not 249 * greater than {@code dst.length - dstOffset}. 250 * @return this buffer. 251 * @throws IndexOutOfBoundsException 252 * if either {@code dstOffset} or {@code longCount} is invalid. 253 * @throws BufferUnderflowException 254 * if {@code longCount} is greater than {@code remaining()}. 255 */ 256 public LongBuffer get(long[] dst, int dstOffset, int longCount) { 257 Arrays.checkOffsetAndCount(dst.length, dstOffset, longCount); 258 if (longCount > remaining()) { 259 throw new BufferUnderflowException(); 260 } 261 for (int i = dstOffset; i < dstOffset + longCount; ++i) { 262 dst[i] = get(); 263 } 264 return this; 265 } 266 267 /** 268 * Returns the long at the specified index; the position is not changed. 269 * 270 * @param index 271 * the index, must not be negative and less than limit. 272 * @return the long at the specified index. 273 * @throws IndexOutOfBoundsException 274 * if index is invalid. 275 */ 276 public abstract long get(int index); 277 278 public final boolean hasArray() { 279 return protectedHasArray(); 280 } 281 282 /** 283 * Calculates this buffer's hash code from the remaining chars. The 284 * position, limit, capacity and mark don't affect the hash code. 285 * 286 * @return the hash code calculated from the remaining longs. 287 */ 288 @Override 289 public int hashCode() { 290 int myPosition = position; 291 int hash = 0; 292 long l; 293 while (myPosition < limit) { 294 l = get(myPosition++); 295 hash = hash + ((int) l) ^ ((int) (l >> 32)); 296 } 297 return hash; 298 } 299 300 /** 301 * Indicates whether this buffer is direct. A direct buffer will try its 302 * best to take advantage of native memory APIs and it may not stay in the 303 * Java heap, so it is not affected by garbage collection. 304 * <p> 305 * A long buffer is direct if it is based on a byte buffer and the byte 306 * buffer is direct. 307 * 308 * @return {@code true} if this buffer is direct, {@code false} otherwise. 309 */ 310 public abstract boolean isDirect(); 311 312 /** 313 * Returns the byte order used by this buffer when converting longs from/to 314 * bytes. 315 * <p> 316 * If this buffer is not based on a byte buffer, then always return the 317 * platform's native byte order. 318 * 319 * @return the byte order used by this buffer when converting longs from/to 320 * bytes. 321 */ 322 public abstract ByteOrder order(); 323 324 /** 325 * Child class implements this method to realize {@code array()}. 326 * 327 * @return see {@code array()} 328 */ 329 abstract long[] protectedArray(); 330 331 /** 332 * Child class implements this method to realize {@code arrayOffset()}. 333 * 334 * @return see {@code arrayOffset()} 335 */ 336 abstract int protectedArrayOffset(); 337 338 /** 339 * Child class implements this method to realize {@code hasArray()}. 340 * 341 * @return see {@code hasArray()} 342 */ 343 abstract boolean protectedHasArray(); 344 345 /** 346 * Writes the given long to the current position and increases the position 347 * by 1. 348 * 349 * @param l 350 * the long to write. 351 * @return this buffer. 352 * @throws BufferOverflowException 353 * if position is equal or greater than limit. 354 * @throws ReadOnlyBufferException 355 * if no changes may be made to the contents of this buffer. 356 */ 357 public abstract LongBuffer put(long l); 358 359 /** 360 * Writes longs from the given long array to the current position and 361 * increases the position by the number of longs written. 362 * <p> 363 * Calling this method has the same effect as 364 * {@code put(src, 0, src.length)}. 365 * 366 * @param src 367 * the source long array. 368 * @return this buffer. 369 * @throws BufferOverflowException 370 * if {@code remaining()} is less than {@code src.length}. 371 * @throws ReadOnlyBufferException 372 * if no changes may be made to the contents of this buffer. 373 */ 374 public final LongBuffer put(long[] src) { 375 return put(src, 0, src.length); 376 } 377 378 /** 379 * Writes longs from the given long array, starting from the specified 380 * offset, to the current position and increases the position by the number 381 * of longs written. 382 * 383 * @param src 384 * the source long array. 385 * @param srcOffset 386 * the offset of long array, must not be negative and not greater 387 * than {@code src.length}. 388 * @param longCount 389 * the number of longs to write, must be no less than zero and 390 * not greater than {@code src.length - srcOffset}. 391 * @return this buffer. 392 * @throws BufferOverflowException 393 * if {@code remaining()} is less than {@code longCount}. 394 * @throws IndexOutOfBoundsException 395 * if either {@code srcOffset} or {@code longCount} is invalid. 396 * @throws ReadOnlyBufferException 397 * if no changes may be made to the contents of this buffer. 398 */ 399 public LongBuffer put(long[] src, int srcOffset, int longCount) { 400 Arrays.checkOffsetAndCount(src.length, srcOffset, longCount); 401 if (longCount > remaining()) { 402 throw new BufferOverflowException(); 403 } 404 for (int i = srcOffset; i < srcOffset + longCount; ++i) { 405 put(src[i]); 406 } 407 return this; 408 } 409 410 /** 411 * Writes all the remaining longs of the {@code src} long buffer to this 412 * buffer's current position, and increases both buffers' position by the 413 * number of longs copied. 414 * 415 * @param src 416 * the source long buffer. 417 * @return this buffer. 418 * @throws BufferOverflowException 419 * if {@code src.remaining()} is greater than this buffer's 420 * {@code remaining()}. 421 * @throws IllegalArgumentException 422 * if {@code src} is this buffer. 423 * @throws ReadOnlyBufferException 424 * if no changes may be made to the contents of this buffer. 425 */ 426 public LongBuffer put(LongBuffer src) { 427 if (isReadOnly()) { 428 throw new ReadOnlyBufferException(); 429 } 430 if (src == this) { 431 throw new IllegalArgumentException("src == this"); 432 } 433 if (src.remaining() > remaining()) { 434 throw new BufferOverflowException(); 435 } 436 long[] contents = new long[src.remaining()]; 437 src.get(contents); 438 put(contents); 439 return this; 440 } 441 442 /** 443 * Writes a long to the specified index of this buffer; the position is not 444 * changed. 445 * 446 * @param index 447 * the index, must not be negative and less than the limit. 448 * @param l 449 * the long to write. 450 * @return this buffer. 451 * @throws IndexOutOfBoundsException 452 * if index is invalid. 453 * @throws ReadOnlyBufferException 454 * if no changes may be made to the contents of this buffer. 455 */ 456 public abstract LongBuffer put(int index, long l); 457 458 /** 459 * Returns a sliced buffer that shares its content with this buffer. 460 * <p> 461 * The sliced buffer's capacity will be this buffer's {@code remaining()}, 462 * and its zero position will correspond to this buffer's current position. 463 * The new buffer's position will be 0, limit will be its capacity, and its 464 * mark is cleared. The new buffer's read-only property and byte order are 465 * same as this buffer's. 466 * <p> 467 * The new buffer shares its content with this buffer, which means either 468 * buffer's change of content will be visible to the other. The two buffers' 469 * position, limit and mark are independent. 470 */ 471 public abstract LongBuffer slice(); 472 } 473