CharReaderBack.java
package space.sunqian.fs.io;
import space.sunqian.annotation.Nonnull;
import space.sunqian.annotation.Nullable;
import space.sunqian.fs.base.chars.CharsKit;
import space.sunqian.fs.base.math.MathKit;
import space.sunqian.fs.base.string.StringKit;
import space.sunqian.fs.io.IOChecker.ReadChecker;
import java.io.IOException;
import java.io.Reader;
import java.nio.CharBuffer;
final class CharReaderBack {
static @Nonnull CharReader of(@Nonnull Reader src, int bufSize) throws IllegalArgumentException {
IOChecker.checkBufSize(bufSize);
return new CharStreamReader(src, bufSize);
}
static @Nonnull CharReader of(char @Nonnull [] src, int off, int len) throws IndexOutOfBoundsException {
IOChecker.checkOffLen(off, len, src.length);
return new CharArrayReader(src, off, len);
}
static @Nonnull CharReader of(@Nonnull CharSequence src, int start, int end) throws IndexOutOfBoundsException {
IOChecker.checkStartEnd(start, end, src.length());
return new CharSequenceReader(src, start, end);
}
static @Nonnull CharReader of(@Nonnull CharBuffer src) {
return new CharBufferReader(src);
}
static @Nonnull CharReader limit(@Nonnull CharReader reader, long limit) throws IllegalArgumentException {
IOChecker.checkLimit(limit);
return new LimitedReader(reader, limit);
}
static @Nonnull CharSegment newSeg(@Nonnull CharBuffer data, boolean end) {
return new CharSegmentImpl(data, end);
}
static @Nonnull CharSegment emptySeg(boolean end) {
return end ? CharSegmentImpl.EMPTY_END : CharSegmentImpl.EMPTY_SEG;
}
static @Nonnull Reader asReader(@Nonnull CharReader reader) {
return new AsReader(reader);
}
private static final class CharSegmentImpl implements CharSegment {
private static final @Nonnull CharSegmentImpl EMPTY_END = new CharSegmentImpl(CharsKit.emptyBuffer(), true);
private static final @Nonnull CharSegmentImpl EMPTY_SEG = new CharSegmentImpl(CharsKit.emptyBuffer(), false);
private final @Nonnull CharBuffer data;
private final boolean end;
private CharSegmentImpl(@Nonnull CharBuffer data, boolean end) {
this.data = data;
this.end = end;
}
@Override
public @Nonnull CharBuffer data() {
return data;
}
@Override
public boolean end() {
return end;
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public @Nonnull CharSegment clone() {
CharBuffer copy = CharBuffer.allocate(data.remaining());
int pos = data.position();
int limit = data.limit();
copy.put(data);
data.position(pos);
data.limit(limit);
copy.flip();
return CharSegment.of(copy, end);
}
}
private static final class CharStreamReader implements CharReader {
private final @Nonnull Reader src;
private final int bufSize;
private CharStreamReader(@Nonnull Reader src, int bufSize) {
this.src = src;
this.bufSize = bufSize;
}
@Override
public int ready() {
return 0;
}
@Override
public @Nonnull CharSegment read(int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
char[] data = IOKit.read0(src, len, bufSize, IOChecker.endChecker());
if (data == null) {
return CharSegment.empty(true);
}
return CharSegment.of(CharBuffer.wrap(data), data.length < len);
}
@Override
public @Nullable CharBuffer read() throws IORuntimeException {
char[] buf = IOKit.read0(src, bufSize, IOChecker.endChecker());
if (buf == null) {
return null;
}
return CharBuffer.wrap(buf);
}
@Override
public long skip(long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkSkip(len);
if (len == 0) {
return 0;
}
try {
return skip0(len);
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
private long skip0(long len) throws Exception {
long hasRead = 0;
while (hasRead < len) {
long onceSize = src.skip(len - hasRead);
if (onceSize == 0) {
if (src.read() == -1) {
break;
} else {
hasRead++;
}
}
hasRead += onceSize;
}
return hasRead;
}
@Override
public long readTo(@Nonnull Appendable dst) throws IORuntimeException {
return readTo(dst, IOChecker.endChecker());
}
@Override
public long readTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
return readTo(dst, len, IOChecker.endChecker());
}
@Override
public int readTo(char @Nonnull [] dst) throws IORuntimeException {
return readTo(dst, IOChecker.endChecker());
}
@Override
public int readTo(char @Nonnull [] dst, int off, int len) throws IndexOutOfBoundsException, IORuntimeException {
return readTo(dst, off, len, IOChecker.endChecker());
}
@Override
public int readTo(@Nonnull CharBuffer dst) throws IORuntimeException {
return readTo(dst, IOChecker.endChecker());
}
@Override
public int readTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
return readTo(dst, len, IOChecker.endChecker());
}
@Override
public @Nonnull CharSegment available(int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
char[] data = IOKit.read0(src, len, bufSize, IOChecker.availableChecker());
if (data == null) {
return CharSegment.empty(true);
}
return CharSegment.of(CharBuffer.wrap(data), false);
}
@Override
public @Nonnull CharSegment available() throws IORuntimeException {
char[] data = IOKit.read0(src, bufSize, IOChecker.availableChecker());
if (data == null) {
return CharSegment.empty(true);
}
return CharSegment.of(CharBuffer.wrap(data), false);
}
@Override
public long availableTo(@Nonnull Appendable dst) throws IORuntimeException {
return readTo(dst, IOChecker.availableChecker());
}
@Override
public long availableTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
return readTo(dst, len, IOChecker.availableChecker());
}
@Override
public int availableTo(char @Nonnull [] dst) throws IORuntimeException {
return readTo(dst, IOChecker.availableChecker());
}
@Override
public int availableTo(
char @Nonnull [] dst, int off, int len
) throws IndexOutOfBoundsException, IORuntimeException {
return readTo(dst, off, len, IOChecker.availableChecker());
}
@Override
public int availableTo(@Nonnull CharBuffer dst) throws IORuntimeException {
return readTo(dst, IOChecker.availableChecker());
}
@Override
public int availableTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
return readTo(dst, len, IOChecker.availableChecker());
}
private long readTo(@Nonnull Appendable dst, ReadChecker readChecker) throws IORuntimeException {
return IOKit.readTo0(src, dst, bufSize, readChecker);
}
private long readTo(
@Nonnull Appendable dst, long len, ReadChecker readChecker
) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
return IOKit.readTo0(src, dst, len, bufSize, readChecker);
}
private int readTo(char @Nonnull [] dst, ReadChecker readChecker) throws IORuntimeException {
return IOKit.readTo0(src, dst, 0, dst.length, readChecker);
}
private int readTo(
char @Nonnull [] dst, int off, int len, ReadChecker readChecker
) throws IndexOutOfBoundsException, IORuntimeException {
IOChecker.checkOffLen(off, len, dst.length);
return IOKit.readTo0(src, dst, off, len, readChecker);
}
private int readTo(@Nonnull CharBuffer dst, ReadChecker readChecker) throws IORuntimeException {
return IOKit.readTo0(src, dst, dst.remaining(), readChecker);
}
private int readTo(
@Nonnull CharBuffer dst, int len, ReadChecker readChecker
) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
return IOKit.readTo0(src, dst, len, readChecker);
}
@Override
public boolean markSupported() {
return src.markSupported();
}
@Override
public void mark() throws IORuntimeException {
try {
src.mark(Integer.MAX_VALUE);
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public void reset() throws IORuntimeException {
try {
src.reset();
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public void close() throws IORuntimeException {
try {
src.close();
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public @Nonnull Reader asReader() {
return src;
}
}
private static abstract class InMemoryReader implements CharReader {
@Override
public @Nonnull CharSegment available(int len) throws IllegalArgumentException, IORuntimeException {
return read(len);
}
@Override
public long availableTo(@Nonnull Appendable dst) throws IORuntimeException {
return readTo(dst);
}
@Override
public long availableTo(
@Nonnull Appendable dst, long len
) throws IllegalArgumentException, IORuntimeException {
return readTo(dst, len);
}
@Override
public int availableTo(char @Nonnull [] dst) throws IORuntimeException {
return readTo(dst);
}
@Override
public int availableTo(
char @Nonnull [] dst, int off, int len
) throws IndexOutOfBoundsException, IORuntimeException {
return readTo(dst, off, len);
}
@Override
public int availableTo(@Nonnull CharBuffer dst) throws IORuntimeException {
return readTo(dst);
}
@Override
public int availableTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
return readTo(dst, len);
}
}
private static final class CharArrayReader extends InMemoryReader {
private final char @Nonnull [] src;
private int pos;
private final int end;
private int mark;
private CharArrayReader(char @Nonnull [] src, int offset, int length) {
this.src = src;
this.pos = offset;
this.end = offset + length;
this.mark = pos;
}
@Override
public int ready() {
return end - pos;
}
@Override
public @Nonnull CharSegment read(int len) throws IllegalArgumentException {
IOChecker.checkLen(len);
if (len == 0) {
return CharSegment.empty(false);
}
if (pos == end) {
return CharSegment.empty(true);
}
int remaining = end - pos;
int actualLen = Math.min(remaining, len);
CharBuffer data = CharBuffer.wrap(src, pos, actualLen).slice();
pos += actualLen;
return CharSegment.of(data, remaining <= len);
}
@Override
public @Nullable CharBuffer read() throws IORuntimeException {
if (pos >= end) {
return null;
}
CharBuffer ret = CharBuffer.wrap(src, pos, end - pos);
pos = end;
return ret;
}
@Override
public long skip(long len) throws IllegalArgumentException {
IOChecker.checkSkip(len);
if (len == 0) {
return 0;
}
if (pos == end) {
return 0;
}
int remaining = end - pos;
int skipped = (int) Math.min(remaining, len);
pos += skipped;
return skipped;
}
@Override
public long readTo(@Nonnull Appendable dst) throws IORuntimeException {
if (end == pos) {
return -1;
}
try {
int remaining = end - pos;
IOKit.write(dst, src, pos, remaining);
pos += remaining;
return remaining;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public long readTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (end == pos) {
return -1;
}
try {
int remaining = end - pos;
int actualLen = (int) Math.min(remaining, len);
IOKit.write(dst, src, pos, actualLen);
pos += actualLen;
return actualLen;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public int readTo(char @Nonnull [] dst) {
return readTo0(dst, 0, dst.length);
}
@Override
public int readTo(char @Nonnull [] dst, int off, int len) throws IndexOutOfBoundsException {
IOChecker.checkOffLen(off, len, dst.length);
return readTo0(dst, off, len);
}
private int readTo0(char @Nonnull [] dst, int off, int len) {
if (len == 0) {
return 0;
}
if (end == pos) {
return -1;
}
int remaining = end - pos;
int copySize = Math.min(remaining, len);
System.arraycopy(src, pos, dst, off, copySize);
pos += copySize;
return copySize;
}
@Override
public int readTo(@Nonnull CharBuffer dst) throws IORuntimeException {
if (dst.remaining() == 0) {
return 0;
}
if (pos == end) {
return -1;
}
int remaining = end - pos;
int putSize = Math.min(remaining, dst.remaining());
return putTo0(dst, putSize);
}
@Override
public int readTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (dst.remaining() == 0) {
return 0;
}
if (pos == end) {
return -1;
}
int remaining = end - pos;
int putSize = MathKit.min(remaining, dst.remaining(), len);
return putTo0(dst, putSize);
}
@Override
public @Nonnull CharSegment available() throws IORuntimeException {
return read(end - pos);
}
private int putTo0(@Nonnull CharBuffer dst, int putSize) throws IORuntimeException {
try {
dst.put(src, pos, putSize);
pos += putSize;
return putSize;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public boolean markSupported() {
return true;
}
@Override
public void mark() {
mark = pos;
}
@Override
public void reset() {
pos = mark;
}
@Override
public void close() {
}
}
private static final class CharSequenceReader extends InMemoryReader {
private final @Nonnull CharSequence src;
private final int endPos;
private int pos;
private int mark;
private CharSequenceReader(@Nonnull CharSequence src, int start, int end) {
this.src = src;
this.pos = start;
this.endPos = end;
this.mark = pos;
}
@Override
public int ready() {
return endPos - pos;
}
@Override
public @Nonnull CharSegment read(int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return CharSegment.empty(false);
}
if (pos == endPos) {
return CharSegment.empty(true);
}
int remaining = endPos - pos;
int actualLen = Math.min(remaining, len);
CharBuffer data = CharBuffer.wrap(src, pos, pos + actualLen).slice();
pos += actualLen;
return CharSegment.of(data, remaining <= len);
}
@Override
public @Nullable CharBuffer read() throws IORuntimeException {
if (pos >= endPos) {
return null;
}
CharBuffer ret = CharBuffer.wrap(src, pos, endPos);
pos = endPos;
return ret;
}
@Override
public long skip(long len) throws IllegalArgumentException {
IOChecker.checkSkip(len);
if (len == 0) {
return 0;
}
if (pos == endPos) {
return 0;
}
int remaining = endPos - pos;
int skipped = (int) Math.min(remaining, len);
pos += skipped;
return skipped;
}
@Override
public long readTo(@Nonnull Appendable dst) throws IORuntimeException {
if (endPos == pos) {
return -1;
}
try {
int remaining = endPos - pos;
dst.append(src, pos, pos + remaining);
pos += remaining;
return remaining;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public long readTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (endPos == pos) {
return -1;
}
try {
int remaining = endPos - pos;
int actualLen = (int) Math.min(remaining, len);
dst.append(src, pos, pos + actualLen);
pos += actualLen;
return actualLen;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public int readTo(char @Nonnull [] dst) {
return readTo0(dst, 0, dst.length);
}
@Override
public int readTo(char @Nonnull [] dst, int off, int len) throws IndexOutOfBoundsException {
IOChecker.checkOffLen(off, len, dst.length);
return readTo0(dst, off, len);
}
private int readTo0(char @Nonnull [] dst, int off, int len) {
if (len == 0) {
return 0;
}
if (endPos == pos) {
return -1;
}
int remaining = endPos - pos;
int copySize = Math.min(remaining, len);
StringKit.charsCopy(src, pos, dst, off, copySize);
pos += copySize;
return copySize;
}
@Override
public int readTo(@Nonnull CharBuffer dst) throws IORuntimeException {
if (dst.remaining() == 0) {
return 0;
}
if (pos == endPos) {
return -1;
}
int remaining = endPos - pos;
int putSize = Math.min(remaining, dst.remaining());
return putTo0(dst, putSize);
}
@Override
public int readTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (dst.remaining() == 0) {
return 0;
}
if (pos == endPos) {
return -1;
}
int remaining = endPos - pos;
int putSize = MathKit.min(remaining, dst.remaining(), len);
return putTo0(dst, putSize);
}
@Override
public @Nonnull CharSegment available() throws IORuntimeException {
return read(endPos - pos);
}
private int putTo0(@Nonnull CharBuffer dst, int putSize) throws IORuntimeException {
try {
dst.put(CharBuffer.wrap(src, pos, pos + putSize));
pos += putSize;
return putSize;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public boolean markSupported() {
return true;
}
@Override
public void mark() {
mark = pos;
}
@Override
public void reset() {
pos = mark;
}
@Override
public void close() {
}
}
private static final class CharBufferReader extends InMemoryReader {
private final @Nonnull CharBuffer src;
private CharBufferReader(@Nonnull CharBuffer src) {
this.src = src;
}
@Override
public int ready() {
return src.remaining();
}
@Override
public @Nonnull CharSegment read(int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return CharSegment.empty(false);
}
if (!src.hasRemaining()) {
return CharSegment.empty(true);
}
int pos = src.position();
int limit = src.limit();
int newPos = Math.min(pos + len, limit);
src.limit(newPos);
CharBuffer data = src.slice();
src.position(newPos);
src.limit(limit);
return CharSegment.of(data, newPos >= limit);
}
@Override
public @Nullable CharBuffer read() throws IORuntimeException {
if (!src.hasRemaining()) {
return null;
}
CharBuffer ret = src.slice();
src.position(src.limit());
return ret;
}
@Override
public long skip(long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkSkip(len);
if (len == 0) {
return 0;
}
if (!src.hasRemaining()) {
return 0;
}
int pos = src.position();
int newPos = (int) Math.min(pos + len, src.limit());
src.position(newPos);
return newPos - pos;
}
@Override
public long readTo(@Nonnull Appendable dst) throws IORuntimeException {
return BufferKit.readTo(src, dst);
}
@Override
public long readTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
int actualLen = (int) Math.min(Integer.MAX_VALUE, len);
return BufferKit.readTo0(src, dst, actualLen);
}
@Override
public int readTo(char @Nonnull [] dst) throws IORuntimeException {
return BufferKit.readTo(src, dst);
}
@Override
public int readTo(char @Nonnull [] dst, int off, int len) throws IndexOutOfBoundsException, IORuntimeException {
return BufferKit.readTo(src, dst, off, len);
}
@Override
public int readTo(@Nonnull CharBuffer dst) throws IORuntimeException {
return BufferKit.readTo(src, dst);
}
@Override
public int readTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
return BufferKit.readTo(src, dst, len);
}
@Override
public @Nonnull CharSegment available() throws IORuntimeException {
return read(src.remaining());
}
@Override
public boolean markSupported() {
return true;
}
@Override
public void mark() throws IORuntimeException {
src.mark();
}
@Override
public void reset() throws IORuntimeException {
try {
src.reset();
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
@Override
public void close() throws IORuntimeException {
}
}
private static final class LimitedReader implements CharReader {
private final @Nonnull CharReader src;
private final long limit;
private long pos = 0;
private long mark = 0;
private LimitedReader(@Nonnull CharReader src, long limit) {
this.src = src;
this.limit = limit;
}
@Override
public int ready() throws IORuntimeException {
return Math.min(src.ready(), MathKit.safeInt(limit - pos));
}
@Override
public @Nonnull CharSegment read(int len) throws IllegalArgumentException, IORuntimeException {
return read(len, false);
}
@Override
public @Nullable CharBuffer read() throws IORuntimeException {
if (pos >= limit) {
return null;
}
int len = MathKit.safeInt(limit - pos);
return read(len).data();
}
@Override
public long skip(long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkSkip(len);
if (len == 0) {
return 0;
}
if (pos >= limit) {
return 0;
}
int actualLen = (int) Math.min(len, limit - pos);
long skipped = src.skip(actualLen);
pos += skipped;
return skipped;
}
@Override
public long readTo(@Nonnull Appendable dst) throws IORuntimeException {
if (pos >= limit) {
return -1;
}
long readSize = src.readTo(dst, limit - pos);
if (readSize < 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public long readTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (pos >= limit) {
return -1;
}
int actualLen = (int) Math.min(len, limit - pos);
long readSize = src.readTo(dst, actualLen);
if (readSize < 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public int readTo(char @Nonnull [] dst) throws IORuntimeException {
return readTo(dst, 0, dst.length);
}
@Override
public int readTo(
char @Nonnull [] dst, int off, int len
) throws IndexOutOfBoundsException, IORuntimeException {
IOChecker.checkOffLen(off, len, dst.length);
if (len == 0) {
return 0;
}
if (pos >= limit) {
return -1;
}
int actualLen = (int) Math.min(len, limit - pos);
int readSize = src.readTo(dst, off, actualLen);
if (readSize < 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public int readTo(@Nonnull CharBuffer dst) throws IORuntimeException {
return readTo(dst, dst.remaining());
}
@Override
public int readTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (!dst.hasRemaining()) {
return 0;
}
if (pos >= limit) {
return -1;
}
int actualLen = (int) Math.min(len, limit - pos);
actualLen = Math.min(actualLen, dst.remaining());
int readSize = src.readTo(dst, actualLen);
if (readSize < 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public @Nonnull CharSegment available(int len) throws IllegalArgumentException, IORuntimeException {
return read(len, true);
}
@Override
public @Nonnull CharSegment available() throws IORuntimeException {
return available(MathKit.safeInt(limit - pos));
}
@Override
public long availableTo(@Nonnull Appendable dst) throws IORuntimeException {
if (pos >= limit) {
return -1;
}
long readSize = src.availableTo(dst, limit - pos);
if (readSize <= 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public long availableTo(@Nonnull Appendable dst, long len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (pos >= limit) {
return -1;
}
int actualLen = (int) Math.min(len, limit - pos);
long readSize = src.availableTo(dst, actualLen);
if (readSize <= 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public int availableTo(char @Nonnull [] dst) throws IORuntimeException {
return availableTo(dst, 0, dst.length);
}
@Override
public int availableTo(
char @Nonnull [] dst, int off, int len
) throws IndexOutOfBoundsException, IORuntimeException {
IOChecker.checkOffLen(off, len, dst.length);
if (len == 0) {
return 0;
}
if (pos >= limit) {
return -1;
}
int actualLen = (int) Math.min(len, limit - pos);
int readSize = src.availableTo(dst, off, actualLen);
if (readSize <= 0) {
return readSize;
}
pos += readSize;
return readSize;
}
@Override
public int availableTo(@Nonnull CharBuffer dst) throws IORuntimeException {
return availableTo(dst, dst.remaining());
}
@Override
public int availableTo(@Nonnull CharBuffer dst, int len) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return 0;
}
if (!dst.hasRemaining()) {
return 0;
}
if (pos >= limit) {
return -1;
}
int actualLen = (int) Math.min(len, limit - pos);
actualLen = Math.min(actualLen, dst.remaining());
int readSize = src.availableTo(dst, actualLen);
if (readSize <= 0) {
return readSize;
}
pos += readSize;
return readSize;
}
private @Nonnull CharSegment read(int len, boolean available) throws IllegalArgumentException, IORuntimeException {
IOChecker.checkLen(len);
if (len == 0) {
return CharSegment.empty(false);
}
if (pos >= limit) {
return CharSegment.empty(true);
}
int maxLen = (int) Math.min(len, limit - pos);
CharSegment segment = available ? src.available(maxLen) : src.read(maxLen);
pos += segment.data().remaining();
if (!segment.end()) {
if (pos >= limit) {
return newSeg(segment.data(), true);
}
}
return segment;
}
@Override
public boolean markSupported() {
return src.markSupported();
}
@Override
public void mark() throws IORuntimeException {
src.mark();
mark = pos;
}
@Override
public void reset() throws IORuntimeException {
src.reset();
pos = mark;
}
@Override
public void close() throws IORuntimeException {
src.close();
}
}
static final class AsReader extends DoReadReader {
private final @Nonnull CharReader in;
private char[] oneChar;
private AsReader(@Nonnull CharReader in) {
this.in = in;
}
@Override
public int read() throws IOException {
try {
if (oneChar == null) {
oneChar = new char[1];
}
int ret = in.readTo(oneChar);
return ret < 0 ? -1 : oneChar[0];
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
protected int doRead(char @Nonnull [] b, int off, int len) throws IOException {
try {
return in.readTo(b, off, len);
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public long skip(long n) throws IllegalArgumentException, IOException {
try {
return in.skip(n);
} catch (IllegalArgumentException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public boolean markSupported() {
return in.markSupported();
}
@Override
public void mark(int readAheadLimit) throws IOException {
try {
in.mark();
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public void reset() throws IOException {
try {
in.reset();
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public void close() throws IOException {
try {
in.close();
} catch (Exception e) {
throw new IOException(e);
}
}
}
private CharReaderBack() {
}
}