org.h2.store.DataReader Maven / Gradle / Ivy
/*
* Copyright 2004-2019 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;
import org.h2.util.IOUtils;
/**
* 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
*/
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
*/
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 a variable size long.
*
* @return the value
*/
public long readVarLong() throws IOException {
long x = readByte();
if (x >= 0) {
return x;
}
x &= 0x7f;
for (int s = 7;; s += 7) {
long b = readByte();
x |= (b & 0x7f) << s;
if (b >= 0) {
return x;
}
}
}
/**
* Read an integer.
*
* @return the value
*/
// public int readInt() throws IOException {
// return (read() << 24) + ((read() & 0xff) << 16) +
// ((read() & 0xff) << 8) + (read() & 0xff);
//}
/**
* Read a long.
*
* @return the value
*/
// public long readLong() throws IOException {
// return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
// }
/**
* Read a number of bytes.
*
* @param buff the target buffer
* @param len the number of bytes to read
*/
public void readFully(byte[] buff, int len) throws IOException {
int got = IOUtils.readFully(in, buff, len);
if (got < len) {
throw new FastEOFException();
}
}
/**
* Read a string from the stream.
*
* @return the string
*/
public String readString() throws IOException {
int len = readVarInt();
return readString(len);
}
private String readString(int len) throws IOException {
char[] chars = new char[len];
for (int i = 0; i < len; i++) {
chars[i] = readChar();
}
return new String(chars);
}
/**
* 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;
}
}
}