/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://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 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 offset the offset within the target buffer * @param len the number of bytes to read */ public void readFully(byte[] buff, int offset, int len) throws IOException { int got = IOUtils.readFully(in, buff, offset, 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)); } } public void close() throws IOException { // ignore } public int read(char[] buff, int off, int len) throws IOException { int i = 0; try { for (; i < len; i++) { buff[i] = readChar(); } return len; } catch (EOFException e) { 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; public synchronized Throwable fillInStackTrace() { return null; } } }