/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; abstract public class ClassFileStruct implements ClassFileConstants { byte[] reference; int structOffset; public ClassFileStruct(byte classFileBytes[], int off) { reference = classFileBytes; structOffset = off; } public ClassFileStruct (byte classFileBytes[], int off, boolean verifyStructure) { reference = classFileBytes; structOffset = off; } public double doubleAt(int relativeOffset) { return (Double.longBitsToDouble(this.i8At(relativeOffset))); } public float floatAt(int relativeOffset) { return (Float.intBitsToFloat(this.i4At(relativeOffset))); } public int i1At(int relativeOffset) { return reference[relativeOffset + structOffset]; } public int i2At(int relativeOffset) { int position = relativeOffset + structOffset; return (reference[position++] << 8) + (reference[position] & 0xFF); } public int i4At(int relativeOffset) { int position = relativeOffset + structOffset; return ((reference[position++] & 0xFF) << 24) + ((reference[position++] & 0xFF) << 16) + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF); } public long i8At(int relativeOffset) { int position = relativeOffset + structOffset; return (((long) (reference[position++] & 0xFF)) << 56) + (((long) (reference[position++] & 0xFF)) << 48) + (((long) (reference[position++] & 0xFF)) << 40) + (((long) (reference[position++] & 0xFF)) << 32) + (((long) (reference[position++] & 0xFF)) << 24) + (((long) (reference[position++] & 0xFF)) << 16) + (((long) (reference[position++] & 0xFF)) << 8) + (reference[position++] & 0xFF); } public static String printTypeModifiers(int modifiers) { java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); java.io.PrintWriter print = new java.io.PrintWriter(out); if ((modifiers & AccPublic) != 0) print.print("public "); //$NON-NLS-1$ if ((modifiers & AccPrivate) != 0) print.print("private "); //$NON-NLS-1$ if ((modifiers & AccFinal) != 0) print.print("final "); //$NON-NLS-1$ if ((modifiers & AccSuper) != 0) print.print("super "); //$NON-NLS-1$ if ((modifiers & AccInterface) != 0) print.print("interface "); //$NON-NLS-1$ if ((modifiers & AccAbstract) != 0) print.print("abstract "); //$NON-NLS-1$ print.flush(); return out.toString(); } public int u1At(int relativeOffset) { return (reference[relativeOffset + structOffset] & 0xFF); } public int u2At(int relativeOffset) { int position = relativeOffset + structOffset; return ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF); } public long u4At(int relativeOffset) { int position = relativeOffset + structOffset; return (((reference[position++] & 0xFFL) << 24) + ((reference[position++] & 0xFF) << 16) + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF)); } public char[] utf8At(int relativeOffset, int bytesAvailable) { int length = bytesAvailable; char outputBuf[] = new char[bytesAvailable]; int outputPos = 0; int readOffset = this.structOffset + relativeOffset; while (length != 0) { int x = this.reference[readOffset++] & 0xFF; length--; if ((0x80 & x) != 0) { if ((x & 0x20) != 0) { length-=2; x = ((x & 0xF) << 12) | ((this.reference[readOffset++] & 0x3F) << 6) | (this.reference[readOffset++] & 0x3F); } else { length--; x = ((x & 0x1F) << 6) | (this.reference[readOffset++] & 0x3F); } } outputBuf[outputPos++] = (char) x; } if (outputPos != bytesAvailable) { System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), 0, outputPos); } return outputBuf; } protected void reset() { this.reference = null; } public char[] utf8At(int relativeOffset, int bytesAvailable, boolean testValidity) throws ClassFormatException { int x, y, z; int length = bytesAvailable; char outputBuf[] = new char[bytesAvailable]; int outputPos = 0; int readOffset = structOffset + relativeOffset; while (length != 0) { x = reference[readOffset++] & 0xFF; length--; if ((0x80 & x) != 0) { if (testValidity) { if ((0x40 & x) == 0) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } if (length < 1) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } } y = this.reference[readOffset++] & 0xFF; length--; if (testValidity) { if ((y & 0xC0) != 0x80) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } } if ((x & 0x20) != 0) { if (testValidity && (length < 1)) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } z = this.reference[readOffset++] & 0xFF; length--; if (testValidity && ((z & 0xC0) != 0x80)) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } x = ((x & 0x1F) << 12) + ((y & 0x3F) << 6) + (z & 0x3F); if (testValidity && (x < 0x0800)) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } } else { x = ((x & 0x1F) << 6) + (y & 0x3F); if (testValidity && !((x == 0) || (x >= 0x80))) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } } } else { if (testValidity && x == 0) { throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8); } } outputBuf[outputPos++] = (char) x; } if (outputPos != bytesAvailable) { System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), 0, outputPos); } return outputBuf; } public static void verifyMethodNameAndSignature(char[] name, char[] signature) throws ClassFormatException { // ensure name is not empty if (name.length == 0) { throw new ClassFormatException(ClassFormatException.ErrInvalidMethodName); } // if name begins with the < character it must be clinit or init if (name[0] == '<') { if (new String(name).equals("<clinit>") || new String(name).equals("<init>")) { //$NON-NLS-2$ //$NON-NLS-1$ int signatureLength = signature.length; if (!((signatureLength > 2) && (signature[0] == '(') && (signature[signatureLength - 2] == ')') && (signature[signatureLength - 1] == 'V'))) { throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature); } } else { throw new ClassFormatException(ClassFormatException.ErrInvalidMethodName); } } } }