1. /*
  2. * @(#)CharArrayReader.java 1.22 04/02/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. /**
  9. * This class implements a character buffer that can be used as a
  10. * character-input stream.
  11. *
  12. * @author Herb Jellinek
  13. * @version 1.22, 02/19/04
  14. * @since JDK1.1
  15. */
  16. public
  17. class CharArrayReader extends Reader {
  18. /** The character buffer. */
  19. protected char buf[];
  20. /** The current buffer position. */
  21. protected int pos;
  22. /** The position of mark in buffer. */
  23. protected int markedPos = 0;
  24. /**
  25. * The index of the end of this buffer. There is not valid
  26. * data at or beyond this index.
  27. */
  28. protected int count;
  29. /**
  30. * Create an CharArrayReader from the specified array of chars.
  31. * @param buf Input buffer (not copied)
  32. */
  33. public CharArrayReader(char buf[]) {
  34. this.buf = buf;
  35. this.pos = 0;
  36. this.count = buf.length;
  37. }
  38. /**
  39. * Create an CharArrayReader from the specified array of chars.
  40. *
  41. * <p> The resulting reader will start reading at the given
  42. * <tt>offset</tt>. The total number of <tt>char</tt> values that can be
  43. * read from this reader will be either <tt>length</tt> or
  44. * <tt>buf.length-offset<tt>, whichever is smaller.
  45. *
  46. * @throws IllegalArgumentException
  47. * If <tt>offset</tt> is negative or greater than
  48. * <tt>buf.length</tt>, or if <tt>length</tt> is negative, or if
  49. * the sum of these two values is negative.
  50. *
  51. * @param buf Input buffer (not copied)
  52. * @param offset Offset of the first char to read
  53. * @param length Number of chars to read
  54. */
  55. public CharArrayReader(char buf[], int offset, int length) {
  56. if ((offset < 0) || (offset > buf.length) || (length < 0) ||
  57. ((offset + length) < 0)) {
  58. throw new IllegalArgumentException();
  59. }
  60. this.buf = buf;
  61. this.pos = offset;
  62. this.count = Math.min(offset + length, buf.length);
  63. this.markedPos = offset;
  64. }
  65. /** Check to make sure that the stream has not been closed */
  66. private void ensureOpen() throws IOException {
  67. if (buf == null)
  68. throw new IOException("Stream closed");
  69. }
  70. /**
  71. * Read a single character.
  72. *
  73. * @exception IOException If an I/O error occurs
  74. */
  75. public int read() throws IOException {
  76. synchronized (lock) {
  77. ensureOpen();
  78. if (pos >= count)
  79. return -1;
  80. else
  81. return buf[pos++];
  82. }
  83. }
  84. /**
  85. * Read characters into a portion of an array.
  86. * @param b Destination buffer
  87. * @param off Offset at which to start storing characters
  88. * @param len Maximum number of characters to read
  89. * @return The actual number of characters read, or -1 if
  90. * the end of the stream has been reached
  91. *
  92. * @exception IOException If an I/O error occurs
  93. */
  94. public int read(char b[], int off, int len) throws IOException {
  95. synchronized (lock) {
  96. ensureOpen();
  97. if ((off < 0) || (off > b.length) || (len < 0) ||
  98. ((off + len) > b.length) || ((off + len) < 0)) {
  99. throw new IndexOutOfBoundsException();
  100. } else if (len == 0) {
  101. return 0;
  102. }
  103. if (pos >= count) {
  104. return -1;
  105. }
  106. if (pos + len > count) {
  107. len = count - pos;
  108. }
  109. if (len <= 0) {
  110. return 0;
  111. }
  112. System.arraycopy(buf, pos, b, off, len);
  113. pos += len;
  114. return len;
  115. }
  116. }
  117. /**
  118. * Skip characters. Returns the number of characters that were skipped.
  119. *
  120. * <p>The <code>n</code> parameter may be negative, even though the
  121. * <code>skip</code> method of the {@link Reader} superclass throws
  122. * an exception in this case. If <code>n</code> is negative, then
  123. * this method does nothing and returns <code>0</code>.
  124. *
  125. * @param n The number of characters to skip
  126. * @return The number of characters actually skipped
  127. * @exception IOException If the stream is closed, or an I/O error occurs
  128. */
  129. public long skip(long n) throws IOException {
  130. synchronized (lock) {
  131. ensureOpen();
  132. if (pos + n > count) {
  133. n = count - pos;
  134. }
  135. if (n < 0) {
  136. return 0;
  137. }
  138. pos += n;
  139. return n;
  140. }
  141. }
  142. /**
  143. * Tell whether this stream is ready to be read. Character-array readers
  144. * are always ready to be read.
  145. *
  146. * @exception IOException If an I/O error occurs
  147. */
  148. public boolean ready() throws IOException {
  149. synchronized (lock) {
  150. ensureOpen();
  151. return (count - pos) > 0;
  152. }
  153. }
  154. /**
  155. * Tell whether this stream supports the mark() operation, which it does.
  156. */
  157. public boolean markSupported() {
  158. return true;
  159. }
  160. /**
  161. * Mark the present position in the stream. Subsequent calls to reset()
  162. * will reposition the stream to this point.
  163. *
  164. * @param readAheadLimit Limit on the number of characters that may be
  165. * read while still preserving the mark. Because
  166. * the stream's input comes from a character array,
  167. * there is no actual limit; hence this argument is
  168. * ignored.
  169. *
  170. * @exception IOException If an I/O error occurs
  171. */
  172. public void mark(int readAheadLimit) throws IOException {
  173. synchronized (lock) {
  174. ensureOpen();
  175. markedPos = pos;
  176. }
  177. }
  178. /**
  179. * Reset the stream to the most recent mark, or to the beginning if it has
  180. * never been marked.
  181. *
  182. * @exception IOException If an I/O error occurs
  183. */
  184. public void reset() throws IOException {
  185. synchronized (lock) {
  186. ensureOpen();
  187. pos = markedPos;
  188. }
  189. }
  190. /**
  191. * Close the stream.
  192. */
  193. public void close() {
  194. buf = null;
  195. }
  196. }