133 lines
3.3 KiB
Java
133 lines
3.3 KiB
Java
/*
|
|
* Copyright (C) 2013 The Guava Authors
|
|
*
|
|
* 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 com.google.common.io;
|
|
|
|
import static com.google.common.base.Preconditions.checkArgument;
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
import static com.google.common.base.Preconditions.checkPositionIndexes;
|
|
|
|
import java.io.IOException;
|
|
import java.io.Reader;
|
|
import java.nio.CharBuffer;
|
|
|
|
/**
|
|
* A {@link Reader} that reads the characters in a {@link CharSequence}. Like
|
|
* {@code StringReader}, but works with any {@link CharSequence}.
|
|
*
|
|
* @author Colin Decker
|
|
*/
|
|
// TODO(user): make this public? as a type, or a method in CharStreams?
|
|
final class CharSequenceReader extends Reader {
|
|
|
|
private CharSequence seq;
|
|
private int pos;
|
|
private int mark;
|
|
|
|
/**
|
|
* Creates a new reader wrapping the given character sequence.
|
|
*/
|
|
public CharSequenceReader(CharSequence seq) {
|
|
this.seq = checkNotNull(seq);
|
|
}
|
|
|
|
private void checkOpen() throws IOException {
|
|
if (seq == null) {
|
|
throw new IOException("reader closed");
|
|
}
|
|
}
|
|
|
|
private boolean hasRemaining() {
|
|
return remaining() > 0;
|
|
}
|
|
|
|
private int remaining() {
|
|
return seq.length() - pos;
|
|
}
|
|
|
|
@Override
|
|
public synchronized int read(CharBuffer target) throws IOException {
|
|
checkNotNull(target);
|
|
checkOpen();
|
|
if (!hasRemaining()) {
|
|
return -1;
|
|
}
|
|
int charsToRead = Math.min(target.remaining(), remaining());
|
|
for (int i = 0; i < charsToRead; i++) {
|
|
target.put(seq.charAt(pos++));
|
|
}
|
|
return charsToRead;
|
|
}
|
|
|
|
@Override
|
|
public synchronized int read() throws IOException {
|
|
checkOpen();
|
|
return hasRemaining() ? seq.charAt(pos++) : -1;
|
|
}
|
|
|
|
@Override
|
|
public synchronized int read(char[] cbuf, int off, int len) throws IOException {
|
|
checkPositionIndexes(off, off + len, cbuf.length);
|
|
checkOpen();
|
|
if (!hasRemaining()) {
|
|
return -1;
|
|
}
|
|
int charsToRead = Math.min(len, remaining());
|
|
for (int i = 0; i < charsToRead; i++) {
|
|
cbuf[off + i] = seq.charAt(pos++);
|
|
}
|
|
return charsToRead;
|
|
}
|
|
|
|
@Override
|
|
public synchronized long skip(long n) throws IOException {
|
|
checkArgument(n >= 0, "n (%s) may not be negative", n);
|
|
checkOpen();
|
|
int charsToSkip = (int) Math.min(remaining(), n); // safe because remaining is an int
|
|
pos += charsToSkip;
|
|
return charsToSkip;
|
|
}
|
|
|
|
@Override
|
|
public synchronized boolean ready() throws IOException {
|
|
checkOpen();
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean markSupported() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public synchronized void mark(int readAheadLimit) throws IOException {
|
|
checkArgument(readAheadLimit >= 0, "readAheadLimit (%s) may not be negative", readAheadLimit);
|
|
checkOpen();
|
|
mark = pos;
|
|
}
|
|
|
|
@Override
|
|
public synchronized void reset() throws IOException {
|
|
checkOpen();
|
|
pos = mark;
|
|
}
|
|
|
|
@Override
|
|
public synchronized void close() throws IOException {
|
|
seq = null;
|
|
}
|
|
}
|