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>long</code>s.
022: * <p>
023: * A long buffer can be created in either of the following ways:
024: * <ul>
025: * <li>{@link #allocate(int) Allocate} a new long array and create a buffer
026: * based on it;</li>
027: * <li>{@link #wrap(long[]) Wrap} an existing long array to create a new
028: * buffer;</li>
029: * <li>Use {@link java.nio.ByteBuffer#asLongBuffer() ByteBuffer.asLongBuffer}
030: * to create a long buffer based on a byte buffer.</li>
031: * </ul>
032: * </p>
033: */
034: public abstract class LongBuffer extends Buffer implements
035: Comparable<LongBuffer> {
036:
037: /**
038: * Creates a long buffer based on a new allocated long array.
039: *
040: * @param capacity
041: * The capacity of the new buffer
042: * @return The created long buffer
043: * @throws IllegalArgumentException
044: * If <code>capacity</code> is less than zero
045: */
046: public static LongBuffer allocate(int capacity) {
047: if (capacity < 0) {
048: throw new IllegalArgumentException();
049: }
050: return BufferFactory.newLongBuffer(capacity);
051: }
052:
053: /**
054: * Creates a new long buffer by wrapping the given long 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 long array which the new buffer will be based on
062: * @return The created long buffer
063: */
064: public static LongBuffer wrap(long[] array) {
065: return wrap(array, 0, array.length);
066: }
067:
068: /**
069: * Creates new a long buffer by wrapping the given long 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 long 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 long buffer
084: * @exception IndexOutOfBoundsException
085: * If either <code>start</code> or <code>len</code> is
086: * invalid
087: */
088: public static LongBuffer wrap(long[] array, int start, int len) {
089: if (array == null) {
090: throw new NullPointerException();
091: }
092: if (start < 0 || len < 0
093: || (long) len + (long) start > array.length) {
094: throw new IndexOutOfBoundsException();
095: }
096:
097: LongBuffer buf = BufferFactory.newLongBuffer(array);
098: buf.position = start;
099: buf.limit = start + len;
100:
101: return buf;
102: }
103:
104: /**
105: * Constructs a <code>LongBuffer</code> with given capacity.
106: *
107: * @param capacity
108: * The capacity of the buffer
109: */
110: LongBuffer(int capacity) {
111: super (capacity);
112: }
113:
114: /**
115: * Returns the long array which this buffer is based on, if there's one.
116: *
117: * @return The long 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 long[] array() {
124: return protectedArray();
125: }
126:
127: /**
128: * Returns the offset of the long 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 long 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 LongBuffer asReadOnlyBuffer();
161:
162: /**
163: * Compacts this long buffer.
164: * <p>
165: * The remaining <code>long</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 LongBuffer compact();
176:
177: /**
178: * Compare the remaining <code>long</code>s of this buffer to another
179: * long buffer's remaining <code>long</code>s.
180: *
181: * @param otherBuffer
182: * Another long 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 long buffer
188: */
189: public int compareTo(LongBuffer otherBuffer) {
190: int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
191: : otherBuffer.remaining();
192: int this Pos = position;
193: int otherPos = otherBuffer.position;
194: long this Byte, otherByte;
195: while (compareRemaining > 0) {
196: this Byte = get(this Pos);
197: otherByte = otherBuffer.get(otherPos);
198: if (this Byte != otherByte) {
199: return this Byte < otherByte ? -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 LongBuffer duplicate();
224:
225: /**
226: * Tests whether this long buffer equals to another object.
227: * <p>
228: * If <code>other</code> is not a long buffer, then false is returned.
229: * </p>
230: * <p>
231: * Two long buffers are equals if, and only if, their remaining
232: * <code>long</code>s are exactly the same. Position, limit, capacity and
233: * mark are not considered.
234: * </p>
235: *
236: * @param other
237: * the object to be compared against
238: * @return Whether this long buffer equals to another object.
239: */
240: @Override
241: public boolean equals(Object other) {
242: if (!(other instanceof LongBuffer)) {
243: return false;
244: }
245: LongBuffer otherBuffer = (LongBuffer) 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 long at the current position and increase the position by 1.
264: *
265: * @return The long at the current position.
266: * @exception BufferUnderflowException
267: * If the position is equal or greater than limit
268: */
269: public abstract long get();
270:
271: /**
272: * Reads <code>long</code>s from the current position into the specified
273: * long array and increase the position by the number of <code>long</code>s
274: * read.
275: * <p>
276: * Calling this method has the same effect as
277: * <code>get(dest, 0, dest.length)</code>.
278: * </p>
279: *
280: * @param dest
281: * The destination long array
282: * @return This buffer
283: * @exception BufferUnderflowException
284: * if <code>dest.length</code> is greater than
285: * <code>remaining()</code>
286: */
287: public LongBuffer get(long[] dest) {
288: return get(dest, 0, dest.length);
289: }
290:
291: /**
292: * Reads <code>long</code>s from the current position into the specified
293: * long array, starting from the specified offset, and increase the position
294: * by the number of <code>long</code>s read.
295: *
296: * @param dest
297: * The target long array
298: * @param off
299: * The offset of the long array, must be no less than zero and no
300: * greater than <code>dest.length</code>
301: * @param len
302: * The number of <code>long</code>s to read, must be no less
303: * than zero and no greater than <code>dest.length - off</code>
304: * @return This buffer
305: * @exception IndexOutOfBoundsException
306: * If either <code>off</code> or <code>len</code> is
307: * invalid
308: * @exception BufferUnderflowException
309: * If <code>len</code> is greater than
310: * <code>remaining()</code>
311: */
312: public LongBuffer get(long[] dest, int off, int len) {
313: int length = dest.length;
314: if (off < 0 || len < 0 || (long) len + (long) off > length) {
315: throw new IndexOutOfBoundsException();
316: }
317:
318: if (len > remaining()) {
319: throw new BufferUnderflowException();
320: }
321: for (int i = off; i < off + len; i++) {
322: dest[i] = get();
323: }
324: return this ;
325: }
326:
327: /**
328: * Returns a long at the specified index, and the position is not changed.
329: *
330: * @param index
331: * The index, must be no less than zero and less than limit
332: * @return A long at the specified index.
333: * @exception IndexOutOfBoundsException
334: * If index is invalid
335: */
336: public abstract long get(int index);
337:
338: /**
339: * Returns whether this buffer is based on a long array and is read/write.
340: * <p>
341: * If this buffer is readonly, then false is returned.
342: * </p>
343: *
344: * @return Whether this buffer is based on a long array and is read/write.
345: */
346: public final boolean hasArray() {
347: return protectedHasArray();
348: }
349:
350: /**
351: * Hash code is calculated from the remaining <code>long</code>s.
352: * <p>
353: * Position, limit, capacity and mark don't affect the hash code.
354: * </p>
355: *
356: * @return The hash code calculated from the remaining <code>long</code>s.
357: */
358: @Override
359: public int hashCode() {
360: int myPosition = position;
361: int hash = 0;
362: long l;
363: while (myPosition < limit) {
364: l = get(myPosition++);
365: hash = hash + ((int) l) ^ ((int) (l >> 32));
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 long 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>long</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>long</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 long[] 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 long to the current position and increase the position
421: * by 1.
422: *
423: * @param l
424: * The long 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 LongBuffer put(long l);
432:
433: /**
434: * Writes <code>long</code>s in the given long array to the current
435: * position and increase the position by the number of <code>long</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 long 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 LongBuffer put(long[] src) {
452: return put(src, 0, src.length);
453: }
454:
455: /**
456: * Writes <code>long</code>s in the given long array, starting from the
457: * specified offset, to the current position and increase the position by
458: * the number of <code>long</code>s written.
459: *
460: * @param src
461: * The source long array
462: * @param off
463: * The offset of long array, must be no less than zero and no
464: * greater than <code>src.length</code>
465: * @param len
466: * The number of <code>long</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 LongBuffer put(long[] src, int off, int len) {
479: int length = src.length;
480: if (off < 0 || len < 0 || (long) len + (long) off > 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>long</code>s of the <code>src</code>
495: * long buffer to this buffer's current position, and increase both buffers'
496: * position by the number of <code>long</code>s copied.
497: *
498: * @param src
499: * The source long 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 LongBuffer put(LongBuffer src) {
510: if (src == this ) {
511: throw new IllegalArgumentException();
512: }
513: if (src.remaining() > remaining()) {
514: throw new BufferOverflowException();
515: }
516: long[] contents = new long[src.remaining()];
517: src.get(contents);
518: put(contents);
519: return this ;
520: }
521:
522: /**
523: * Write a long 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 l
529: * The long 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 LongBuffer put(int index, long l);
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 LongBuffer slice();
556:
557: /**
558: * Returns a string represents the state of this long buffer.
559: *
560: * @return A string represents the state of this long 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: }
|