KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > nio > Buffer


1 /*
2  * @(#)Buffer.java 1.35 06/08/11
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.nio;
9
10
11 /**
12  * A container for data of a specific primitive type.
13  *
14  * <p> A buffer is a linear, finite sequence of elements of a specific
15  * primitive type. Aside from its content, the essential properties of a
16  * buffer are its capacity, limit, and position: </p>
17  *
18  * <blockquote>
19  *
20  * <p> A buffer's <i>capacity</i> is the number of elements it contains. The
21  * capacity of a buffer is never negative and never changes. </p>
22  *
23  * <p> A buffer's <i>limit</i> is the index of the first element that should
24  * not be read or written. A buffer's limit is never negative and is never
25  * greater than its capacity. </p>
26  *
27  * <p> A buffer's <i>position</i> is the index of the next element to be
28  * read or written. A buffer's position is never negative and is never
29  * greater than its limit. </p>
30  *
31  * </blockquote>
32  *
33  * <p> There is one subclass of this class for each non-boolean primitive type.
34  *
35  *
36  * <h4> Transferring data </h4>
37  *
38  * <p> Each subclass of this class defines two categories of <i>get</i> and
39  * <i>put</i> operations: </p>
40  *
41  * <blockquote>
42  *
43  * <p> <i>Relative</i> operations read or write one or more elements starting
44  * at the current position and then increment the position by the number of
45  * elements transferred. If the requested transfer exceeds the limit then a
46  * relative <i>get</i> operation throws a {@link BufferUnderflowException}
47  * and a relative <i>put</i> operation throws a {@link
48  * BufferOverflowException}; in either case, no data is transferred. </p>
49  *
50  * <p> <i>Absolute</i> operations take an explicit element index and do not
51  * affect the position. Absolute <i>get</i> and <i>put</i> operations throw
52  * an {@link IndexOutOfBoundsException} if the index argument exceeds the
53  * limit. </p>
54  *
55  * </blockquote>
56  *
57  * <p> Data may also, of course, be transferred in to or out of a buffer by the
58  * I/O operations of an appropriate channel, which are always relative to the
59  * current position.
60  *
61  *
62  * <h4> Marking and resetting </h4>
63  *
64  * <p> A buffer's <i>mark</i> is the index to which its position will be reset
65  * when the {@link #reset reset} method is invoked. The mark is not always
66  * defined, but when it is defined it is never negative and is never greater
67  * than the position. If the mark is defined then it is discarded when the
68  * position or the limit is adjusted to a value smaller than the mark. If the
69  * mark is not defined then invoking the {@link #reset reset} method causes an
70  * {@link InvalidMarkException} to be thrown.
71  *
72  *
73  * <h4> Invariants </h4>
74  *
75  * <p> The following invariant holds for the mark, position, limit, and
76  * capacity values:
77  *
78  * <blockquote>
79  * <tt>0</tt> <tt>&lt;=</tt>
80  * <i>mark</i> <tt>&lt;=</tt>
81  * <i>position</i> <tt>&lt;=</tt>
82  * <i>limit</i> <tt>&lt;=</tt>
83  * <i>capacity</i>
84  * </blockquote>
85  *
86  * <p> A newly-created buffer always has a position of zero and a mark that is
87  * undefined. The initial limit may be zero, or it may be some other value
88  * that depends upon the type of the buffer and the manner in which it is
89  * constructed. The initial content of a buffer is, in general,
90  * undefined.
91  *
92  *
93  * <h4> Clearing, flipping, and rewinding </h4>
94  *
95  * <p> In addition to methods for accessing the position, limit, and capacity
96  * values and for marking and resetting, this class also defines the following
97  * operations upon buffers:
98  *
99  * <ul>
100  *
101  * <li><p> {@link #clear} makes a buffer ready for a new sequence of
102  * channel-read or relative <i>put</i> operations: It sets the limit to the
103  * capacity and the position to zero. </p></li>
104  *
105  * <li><p> {@link #flip} makes a buffer ready for a new sequence of
106  * channel-write or relative <i>get</i> operations: It sets the limit to the
107  * current position and then sets the position to zero. </p></li>
108  *
109  * <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
110  * it already contains: It leaves the limit unchanged and sets the position
111  * to zero. </p></li>
112  *
113  * </ul>
114  *
115  *
116  * <h4> Read-only buffers </h4>
117  *
118  * <p> Every buffer is readable, but not every buffer is writable. The
119  * mutation methods of each buffer class are specified as <i>optional
120  * operations</i> that will throw a {@link ReadOnlyBufferException} when
121  * invoked upon a read-only buffer. A read-only buffer does not allow its
122  * content to be changed, but its mark, position, and limit values are mutable.
123  * Whether or not a buffer is read-only may be determined by invoking its
124  * {@link #isReadOnly isReadOnly} method.
125  *
126  *
127  * <h4> Thread safety </h4>
128  *
129  * <p> Buffers are not safe for use by multiple concurrent threads. If a
130  * buffer is to be used by more than one thread then access to the buffer
131  * should be controlled by appropriate synchronization.
132  *
133  *
134  * <h4> Invocation chaining </h4>
135  *
136  * <p> Methods in this class that do not otherwise have a value to return are
137  * specified to return the buffer upon which they are invoked. This allows
138  * method invocations to be chained; for example, the sequence of statements
139  *
140  * <blockquote><pre>
141  * b.flip();
142  * b.position(23);
143  * b.limit(42);</pre></blockquote>
144  *
145  * can be replaced by the single, more compact statement
146  *
147  * <blockquote><pre>
148  * b.flip().position(23).limit(42);</pre></blockquote>
149  *
150  *
151  * @author Mark Reinhold
152  * @author JSR-51 Expert Group
153  * @version 1.35, 06/08/11
154  * @since 1.4
155  */

156
157 public abstract class Buffer {
158
159     // Invariants: mark <= position <= limit <= capacity
160
private int mark = -1;
161     private int position = 0;
162     private int limit;
163     private int capacity;
164
165     // Used only by direct buffers
166
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
167
long address;
168
169     // Creates a new buffer with the given mark, position, limit, and capacity,
170
// after checking invariants.
171
//
172
Buffer(int mark, int pos, int lim, int cap) { // package-private
173
if (cap < 0)
174         throw new IllegalArgumentException JavaDoc();
175     this.capacity = cap;
176     limit(lim);
177     position(pos);
178     if (mark >= 0) {
179         if (mark > pos)
180         throw new IllegalArgumentException JavaDoc();
181         this.mark = mark;
182     }
183     }
184
185     /**
186      * Returns this buffer's capacity. </p>
187      *
188      * @return The capacity of this buffer
189      */

190     public final int capacity() {
191     return capacity;
192     }
193
194     /**
195      * Returns this buffer's position. </p>
196      *
197      * @return The position of this buffer
198      */

199     public final int position() {
200     return position;
201     }
202
203     /**
204      * Sets this buffer's position. If the mark is defined and larger than the
205      * new position then it is discarded. </p>
206      *
207      * @param newPosition
208      * The new position value; must be non-negative
209      * and no larger than the current limit
210      *
211      * @return This buffer
212      *
213      * @throws IllegalArgumentException
214      * If the preconditions on <tt>newPosition</tt> do not hold
215      */

216     public final Buffer JavaDoc position(int newPosition) {
217     if ((newPosition > limit) || (newPosition < 0))
218         throw new IllegalArgumentException JavaDoc();
219     position = newPosition;
220     if (mark > position) mark = -1;
221     return this;
222     }
223
224     /**
225      * Returns this buffer's limit. </p>
226      *
227      * @return The limit of this buffer
228      */

229     public final int limit() {
230     return limit;
231     }
232
233     /**
234      * Sets this buffer's limit. If the position is larger than the new limit
235      * then it is set to the new limit. If the mark is defined and larger than
236      * the new limit then it is discarded. </p>
237      *
238      * @param newLimit
239      * The new limit value; must be non-negative
240      * and no larger than this buffer's capacity
241      *
242      * @return This buffer
243      *
244      * @throws IllegalArgumentException
245      * If the preconditions on <tt>newLimit</tt> do not hold
246      */

247     public final Buffer JavaDoc limit(int newLimit) {
248     if ((newLimit > capacity) || (newLimit < 0))
249         throw new IllegalArgumentException JavaDoc();
250     limit = newLimit;
251     if (position > limit) position = limit;
252     if (mark > limit) mark = -1;
253     return this;
254     }
255
256     /**
257      * Sets this buffer's mark at its position. </p>
258      *
259      * @return This buffer
260      */

261     public final Buffer JavaDoc mark() {
262     mark = position;
263     return this;
264     }
265
266     /**
267      * Resets this buffer's position to the previously-marked position.
268      *
269      * <p> Invoking this method neither changes nor discards the mark's
270      * value. </p>
271      *
272      * @return This buffer
273      *
274      * @throws InvalidMarkException
275      * If the mark has not been set
276      */

277     public final Buffer JavaDoc reset() {
278         int m = mark;
279     if (m < 0)
280         throw new InvalidMarkException JavaDoc();
281     position = m;
282     return this;
283     }
284
285     /**
286      * Clears this buffer. The position is set to zero, the limit is set to
287      * the capacity, and the mark is discarded.
288      *
289      * <p> Invoke this method before using a sequence of channel-read or
290      * <i>put</i> operations to fill this buffer. For example:
291      *
292      * <blockquote><pre>
293      * buf.clear(); // Prepare buffer for reading
294      * in.read(buf); // Read data</pre></blockquote>
295      *
296      * <p> This method does not actually erase the data in the buffer, but it
297      * is named as if it did because it will most often be used in situations
298      * in which that might as well be the case. </p>
299      *
300      * @return This buffer
301      */

302     public final Buffer JavaDoc clear() {
303     position = 0;
304     limit = capacity;
305     mark = -1;
306     return this;
307     }
308
309     /**
310      * Flips this buffer. The limit is set to the current position and then
311      * the position is set to zero. If the mark is defined then it is
312      * discarded.
313      *
314      * <p> After a sequence of channel-read or <i>put</i> operations, invoke
315      * this method to prepare for a sequence of channel-write or relative
316      * <i>get</i> operations. For example:
317      *
318      * <blockquote><pre>
319      * buf.put(magic); // Prepend header
320      * in.read(buf); // Read data into rest of buffer
321      * buf.flip(); // Flip buffer
322      * out.write(buf); // Write header + data to channel</pre></blockquote>
323      *
324      * <p> This method is often used in conjunction with the {@link
325      * java.nio.ByteBuffer#compact compact} method when transferring data from
326      * one place to another. </p>
327      *
328      * @return This buffer
329      */

330     public final Buffer JavaDoc flip() {
331     limit = position;
332     position = 0;
333     mark = -1;
334     return this;
335     }
336
337     /**
338      * Rewinds this buffer. The position is set to zero and the mark is
339      * discarded.
340      *
341      * <p> Invoke this method before a sequence of channel-write or <i>get</i>
342      * operations, assuming that the limit has already been set
343      * appropriately. For example:
344      *
345      * <blockquote><pre>
346      * out.write(buf); // Write remaining data
347      * buf.rewind(); // Rewind buffer
348      * buf.get(array); // Copy data into array</pre></blockquote>
349      *
350      * @return This buffer
351      */

352     public final Buffer JavaDoc rewind() {
353     position = 0;
354     mark = -1;
355     return this;
356     }
357
358     /**
359      * Returns the number of elements between the current position and the
360      * limit. </p>
361      *
362      * @return The number of elements remaining in this buffer
363      */

364     public final int remaining() {
365     return limit - position;
366     }
367
368     /**
369      * Tells whether there are any elements between the current position and
370      * the limit. </p>
371      *
372      * @return <tt>true</tt> if, and only if, there is at least one element
373      * remaining in this buffer
374      */

375     public final boolean hasRemaining() {
376     return position < limit;
377     }
378
379     /**
380      * Tells whether or not this buffer is read-only. </p>
381      *
382      * @return <tt>true</tt> if, and only if, this buffer is read-only
383      */

384     public abstract boolean isReadOnly();
385
386
387     // -- Package-private methods for bounds checking, etc. --
388

389     /**
390      * Checks the current position against the limit, throwing a {@link
391      * BufferUnderflowException} if it is not smaller than the limit, and then
392      * increments the position. </p>
393      *
394      * @return The current position value, before it is incremented
395      */

396     final int nextGetIndex() { // package-private
397
if (position >= limit)
398         throw new BufferUnderflowException JavaDoc();
399     return position++;
400     }
401
402     final int nextGetIndex(int nb) { // package-private
403
if (limit - position < nb)
404         throw new BufferUnderflowException JavaDoc();
405     int p = position;
406     position += nb;
407     return p;
408     }
409
410     /**
411      * Checks the current position against the limit, throwing a {@link
412      * BufferOverflowException} if it is not smaller than the limit, and then
413      * increments the position. </p>
414      *
415      * @return The current position value, before it is incremented
416      */

417     final int nextPutIndex() { // package-private
418
if (position >= limit)
419         throw new BufferOverflowException JavaDoc();
420     return position++;
421     }
422
423     final int nextPutIndex(int nb) { // package-private
424
if (limit - position < nb)
425         throw new BufferOverflowException JavaDoc();
426     int p = position;
427     position += nb;
428     return p;
429     }
430
431     /**
432      * Checks the given index against the limit, throwing an {@link
433      * IndexOutOfBoundsException} if it is not smaller than the limit
434      * or is smaller than zero.
435      */

436     final int checkIndex(int i) { // package-private
437
if ((i < 0) || (i >= limit))
438         throw new IndexOutOfBoundsException JavaDoc();
439     return i;
440     }
441
442     final int checkIndex(int i, int nb) { // package-private
443
if ((i < 0) || (nb > limit - i))
444         throw new IndexOutOfBoundsException JavaDoc();
445     return i;
446     }
447
448     final int markValue() { // package-private
449
return mark;
450     }
451
452     static void checkBounds(int off, int len, int size) { // package-private
453
if ((off | len | (off + len) | (size - (off + len))) < 0)
454         throw new IndexOutOfBoundsException JavaDoc();
455     }
456
457 }
458
Popular Tags