1. /*
  2. * @(#)CharArrayReader.java 1.13 01/11/29
  3. *
  4. * Copyright 2002 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.13, 11/29/01
  14. * @since JDK1.1
  15. */
  16. public
  17. class CharArrayReader extends Reader {
  18. /** Character buffer */
  19. protected char buf[];
  20. /** Current buffer position */
  21. protected int pos;
  22. /** Position of mark in buffer */
  23. protected int markedPos = 0;
  24. /** Number of valid characters in buffer */
  25. protected int count;
  26. /**
  27. * Create an CharArrayReader from the specified array of chars.
  28. * @param buf Input buffer (not copied)
  29. */
  30. public CharArrayReader(char buf[]) {
  31. this.buf = buf;
  32. this.pos = 0;
  33. this.count = buf.length;
  34. }
  35. /**
  36. * Create an CharArrayReader from the specified array of chars.
  37. * @param buf Input buffer (not copied)
  38. * @param offset Offset of the first char to read
  39. * @param length Number of chars to read
  40. */
  41. public CharArrayReader(char buf[], int offset, int length) {
  42. if ((offset < 0) || (offset > buf.length) || (length < 0) ||
  43. ((offset + length) < 0)) {
  44. throw new IllegalArgumentException();
  45. }
  46. this.buf = buf;
  47. this.pos = offset;
  48. this.count = Math.min(offset + length, buf.length);
  49. this.markedPos = offset;
  50. }
  51. /** Check to make sure that the stream has not been closed */
  52. private void ensureOpen() throws IOException {
  53. if (buf == null)
  54. throw new IOException("Stream closed");
  55. }
  56. /**
  57. * Read a single character.
  58. *
  59. * @exception IOException If an I/O error occurs
  60. */
  61. public int read() throws IOException {
  62. synchronized (lock) {
  63. ensureOpen();
  64. if (pos >= count)
  65. return -1;
  66. else
  67. return buf[pos++];
  68. }
  69. }
  70. /**
  71. * Read characters into a portion of an array.
  72. * @param b Destination buffer
  73. * @param off Offset at which to start storing characters
  74. * @param len Maximum number of characters to read
  75. * @return The actual number of characters read, or -1 if
  76. * the end of the stream has been reached
  77. *
  78. * @exception IOException If an I/O error occurs
  79. */
  80. public int read(char b[], int off, int len) throws IOException {
  81. synchronized (lock) {
  82. ensureOpen();
  83. if ((off < 0) || (off > b.length) || (len < 0) ||
  84. ((off + len) > b.length) || ((off + len) < 0)) {
  85. throw new IndexOutOfBoundsException();
  86. } else if (len == 0) {
  87. return 0;
  88. }
  89. if (pos >= count) {
  90. return -1;
  91. }
  92. if (pos + len > count) {
  93. len = count - pos;
  94. }
  95. if (len <= 0) {
  96. return 0;
  97. }
  98. System.arraycopy(buf, pos, b, off, len);
  99. pos += len;
  100. return len;
  101. }
  102. }
  103. /**
  104. * Skip characters.
  105. * @param n The number of characters to skip
  106. * @return The number of characters actually skipped
  107. *
  108. * @exception IOException If an I/O error occurs
  109. */
  110. public long skip(long n) throws IOException {
  111. synchronized (lock) {
  112. ensureOpen();
  113. if (pos + n > count) {
  114. n = count - pos;
  115. }
  116. if (n < 0) {
  117. return 0;
  118. }
  119. pos += n;
  120. return n;
  121. }
  122. }
  123. /**
  124. * Tell whether this stream is ready to be read. Character-array readers
  125. * are always ready to be read.
  126. *
  127. * @exception IOException If an I/O error occurs
  128. */
  129. public boolean ready() throws IOException {
  130. synchronized (lock) {
  131. ensureOpen();
  132. return (count - pos) > 0;
  133. }
  134. }
  135. /**
  136. * Tell whether this stream supports the mark() operation, which it does.
  137. */
  138. public boolean markSupported() {
  139. return true;
  140. }
  141. /**
  142. * Mark the present position in the stream. Subsequent calls to reset()
  143. * will reposition the stream to this point.
  144. *
  145. * @param readAheadLimit Limit on the number of characters that may be
  146. * read while still preserving the mark. Because
  147. * the stream's input comes from a character array,
  148. * there is no actual limit; hence this argument is
  149. * ignored.
  150. *
  151. * @exception IOException If an I/O error occurs
  152. */
  153. public void mark(int readAheadLimit) throws IOException {
  154. synchronized (lock) {
  155. ensureOpen();
  156. markedPos = pos;
  157. }
  158. }
  159. /**
  160. * Reset the stream to the most recent mark, or to the beginning if it has
  161. * never been marked.
  162. *
  163. * @exception IOException If an I/O error occurs
  164. */
  165. public void reset() throws IOException {
  166. synchronized (lock) {
  167. ensureOpen();
  168. pos = markedPos;
  169. }
  170. }
  171. /**
  172. * Close the stream.
  173. */
  174. public void close() {
  175. buf = null;
  176. }
  177. }