CharArrayReader.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /* CharArrayReader.java -- Read an array of characters as a stream
  2. Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.io;
  32. /**
  33. * This class permits an array of chars to be read as an input stream.
  34. *
  35. * @author Aaron M. Renn (arenn@urbanophile.com)
  36. * @author Warren Levy (warrenl@cygnus.com)
  37. */
  38. public class CharArrayReader extends Reader
  39. {
  40. /**
  41. * The array that contains the data supplied during read operations
  42. */
  43. protected char[] buf;
  44. /**
  45. * The array index of the next char to be read from the buffer
  46. * <code>buf</code>
  47. */
  48. protected int pos;
  49. /**
  50. * The currently marked position in the stream. This defaults to 0, so a
  51. * reset operation on the stream resets it to read from array index 0 in
  52. * the buffer - even if the stream was initially created with an offset
  53. * greater than 0
  54. */
  55. protected int markedPos;
  56. /**
  57. * This indicates the maximum number of chars that can be read from this
  58. * stream. It is the array index of the position after the last valid
  59. * char in the buffer <code>buf</code>
  60. */
  61. protected int count;
  62. /**
  63. * Create a new CharArrayReader that will read chars from the passed
  64. * in char array. This stream will read from the beginning to the end
  65. * of the array. It is identical to calling an overloaded constructor
  66. * as <code>CharArrayReader(buf, 0, buf.length)</code>.
  67. * <p>
  68. * Note that this array is not copied. If its contents are changed
  69. * while this stream is being read, those changes will be reflected in the
  70. * chars supplied to the reader. Please use caution in changing the
  71. * contents of the buffer while this stream is open.
  72. *
  73. * @param buffer The char array buffer this stream will read from.
  74. */
  75. public CharArrayReader(char[] buffer)
  76. {
  77. this(buffer, 0, buffer.length);
  78. }
  79. /**
  80. * Create a new CharArrayReader that will read chars from the passed
  81. * in char array. This stream will read from position
  82. * <code>offset</code> in the array for a length of
  83. * <code>length</code> chars past <code>offset</code>. If the
  84. * stream is reset to a position before <code>offset</code> then
  85. * more than <code>length</code> chars can be read from the stream.
  86. * The <code>length</code> value should be viewed as the array index
  87. * one greater than the last position in the buffer to read.
  88. * <p>
  89. * Note that this array is not copied. If its contents are changed
  90. * while this stream is being read, those changes will be reflected in the
  91. * chars supplied to the reader. Please use caution in changing the
  92. * contents of the buffer while this stream is open.
  93. *
  94. * @param buffer The char array buffer this stream will read from.
  95. * @param offset The index into the buffer to start reading chars from
  96. * @param length The number of chars to read from the buffer
  97. */
  98. public CharArrayReader(char[] buffer, int offset, int length)
  99. {
  100. super();
  101. if (offset < 0 || length < 0 || offset > buffer.length)
  102. throw new IllegalArgumentException();
  103. buf = buffer;
  104. count = offset + length;
  105. if (count > buf.length)
  106. count = buf.length;
  107. pos = offset;
  108. markedPos = pos;
  109. }
  110. /**
  111. * This method closes the stream.
  112. */
  113. public void close()
  114. {
  115. synchronized (lock)
  116. {
  117. buf = null;
  118. }
  119. }
  120. /**
  121. * This method sets the mark position in this stream to the current
  122. * position. Note that the <code>readlimit</code> parameter in this
  123. * method does nothing as this stream is always capable of
  124. * remembering all the chars int it.
  125. * <p>
  126. * Note that in this class the mark position is set by default to
  127. * position 0 in the stream. This is in constrast to some other
  128. * stream types where there is no default mark position.
  129. *
  130. * @param readAheadLimit The number of chars this stream must
  131. * remember. This parameter is ignored.
  132. *
  133. * @exception IOException If an error occurs
  134. */
  135. public void mark(int readAheadLimit) throws IOException
  136. {
  137. synchronized (lock)
  138. {
  139. if (buf == null)
  140. throw new IOException("Stream closed");
  141. // readAheadLimit is ignored per Java Class Lib. book, p. 318.
  142. markedPos = pos;
  143. }
  144. }
  145. /**
  146. * This method overrides the <code>markSupported</code> method in
  147. * <code>Reader</code> in order to return <code>true</code> -
  148. * indicating that this stream class supports mark/reset
  149. * functionality.
  150. *
  151. * @return <code>true</code> to indicate that this class supports
  152. * mark/reset.
  153. */
  154. public boolean markSupported()
  155. {
  156. return true;
  157. }
  158. /**
  159. * This method reads one char from the stream. The <code>pos</code>
  160. * counter is advanced to the next char to be read. The char read
  161. * is returned as an int in the range of 0-65535. If the stream
  162. * position is already at the end of the buffer, no char is read and
  163. * a -1 is returned in order to indicate the end of the stream.
  164. *
  165. * @return The char read, or -1 if end of stream
  166. */
  167. public int read() throws IOException
  168. {
  169. synchronized (lock)
  170. {
  171. if (buf == null)
  172. throw new IOException("Stream closed");
  173. if (pos < 0)
  174. throw new ArrayIndexOutOfBoundsException(pos);
  175. if (pos < count)
  176. return ((int) buf[pos++]) & 0xFFFF;
  177. return -1;
  178. }
  179. }
  180. /**
  181. * This method reads chars from the stream and stores them into a
  182. * caller supplied buffer. It starts storing the data at index
  183. * <code>offset</code> into the buffer and attempts to read
  184. * <code>len</code> chars. This method can return before reading
  185. * the number of chars requested if the end of the stream is
  186. * encountered first. The actual number of chars read is returned.
  187. * If no chars can be read because the stream is already at the end
  188. * of stream position, a -1 is returned.
  189. * <p>
  190. * This method does not block.
  191. *
  192. * @param b The array into which the chars read should be stored.
  193. * @param off The offset into the array to start storing chars
  194. * @param len The requested number of chars to read
  195. *
  196. * @return The actual number of chars read, or -1 if end of stream.
  197. */
  198. public int read(char[] b, int off, int len) throws IOException
  199. {
  200. synchronized (lock)
  201. {
  202. if (buf == null)
  203. throw new IOException("Stream closed");
  204. /* Don't need to check pos value, arraycopy will check it. */
  205. if (off < 0 || len < 0 || off + len > b.length)
  206. throw new IndexOutOfBoundsException();
  207. if (pos >= count)
  208. return -1;
  209. int numChars = Math.min(count - pos, len);
  210. System.arraycopy(buf, pos, b, off, numChars);
  211. pos += numChars;
  212. return numChars;
  213. }
  214. }
  215. /**
  216. * Return true if more characters are available to be read.
  217. *
  218. * @return <code>true</code> to indicate that this stream is ready
  219. * to be read.
  220. *
  221. * @specnote The JDK 1.3 API docs are wrong here. This method will
  222. * return false if there are no more characters available.
  223. */
  224. public boolean ready() throws IOException
  225. {
  226. if (buf == null)
  227. throw new IOException("Stream closed");
  228. return (pos < count);
  229. }
  230. /**
  231. * This method sets the read position in the stream to the mark
  232. * point by setting the <code>pos</code> variable equal to the
  233. * <code>mark</code> variable. Since a mark can be set anywhere in
  234. * the array, the mark/reset methods int this class can be used to
  235. * provide random search capabilities for this type of stream.
  236. */
  237. public void reset() throws IOException
  238. {
  239. synchronized (lock)
  240. {
  241. if (buf == null)
  242. throw new IOException("Stream closed");
  243. pos = markedPos;
  244. }
  245. }
  246. /**
  247. * This method attempts to skip the requested number of chars in the
  248. * input stream. It does this by advancing the <code>pos</code> value by the
  249. * specified number of chars. It this would exceed the length of the
  250. * buffer, then only enough chars are skipped to position the stream at
  251. * the end of the buffer. The actual number of chars skipped is returned.
  252. *
  253. * @param n The requested number of chars to skip
  254. *
  255. * @return The actual number of chars skipped.
  256. */
  257. public long skip(long n) throws IOException
  258. {
  259. synchronized (lock)
  260. {
  261. if (buf == null)
  262. throw new IOException("Stream closed");
  263. // Even though the var numChars is a long, in reality it can never
  264. // be larger than an int since the result of subtracting 2 positive
  265. // ints will always fit in an int. Since we have to return a long
  266. // anyway, numChars might as well just be a long.
  267. long numChars = Math.min((long) (count - pos), n < 0 ? 0L : n);
  268. pos += numChars;
  269. return numChars;
  270. }
  271. }
  272. }