org.h2.store.DataReader Maven / Gradle / Ivy
/*
* Copyright 2004-2022 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
/**
* This class is backed by an input stream and supports reading values and
* variable size data.
*/
public class DataReader extends Reader {
private final InputStream in;
/**
* Create a new data reader.
*
* @param in the input stream
*/
public DataReader(InputStream in) {
this.in = in;
}
/**
* Read a byte.
*
* @return the byte
* @throws IOException on failure
*/
public byte readByte() throws IOException {
int x = in.read();
if (x < 0) {
throw new FastEOFException();
}
return (byte) x;
}
/**
* Read a variable size integer.
*
* @return the value
* @throws IOException on failure
*/
public int readVarInt() throws IOException {
int b = readByte();
if (b >= 0) {
return b;
}
int x = b & 0x7f;
b = readByte();
if (b >= 0) {
return x | (b << 7);
}
x |= (b & 0x7f) << 7;
b = readByte();
if (b >= 0) {
return x | (b << 14);
}
x |= (b & 0x7f) << 14;
b = readByte();
if (b >= 0) {
return x | b << 21;
}
return x | ((b & 0x7f) << 21) | (readByte() << 28);
}
/**
* Read one character from the input stream.
*
* @return the character
*/
private char readChar() throws IOException {
int x = readByte() & 0xff;
if (x < 0x80) {
return (char) x;
} else if (x >= 0xe0) {
return (char) (((x & 0xf) << 12) +
((readByte() & 0x3f) << 6) +
(readByte() & 0x3f));
} else {
return (char) (((x & 0x1f) << 6) +
(readByte() & 0x3f));
}
}
@Override
public void close() throws IOException {
// ignore
}
@Override
public int read(char[] buff, int off, int len) throws IOException {
if (len == 0) {
return 0;
}
int i = 0;
try {
for (; i < len; i++) {
buff[off + i] = readChar();
}
return len;
} catch (EOFException e) {
if (i == 0) {
return -1;
}
return i;
}
}
/**
* Constructing such an EOF exception is fast, because the stack trace is
* not filled in. If used in a static context, this will also avoid
* classloader memory leaks.
*/
static class FastEOFException extends EOFException {
private static final long serialVersionUID = 1L;
@Override
public synchronized Throwable fillInStackTrace() {
return null;
}
}
}