1. /*
  2. * @(#)StringReader.java 1.15 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.io;
  11. /**
  12. * A character stream whose source is a string.
  13. *
  14. * @version 1.15, 00/02/02
  15. * @author Mark Reinhold
  16. * @since JDK1.1
  17. */
  18. public class StringReader extends Reader {
  19. private String str;
  20. private int length;
  21. private int next = 0;
  22. private int mark = 0;
  23. /**
  24. * Create a new string reader.
  25. *
  26. * @param s String providing the character stream.
  27. */
  28. public StringReader(String s) {
  29. this.str = s;
  30. this.length = s.length();
  31. }
  32. /** Check to make sure that the stream has not been closed */
  33. private void ensureOpen() throws IOException {
  34. if (str == null)
  35. throw new IOException("Stream closed");
  36. }
  37. /**
  38. * Read a single character.
  39. *
  40. * @return The character read, or -1 if the end of the stream has been
  41. * reached
  42. *
  43. * @exception IOException If an I/O error occurs
  44. */
  45. public int read() throws IOException {
  46. synchronized (lock) {
  47. ensureOpen();
  48. if (next >= length)
  49. return -1;
  50. return str.charAt(next++);
  51. }
  52. }
  53. /**
  54. * Read characters into a portion of an array.
  55. *
  56. * @param cbuf Destination buffer
  57. * @param off Offset at which to start writing characters
  58. * @param len Maximum number of characters to read
  59. *
  60. * @return The number of characters read, or -1 if the end of the
  61. * stream has been reached
  62. *
  63. * @exception IOException If an I/O error occurs
  64. */
  65. public int read(char cbuf[], int off, int len) throws IOException {
  66. synchronized (lock) {
  67. ensureOpen();
  68. if ((off < 0) || (off > cbuf.length) || (len < 0) ||
  69. ((off + len) > cbuf.length) || ((off + len) < 0)) {
  70. throw new IndexOutOfBoundsException();
  71. } else if (len == 0) {
  72. return 0;
  73. }
  74. if (next >= length)
  75. return -1;
  76. int n = Math.min(length - next, len);
  77. str.getChars(next, next + n, cbuf, off);
  78. next += n;
  79. return n;
  80. }
  81. }
  82. /**
  83. * Skip characters.
  84. *
  85. * @exception IOException If an I/O error occurs
  86. */
  87. public long skip(long ns) throws IOException {
  88. synchronized (lock) {
  89. ensureOpen();
  90. if (next >= length)
  91. return 0;
  92. long n = Math.min(length - next, ns);
  93. next += n;
  94. return n;
  95. }
  96. }
  97. /**
  98. * Tell whether this stream is ready to be read.
  99. *
  100. * @return True if the next read() is guaranteed not to block for input
  101. *
  102. * @exception IOException If the stream is closed
  103. */
  104. public boolean ready() throws IOException {
  105. synchronized (lock) {
  106. ensureOpen();
  107. return true;
  108. }
  109. }
  110. /**
  111. * Tell whether this stream supports the mark() operation, which it does.
  112. */
  113. public boolean markSupported() {
  114. return true;
  115. }
  116. /**
  117. * Mark the present position in the stream. Subsequent calls to reset()
  118. * will reposition the stream to this point.
  119. *
  120. * @param readAheadLimit Limit on the number of characters that may be
  121. * read while still preserving the mark. Because
  122. * the stream's input comes from a string, there
  123. * is no actual limit, so this argument must not
  124. * be negative, but is otherwise ignored.
  125. *
  126. * @exception IllegalArgumentException If readAheadLimit is < 0
  127. * @exception IOException If an I/O error occurs
  128. */
  129. public void mark(int readAheadLimit) throws IOException {
  130. if (readAheadLimit < 0){
  131. throw new IllegalArgumentException("Read-ahead limit < 0");
  132. }
  133. synchronized (lock) {
  134. ensureOpen();
  135. mark = next;
  136. }
  137. }
  138. /**
  139. * Reset the stream to the most recent mark, or to the beginning of the
  140. * string if it has never been marked.
  141. *
  142. * @exception IOException If an I/O error occurs
  143. */
  144. public void reset() throws IOException {
  145. synchronized (lock) {
  146. ensureOpen();
  147. next = mark;
  148. }
  149. }
  150. /**
  151. * Close the stream.
  152. */
  153. public void close() {
  154. str = null;
  155. }
  156. }