1
package com.thaiopensource.validate.auto;
3
import java.io.IOException;
7
* Rewindable implementation over a reader.
8
* Modified from RewindableInputStream by replacing the input stream with a reader.
11
public class RewindableReader extends Reader implements Rewindable {
16
static final int MIN_SIZE = 1024;
18
buf = new char[Math.max(MIN_SIZE, minSize)];
29
void append(char[] b, int off, int len) {
30
System.arraycopy(b, off, buf, used, len);
37
* If curBlockAvail > 0, then there are curBlockAvail chars available to be
38
* returned starting at curBlockPos in curBlock.buf.
40
private int curBlockAvail;
41
private Block curBlock;
42
private int curBlockPos;
43
private Block lastBlock;
45
* true unless willNotRewind has been called
47
private boolean saving = true;
48
private final Reader in;
49
private boolean pretendClosed = false;
51
* true if we have got an EOF from the underlying Reader
55
public RewindableReader(Reader in) {
57
throw new NullPointerException();
61
public void close() throws IOException {
77
public void rewind() {
79
throw new IllegalStateException("rewind() after willNotRewind()");
80
pretendClosed = false;
85
curBlockAvail = curBlock.used;
88
public boolean canRewind() {
92
public void willNotRewind() {
97
pretendClosed = false;
101
catch (IOException e) { }
105
public int read() throws IOException {
106
if (curBlockAvail > 0) {
107
int c = curBlock.buf[curBlockPos++] & 0xFF;
109
if (curBlockAvail == 0) {
110
curBlock = curBlock.next;
111
if (curBlock != null) {
113
curBlockAvail = curBlock.used;
119
if (saving && c != -1) {
120
if (lastBlock == null)
121
lastBlock = head = new Block();
122
else if (lastBlock.used == lastBlock.buf.length)
123
lastBlock = lastBlock.next = new Block();
124
lastBlock.append((char)c);
129
public int read(char b[], int off, int len) throws IOException {
130
if (curBlockAvail == 0 && !saving)
131
return in.read(b, off, len);
133
throw new NullPointerException();
135
throw new IndexOutOfBoundsException();
137
if (curBlockAvail != 0) {
141
b[off++] = curBlock.buf[curBlockPos++];
145
if (curBlockAvail == 0) {
146
curBlock = curBlock.next;
147
if (curBlock == null)
149
curBlockAvail = curBlock.used;
157
return nRead > 0 ? nRead : -1;
159
int n = in.read(b, off, len);
162
return nRead > 0 ? nRead : -1;
166
if (lastBlock == null)
167
lastBlock = head = new Block(n);
168
else if (lastBlock.buf.length - lastBlock.used < n) {
169
if (lastBlock.used != lastBlock.buf.length) {
170
int free = lastBlock.buf.length - lastBlock.used;
171
lastBlock.append(b, off, free);
175
lastBlock = lastBlock.next = new Block(n);
177
lastBlock.append(b, off, n);
180
catch (IOException e) {