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