forked from bndtools/bnd
/
LineSeparatorBufferedReader.java
157 lines (141 loc) · 3.22 KB
/
LineSeparatorBufferedReader.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package aQute.lib.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.CharBuffer;
/**
* BufferedReader which returns the line separator string for the
* previously read line.
*/
public class LineSeparatorBufferedReader extends BufferedReader {
public LineSeparatorBufferedReader(Reader in) {
super(in);
}
public LineSeparatorBufferedReader(Reader in, int size) {
super(in, size);
}
private int markedPushBack = -1;
private int pushBack = -1;
private int markedEol;
private int eol;
@Override
public void mark(int readAheadLimit) throws IOException {
super.mark(readAheadLimit);
markedPushBack = pushBack;
markedEol = eol;
}
@Override
public void reset() throws IOException {
super.reset();
pushBack = markedPushBack;
eol = markedEol;
}
@Override
public int read() throws IOException {
lineSeparator(); // consume any line separator characters
return read0();
}
private int read0() throws IOException {
int c = pushBack;
if (c != -1) {
pushBack = -1;
return c;
}
return super.read();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
lineSeparator(); // consume any line separator characters
int c = pushBack;
if (c != -1) {
if ((off >= 0) && (off < cbuf.length) && (len > 0)) {
pushBack = -1;
cbuf[off] = (char) c;
return 1;
}
}
return super.read(cbuf, off, len);
}
@Override
public int read(CharBuffer target) throws IOException {
lineSeparator(); // consume any line separator characters
int c = pushBack;
if (c != -1) {
if (target.remaining() > 0) {
pushBack = -1;
target.put((char) c);
return 1;
}
}
return super.read(target);
}
@Override
public int read(char[] cbuf) throws IOException {
return read(cbuf, 0, cbuf.length);
}
@Override
public String readLine() throws IOException {
int c = read0();
if (c == -1) {
eol = 0;
return null;
}
StringBuilder sb = new StringBuilder(80);
for (; c != -1; c = read0()) {
if (c == '\n') {
if (eol == '\r') {
eol = 0;
continue;
}
eol = c;
return sb.toString();
}
if (c == '\r') {
eol = c;
return sb.toString();
}
sb.append((char)c);
}
eol = 0;
return sb.toString();
}
@Override
public long skip(long n) throws IOException {
lineSeparator(); // consume any line separator characters
if ((pushBack != -1) && (n > 0L)) {
pushBack = -1;
return super.skip(n - 1) + 1;
}
return super.skip(n);
}
@Override
public boolean ready() throws IOException {
return (pushBack != -1) || super.ready();
}
/**
* Return the line separator string from the previously read line
* using {@link #readLine()} or the empty string if end of file.
* This method can be called once per read line. Subsequent calls
* per read line will return the empty string.
*
* @return The line separator string from the previously read line.
* @throws IOException If an exception occurs reading.
*/
public String lineSeparator() throws IOException {
int e = eol;
if (e == '\n') {
eol = 0;
return "\n";
}
if (e == '\r') {
eol = 0;
int c = read0();
if (c != '\n') {
pushBack = c;
return "\r";
}
return "\r\n";
}
return "";
}
}