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