blob: 3804057974f1cdbe3be3815b5d91aa73b58adb5a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.nio;
27
28
29/**
30 * A container for data of a specific primitive type.
31 *
32 * <p> A buffer is a linear, finite sequence of elements of a specific
33 * primitive type. Aside from its content, the essential properties of a
34 * buffer are its capacity, limit, and position: </p>
35 *
36 * <blockquote>
37 *
38 * <p> A buffer's <i>capacity</i> is the number of elements it contains. The
39 * capacity of a buffer is never negative and never changes. </p>
40 *
41 * <p> A buffer's <i>limit</i> is the index of the first element that should
42 * not be read or written. A buffer's limit is never negative and is never
43 * greater than its capacity. </p>
44 *
45 * <p> A buffer's <i>position</i> is the index of the next element to be
46 * read or written. A buffer's position is never negative and is never
47 * greater than its limit. </p>
48 *
49 * </blockquote>
50 *
51 * <p> There is one subclass of this class for each non-boolean primitive type.
52 *
53 *
54 * <h4> Transferring data </h4>
55 *
56 * <p> Each subclass of this class defines two categories of <i>get</i> and
57 * <i>put</i> operations: </p>
58 *
59 * <blockquote>
60 *
61 * <p> <i>Relative</i> operations read or write one or more elements starting
62 * at the current position and then increment the position by the number of
63 * elements transferred. If the requested transfer exceeds the limit then a
64 * relative <i>get</i> operation throws a {@link BufferUnderflowException}
65 * and a relative <i>put</i> operation throws a {@link
66 * BufferOverflowException}; in either case, no data is transferred. </p>
67 *
68 * <p> <i>Absolute</i> operations take an explicit element index and do not
69 * affect the position. Absolute <i>get</i> and <i>put</i> operations throw
70 * an {@link IndexOutOfBoundsException} if the index argument exceeds the
71 * limit. </p>
72 *
73 * </blockquote>
74 *
75 * <p> Data may also, of course, be transferred in to or out of a buffer by the
76 * I/O operations of an appropriate channel, which are always relative to the
77 * current position.
78 *
79 *
80 * <h4> Marking and resetting </h4>
81 *
82 * <p> A buffer's <i>mark</i> is the index to which its position will be reset
83 * when the {@link #reset reset} method is invoked. The mark is not always
84 * defined, but when it is defined it is never negative and is never greater
85 * than the position. If the mark is defined then it is discarded when the
86 * position or the limit is adjusted to a value smaller than the mark. If the
87 * mark is not defined then invoking the {@link #reset reset} method causes an
88 * {@link InvalidMarkException} to be thrown.
89 *
90 *
91 * <h4> Invariants </h4>
92 *
93 * <p> The following invariant holds for the mark, position, limit, and
94 * capacity values:
95 *
96 * <blockquote>
97 * <tt>0</tt> <tt>&lt;=</tt>
98 * <i>mark</i> <tt>&lt;=</tt>
99 * <i>position</i> <tt>&lt;=</tt>
100 * <i>limit</i> <tt>&lt;=</tt>
101 * <i>capacity</i>
102 * </blockquote>
103 *
104 * <p> A newly-created buffer always has a position of zero and a mark that is
105 * undefined. The initial limit may be zero, or it may be some other value
106 * that depends upon the type of the buffer and the manner in which it is
107 * constructed. Each element of a newly-allocated buffer is initialized
108 * to zero.
109 *
110 *
111 * <h4> Clearing, flipping, and rewinding </h4>
112 *
113 * <p> In addition to methods for accessing the position, limit, and capacity
114 * values and for marking and resetting, this class also defines the following
115 * operations upon buffers:
116 *
117 * <ul>
118 *
119 * <li><p> {@link #clear} makes a buffer ready for a new sequence of
120 * channel-read or relative <i>put</i> operations: It sets the limit to the
121 * capacity and the position to zero. </p></li>
122 *
123 * <li><p> {@link #flip} makes a buffer ready for a new sequence of
124 * channel-write or relative <i>get</i> operations: It sets the limit to the
125 * current position and then sets the position to zero. </p></li>
126 *
127 * <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
128 * it already contains: It leaves the limit unchanged and sets the position
129 * to zero. </p></li>
130 *
131 * </ul>
132 *
133 *
134 * <h4> Read-only buffers </h4>
135 *
136 * <p> Every buffer is readable, but not every buffer is writable. The
137 * mutation methods of each buffer class are specified as <i>optional
138 * operations</i> that will throw a {@link ReadOnlyBufferException} when
139 * invoked upon a read-only buffer. A read-only buffer does not allow its
140 * content to be changed, but its mark, position, and limit values are mutable.
141 * Whether or not a buffer is read-only may be determined by invoking its
142 * {@link #isReadOnly isReadOnly} method.
143 *
144 *
145 * <h4> Thread safety </h4>
146 *
147 * <p> Buffers are not safe for use by multiple concurrent threads. If a
148 * buffer is to be used by more than one thread then access to the buffer
149 * should be controlled by appropriate synchronization.
150 *
151 *
152 * <h4> Invocation chaining </h4>
153 *
154 * <p> Methods in this class that do not otherwise have a value to return are
155 * specified to return the buffer upon which they are invoked. This allows
156 * method invocations to be chained; for example, the sequence of statements
157 *
158 * <blockquote><pre>
159 * b.flip();
160 * b.position(23);
161 * b.limit(42);</pre></blockquote>
162 *
163 * can be replaced by the single, more compact statement
164 *
165 * <blockquote><pre>
166 * b.flip().position(23).limit(42);</pre></blockquote>
167 *
168 *
169 * @author Mark Reinhold
170 * @author JSR-51 Expert Group
171 * @since 1.4
172 */
173
174public abstract class Buffer {
175
176 // Invariants: mark <= position <= limit <= capacity
177 private int mark = -1;
178 private int position = 0;
179 private int limit;
180 private int capacity;
181
182 // Used only by direct buffers
183 // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
184 long address;
185
186 // Creates a new buffer with the given mark, position, limit, and capacity,
187 // after checking invariants.
188 //
189 Buffer(int mark, int pos, int lim, int cap) { // package-private
190 if (cap < 0)
191 throw new IllegalArgumentException("Negative capacity: " + cap);
192 this.capacity = cap;
193 limit(lim);
194 position(pos);
195 if (mark >= 0) {
196 if (mark > pos)
197 throw new IllegalArgumentException("mark > position: ("
198 + mark + " > " + pos + ")");
199 this.mark = mark;
200 }
201 }
202
203 /**
204 * Returns this buffer's capacity. </p>
205 *
206 * @return The capacity of this buffer
207 */
208 public final int capacity() {
209 return capacity;
210 }
211
212 /**
213 * Returns this buffer's position. </p>
214 *
215 * @return The position of this buffer
216 */
217 public final int position() {
218 return position;
219 }
220
221 /**
222 * Sets this buffer's position. If the mark is defined and larger than the
223 * new position then it is discarded. </p>
224 *
225 * @param newPosition
226 * The new position value; must be non-negative
227 * and no larger than the current limit
228 *
229 * @return This buffer
230 *
231 * @throws IllegalArgumentException
232 * If the preconditions on <tt>newPosition</tt> do not hold
233 */
234 public final Buffer position(int newPosition) {
235 if ((newPosition > limit) || (newPosition < 0))
236 throw new IllegalArgumentException();
237 position = newPosition;
238 if (mark > position) mark = -1;
239 return this;
240 }
241
242 /**
243 * Returns this buffer's limit. </p>
244 *
245 * @return The limit of this buffer
246 */
247 public final int limit() {
248 return limit;
249 }
250
251 /**
252 * Sets this buffer's limit. If the position is larger than the new limit
253 * then it is set to the new limit. If the mark is defined and larger than
254 * the new limit then it is discarded. </p>
255 *
256 * @param newLimit
257 * The new limit value; must be non-negative
258 * and no larger than this buffer's capacity
259 *
260 * @return This buffer
261 *
262 * @throws IllegalArgumentException
263 * If the preconditions on <tt>newLimit</tt> do not hold
264 */
265 public final Buffer limit(int newLimit) {
266 if ((newLimit > capacity) || (newLimit < 0))
267 throw new IllegalArgumentException();
268 limit = newLimit;
269 if (position > limit) position = limit;
270 if (mark > limit) mark = -1;
271 return this;
272 }
273
274 /**
275 * Sets this buffer's mark at its position. </p>
276 *
277 * @return This buffer
278 */
279 public final Buffer mark() {
280 mark = position;
281 return this;
282 }
283
284 /**
285 * Resets this buffer's position to the previously-marked position.
286 *
287 * <p> Invoking this method neither changes nor discards the mark's
288 * value. </p>
289 *
290 * @return This buffer
291 *
292 * @throws InvalidMarkException
293 * If the mark has not been set
294 */
295 public final Buffer reset() {
296 int m = mark;
297 if (m < 0)
298 throw new InvalidMarkException();
299 position = m;
300 return this;
301 }
302
303 /**
304 * Clears this buffer. The position is set to zero, the limit is set to
305 * the capacity, and the mark is discarded.
306 *
307 * <p> Invoke this method before using a sequence of channel-read or
308 * <i>put</i> operations to fill this buffer. For example:
309 *
310 * <blockquote><pre>
311 * buf.clear(); // Prepare buffer for reading
312 * in.read(buf); // Read data</pre></blockquote>
313 *
314 * <p> This method does not actually erase the data in the buffer, but it
315 * is named as if it did because it will most often be used in situations
316 * in which that might as well be the case. </p>
317 *
318 * @return This buffer
319 */
320 public final Buffer clear() {
321 position = 0;
322 limit = capacity;
323 mark = -1;
324 return this;
325 }
326
327 /**
328 * Flips this buffer. The limit is set to the current position and then
329 * the position is set to zero. If the mark is defined then it is
330 * discarded.
331 *
332 * <p> After a sequence of channel-read or <i>put</i> operations, invoke
333 * this method to prepare for a sequence of channel-write or relative
334 * <i>get</i> operations. For example:
335 *
336 * <blockquote><pre>
337 * buf.put(magic); // Prepend header
338 * in.read(buf); // Read data into rest of buffer
339 * buf.flip(); // Flip buffer
340 * out.write(buf); // Write header + data to channel</pre></blockquote>
341 *
342 * <p> This method is often used in conjunction with the {@link
343 * java.nio.ByteBuffer#compact compact} method when transferring data from
344 * one place to another. </p>
345 *
346 * @return This buffer
347 */
348 public final Buffer flip() {
349 limit = position;
350 position = 0;
351 mark = -1;
352 return this;
353 }
354
355 /**
356 * Rewinds this buffer. The position is set to zero and the mark is
357 * discarded.
358 *
359 * <p> Invoke this method before a sequence of channel-write or <i>get</i>
360 * operations, assuming that the limit has already been set
361 * appropriately. For example:
362 *
363 * <blockquote><pre>
364 * out.write(buf); // Write remaining data
365 * buf.rewind(); // Rewind buffer
366 * buf.get(array); // Copy data into array</pre></blockquote>
367 *
368 * @return This buffer
369 */
370 public final Buffer rewind() {
371 position = 0;
372 mark = -1;
373 return this;
374 }
375
376 /**
377 * Returns the number of elements between the current position and the
378 * limit. </p>
379 *
380 * @return The number of elements remaining in this buffer
381 */
382 public final int remaining() {
383 return limit - position;
384 }
385
386 /**
387 * Tells whether there are any elements between the current position and
388 * the limit. </p>
389 *
390 * @return <tt>true</tt> if, and only if, there is at least one element
391 * remaining in this buffer
392 */
393 public final boolean hasRemaining() {
394 return position < limit;
395 }
396
397 /**
398 * Tells whether or not this buffer is read-only. </p>
399 *
400 * @return <tt>true</tt> if, and only if, this buffer is read-only
401 */
402 public abstract boolean isReadOnly();
403
404 /**
405 * Tells whether or not this buffer is backed by an accessible
406 * array.
407 *
408 * <p> If this method returns <tt>true</tt> then the {@link #array() array}
409 * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
410 * </p>
411 *
412 * @return <tt>true</tt> if, and only if, this buffer
413 * is backed by an array and is not read-only
414 *
415 * @since 1.6
416 */
417 public abstract boolean hasArray();
418
419 /**
420 * Returns the array that backs this
421 * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
422 *
423 * <p> This method is intended to allow array-backed buffers to be
424 * passed to native code more efficiently. Concrete subclasses
425 * provide more strongly-typed return values for this method.
426 *
427 * <p> Modifications to this buffer's content will cause the returned
428 * array's content to be modified, and vice versa.
429 *
430 * <p> Invoke the {@link #hasArray hasArray} method before invoking this
431 * method in order to ensure that this buffer has an accessible backing
432 * array. </p>
433 *
434 * @return The array that backs this buffer
435 *
436 * @throws ReadOnlyBufferException
437 * If this buffer is backed by an array but is read-only
438 *
439 * @throws UnsupportedOperationException
440 * If this buffer is not backed by an accessible array
441 *
442 * @since 1.6
443 */
444 public abstract Object array();
445
446 /**
447 * Returns the offset within this buffer's backing array of the first
448 * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
449 *
450 * <p> If this buffer is backed by an array then buffer position <i>p</i>
451 * corresponds to array index <i>p</i>&nbsp;+&nbsp;<tt>arrayOffset()</tt>.
452 *
453 * <p> Invoke the {@link #hasArray hasArray} method before invoking this
454 * method in order to ensure that this buffer has an accessible backing
455 * array. </p>
456 *
457 * @return The offset within this buffer's array
458 * of the first element of the buffer
459 *
460 * @throws ReadOnlyBufferException
461 * If this buffer is backed by an array but is read-only
462 *
463 * @throws UnsupportedOperationException
464 * If this buffer is not backed by an accessible array
465 *
466 * @since 1.6
467 */
468 public abstract int arrayOffset();
469
470 /**
471 * Tells whether or not this buffer is
472 * <a href="ByteBuffer.html#direct"><i>direct</i></a>. </p>
473 *
474 * @return <tt>true</tt> if, and only if, this buffer is direct
475 *
476 * @since 1.6
477 */
478 public abstract boolean isDirect();
479
480
481 // -- Package-private methods for bounds checking, etc. --
482
483 /**
484 * Checks the current position against the limit, throwing a {@link
485 * BufferUnderflowException} if it is not smaller than the limit, and then
486 * increments the position. </p>
487 *
488 * @return The current position value, before it is incremented
489 */
490 final int nextGetIndex() { // package-private
491 if (position >= limit)
492 throw new BufferUnderflowException();
493 return position++;
494 }
495
496 final int nextGetIndex(int nb) { // package-private
497 if (limit - position < nb)
498 throw new BufferUnderflowException();
499 int p = position;
500 position += nb;
501 return p;
502 }
503
504 /**
505 * Checks the current position against the limit, throwing a {@link
506 * BufferOverflowException} if it is not smaller than the limit, and then
507 * increments the position. </p>
508 *
509 * @return The current position value, before it is incremented
510 */
511 final int nextPutIndex() { // package-private
512 if (position >= limit)
513 throw new BufferOverflowException();
514 return position++;
515 }
516
517 final int nextPutIndex(int nb) { // package-private
518 if (limit - position < nb)
519 throw new BufferOverflowException();
520 int p = position;
521 position += nb;
522 return p;
523 }
524
525 /**
526 * Checks the given index against the limit, throwing an {@link
527 * IndexOutOfBoundsException} if it is not smaller than the limit
528 * or is smaller than zero.
529 */
530 final int checkIndex(int i) { // package-private
531 if ((i < 0) || (i >= limit))
532 throw new IndexOutOfBoundsException();
533 return i;
534 }
535
536 final int checkIndex(int i, int nb) { // package-private
537 if ((i < 0) || (nb > limit - i))
538 throw new IndexOutOfBoundsException();
539 return i;
540 }
541
542 final int markValue() { // package-private
543 return mark;
544 }
545
546 static void checkBounds(int off, int len, int size) { // package-private
547 if ((off | len | (off + len) | (size - (off + len))) < 0)
548 throw new IndexOutOfBoundsException();
549 }
550
551}