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