source: trunk/gcc/libjava/java/io/LineNumberReader.java

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 5.7 KB
Line 
1/* Copyright (C) 1998, 1999, 2001 Free Software Foundation
2
3 This file is part of libgcj.
4
5This software is copyrighted work licensed under the terms of the
6Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7details. */
8
9package java.io;
10
11/**
12 * @author Per Bothner <bothner@cygnus.com>
13 * @date April 22, 1998.
14 */
15/* Written using "Java Class Libraries", 2nd edition, plus online
16 * API docs for JDK 1.2 beta from http://www.javasoft.com.
17 * Status: Believed complete and correct.
18 *
19 * This implementation has the feature that if '\r' is read, it
20 * does not look for a '\n', but immediately returns '\n'.
21 * On the next read(), if a '\n' is read, it is skipped.
22 * This has the advantage that we do not read (and hang) unnecessarily.
23 *
24 * This implementation is also minimal in the number of fields it uses.
25 */
26
27public class LineNumberReader extends BufferedReader
28{
29 /** The current line number. */
30 int lineNumber;
31
32 public LineNumberReader(Reader in)
33 {
34 super(in, 8192);
35 }
36
37 public LineNumberReader(Reader in, int size)
38 {
39 super(in, size);
40 }
41
42 public int getLineNumber()
43 {
44 return lineNumber;
45 }
46
47 public void setLineNumber(int lineNumber)
48 {
49 this.lineNumber = lineNumber;
50 }
51
52 private static int countLines (char[] buffer, int off, int len)
53 {
54 int count = 0;
55 char prev = '\0';
56 for (int i = 0; i < len; i++)
57 {
58 char ch = buffer[i+off];
59 if ((ch == '\n' && prev != '\r') || ch == '\r')
60 count++;
61 prev = ch;
62 }
63 return count;
64 }
65
66 public void mark(int readLimit) throws IOException
67 {
68 synchronized (lock)
69 {
70 // This is basically the same as BufferedReader.mark.
71 // However, if the previous character was a '\r', we need to
72 // save that 'r', in case the next character is a '\n'.
73 if (pos + readLimit > limit)
74 {
75 int saveCR = (pos > 0 && buffer[pos-1] == '\r') ? 1 : 0;
76 char[] old_buffer = buffer;
77 if (readLimit > limit)
78 buffer = new char[saveCR + readLimit];
79 int copy_start = pos - saveCR;
80 limit -= copy_start;
81 System.arraycopy(old_buffer, copy_start, buffer, 0, limit);
82 pos = saveCR;
83 }
84 markPos = pos;
85 }
86 }
87
88 public void reset() throws IOException
89 {
90 synchronized (lock)
91 {
92 if (markPos < 0)
93 throw new IOException("mark never set or invalidated");
94 if (markPos > 0 && pos > markPos && buffer[markPos-1] == '\r'
95 && buffer[markPos] == '\n')
96 lineNumber--;
97 lineNumber -= countLines(buffer, markPos, pos - markPos);
98 pos = markPos;
99 }
100 }
101
102 public int read() throws IOException
103 {
104 synchronized (lock)
105 {
106 skipRedundantLF();
107 if (pos >= limit)
108 {
109 if (markPos >= 0 && limit == buffer.length)
110 markPos = -1;
111 if (markPos <= 0)
112 pos = limit = 0;
113 int count = in.read(buffer, limit, buffer.length - limit);
114 if (count <= 0)
115 return -1;
116 limit += count;
117 }
118 char ch = buffer[pos++];
119 if (ch == '\r' || ch == '\n')
120 {
121 lineNumber++;
122 return '\n';
123 }
124 return (int) ch;
125 }
126 }
127
128 public int read(char[] buf, int offset, int count) throws IOException
129 {
130 if (count <= 0)
131 {
132 if (count < 0)
133 throw new IndexOutOfBoundsException();
134 return 0;
135 }
136 synchronized (lock)
137 {
138 int first = read();
139 if (first < 0)
140 return -1;
141 int start_offset = offset;
142 buf[offset++] = (char) first;
143 if (buffer[pos-1] == '\r' && pos < limit && buffer[pos] == '\n')
144 pos++;
145 count--;
146 while (count-- > 0 && pos < limit)
147 {
148 char ch = buffer[pos++];
149 if (ch == '\r')
150 {
151 lineNumber++;
152 ch = '\n';
153 if (pos < limit && buffer[pos] == '\n')
154 pos++;
155 }
156 else if (ch == '\n')
157 lineNumber++;
158 buf[offset++] = ch;
159 }
160 return offset - start_offset;
161 }
162 }
163
164 private void skipRedundantLF() throws IOException
165 {
166 if (pos > 0 && buffer[pos-1] == '\r')
167 {
168 if (pos < limit)
169 { // fast case
170 if (buffer[pos] == '\n')
171 pos++;
172 }
173 else
174 { // use read() to deal with the general case.
175 // Set pos and limit to zero to avoid infinite recursion in read.
176 // May need to invalidate markPos if we've exceeded the buffer.
177 if (pos >= buffer.length)
178 markPos = -1;
179 pos = limit = 0;
180 int ch = read();
181 if (ch >= 0 && ch != '\n')
182 pos--;
183 }
184 }
185 }
186
187 public String readLine() throws IOException
188 {
189 // BufferedReader.readLine already does this. Shouldn't need to keep
190 // track of newlines (since the read method deals with this for us).
191 // But if the buffer is large, we may not call the read method at all
192 // and super.readLine can't increment lineNumber itself.
193 // Though it may seem kludgy, the safest thing to do is to save off
194 // lineNumber and increment it explicitly when we're done (iff we
195 // ended with a '\n' or '\r' as opposed to EOF).
196 //
197 // Also, we need to undo the special casing done by BufferedReader.readLine
198 // when a '\r' is the last char in the buffer. That situation is marked
199 // by 'pos > limit'.
200 int tmpLineNumber = lineNumber;
201 skipRedundantLF();
202 String str = super.readLine();
203 if (pos > limit)
204 --pos;
205
206 int ch;
207 if (pos > 0 && ((ch = buffer[pos - 1]) == '\n' || ch == '\r'))
208 lineNumber = tmpLineNumber + 1;
209
210 return str;
211 }
212
213 public long skip(long count) throws IOException
214 {
215 if (count <= 0)
216 return 0;
217 long to_do = count;
218 do
219 {
220 int ch = read();
221 if (ch < 0)
222 break;
223 to_do--;
224 if (ch == '\n' || ch == '\r')
225 lineNumber++;
226 else
227 {
228 long fence = pos + to_do;
229 if (limit < fence)
230 fence = limit;
231 int end = pos;
232 for (; end < fence; end++)
233 {
234 char endch = buffer[end];
235 if (endch == '\n' || endch == '\r')
236 break;
237 }
238 to_do -= end - pos;
239 pos = end;
240 }
241 }
242 while (to_do > 0);
243 return count - to_do;
244 }
245}
Note: See TracBrowser for help on using the repository browser.