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