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