Source code: gnu/xml/dom/ls/ReaderInputStream.java
1 /* ReaderInputStream.java --
2 Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package gnu.xml.dom.ls;
39
40 import java.io.InputStream;
41 import java.io.IOException;
42 import java.io.Reader;
43
44 /**
45 * Character stream wrapper.
46 *
47 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
48 * @author <a href='mailto:mark@klomp.org'>Mark Wielaard</a>
49 */
50 public class ReaderInputStream
51 extends InputStream
52 {
53
54 private Reader reader;
55 private String encoding;
56
57 // Holds extra spillover data if necessary
58 private byte extra[];
59 private int pos;
60
61 private byte extra_marked[];
62 private int pos_marked;
63
64 public ReaderInputStream(Reader reader)
65 {
66 this.reader = reader;
67 this.encoding = "UTF-8";
68 }
69
70 void setEncoding(String encoding)
71 {
72 this.encoding = encoding;
73 }
74
75 public int read()
76 throws IOException
77 {
78 if (extra != null)
79 {
80 int result = extra[pos];
81 pos++;
82 if (pos >= extra.length)
83 {
84 extra = null;
85 }
86 return result;
87 }
88 return reader.read();
89 }
90
91 public int read(byte[] b)
92 throws IOException
93 {
94 return read(b, 0, b.length);
95 }
96
97 public int read(byte[] b, int off, int len)
98 throws IOException
99 {
100 if (len == 0)
101 {
102 return 0;
103 }
104
105 if (extra != null)
106 {
107 int available = extra.length - pos;
108 int l = available < len ? available : len;
109 System.arraycopy(extra, 0, b, off, l);
110 pos += l;
111 if (pos >= extra.length)
112 {
113 extra = null;
114 }
115 return l;
116 }
117
118 char[] c = new char[len];
119 int l = reader.read(c, 0, len);
120 if (l == -1)
121 {
122 return -1;
123 }
124
125 String s = new String(c, 0, l);
126 byte[] d = s.getBytes(encoding);
127
128 int available = d.length;
129 int more = d.length - len;
130 if (more > 0)
131 {
132 extra = new byte[more];
133 pos = 0;
134 System.arraycopy(d, len, extra, 0, more);
135 available -= more;
136 }
137
138 System.arraycopy(d, 0, b, off, available);
139 return available;
140 }
141
142 public void close()
143 throws IOException
144 {
145 reader.close();
146 }
147
148 public boolean markSupported()
149 {
150 return reader.markSupported();
151 }
152
153 public void mark(int limit)
154 {
155 if (extra != null)
156 {
157 extra_marked = new byte[extra.length];
158 System.arraycopy(extra, 0, extra_marked, 0, extra.length);
159 pos_marked = pos;
160 }
161 else
162 {
163 extra_marked = null;
164 }
165
166 try
167 {
168 // Note that this might be a bit more than asked for.
169 // Because we might also have the extra_marked bytes.
170 // That is fine (and necessary for reset() to work).
171 reader.mark(limit);
172 }
173 catch (IOException ioe)
174 {
175 throw new RuntimeException(ioe);
176 }
177 }
178
179 public void reset()
180 throws IOException
181 {
182 extra = extra_marked;
183 pos = pos_marked;
184 extra_marked = null;
185
186 reader.reset();
187 }
188
189 public long skip(long n)
190 throws IOException
191 {
192 long done = 0;
193 if (extra != null)
194 {
195 int available = extra.length - pos;
196 done = available < n ? available : n;
197 pos += done;
198 if (pos >= extra.length)
199 {
200 extra = null;
201 }
202 }
203
204 n -= done;
205 if (n > 0)
206 {
207 return reader.skip(n) + done;
208 }
209 else
210 {
211 return done;
212 }
213 }
214
215 /**
216 * Returns conservative number of bytes available without blocking.
217 * Actual number of bytes that can be read without blocking might
218 * be (much) bigger.
219 */
220 public int available()
221 throws IOException
222 {
223 if (extra != null)
224 {
225 return pos - extra.length;
226 }
227
228 return reader.ready() ? 1 : 0;
229 }
230
231 public String toString()
232 {
233 return getClass().getName() + "[" + reader + ", " + encoding + "]";
234 }
235
236 }
237