1. /*
  2. * @(#)Buffer.java 1.29 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.nio;
  8. /**
  9. * A container for data of a specific primitive type.
  10. *
  11. * <p> A buffer is a linear, finite sequence of elements of a specific
  12. * primitive type. Aside from its content, the essential properties of a
  13. * buffer are its capacity, limit, and position: </p>
  14. *
  15. * <blockquote>
  16. *
  17. * <p> A buffer's <i>capacity</i> is the number of elements it contains. The
  18. * capacity of a buffer is never negative and never changes. </p>
  19. *
  20. * <p> A buffer's <i>limit</i> is the index of the first element that should
  21. * not be read or written. A buffer's limit is never negative and is never
  22. * greater than the its capacity. </p>
  23. *
  24. * <p> A buffer's <i>position</i> is the index of the next element to be
  25. * read or written. A buffer's position is never negative and is never
  26. * greater than its limit. </p>
  27. *
  28. * </blockquote>
  29. *
  30. * <p> There is one subclass of this class for each non-boolean primitive type.
  31. *
  32. *
  33. * <h4> Transferring data </h4>
  34. *
  35. * <p> Each subclass of this class defines two categories of <i>get</i> and
  36. * <i>put</i> operations: </p>
  37. *
  38. * <blockquote>
  39. *
  40. * <p> <i>Relative</i> operations read or write one or more elements starting
  41. * at the current position and then increment the position by the number of
  42. * elements transferred. If the requested transfer exceeds the limit then a
  43. * relative <i>get</i> operation throws a {@link BufferUnderflowException}
  44. * and a relative <i>put</i> operation throws a {@link
  45. * BufferOverflowException}; in either case, no data is transferred. </p>
  46. *
  47. * <p> <i>Absolute</i> operations take an explicit element index and do not
  48. * affect the position. Absolute <i>get</i> and <i>put</i> operations throw
  49. * an {@link IndexOutOfBoundsException} if the index argument exceeds the
  50. * limit. </p>
  51. *
  52. * </blockquote>
  53. *
  54. * <p> Data may also, of course, be transferred in to or out of a buffer by the
  55. * I/O operations of an appropriate channel, which are always relative to the
  56. * current position.
  57. *
  58. *
  59. * <h4> Marking and resetting </h4>
  60. *
  61. * <p> A buffer's <i>mark</i> is the index to which its position will be reset
  62. * when the {@link #reset reset} method is invoked. The mark is not always
  63. * defined, but when it is defined it is never negative and is never greater
  64. * than the position. If the mark is defined then it is discarded when the
  65. * position or the limit is adjusted to a value smaller than the mark. If the
  66. * mark is not defined then invoking the {@link #reset reset} method causes an
  67. * {@link InvalidMarkException} to be thrown.
  68. *
  69. *
  70. * <h4> Invariants </h4>
  71. *
  72. * <p> The following invariant holds for the mark, position, limit, and
  73. * capacity values:
  74. *
  75. * <blockquote>
  76. * <tt>0</tt> <tt><=</tt>
  77. * <i>mark</i> <tt><=</tt>
  78. * <i>position</i> <tt><=</tt>
  79. * <i>limit</i> <tt><=</tt>
  80. * <i>capacity</i>
  81. * </blockquote>
  82. *
  83. * <p> A newly-created buffer always has a position of zero and a mark that is
  84. * undefined. The initial limit may be zero, or it may be some other value
  85. * that depends upon the type of the buffer and the manner in which it is
  86. * constructed. The initial content of a buffer is, in general,
  87. * undefined.
  88. *
  89. *
  90. * <h4> Clearing, flipping, and rewinding </h4>
  91. *
  92. * <p> In addition to methods for accessing the position, limit, and capacity
  93. * values and for marking and resetting, this class also defines the following
  94. * operations upon buffers:
  95. *
  96. * <ul>
  97. *
  98. * <li><p> {@link #clear} makes a buffer ready for a new sequence of
  99. * channel-read or relative <i>put</i> operations: It sets the limit to the
  100. * capacity and the position to zero. </p></li>
  101. *
  102. * <li><p> {@link #flip} makes a buffer ready for a new sequence of
  103. * channel-write or relative <i>get</i> operations: It sets the limit to the
  104. * current position and then sets the position to zero. </p></li>
  105. *
  106. * <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
  107. * it already contains: It leaves the limit unchanged and sets the position
  108. * to zero. </p></li>
  109. *
  110. * </ul>
  111. *
  112. *
  113. * <h4> Read-only buffers </h4>
  114. *
  115. * <p> Every buffer is readable, but not every buffer is writable. The
  116. * mutation methods of each buffer class are specified as <i>optional
  117. * operations</i> that will throw a {@link ReadOnlyBufferException} when
  118. * invoked upon a read-only buffer. A read-only buffer does not allow its
  119. * content to be changed, but its mark, position, and limit values are mutable.
  120. * Whether or not a buffer is read-only may be determined by invoking its
  121. * {@link #isReadOnly isReadOnly} method.
  122. *
  123. *
  124. * <h4> Thread safety </h4>
  125. *
  126. * <p> Buffers are not safe for use by multiple concurrent threads. If a
  127. * buffer is to be used by more than one thread then access to the buffer
  128. * should be controlled by appropriate synchronization.
  129. *
  130. *
  131. * <h4> Invocation chaining </h4>
  132. *
  133. * <p> Methods in this class that do not otherwise have a value to return are
  134. * specified to return the buffer upon which they are invoked. This allows
  135. * method invocations to be chained; for example, the sequence of statements
  136. *
  137. * <blockquote><pre>
  138. * b.flip();
  139. * b.position(23);
  140. * b.limit(42);</pre></blockquote>
  141. *
  142. * can be replaced by the single, more compact statement
  143. *
  144. * <blockquote><pre>
  145. * b.flip().position(23).limit(42);</pre></blockquote>
  146. *
  147. *
  148. * @author Mark Reinhold
  149. * @author JSR-51 Expert Group
  150. * @version 1.29, 03/01/23
  151. * @since 1.4
  152. */
  153. public abstract class Buffer {
  154. // Invariants: mark <= position <= limit <= capacity
  155. private int mark = -1;
  156. private int position = 0;
  157. private int limit;
  158. private int capacity;
  159. // Used only by direct buffers
  160. // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
  161. long address;
  162. // Creates a new buffer with the given mark, position, limit, and capacity,
  163. // after checking invariants.
  164. //
  165. Buffer(int mark, int pos, int lim, int cap) { // package-private
  166. if (cap < 0)
  167. throw new IllegalArgumentException();
  168. this.capacity = cap;
  169. limit(lim);
  170. position(pos);
  171. if (mark > 0) {
  172. if (mark > pos)
  173. throw new IllegalArgumentException();
  174. this.mark = mark;
  175. }
  176. }
  177. /**
  178. * Returns this buffer's capacity. </p>
  179. *
  180. * @return The capacity of this buffer
  181. */
  182. public final int capacity() {
  183. return capacity;
  184. }
  185. /**
  186. * Returns this buffer's position. </p>
  187. *
  188. * @return The position of this buffer
  189. */
  190. public final int position() {
  191. return position;
  192. }
  193. /**
  194. * Sets this buffer's position. If the mark is defined and larger than the
  195. * new position then it is discarded. </p>
  196. *
  197. * @param newPosition
  198. * The new position value; must be non-negative
  199. * and no larger than the current limit
  200. *
  201. * @return This buffer
  202. *
  203. * @throws IllegalArgumentException
  204. * If the preconditions on <tt>newPosition</tt> do not hold
  205. */
  206. public final Buffer position(int newPosition) {
  207. if ((newPosition > limit) || (newPosition < 0))
  208. throw new IllegalArgumentException();
  209. position = newPosition;
  210. if (mark > position) mark = -1;
  211. return this;
  212. }
  213. /**
  214. * Returns this buffer's limit. </p>
  215. *
  216. * @return The limit of this buffer
  217. */
  218. public final int limit() {
  219. return limit;
  220. }
  221. /**
  222. * Sets this buffer's limit. If the position is larger than the new limit
  223. * then it is set to the new limit. If the mark is defined and larger than
  224. * the new limit then it is discarded. </p>
  225. *
  226. * @param newLimit
  227. * The new limit value; must be non-negative
  228. * and no larger than this buffer's capacity
  229. *
  230. * @return This buffer
  231. *
  232. * @throws IllegalArgumentException
  233. * If the preconditions on <tt>newLimit</tt> do not hold
  234. */
  235. public final Buffer limit(int newLimit) {
  236. if ((newLimit > capacity) || (newLimit < 0))
  237. throw new IllegalArgumentException();
  238. limit = newLimit;
  239. if (position > limit) position = limit;
  240. if (mark > limit) mark = -1;
  241. return this;
  242. }
  243. /**
  244. * Sets this buffer's mark at its position. </p>
  245. *
  246. * @return This buffer
  247. */
  248. public final Buffer mark() {
  249. mark = position;
  250. return this;
  251. }
  252. /**
  253. * Resets this buffer's position to the previously-marked position.
  254. *
  255. * <p> Invoking this method neither changes nor discards the mark's
  256. * value. </p>
  257. *
  258. * @return This buffer
  259. *
  260. * @throws InvalidMarkException
  261. * If the mark has not been set
  262. */
  263. public final Buffer reset() {
  264. int m = mark;
  265. if (m < 0)
  266. throw new InvalidMarkException();
  267. position = m;
  268. return this;
  269. }
  270. /**
  271. * Clears this buffer. The position is set to zero, the limit is set to
  272. * the capacity, and the mark is discarded.
  273. *
  274. * <p> Invoke this method before using a sequence of channel-read or
  275. * <i>put</i> operations to fill this buffer. For example:
  276. *
  277. * <blockquote><pre>
  278. * buf.clear(); // Prepare buffer for reading
  279. * in.read(buf); // Read data</pre></blockquote>
  280. *
  281. * <p> This method does not actually erase the data in the buffer, but it
  282. * is named as if it did because it will most often be used in situations
  283. * in which that might as well be the case. </p>
  284. *
  285. * @return This buffer
  286. */
  287. public final Buffer clear() {
  288. position = 0;
  289. limit = capacity;
  290. mark = -1;
  291. return this;
  292. }
  293. /**
  294. * Flips this buffer. The limit is set to the current position and then
  295. * the position is set to zero. If the mark is defined then it is
  296. * discarded.
  297. *
  298. * <p> After a sequence of channel-read or <i>put</i> operations, invoke
  299. * this method to prepare for a sequence of channel-write or relative
  300. * <i>get</i> operations. For example:
  301. *
  302. * <blockquote><pre>
  303. * buf.put(magic); // Prepend header
  304. * in.read(buf); // Read data into rest of buffer
  305. * buf.flip(); // Flip buffer
  306. * out.write(buf); // Write header + data to channel</pre></blockquote>
  307. *
  308. * <p> This method is often used in conjunction with the {@link
  309. * java.nio.ByteBuffer#compact compact} method when transferring data from
  310. * one place to another. </p>
  311. *
  312. * @return This buffer
  313. */
  314. public final Buffer flip() {
  315. limit = position;
  316. position = 0;
  317. mark = -1;
  318. return this;
  319. }
  320. /**
  321. * Rewinds this buffer. The position is set to zero and the mark is
  322. * discarded.
  323. *
  324. * <p> Invoke this method before a sequence of channel-write or <i>get</i>
  325. * operations, assuming that the limit has already been set
  326. * appropriately. For example:
  327. *
  328. * <blockquote><pre>
  329. * out.write(buf); // Write remaining data
  330. * buf.rewind(); // Rewind buffer
  331. * buf.get(array); // Copy data into array</pre></blockquote>
  332. *
  333. * @return This buffer
  334. */
  335. public final Buffer rewind() {
  336. position = 0;
  337. mark = -1;
  338. return this;
  339. }
  340. /**
  341. * Returns the number of elements between the current position and the
  342. * limit. </p>
  343. *
  344. * @return The number of elements remaining in this buffer
  345. */
  346. public final int remaining() {
  347. return limit - position;
  348. }
  349. /**
  350. * Tells whether there are any elements between the current position and
  351. * the limit. </p>
  352. *
  353. * @return <tt>true</tt> if, and only if, there is at least one element
  354. * remaining in this buffer
  355. */
  356. public final boolean hasRemaining() {
  357. return position < limit;
  358. }
  359. /**
  360. * Tells whether or not this buffer is read-only. </p>
  361. *
  362. * @return <tt>true</tt> if, and only if, this buffer is read-only
  363. */
  364. public abstract boolean isReadOnly();
  365. // -- Package-private methods for bounds checking, etc. --
  366. /**
  367. * Checks the current position against the limit, throwing a {@link
  368. * BufferUnderflowException} if it is not smaller than the limit, and then
  369. * increments the position. </p>
  370. *
  371. * @return The current position value, before it is incremented
  372. */
  373. final int nextGetIndex() { // package-private
  374. if (position >= limit)
  375. throw new BufferUnderflowException();
  376. return position++;
  377. }
  378. final int nextGetIndex(int nb) { // package-private
  379. if (position + nb > limit)
  380. throw new BufferUnderflowException();
  381. int p = position;
  382. position += nb;
  383. return p;
  384. }
  385. /**
  386. * Checks the current position against the limit, throwing a {@link
  387. * BufferOverflowException} if it is not smaller than the limit, and then
  388. * increments the position. </p>
  389. *
  390. * @return The current position value, before it is incremented
  391. */
  392. final int nextPutIndex() { // package-private
  393. if (position >= limit)
  394. throw new BufferOverflowException();
  395. return position++;
  396. }
  397. final int nextPutIndex(int nb) { // package-private
  398. if (position + nb > limit)
  399. throw new BufferOverflowException();
  400. int p = position;
  401. position += nb;
  402. return p;
  403. }
  404. /**
  405. * Checks the given index against the limit, throwing an {@link
  406. * IndexOutOfBoundsException} if it is not smaller than the limit
  407. * or is smaller than zero.
  408. */
  409. final int checkIndex(int i) { // package-private
  410. if ((i < 0) || (i >= limit))
  411. throw new IndexOutOfBoundsException();
  412. return i;
  413. }
  414. final int checkIndex(int i, int nb) { // package-private
  415. if ((i < 0) || (i + nb > limit))
  416. throw new IndexOutOfBoundsException();
  417. return i;
  418. }
  419. final int markValue() { // package-private
  420. return mark;
  421. }
  422. static void checkBounds(int off, int len, int size) { // package-private
  423. if ((off | len | (off + len) | (size - (off + len))) < 0)
  424. throw new IndexOutOfBoundsException();
  425. }
  426. }