org.httprpc.kilo.io.PagedReader Maven / Gradle / Ivy
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.httprpc.kilo.io;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
class PagedReader extends Reader {
private Reader reader;
private int pageSize;
private int position = 0;
private int count = 0;
private boolean endOfFile = false;
private List pages = new ArrayList<>();
private Deque marks = new LinkedList<>();
private static final int DEFAULT_PAGE_SIZE = 1024;
private static final int EOF = -1;
PagedReader(Reader reader) {
this(reader, DEFAULT_PAGE_SIZE);
}
PagedReader(Reader reader, int pageSize) {
this.reader = reader;
this.pageSize = pageSize;
}
@Override
public int read() throws IOException {
int c;
if (position < count) {
c = pages.get(position / pageSize)[position % pageSize];
position++;
} else if (!endOfFile) {
c = reader.read();
if (c != EOF) {
if (position / pageSize == pages.size()) {
pages.add(new char[pageSize]);
}
pages.get(pages.size() - 1)[position % pageSize] = (char)c;
position++;
count++;
} else {
endOfFile = true;
}
} else {
c = EOF;
}
return c;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
var c = 0;
var n = 0;
for (var i = off; i < cbuf.length && n < len; i++) {
c = read();
if (c == EOF) {
break;
}
cbuf[i] = (char)c;
n++;
}
return c == EOF && n == 0 ? EOF : n;
}
@Override
public boolean ready() throws IOException {
return position < count || reader.ready();
}
@Override
public void mark(int readAheadLimit) {
marks.push(position);
}
@Override
public boolean markSupported() {
return true;
}
@Override
public void reset() {
if (marks.isEmpty()) {
position = 0;
} else {
position = marks.pop();
}
}
@Override
public void close() throws IOException {
reader.close();
}
}