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 17 package java.nio; 18 19 /** A buffer is a list of elements of a specific primitive type. 20 * <p> 21 * A buffer can be described by the following properties: 22 * <ul> 23 * <li>Capacity: the number of elements a buffer can hold. Capacity may not be negative and never changes.</li> 24 * <li>Position: a cursor of this buffer. Elements are read or written at the position if you do not specify an index explicitly. 25 * Position may not be negative and not greater than the limit.</li> 26 * <li>Limit: controls the scope of accessible elements. You can only read or write elements from index zero to 27 * <code>limit - 1</code>. Accessing elements out of the scope will cause an exception. Limit may not be negative and not greater 28 * than capacity.</li> 29 * <li>Mark: used to remember the current position, so that you can reset the position later. Mark may not be negative and no 30 * greater than position.</li> 31 * <li>A buffer can be read-only or read-write. Trying to modify the elements of a read-only buffer will cause a 32 * <code>ReadOnlyBufferException</code>, while changing the position, limit and mark of a read-only buffer is OK.</li> 33 * <li>A buffer can be direct or indirect. A direct buffer will try its best to take advantage of native memory APIs and it may 34 * not stay in the Java heap, thus it is not affected by garbage collection.</li> 35 * </ul> 36 * </p> 37 * <p> 38 * Buffers are not thread-safe. If concurrent access to a buffer instance is required, then the callers are responsible to take 39 * care of the synchronization issues. 40 * </p> 41 * 42 * @since Android 1.0 */ 43 public abstract class Buffer { 44 45 /** <code>UNSET_MARK</code> means the mark has not been set. */ 46 final static int UNSET_MARK = -1; 47 48 /** The capacity of this buffer, which never change. */ 49 final int capacity; 50 51 /** <code>limit - 1</code> is the last element that can be read or written. Limit must be no less than zero and no greater than 52 * <code>capacity</code>. */ 53 int limit; 54 55 /** Mark is where position will be set when <code>reset()</code> is called. Mark is not set by default. Mark is always no less 56 * than zero and no greater than <code>position</code>. */ 57 int mark = UNSET_MARK; 58 59 /** The current position of this buffer. Position is always no less than zero and no greater than <code>limit</code>. */ 60 int position = 0; 61 62 /** Construct a buffer with the specified capacity. 63 * 64 * @param capacity the capacity of this buffer. */ Buffer(int capacity)65 Buffer (int capacity) { 66 super(); 67 if (capacity < 0) { 68 throw new IllegalArgumentException(); 69 } 70 this.capacity = this.limit = capacity; 71 } 72 73 /** Returns the capacity of this buffer. 74 * 75 * @return the number of elements that are contained in this buffer. 76 * @since Android 1.0 */ capacity()77 public final int capacity () { 78 return capacity; 79 } 80 81 /** Clears this buffer. 82 * <p> 83 * While the content of this buffer is not changed, the following internal changes take place: the current position is reset 84 * back to the start of the buffer, the value of the buffer limit is made equal to the capacity and mark is cleared. 85 * </p> 86 * 87 * @return this buffer. 88 * @since Android 1.0 */ clear()89 public final Buffer clear () { 90 position = 0; 91 mark = UNSET_MARK; 92 limit = capacity; 93 return this; 94 } 95 96 /** Flips this buffer. 97 * <p> 98 * The limit is set to the current position, then the position is set to zero, and the mark is cleared. 99 * </p> 100 * <p> 101 * The content of this buffer is not changed. 102 * </p> 103 * 104 * @return this buffer. 105 * @since Android 1.0 */ flip()106 public final Buffer flip () { 107 limit = position; 108 position = 0; 109 mark = UNSET_MARK; 110 return this; 111 } 112 113 /** Indicates if there are elements remaining in this buffer, that is if {@code position < limit}. 114 * 115 * @return {@code true} if there are elements remaining in this buffer, {@code false} otherwise. 116 * @since Android 1.0 */ hasRemaining()117 public final boolean hasRemaining () { 118 return position < limit; 119 } 120 121 /** Indicates whether this buffer is read-only. 122 * 123 * @return {@code true} if this buffer is read-only, {@code false} otherwise. 124 * @since Android 1.0 */ isReadOnly()125 public abstract boolean isReadOnly (); 126 127 /** Returns the limit of this buffer. 128 * 129 * @return the limit of this buffer. 130 * @since Android 1.0 */ limit()131 public final int limit () { 132 return limit; 133 } 134 135 /** Sets the limit of this buffer. 136 * <p> 137 * If the current position in the buffer is in excess of <code>newLimit</code> then, on returning from this call, it will have 138 * been adjusted to be equivalent to <code>newLimit</code>. If the mark is set and is greater than the new limit, then it is 139 * cleared. 140 * </p> 141 * 142 * @param newLimit the new limit, must not be negative and not greater than capacity. 143 * @return this buffer. 144 * @exception IllegalArgumentException if <code>newLimit</code> is invalid. 145 * @since Android 1.0 */ limit(int newLimit)146 public final Buffer limit (int newLimit) { 147 if (newLimit < 0 || newLimit > capacity) { 148 throw new IllegalArgumentException(); 149 } 150 151 limit = newLimit; 152 if (position > newLimit) { 153 position = newLimit; 154 } 155 if ((mark != UNSET_MARK) && (mark > newLimit)) { 156 mark = UNSET_MARK; 157 } 158 return this; 159 } 160 161 /** Marks the current position, so that the position may return to this point later by calling <code>reset()</code>. 162 * 163 * @return this buffer. 164 * @since Android 1.0 */ mark()165 public final Buffer mark () { 166 mark = position; 167 return this; 168 } 169 170 /** Returns the position of this buffer. 171 * 172 * @return the value of this buffer's current position. 173 * @since Android 1.0 */ position()174 public final int position () { 175 return position; 176 } 177 178 /** Sets the position of this buffer. 179 * <p> 180 * If the mark is set and it is greater than the new position, then it is cleared. 181 * </p> 182 * 183 * @param newPosition the new position, must be not negative and not greater than limit. 184 * @return this buffer. 185 * @exception IllegalArgumentException if <code>newPosition</code> is invalid. 186 * @since Android 1.0 */ position(int newPosition)187 public final Buffer position (int newPosition) { 188 if (newPosition < 0 || newPosition > limit) { 189 throw new IllegalArgumentException(); 190 } 191 192 position = newPosition; 193 if ((mark != UNSET_MARK) && (mark > position)) { 194 mark = UNSET_MARK; 195 } 196 return this; 197 } 198 199 /** Returns the number of remaining elements in this buffer, that is {@code limit - position}. 200 * 201 * @return the number of remaining elements in this buffer. 202 * @since Android 1.0 */ remaining()203 public final int remaining () { 204 return limit - position; 205 } 206 207 /** Resets the position of this buffer to the <code>mark</code>. 208 * 209 * @return this buffer. 210 * @exception InvalidMarkException if the mark is not set. 211 * @since Android 1.0 */ reset()212 public final Buffer reset () { 213 if (mark == UNSET_MARK) { 214 throw new InvalidMarkException(); 215 } 216 position = mark; 217 return this; 218 } 219 220 /** Rewinds this buffer. 221 * <p> 222 * The position is set to zero, and the mark is cleared. The content of this buffer is not changed. 223 * </p> 224 * 225 * @return this buffer. 226 * @since Android 1.0 */ rewind()227 public final Buffer rewind () { 228 position = 0; 229 mark = UNSET_MARK; 230 return this; 231 } 232 } 233