001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.nio;
019:
020: /**
021: * A buffer of <code>float</code>s.
022: * <p>
023: * A float buffer can be created in either of the following ways:
024: * <ul>
025: * <li>{@link #allocate(int) Allocate} a new float array and create a buffer
026: * based on it;</li>
027: * <li>{@link #wrap(float[]) Wrap} an existing float array to create a new
028: * buffer;</li>
029: * <li>Use {@link java.nio.ByteBuffer#asFloatBuffer() ByteBuffer.asFloatBuffer}
030: * to create a float buffer based on a byte buffer.</li>
031: * </ul>
032: * </p>
033: */
034: public abstract class FloatBuffer extends Buffer implements
035: Comparable<FloatBuffer> {
036:
037: /**
038: * Creates a float buffer based on a new allocated float array.
039: *
040: * @param capacity
041: * The capacity of the new buffer
042: * @return The created float buffer
043: * @throws IllegalArgumentException
044: * If <code>capacity</code> is less than zero
045: */
046: public static FloatBuffer allocate(int capacity) {
047: if (capacity < 0) {
048: throw new IllegalArgumentException();
049: }
050: return BufferFactory.newFloatBuffer(capacity);
051: }
052:
053: /**
054: * Creates a new float buffer by wrapping the given float array.
055: * <p>
056: * Calling this method has the same effect as
057: * <code>wrap(array, 0, array.length)</code>.
058: * </p>
059: *
060: * @param array
061: * The float array which the new buffer will be based on
062: * @return The created float buffer
063: */
064: public static FloatBuffer wrap(float[] array) {
065: return wrap(array, 0, array.length);
066: }
067:
068: /**
069: * Creates new a float buffer by wrapping the given float array.
070: * <p>
071: * The new buffer's position will be <code>start</code>, limit will be
072: * <code>start + len</code>, capacity will be the length of the array.
073: * </p>
074: *
075: * @param array
076: * The float array which the new buffer will be based on
077: * @param start
078: * The start index, must be no less than zero and no greater than
079: * <code>array.length</code>
080: * @param len
081: * The length, must be no less than zero and no greater than
082: * <code>array.length - start</code>
083: * @return The created float buffer
084: * @exception IndexOutOfBoundsException
085: * If either <code>start</code> or <code>len</code> is
086: * invalid
087: */
088: public static FloatBuffer wrap(float[] array, int start, int len) {
089: if (array == null) {
090: throw new NullPointerException();
091: }
092: if (start < 0 || len < 0
093: || (long) start + (long) len > array.length) {
094: throw new IndexOutOfBoundsException();
095: }
096:
097: FloatBuffer buf = BufferFactory.newFloatBuffer(array);
098: buf.position = start;
099: buf.limit = start + len;
100:
101: return buf;
102: }
103:
104: /**
105: * Constructs a <code>FloatBuffer</code> with given capacity.
106: *
107: * @param capacity
108: * The capacity of the buffer
109: */
110: FloatBuffer(int capacity) {
111: super (capacity);
112: }
113:
114: /**
115: * Returns the float array which this buffer is based on, if there's one.
116: *
117: * @return The float array which this buffer is based on
118: * @exception ReadOnlyBufferException
119: * If this buffer is based on an array, but it is readonly
120: * @exception UnsupportedOperationException
121: * If this buffer is not based on an array
122: */
123: public final float[] array() {
124: return protectedArray();
125: }
126:
127: /**
128: * Returns the offset of the float array which this buffer is based on, if
129: * there's one.
130: * <p>
131: * The offset is the index of the array corresponds to the zero position of
132: * the buffer.
133: * </p>
134: *
135: * @return The offset of the float array which this buffer is based on
136: * @exception ReadOnlyBufferException
137: * If this buffer is based on an array, but it is readonly
138: * @exception UnsupportedOperationException
139: * If this buffer is not based on an array
140: */
141: public final int arrayOffset() {
142: return protectedArrayOffset();
143: }
144:
145: /**
146: * Returns a readonly buffer that shares content with this buffer.
147: * <p>
148: * The returned buffer is guaranteed to be a new instance, even this buffer
149: * is readonly itself. The new buffer's position, limit, capacity and mark
150: * are the same as this buffer.
151: * </p>
152: * <p>
153: * The new buffer shares content with this buffer, which means this buffer's
154: * change of content will be visible to the new buffer. The two buffer's
155: * position, limit and mark are independent.
156: * </p>
157: *
158: * @return A readonly version of this buffer.
159: */
160: public abstract FloatBuffer asReadOnlyBuffer();
161:
162: /**
163: * Compacts this float buffer.
164: * <p>
165: * The remaining <code>float</code>s will be moved to the head of the
166: * buffer, staring from position zero. Then the position is set to
167: * <code>remaining()</code>; the limit is set to capacity; the mark is
168: * cleared.
169: * </p>
170: *
171: * @return This buffer
172: * @exception ReadOnlyBufferException
173: * If no changes may be made to the contents of this buffer
174: */
175: public abstract FloatBuffer compact();
176:
177: /**
178: * Compare the remaining <code>float</code>s of this buffer to another
179: * float buffer's remaining <code>float</code>s.
180: *
181: * @param otherBuffer
182: * Another float buffer
183: * @return a negative value if this is less than <code>other</code>; 0 if
184: * this equals to <code>other</code>; a positive value if this is
185: * greater than <code>other</code>
186: * @exception ClassCastException
187: * If <code>other</code> is not a float buffer
188: */
189: public int compareTo(FloatBuffer otherBuffer) {
190: int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
191: : otherBuffer.remaining();
192: int this Pos = position;
193: int otherPos = otherBuffer.position;
194: float this Float, otherFloat;
195: while (compareRemaining > 0) {
196: this Float = get(this Pos);
197: otherFloat = otherBuffer.get(otherPos);
198: // checks for float and NaN inequality
199: if ((this Float != otherFloat)
200: && ((this Float == this Float) || (otherFloat == otherFloat))) {
201: return this Float < otherFloat ? -1 : 1;
202: }
203: this Pos++;
204: otherPos++;
205: compareRemaining--;
206: }
207: return remaining() - otherBuffer.remaining();
208: }
209:
210: /**
211: * Returns a duplicated buffer that shares content with this buffer.
212: * <p>
213: * The duplicated buffer's position, limit, capacity and mark are the same
214: * as this buffer. The duplicated buffer's readonly property and byte order
215: * are same as this buffer too.
216: * </p>
217: * <p>
218: * The new buffer shares content with this buffer, which means either
219: * buffer's change of content will be visible to the other. The two buffer's
220: * position, limit and mark are independent.
221: * </p>
222: *
223: * @return A duplicated buffer that shares content with this buffer.
224: */
225: public abstract FloatBuffer duplicate();
226:
227: /**
228: * Tests whether this float buffer equals to another object.
229: * <p>
230: * If <code>other</code> is not a float buffer, then false is returned.
231: * </p>
232: * <p>
233: * Two float buffers are equals if, and only if, their remaining
234: * <code>float</code>s are exactly the same. Position, limit, capacity
235: * and mark are not considered.
236: * </p>
237: *
238: * @param other
239: * the object to be compared against
240: * @return Whether this float buffer equals to another object.
241: */
242: @Override
243: public boolean equals(Object other) {
244: if (!(other instanceof FloatBuffer)) {
245: return false;
246: }
247: FloatBuffer otherBuffer = (FloatBuffer) other;
248:
249: if (remaining() != otherBuffer.remaining()) {
250: return false;
251: }
252:
253: int myPosition = position;
254: int otherPosition = otherBuffer.position;
255: boolean equalSoFar = true;
256: while (equalSoFar && (myPosition < limit)) {
257: equalSoFar = get(myPosition++) == otherBuffer
258: .get(otherPosition++);
259: }
260:
261: return equalSoFar;
262: }
263:
264: /**
265: * Returns the float at the current position and increase the position by 1.
266: *
267: * @return The float at the current position.
268: * @exception BufferUnderflowException
269: * If the position is equal or greater than limit
270: */
271: public abstract float get();
272:
273: /**
274: * Reads <code>float</code>s from the current position into the specified
275: * float array and increase the position by the number of <code>float</code>s
276: * read.
277: * <p>
278: * Calling this method has the same effect as
279: * <code>get(dest, 0, dest.length)</code>.
280: * </p>
281: *
282: * @param dest
283: * The destination float array
284: * @return This buffer
285: * @exception BufferUnderflowException
286: * if <code>dest.length</code> is greater than
287: * <code>remaining()</code>
288: */
289: public FloatBuffer get(float[] dest) {
290: return get(dest, 0, dest.length);
291: }
292:
293: /**
294: * Reads <code>float</code>s from the current position into the specified
295: * float array, starting from the specified offset, and increase the
296: * position by the number of <code>float</code>s read.
297: *
298: * @param dest
299: * The target float array
300: * @param off
301: * The offset of the float array, must be no less than zero and
302: * no greater than <code>dest.length</code>
303: * @param len
304: * The number of <code>float</code>s to read, must be no less
305: * than zero and no greater than <code>dest.length - off</code>
306: * @return This buffer
307: * @exception IndexOutOfBoundsException
308: * If either <code>off</code> or <code>len</code> is
309: * invalid
310: * @exception BufferUnderflowException
311: * If <code>len</code> is greater than
312: * <code>remaining()</code>
313: */
314: public FloatBuffer get(float[] dest, int off, int len) {
315: int length = dest.length;
316: if (off < 0 || len < 0 || (long) off + (long) len > length) {
317: throw new IndexOutOfBoundsException();
318: }
319:
320: if (len > remaining()) {
321: throw new BufferUnderflowException();
322: }
323: for (int i = off; i < off + len; i++) {
324: dest[i] = get();
325: }
326: return this ;
327: }
328:
329: /**
330: * Returns a float at the specified index, and the position is not changed.
331: *
332: * @param index
333: * The index, must be no less than zero and less than limit
334: * @return A float at the specified index.
335: * @exception IndexOutOfBoundsException
336: * If index is invalid
337: */
338: public abstract float get(int index);
339:
340: /**
341: * Returns whether this buffer is based on a float array and is read/write.
342: * <p>
343: * If this buffer is readonly, then false is returned.
344: * </p>
345: *
346: * @return Whether this buffer is based on a float array and is read/write.
347: */
348: public final boolean hasArray() {
349: return protectedHasArray();
350: }
351:
352: /**
353: * Hash code is calculated from the remaining <code>float</code>s.
354: * <p>
355: * Position, limit, capacity and mark don't affect the hash code.
356: * </p>
357: *
358: * @return The hash code calculated from the remaining <code>float</code>s.
359: */
360: @Override
361: public int hashCode() {
362: int myPosition = position;
363: int hash = 0;
364: while (myPosition < limit) {
365: hash = hash + Float.floatToIntBits(get(myPosition++));
366: }
367: return hash;
368: }
369:
370: /**
371: * Returns true if this buffer is direct.
372: * <p>
373: * A direct buffer will try its best to take advantage of native memory APIs
374: * and it may not stay in java heap, thus not affected by GC.
375: * </p>
376: * <p>
377: * A float buffer is direct, if it is based on a byte buffer and the byte
378: * buffer is direct.
379: * </p>
380: *
381: * @return True if this buffer is direct.
382: */
383: public abstract boolean isDirect();
384:
385: /**
386: * Returns the byte order used by this buffer when converting
387: * <code>float</code>s from/to <code>byte</code>s.
388: * <p>
389: * If this buffer is not based on a byte buffer, then always return the
390: * platform's native byte order.
391: * </p>
392: *
393: * @return The byte order used by this buffer when converting
394: * <code>float</code>s from/to <code>byte</code>s.
395: */
396: public abstract ByteOrder order();
397:
398: /**
399: * Child class implements this method to realize <code>array()</code>.
400: *
401: * @return see <code>array()</code>
402: */
403: abstract float[] protectedArray();
404:
405: /**
406: * Child class implements this method to realize <code>arrayOffset()</code>.
407: *
408: * @return see <code>arrayOffset()</code>
409: */
410: abstract int protectedArrayOffset();
411:
412: /**
413: * Child class implements this method to realize <code>hasArray()</code>.
414: *
415: * @return see <code>hasArray()</code>
416: */
417: abstract boolean protectedHasArray();
418:
419: /**
420: * Writes the given float to the current position and increase the position
421: * by 1.
422: *
423: * @param f
424: * The float to write
425: * @return This buffer
426: * @exception BufferOverflowException
427: * If position is equal or greater than limit
428: * @exception ReadOnlyBufferException
429: * If no changes may be made to the contents of this buffer
430: */
431: public abstract FloatBuffer put(float f);
432:
433: /**
434: * Writes <code>float</code>s in the given float array to the current
435: * position and increase the position by the number of <code>float</code>s
436: * written.
437: * <p>
438: * Calling this method has the same effect as
439: * <code>put(src, 0, src.length)</code>.
440: * </p>
441: *
442: * @param src
443: * The source float array
444: * @return This buffer
445: * @exception BufferOverflowException
446: * If <code>remaining()</code> is less than
447: * <code>src.length</code>
448: * @exception ReadOnlyBufferException
449: * If no changes may be made to the contents of this buffer
450: */
451: public final FloatBuffer put(float[] src) {
452: return put(src, 0, src.length);
453: }
454:
455: /**
456: * Writes <code>float</code>s in the given float array, starting from the
457: * specified offset, to the current position and increase the position by
458: * the number of <code>float</code>s written.
459: *
460: * @param src
461: * The source float array
462: * @param off
463: * The offset of float array, must be no less than zero and no
464: * greater than <code>src.length</code>
465: * @param len
466: * The number of <code>float</code>s to write, must be no less
467: * than zero and no greater than <code>src.length - off</code>
468: * @return This buffer
469: * @exception BufferOverflowException
470: * If <code>remaining()</code> is less than
471: * <code>len</code>
472: * @exception IndexOutOfBoundsException
473: * If either <code>off</code> or <code>len</code> is
474: * invalid
475: * @exception ReadOnlyBufferException
476: * If no changes may be made to the contents of this buffer
477: */
478: public FloatBuffer put(float[] src, int off, int len) {
479: int length = src.length;
480: if (off < 0 || len < 0 || (long) off + (long) len > length) {
481: throw new IndexOutOfBoundsException();
482: }
483:
484: if (len > remaining()) {
485: throw new BufferOverflowException();
486: }
487: for (int i = off; i < off + len; i++) {
488: put(src[i]);
489: }
490: return this ;
491: }
492:
493: /**
494: * Writes all the remaining <code>float</code>s of the <code>src</code>
495: * float buffer to this buffer's current position, and increase both
496: * buffers' position by the number of <code>float</code>s copied.
497: *
498: * @param src
499: * The source float buffer
500: * @return This buffer
501: * @exception BufferOverflowException
502: * If <code>src.remaining()</code> is greater than this
503: * buffer's <code>remaining()</code>
504: * @exception IllegalArgumentException
505: * If <code>src</code> is this buffer
506: * @exception ReadOnlyBufferException
507: * If no changes may be made to the contents of this buffer
508: */
509: public FloatBuffer put(FloatBuffer src) {
510: if (src == this ) {
511: throw new IllegalArgumentException();
512: }
513: if (src.remaining() > remaining()) {
514: throw new BufferOverflowException();
515: }
516: float[] contents = new float[src.remaining()];
517: src.get(contents);
518: put(contents);
519: return this ;
520: }
521:
522: /**
523: * Write a float to the specified index of this buffer and the position is
524: * not changed.
525: *
526: * @param index
527: * The index, must be no less than zero and less than the limit
528: * @param f
529: * The float to write
530: * @return This buffer
531: * @exception IndexOutOfBoundsException
532: * If index is invalid
533: * @exception ReadOnlyBufferException
534: * If no changes may be made to the contents of this buffer
535: */
536: public abstract FloatBuffer put(int index, float f);
537:
538: /**
539: * Returns a sliced buffer that shares content with this buffer.
540: * <p>
541: * The sliced buffer's capacity will be this buffer's
542: * <code>remaining()</code>, and its zero position will correspond to
543: * this buffer's current position. The new buffer's position will be 0,
544: * limit will be its capacity, and its mark is unset. The new buffer's
545: * readonly property and byte order are same as this buffer.
546: * </p>
547: * <p>
548: * The new buffer shares content with this buffer, which means either
549: * buffer's change of content will be visible to the other. The two buffer's
550: * position, limit and mark are independent.
551: * </p>
552: *
553: * @return A sliced buffer that shares content with this buffer.
554: */
555: public abstract FloatBuffer slice();
556:
557: /**
558: * Returns a string represents the state of this float buffer.
559: *
560: * @return A string represents the state of this float buffer.
561: */
562: @Override
563: public String toString() {
564: StringBuffer buf = new StringBuffer();
565: buf.append(getClass().getName());
566: buf.append(", status: capacity="); //$NON-NLS-1$
567: buf.append(capacity());
568: buf.append(" position="); //$NON-NLS-1$
569: buf.append(position());
570: buf.append(" limit="); //$NON-NLS-1$
571: buf.append(limit());
572: return buf.toString();
573: }
574: }
|