/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.vm.classfile; import static com.sun.max.vm.classfile.ErrorContext.*; import java.io.*; import com.sun.max.util.*; /** * Operations for sequentially scanning data items in a class file. Any IO exceptions that occur during scanning * are converted to {@link ClassFormatError}s. */ public class ClassfileStream { private final int length; private final DataInputStream stream; private int pos; public ClassfileStream(byte[] bytes) { this(bytes, 0, bytes.length); } public ClassfileStream(byte[] bytes, int offset, int length) { this.length = length; this.stream = new DataInputStream(new ByteArrayInputStream(bytes, offset, length)); } public byte readByte() { try { final byte value = stream.readByte(); pos = pos++; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public short readShort() { try { final short value = stream.readShort(); pos += 2; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public char readChar() { try { final char value = stream.readChar(); pos += 2; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readInt() { try { final int value = stream.readInt(); pos += 4; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public float readFloat() { try { final float value = stream.readFloat(); pos += 4; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public long readLong() { try { final long value = stream.readLong(); pos += 8; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public double readDouble() { try { final double value = stream.readDouble(); pos += 8; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readUnsigned1() { try { final int value = stream.readUnsignedByte(); pos++; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readUnsigned2() { try { final int value = stream.readUnsignedShort(); pos += 2; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readSize4() { try { final int value = stream.readInt(); pos += 4; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readSigned1() { try { final byte value = stream.readByte(); pos++; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readSigned2() { try { final short value = stream.readShort(); pos += 2; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public int readSigned4() { try { final int value = stream.readInt(); pos += 4; return value; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public byte[] readByteArray(int len) { try { final byte[] bytes = new byte[len]; stream.readFully(bytes); pos += len; return bytes; } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public String readUtf8String() { try { final int utflen = stream.readUnsignedShort(); final String value = Utf8.readUtf8(stream, true, utflen); pos += 2 + utflen; return value; } catch (Utf8Exception e) { throw classFormatError("Invalid UTF-8 encoded string", e); } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public void skip(int nBytes) { try { pos += nBytes; stream.skipBytes(nBytes); } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public boolean isAtEndOfFile() { return pos == length; } public void checkEndOfFile() { if (!isAtEndOfFile()) { throw classFormatError("Extra bytes in class file"); } } public int getPosition() { return pos; } public void close() { try { stream.close(); } catch (EOFException eofException) { throw eofError(); } catch (IOException ioException) { throw ioError(ioException); } } public ClassFormatError ioError(IOException ioException) { throw classFormatError("IO error while reading class file (" + ioException + ")"); } public ClassFormatError eofError() { throw classFormatError("Truncated class file"); } }