1 |
/* LineNumberReader.java -- A character input stream which counts line numbers |
/* LineNumberReader.java -- A character input stream which counts line numbers |
2 |
Copyright (C) 1998 Free Software Foundation, Inc. |
Copyright (C) 1998,2003 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
53 |
* read from the stream does not end in a line termination sequence, it |
* read from the stream does not end in a line termination sequence, it |
54 |
* will not be counted as a line. |
* will not be counted as a line. |
55 |
* |
* |
|
* @version 0.0 |
|
|
* |
|
56 |
* @author Aaron M. Renn (arenn@urbanophile.com) |
* @author Aaron M. Renn (arenn@urbanophile.com) |
57 |
*/ |
*/ |
58 |
public class LineNumberReader extends BufferedReader |
public class LineNumberReader extends BufferedReader |
59 |
{ |
{ |
60 |
|
|
61 |
/*************************************************************************/ |
/*************************************************************************/ |
|
|
|
|
/* |
|
|
* Instance Variables |
|
|
*/ |
|
|
|
|
|
/** |
|
|
* This variable is used to keep track of the current line number |
|
|
*/ |
|
|
private int line_number; |
|
|
|
|
|
/** |
|
|
* This variable is used to keep track of the line number that was |
|
|
* current when the <code>mark()</code> method was called. |
|
|
*/ |
|
|
private int marked_line_number; |
|
|
|
|
|
/** |
|
|
* Determines whether or not a '\n' as the first character of a read |
|
|
* is the continuation of a '\r' as the last character of the previous |
|
|
* read or not |
|
|
*/ |
|
|
private boolean continued_newline; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/* |
|
|
* Constructors |
|
|
*/ |
|
|
|
|
|
/** |
|
|
* Create a new <code>LineNumberReader</code> that reads from the |
|
|
* specified subordinate <code>Reader</code>. A default 4096 char sized |
|
|
* buffer will be used for reads. |
|
|
* |
|
|
* @param in The subordinate <code>Reader</code> to read from |
|
|
*/ |
|
|
public |
|
|
LineNumberReader(Reader in) |
|
|
{ |
|
|
this(in, DEFAULT_BUFFER_SIZE); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method initializes a new <code>LineNumberReader</code> to read |
|
|
* from the specified subordinate <code>Reader</code> using the specified |
|
|
* read buffer size. |
|
|
* |
|
|
* @param in The subordinate <code>Reader</code> to read from |
|
|
* @param size The buffer size to use for reading |
|
|
*/ |
|
|
public |
|
|
LineNumberReader(Reader in, int size) |
|
|
{ |
|
|
super(in, size); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/* |
|
|
* Instance Methods |
|
|
*/ |
|
|
|
|
|
/** |
|
|
* This method returns the current line number |
|
|
* |
|
|
* @returns The current line number |
|
|
*/ |
|
|
public int |
|
|
getLineNumber() |
|
|
{ |
|
|
return(line_number); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method sets the current line number to the specified value. |
|
|
* |
|
|
* @param line_number The new line number |
|
|
*/ |
|
|
public void |
|
|
setLineNumber(int line_number) |
|
|
{ |
|
|
this.line_number = line_number; |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method marks a position in the input to which the stream can be |
|
|
* "reset" char calling the <code>reset()</code> method. The parameter |
|
|
* <code>readlimit</code> is the number of chars that can be read from the |
|
|
* stream after setting the mark before the mark becomes invalid. For |
|
|
* example, if <code>mark()</code> is called with a read limit of 10, then when |
|
|
* 11 chars of data are read from the stream before the <code>reset()</code> |
|
|
* method is called, then the mark is invalid and the stream object |
|
|
* instance is not required to remember the mark. |
|
|
* <p> |
|
|
* In this class, this method will remember the current line number as well |
|
|
* as the current position in the stream. When the <code>reset()</code> method |
|
|
* is called, the line number will be restored to the saved line number in |
|
|
* addition to the stream position. |
|
|
* |
|
|
* @param readlimit The number of chars that can be read before the mark becomes invalid |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public void |
|
|
mark(int readlimit) throws IOException |
|
|
{ |
|
|
synchronized (lock) { |
|
|
|
|
|
super.mark(readlimit); |
|
|
|
|
|
marked_line_number = line_number; |
|
|
|
|
|
} // synchronized |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method resets a stream to the point where the <code>mark()</code> method |
|
|
* was called. Any chars that were read after the mark point was set will |
|
|
* be re-read during subsequent reads. |
|
|
* <p> |
|
|
* In this class, this method will also restore the line number that was |
|
|
* current when the <code>mark()</code> method was called. |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public void |
|
|
reset() throws IOException |
|
|
{ |
|
|
synchronized (lock) { |
|
|
|
|
|
super.reset(); |
|
|
|
|
|
line_number = marked_line_number; |
|
|
|
|
|
} // synchronized |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method reads an unsigned char from the input stream and returns it |
|
|
* as an int in the range of 0-255. This method will return -1 if the |
|
|
* end of the stream has been reached. |
|
|
* <p> |
|
|
* Note that if a line termination sequence is encountered (ie, "\r", |
|
|
* "\n", or "\r\n") then that line termination sequence is converted to |
|
|
* a single "\n" value which is returned from this method. This means |
|
|
* that it is possible this method reads two chars from the subordinate |
|
|
* stream instead of just one. |
|
|
* <p> |
|
|
* Note that this method will block until a char of data is available |
|
|
* to be read. |
|
|
* |
|
|
* @return The char read or -1 if end of stream |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public int |
|
|
read() throws IOException |
|
|
{ |
|
|
synchronized (lock) { |
|
|
|
|
|
int char_read = super.read(); |
|
|
|
|
|
if (char_read == '\n') |
|
|
++line_number; |
|
|
|
|
|
if (char_read == '\r') |
|
|
{ |
|
|
int extra_char_read = super.read(); |
|
|
|
|
|
if ((extra_char_read != '\n') && (extra_char_read != -1)) |
|
|
pos--; |
|
|
|
|
|
char_read = '\n'; |
|
|
++line_number; |
|
|
} |
|
|
|
|
|
return(char_read); |
|
|
|
|
|
} // synchronized |
|
|
} |
|
62 |
|
|
63 |
/*************************************************************************/ |
/* |
64 |
|
* Instance Variables |
65 |
/** |
*/ |
66 |
* This method reads chars from a stream and stores them into a caller |
|
67 |
* supplied buffer. It starts storing data at index <code>offset</code> into |
/** |
68 |
* the buffer and attemps to read <code>len</code> chars. This method can |
* This variable is used to keep track of the current line number |
69 |
* return before reading the number of chars requested. The actual number |
*/ |
70 |
* of chars read is returned as an int. A -1 is returned to indicated the |
private int line_number; |
71 |
* end of the stream. |
|
72 |
* <p> |
/** |
73 |
* This method will block until some data can be read. |
* This variable is used to keep track of the line number that was |
74 |
* <p> |
* current when the <code>mark()</code> method was called. |
75 |
* Note that if a line termination sequence is encountered (ie, "\r", |
*/ |
76 |
* "\n", or "\r\n") then that line termination sequence is converted to |
private int marked_line_number; |
77 |
* a single "\n" value which is stored in the buffer. Only a single |
|
78 |
* char is counted towards the number of chars read in this case. |
/** |
79 |
* |
* Determines whether or not a '\n' as the first character of a read |
80 |
* @param buf The array into which the chars read should be stored |
* is the continuation of a '\r' as the last character of the previous |
81 |
* @param offset The offset into the array to start storing chars |
* read or not |
82 |
* @param len The requested number of chars to read |
*/ |
83 |
* |
private boolean continued_newline; |
84 |
* @return The actual number of chars read, or -1 if end of stream |
|
85 |
* |
/*************************************************************************/ |
86 |
* @exception IOException If an error occurs. |
|
87 |
*/ |
/* |
88 |
public int |
* Constructors |
89 |
read(char[] buf, int offset, int len) throws IOException |
*/ |
90 |
{ |
|
91 |
if (len == 0) |
/** |
92 |
return(0); |
* Create a new <code>LineNumberReader</code> that reads from the |
93 |
|
* specified subordinate <code>Reader</code>. A default 4096 char sized |
94 |
synchronized (lock) { |
* buffer will be used for reads. |
95 |
|
* |
96 |
// Read the first char here in order to allow IOException's to |
* @param in The subordinate <code>Reader</code> to read from |
97 |
// propagate up |
*/ |
98 |
int char_read = read(); |
public LineNumberReader(Reader in) |
99 |
if (char_read == -1) |
{ |
100 |
return(-1); |
this(in, DEFAULT_BUFFER_SIZE); |
101 |
buf[offset] = (char)char_read; |
} |
102 |
|
|
103 |
int total_read = 1; |
/*************************************************************************/ |
104 |
|
|
105 |
// Read the rest of the chars. We do this in a single char read() loop, |
/** |
106 |
// which is bad and should be fixed in the future. *****RECODE THIS**** |
* This method initializes a new <code>LineNumberReader</code> to read |
107 |
try |
* from the specified subordinate <code>Reader</code> using the specified |
108 |
{ |
* read buffer size. |
109 |
for (int i = 1; i < len; i++) |
* |
110 |
{ |
* @param in The subordinate <code>Reader</code> to read from |
111 |
char_read = read(); |
* @param size The buffer size to use for reading |
112 |
if (char_read == -1) |
*/ |
113 |
|
public LineNumberReader(Reader in, int size) |
114 |
|
{ |
115 |
|
super(in, size); |
116 |
|
} |
117 |
|
|
118 |
|
/*************************************************************************/ |
119 |
|
|
120 |
|
/* |
121 |
|
* Instance Methods |
122 |
|
*/ |
123 |
|
|
124 |
|
/** |
125 |
|
* This method returns the current line number |
126 |
|
* |
127 |
|
* @returns The current line number |
128 |
|
*/ |
129 |
|
public int getLineNumber() |
130 |
|
{ |
131 |
|
return(line_number); |
132 |
|
} |
133 |
|
|
134 |
|
/*************************************************************************/ |
135 |
|
|
136 |
|
/** |
137 |
|
* This method sets the current line number to the specified value. |
138 |
|
* |
139 |
|
* @param line_number The new line number |
140 |
|
*/ |
141 |
|
public void setLineNumber(int line_number) |
142 |
|
{ |
143 |
|
this.line_number = line_number; |
144 |
|
} |
145 |
|
|
146 |
|
/*************************************************************************/ |
147 |
|
|
148 |
|
/** |
149 |
|
* This method marks a position in the input to which the stream can be |
150 |
|
* "reset" char calling the <code>reset()</code> method. The parameter |
151 |
|
* <code>readlimit</code> is the number of chars that can be read from the |
152 |
|
* stream after setting the mark before the mark becomes invalid. For |
153 |
|
* example, if <code>mark()</code> is called with a read limit of 10, |
154 |
|
* then when |
155 |
|
* 11 chars of data are read from the stream before the <code>reset()</code> |
156 |
|
* method is called, then the mark is invalid and the stream object |
157 |
|
* instance is not required to remember the mark. |
158 |
|
* <p> |
159 |
|
* In this class, this method will remember the current line number as well |
160 |
|
* as the current position in the stream. When the <code>reset()</code> |
161 |
|
* method |
162 |
|
* is called, the line number will be restored to the saved line number in |
163 |
|
* addition to the stream position. |
164 |
|
* |
165 |
|
* @param readlimit The number of chars that can be read before the |
166 |
|
* mark becomes invalid |
167 |
|
* |
168 |
|
* @exception IOException If an error occurs |
169 |
|
*/ |
170 |
|
public void mark(int readlimit) throws IOException |
171 |
|
{ |
172 |
|
synchronized (lock) { |
173 |
|
|
174 |
|
super.mark(readlimit); |
175 |
|
|
176 |
|
marked_line_number = line_number; |
177 |
|
|
178 |
|
} // synchronized |
179 |
|
} |
180 |
|
|
181 |
|
/*************************************************************************/ |
182 |
|
|
183 |
|
/** |
184 |
|
* This method resets a stream to the point where the <code>mark()</code> |
185 |
|
* method |
186 |
|
* was called. Any chars that were read after the mark point was set will |
187 |
|
* be re-read during subsequent reads. |
188 |
|
* <p> |
189 |
|
* In this class, this method will also restore the line number that was |
190 |
|
* current when the <code>mark()</code> method was called. |
191 |
|
* |
192 |
|
* @exception IOException If an error occurs |
193 |
|
*/ |
194 |
|
public void reset() throws IOException |
195 |
|
{ |
196 |
|
synchronized (lock) { |
197 |
|
|
198 |
|
super.reset(); |
199 |
|
|
200 |
|
line_number = marked_line_number; |
201 |
|
|
202 |
|
} // synchronized |
203 |
|
} |
204 |
|
|
205 |
|
/*************************************************************************/ |
206 |
|
|
207 |
|
/** |
208 |
|
* This method reads an unsigned char from the input stream and returns it |
209 |
|
* as an int in the range of 0-255. This method will return -1 if the |
210 |
|
* end of the stream has been reached. |
211 |
|
* <p> |
212 |
|
* Note that if a line termination sequence is encountered (ie, "\r", |
213 |
|
* "\n", or "\r\n") then that line termination sequence is converted to |
214 |
|
* a single "\n" value which is returned from this method. This means |
215 |
|
* that it is possible this method reads two chars from the subordinate |
216 |
|
* stream instead of just one. |
217 |
|
* <p> |
218 |
|
* Note that this method will block until a char of data is available |
219 |
|
* to be read. |
220 |
|
* |
221 |
|
* @return The char read or -1 if end of stream |
222 |
|
* |
223 |
|
* @exception IOException If an error occurs |
224 |
|
*/ |
225 |
|
public int read() throws IOException |
226 |
|
{ |
227 |
|
synchronized (lock) |
228 |
|
{ |
229 |
|
int char_read = super.read(); |
230 |
|
|
231 |
|
if (char_read == '\n') |
232 |
|
++line_number; |
233 |
|
|
234 |
|
if (char_read == '\r') |
235 |
|
{ |
236 |
|
int extra_char_read = super.read(); |
237 |
|
|
238 |
|
if ((extra_char_read != '\n') && (extra_char_read != -1)) |
239 |
|
pos--; |
240 |
|
|
241 |
|
char_read = '\n'; |
242 |
|
++line_number; |
243 |
|
} |
244 |
|
|
245 |
|
return(char_read); |
246 |
|
} // synchronized |
247 |
|
} |
248 |
|
|
249 |
|
/*************************************************************************/ |
250 |
|
|
251 |
|
/** |
252 |
|
* This method reads chars from a stream and stores them into a caller |
253 |
|
* supplied buffer. It starts storing data at index <code>offset</code> into |
254 |
|
* the buffer and attemps to read <code>len</code> chars. This method can |
255 |
|
* return before reading the number of chars requested. The actual number |
256 |
|
* of chars read is returned as an int. A -1 is returned to indicated the |
257 |
|
* end of the stream. |
258 |
|
* <p> |
259 |
|
* This method will block until some data can be read. |
260 |
|
* <p> |
261 |
|
* Note that if a line termination sequence is encountered (ie, "\r", |
262 |
|
* "\n", or "\r\n") then that line termination sequence is converted to |
263 |
|
* a single "\n" value which is stored in the buffer. Only a single |
264 |
|
* char is counted towards the number of chars read in this case. |
265 |
|
* |
266 |
|
* @param buf The array into which the chars read should be stored |
267 |
|
* @param offset The offset into the array to start storing chars |
268 |
|
* @param len The requested number of chars to read |
269 |
|
* |
270 |
|
* @return The actual number of chars read, or -1 if end of stream |
271 |
|
* |
272 |
|
* @exception IOException If an error occurs. |
273 |
|
*/ |
274 |
|
public int read(char[] buf, int offset, int len) throws IOException |
275 |
|
{ |
276 |
|
if (len == 0) |
277 |
|
return(0); |
278 |
|
|
279 |
|
synchronized (lock) |
280 |
|
{ |
281 |
|
|
282 |
|
// Read the first char here in order to allow IOException's to |
283 |
|
// propagate up |
284 |
|
int char_read = read(); |
285 |
|
if (char_read == -1) |
286 |
|
return(-1); |
287 |
|
buf[offset] = (char)char_read; |
288 |
|
|
289 |
|
int total_read = 1; |
290 |
|
|
291 |
|
// Read the rest of the chars. We do this in a single char read() loop, |
292 |
|
// which is bad and should be fixed in the future. *****RECODE THIS**** |
293 |
|
try |
294 |
|
{ |
295 |
|
for (int i = 1; i < len; i++) |
296 |
|
{ |
297 |
|
char_read = read(); |
298 |
|
if (char_read == -1) |
299 |
|
return(total_read); |
300 |
|
|
301 |
|
buf[offset + i] = (char)char_read; |
302 |
|
|
303 |
|
++total_read; |
304 |
|
} |
305 |
|
} |
306 |
|
catch (IOException e) |
307 |
|
{ |
308 |
return(total_read); |
return(total_read); |
309 |
|
} |
310 |
|
|
311 |
buf[offset + i] = (char)char_read; |
return(total_read); |
312 |
|
} // synchronized |
313 |
++total_read; |
} |
314 |
} |
|
315 |
} |
/*************************************************************************/ |
316 |
catch (IOException e) |
|
317 |
{ |
/** |
318 |
return(total_read); |
* This method reads a line of text from the input stream and returns |
319 |
} |
* it as a <code>String</code>. A line is considered to be terminated |
320 |
|
* by a "\r", "\n", or "\r\n" sequence, not by the system dependent line |
321 |
return(total_read); |
* separator. |
322 |
|
* |
323 |
} // synchronized |
* @return The line read as a <code>String</code> or <code>null</code> |
324 |
} |
* if end of stream. |
325 |
|
* |
326 |
/*************************************************************************/ |
* @exception IOException If an error occurs |
327 |
|
*/ |
328 |
/** |
public String readLine() throws IOException |
329 |
* This method reads a line of text from the input stream and returns |
{ |
330 |
* it as a <code>String</code>. A line is considered to be terminated |
synchronized (lock) |
331 |
* by a "\r", "\n", or "\r\n" sequence, not by the system dependent line |
{ |
332 |
* separator. |
String line = super.readLine(); |
333 |
* |
if (line != null) |
334 |
* @return The line read as a <code>String</code> or <code>null</code> if end of stream. |
++line_number; |
335 |
* |
|
336 |
* @exception IOException If an error occurs |
return(line); |
337 |
*/ |
} // synchronized |
338 |
public String |
} |
339 |
readLine() throws IOException |
|
340 |
{ |
/*************************************************************************/ |
341 |
synchronized (lock) { |
|
342 |
|
/** |
343 |
String line = super.readLine(); |
* This method skips over characters in the stream. This method will |
344 |
if (line != null) |
* skip the specified number of characters if possible, but is not required |
345 |
++line_number; |
* to skip them all. The actual number of characters skipped is returned. |
346 |
|
* This method returns 0 if the specified number of chars is less than 1. |
347 |
return(line); |
* |
348 |
|
* @param num_chars The specified number of chars to skip. |
349 |
} // synchronized |
* |
350 |
} |
* @return The actual number of chars skipped. |
351 |
|
* |
352 |
/*************************************************************************/ |
* @exception IOException If an error occurs |
353 |
|
*/ |
354 |
/** |
public long skip(long num_chars) throws IOException |
355 |
* This method skips over characters in the stream. This method will |
{ |
356 |
* skip the specified number of characters if possible, but is not required |
// The spec says to override this method so we do even though we |
357 |
* to skip them all. The actual number of characters skipped is returned. |
// don't need to. Assume we aren't counting lines in skipped chars. |
358 |
* This method returns 0 if the specified number of chars is less than 1. |
return(super.skip(num_chars)); |
359 |
* |
} |
|
* @param num_chars The specified number of chars to skip. |
|
|
* |
|
|
* @return The actual number of chars skipped. |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public long |
|
|
skip(long num_chars) throws IOException |
|
|
{ |
|
|
// The spec says to override this method so we do even though we |
|
|
// don't need to. Assume we aren't counting lines in skipped chars. |
|
|
return(super.skip(num_chars)); |
|
|
} |
|
360 |
|
|
361 |
} // class LineNumberReader |
} // class LineNumberReader |
362 |
|
|