Buffer.java revision 29dbfe19b113a13b712be2bc762ef1c81cd06c47
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package java.nio;
18
19/**
20 * A buffer is a list of elements of a specific primitive type.
21 * <p>
22 * A buffer can be described by the following properties:
23 * <ul>
24 * <li>Capacity: the number of elements a buffer can hold. Capacity may not be
25 * negative and never changes.</li>
26 * <li>Position: a cursor of this buffer. Elements are read or written at the
27 * position if you do not specify an index explicitly. Position may not be
28 * negative and not greater than the limit.</li>
29 * <li>Limit: controls the scope of accessible elements. You can only read or
30 * write elements from index zero to <code>limit - 1</code>. Accessing
31 * elements out of the scope will cause an exception. Limit may not be negative
32 * and not greater than capacity.</li>
33 * <li>Mark: used to remember the current position, so that you can reset the
34 * position later. Mark may not be negative and no greater than position.</li>
35 * <li>A buffer can be read-only or read-write. Trying to modify the elements
36 * of a read-only buffer will cause a <code>ReadOnlyBufferException</code>,
37 * while changing the position, limit and mark of a read-only buffer is OK.</li>
38 * <li>A buffer can be direct or indirect. A direct buffer will try its best to
39 * take advantage of native memory APIs and it may not stay in the Java heap,
40 * thus it is not affected by garbage collection.</li>
41 * </ul>
42 * <p>
43 * Buffers are not thread-safe. If concurrent access to a buffer instance is
44 * required, then the callers are responsible to take care of the
45 * synchronization issues.
46 */
47public abstract class Buffer {
48
49    static final int SIZEOF_CHAR = 2;
50    static final int SIZEOF_DOUBLE = 8;
51    static final int SIZEOF_FLOAT = 4;
52    static final int SIZEOF_INT = 4;
53    static final int SIZEOF_LONG = 8;
54    static final int SIZEOF_SHORT = 2;
55
56    /**
57     * <code>UNSET_MARK</code> means the mark has not been set.
58     */
59    final static int UNSET_MARK = -1;
60
61    /**
62     * The capacity of this buffer, which never changes.
63     */
64    final int capacity;
65
66    /**
67     * <code>limit - 1</code> is the last element that can be read or written.
68     * Limit must be no less than zero and no greater than <code>capacity</code>.
69     */
70    int limit;
71
72    /**
73     * Mark is where position will be set when <code>reset()</code> is called.
74     * Mark is not set by default. Mark is always no less than zero and no
75     * greater than <code>position</code>.
76     */
77    int mark = UNSET_MARK;
78
79    /**
80     * The current position of this buffer. Position is always no less than zero
81     * and no greater than <code>limit</code>.
82     */
83    int position = 0;
84
85    // BEGIN android-added
86    /**
87     * The log base 2 of the element size of this buffer.  Each typed subclass
88     * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this
89     * value.  The value is used by JNI code in frameworks/base/ to avoid the
90     * need for costly 'instanceof' tests.
91     */
92    int _elementSizeShift;
93
94    /**
95     * For direct buffers, the effective address of the data.  This is set
96     * on first use.  If the field is zero, this is either not a direct
97     * buffer or the field has not been initialized, and you need to issue
98     * the getEffectiveAddress() call and use the result of that.
99     *
100     * This is an optimization used by the GetDirectBufferAddress JNI call.
101     */
102    int effectiveDirectAddress = 0;
103    // END android-added
104
105    /**
106     * Construct a buffer with the specified capacity.
107     *
108     * @param capacity
109     *            The capacity of this buffer
110     */
111    Buffer(int capacity) {
112        super();
113        if (capacity < 0) {
114            throw new IllegalArgumentException();
115        }
116        this.capacity = this.limit = capacity;
117    }
118
119    /**
120     * Returns the array that backs this buffer (optional operation).
121     * The returned value is the actual array, not a copy, so modifications
122     * to the array write through to the buffer.
123     *
124     * <p>Subclasses should override this method with a covariant return type
125     * to provide the exact type of the array.
126     *
127     * <p>Use {@code hasArray} to ensure this method won't throw.
128     * (A separate call to {@code isReadOnly} is not necessary.)
129     *
130     * @return the array
131     * @throws ReadOnlyBufferException if the buffer is read-only
132     *         UnsupportedOperationException if the buffer does not expose an array
133     * @since 1.6
134     */
135    public abstract Object array();
136
137    /**
138     * Returns the offset into the array returned by {@code array} of the first
139     * element of the buffer (optional operation). The backing array (if there is one)
140     * is not necessarily the same size as the buffer, and position 0 in the buffer is
141     * not necessarily the 0th element in the array. Use
142     * {@code buffer.array()[offset + buffer.arrayOffset()} to access element {@code offset}
143     * in {@code buffer}.
144     *
145     * <p>Use {@code hasArray} to ensure this method won't throw.
146     * (A separate call to {@code isReadOnly} is not necessary.)
147     *
148     * @return the offset
149     * @throws ReadOnlyBufferException if the buffer is read-only
150     *         UnsupportedOperationException if the buffer does not expose an array
151     * @since 1.6
152     */
153    public abstract int arrayOffset();
154
155    /**
156     * Returns the capacity of this buffer.
157     *
158     * @return the number of elements that are contained in this buffer.
159     */
160    public final int capacity() {
161        return capacity;
162    }
163
164    /**
165     * Clears this buffer.
166     * <p>
167     * While the content of this buffer is not changed, the following internal
168     * changes take place: the current position is reset back to the start of
169     * the buffer, the value of the buffer limit is made equal to the capacity
170     * and mark is cleared.
171     *
172     * @return this buffer.
173     */
174    public final Buffer clear() {
175        position = 0;
176        mark = UNSET_MARK;
177        limit = capacity;
178        return this;
179    }
180
181    /**
182     * Flips this buffer.
183     * <p>
184     * The limit is set to the current position, then the position is set to
185     * zero, and the mark is cleared.
186     * <p>
187     * The content of this buffer is not changed.
188     *
189     * @return this buffer.
190     */
191    public final Buffer flip() {
192        limit = position;
193        position = 0;
194        mark = UNSET_MARK;
195        return this;
196    }
197
198    /**
199     * Returns true if {@code array} and {@code arrayOffset} won't throw. This method does not
200     * return true for buffers not backed by arrays because the other methods would throw
201     * {@code UnsupportedOperationException}, nor does it return true for buffers backed by
202     * read-only arrays, because the other methods would throw {@code ReadOnlyBufferException}.
203     * @since 1.6
204     */
205    public abstract boolean hasArray();
206
207    /**
208     * Indicates if there are elements remaining in this buffer, that is if
209     * {@code position < limit}.
210     *
211     * @return {@code true} if there are elements remaining in this buffer,
212     *         {@code false} otherwise.
213     */
214    public final boolean hasRemaining() {
215        return position < limit;
216    }
217
218    /**
219     * Returns true if this is a direct buffer.
220     * @since 1.6
221     */
222    public abstract boolean isDirect();
223
224    /**
225     * Indicates whether this buffer is read-only.
226     *
227     * @return {@code true} if this buffer is read-only, {@code false}
228     *         otherwise.
229     */
230    public abstract boolean isReadOnly();
231
232    /**
233     * Returns the limit of this buffer.
234     *
235     * @return the limit of this buffer.
236     */
237    public final int limit() {
238        return limit;
239    }
240
241    /**
242     * Sets the limit of this buffer.
243     * <p>
244     * If the current position in the buffer is in excess of
245     * <code>newLimit</code> then, on returning from this call, it will have
246     * been adjusted to be equivalent to <code>newLimit</code>. If the mark
247     * is set and is greater than the new limit, then it is cleared.
248     *
249     * @param newLimit
250     *            the new limit, must not be negative and not greater than
251     *            capacity.
252     * @return this buffer.
253     * @exception IllegalArgumentException
254     *                if <code>newLimit</code> is invalid.
255     */
256    public final Buffer limit(int newLimit) {
257        if (newLimit < 0 || newLimit > capacity) {
258            throw new IllegalArgumentException();
259        }
260
261        limit = newLimit;
262        if (position > newLimit) {
263            position = newLimit;
264        }
265        if ((mark != UNSET_MARK) && (mark > newLimit)) {
266            mark = UNSET_MARK;
267        }
268        return this;
269    }
270
271    /**
272     * Marks the current position, so that the position may return to this point
273     * later by calling <code>reset()</code>.
274     *
275     * @return this buffer.
276     */
277    public final Buffer mark() {
278        mark = position;
279        return this;
280    }
281
282    /**
283     * Returns the position of this buffer.
284     *
285     * @return the value of this buffer's current position.
286     */
287    public final int position() {
288        return position;
289    }
290
291    /**
292     * Sets the position of this buffer.
293     * <p>
294     * If the mark is set and it is greater than the new position, then it is
295     * cleared.
296     *
297     * @param newPosition
298     *            the new position, must be not negative and not greater than
299     *            limit.
300     * @return this buffer.
301     * @exception IllegalArgumentException
302     *                if <code>newPosition</code> is invalid.
303     */
304    public final Buffer position(int newPosition) {
305        if (newPosition < 0 || newPosition > limit) {
306            throw new IllegalArgumentException();
307        }
308
309        position = newPosition;
310        if ((mark != UNSET_MARK) && (mark > position)) {
311            mark = UNSET_MARK;
312        }
313        return this;
314    }
315
316    /**
317     * Returns the number of remaining elements in this buffer, that is
318     * {@code limit - position}.
319     *
320     * @return the number of remaining elements in this buffer.
321     */
322    public final int remaining() {
323        return limit - position;
324    }
325
326    /**
327     * Resets the position of this buffer to the <code>mark</code>.
328     *
329     * @return this buffer.
330     * @exception InvalidMarkException
331     *                if the mark is not set.
332     */
333    public final Buffer reset() {
334        if (mark == UNSET_MARK) {
335            throw new InvalidMarkException();
336        }
337        position = mark;
338        return this;
339    }
340
341    /**
342     * Rewinds this buffer.
343     * <p>
344     * The position is set to zero, and the mark is cleared. The content of this
345     * buffer is not changed.
346     *
347     * @return this buffer.
348     */
349    public final Buffer rewind() {
350        position = 0;
351        mark = UNSET_MARK;
352        return this;
353    }
354}
355