All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.zving.framework.thirdparty.asm.ClassReader Maven / Gradle / Ivy

There is a newer version: 0.3.0
Show newest version
package com.zving.framework.thirdparty.asm;

import java.io.IOException;
import java.io.InputStream;

import com.zving.preloader.Util;

// fix

public class ClassReader {

	public ClassReader(byte b[]) {
		this(b, 0, b.length);
	}

	public ClassReader(byte b[], int off, int len) {
		this.b = b;
		if (readShort(off + 6) > 51)
			throw new IllegalArgumentException();
		items = new int[readUnsignedShort(off + 8)];
		int n = items.length;
		strings = new String[n];
		int max = 0;
		int index = off + 10;
		for (int i = 1; i < n; i++) {
			items[i] = index + 1;
			int size;
			switch (b[index]) {
			case 3: // '\003'
			case 4: // '\004'
			case 9: // '\t'
			case 10: // '\n'
			case 11: // '\013'
			case 12: // '\f'
			case 18: // '\022'
				size = 5;
				break;

			case 5: // '\005'
			case 6: // '\006'
				size = 9;
				i++;
				break;

			case 1: // '\001'
				size = 3 + readUnsignedShort(index + 1);
				if (size > max)
					max = size;
				break;

			case 15: // '\017'
				size = 4;
				break;

			case 2: // '\002'
			case 7: // '\007'
			case 8: // '\b'
			case 13: // '\r'
			case 14: // '\016'
			case 16: // '\020'
			case 17: // '\021'
			default:
				size = 3;
				break;
			}
			index += size;
		}

		maxStringLength = max;
		header = index;
	}

	public int getAccess() {
		return readUnsignedShort(header);
	}

	public String getClassName() {
		return readClass(header + 2, new char[maxStringLength]);
	}

	public String getSuperName() {
		return readClass(header + 4, new char[maxStringLength]);
	}

	public String[] getInterfaces() {
		int index = header + 6;
		int n = readUnsignedShort(index);
		String interfaces[] = new String[n];
		if (n > 0) {
			char buf[] = new char[maxStringLength];
			for (int i = 0; i < n; i++) {
				index += 2;
				interfaces[i] = readClass(index, buf);
			}

		}
		return interfaces;
	}

	void copyPool(ClassWriter classWriter) {
		char buf[] = new char[maxStringLength];
		int ll = items.length;
		Item items2[] = new Item[ll];
		for (int i = 1; i < ll; i++) {
			int index = items[i];
			int tag = b[index - 1];
			Item item = new Item(i);
			switch (tag) {
			case 9: // '\t'
			case 10: // '\n'
			case 11: // '\013'
			{
				int nameType = items[readUnsignedShort(index + 2)];
				item.set(tag, readClass(index, buf), readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
				break;
			}

			case 3: // '\003'
			{
				item.set(readInt(index));
				break;
			}

			case 4: // '\004'
			{
				item.set(Float.intBitsToFloat(readInt(index)));
				break;
			}

			case 12: // '\f'
			{
				item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), null);
				break;
			}

			case 5: // '\005'
			{
				item.set(readLong(index));
				i++;
				break;
			}

			case 6: // '\006'
			{
				item.set(Double.longBitsToDouble(readLong(index)));
				i++;
				break;
			}

			case 1: // '\001'
			{
				String s = strings[i];
				if (s == null) {
					index = items[i];
					s = strings[i] = readUTF(index + 2, readUnsignedShort(index), buf);
				}
				item.set(tag, s, null, null);
				break;
			}

			case 15: // '\017'
			{
				int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
				int nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
				item.set(20 + readByte(index), readClass(fieldOrMethodRef, buf), readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
				break;
			}

			case 18: // '\022'
			{
				if (classWriter.bootstrapMethods == null)
					copyBootstrapMethods(classWriter, items2, buf);
				int nameType = items[readUnsignedShort(index + 2)];
				item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), readUnsignedShort(index));
				break;
			}

			case 2: // '\002'
			case 7: // '\007'
			case 8: // '\b'
			case 13: // '\r'
			case 14: // '\016'
			case 16: // '\020'
			case 17: // '\021'
			default: {
				item.set(tag, readUTF8(index, buf), null, null);
				break;
			}
			}
			int index2 = item.hashCode % items2.length;
			item.next = items2[index2];
			items2[index2] = item;
		}

		int off = items[1] - 1;
		classWriter.pool.putByteArray(b, off, header - off);
		classWriter.items = items2;
		classWriter.threshold = (int) (0.75D * (double) ll);
		classWriter.index = ll;
	}

	private void copyBootstrapMethods(ClassWriter classWriter, Item items[], char c[]) {
		int u = getAttributes();
		boolean found = false;
		for (int i = readUnsignedShort(u); i > 0; i--) {
			String attrName = readUTF8(u + 2, c);
			if ("BootstrapMethods".equals(attrName)) {
				found = true;
				break;
			}
			u += 6 + readInt(u + 4);
		}

		if (!found)
			return;
		int boostrapMethodCount = readUnsignedShort(u + 8);
		int j = 0;
		int v = u + 10;
		for (; j < boostrapMethodCount; j++) {
			int position = v - u - 10;
			int hashCode = readConst(readUnsignedShort(v), c).hashCode();
			for (int k = readUnsignedShort(v + 2); k > 0; k--) {
				hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
				v += 2;
			}

			v += 4;
			Item item = new Item(j);
			item.set(position, hashCode & 0x7fffffff);
			int index = item.hashCode % items.length;
			item.next = items[index];
			items[index] = item;
		}

		int attrSize = readInt(u + 4);
		ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
		bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
		classWriter.bootstrapMethodsCount = boostrapMethodCount;
		classWriter.bootstrapMethods = bootstrapMethods;
	}

	public ClassReader(InputStream is) throws IOException {
		this(readClass(is, false));
	}

	public ClassReader(String name) throws IOException {
		this(readClass(ClassLoader.getSystemResourceAsStream((new StringBuilder(String.valueOf(name.replace('.', '/')))).append(".class").toString()), true));
	}

	private static byte[] readClass(InputStream is, boolean close) throws IOException {
		byte[] bs = Util.readByte(is);
		if (close) {
			is.close();
		}
		return bs;
		// if(is == null)
		// throw new IOException("Class not found");
		// byte b[];
		// int len;
		// b = new byte[is.available()];
		// len = 0;
		// _L4:
		// int n = is.read(b, len, b.length - len);
		// if(n != -1) {
		// len += n;
		// if(len != b.length) goto _L4; else goto _L3
		// } else goto {
		// byte abyte0[];
		// if(len < b.length)
		// {
		// byte c[] = new byte[len];
		// System.arraycopy(b, 0, c, 0, len);
		// b = c;
		// }
		// abyte0 = b;
		// if(close)
		// is.close();
		// return abyte0;
		// }
		// _L1:
		//
		// _L2:
		//
		// _L3:
		// int last;
		// last = is.read();
		// if(last >= 0)
		// break MISSING_BLOCK_LABEL_115;
		// abyte0 = b;
		// if(close)
		// is.close();
		// return abyte0;
		// byte c[] = new byte[b.length + 1000];
		// System.arraycopy(b, 0, c, 0, len);
		// c[len++] = (byte)last;
		// b = c;
		// goto _L4
		// Exception exception;
		// exception;
		// if(close)
		// is.close();
		// throw exception;
	}

	public void accept(ClassVisitor classVisitor, int flags) {
		accept(classVisitor, new Attribute[0], flags);
	}

	public void accept(ClassVisitor classVisitor, Attribute attrs[], int flags) {
		int u = header;
		char c[] = new char[maxStringLength];
		Context context = new Context();
		context.attrs = attrs;
		context.flags = flags;
		context.buffer = c;
		int access = readUnsignedShort(u);
		String name = readClass(u + 2, c);
		String superClass = readClass(u + 4, c);
		String interfaces[] = new String[readUnsignedShort(u + 6)];
		u += 8;
		for (int i = 0; i < interfaces.length; i++) {
			interfaces[i] = readClass(u, c);
			u += 2;
		}

		String signature = null;
		String sourceFile = null;
		String sourceDebug = null;
		String enclosingOwner = null;
		String enclosingName = null;
		String enclosingDesc = null;
		int anns = 0;
		int ianns = 0;
		int innerClasses = 0;
		Attribute attributes = null;
		u = getAttributes();
		for (int i = readUnsignedShort(u); i > 0; i--) {
			String attrName = readUTF8(u + 2, c);
			if ("SourceFile".equals(attrName))
				sourceFile = readUTF8(u + 8, c);
			else if ("InnerClasses".equals(attrName))
				innerClasses = u + 8;
			else if ("EnclosingMethod".equals(attrName)) {
				enclosingOwner = readClass(u + 8, c);
				int item = readUnsignedShort(u + 10);
				if (item != 0) {
					enclosingName = readUTF8(items[item], c);
					enclosingDesc = readUTF8(items[item] + 2, c);
				}
			} else if ("Signature".equals(attrName))
				signature = readUTF8(u + 8, c);
			else if ("RuntimeVisibleAnnotations".equals(attrName))
				anns = u + 8;
			else if ("Deprecated".equals(attrName))
				access |= 0x20000;
			else if ("Synthetic".equals(attrName))
				access |= 0x41000;
			else if ("SourceDebugExtension".equals(attrName)) {
				int len = readInt(u + 4);
				sourceDebug = readUTF(u + 8, len, new char[len]);
			} else if ("RuntimeInvisibleAnnotations".equals(attrName))
				ianns = u + 8;
			else if ("BootstrapMethods".equals(attrName)) {
				int bootstrapMethods[] = new int[readUnsignedShort(u + 8)];
				int j = 0;
				int v = u + 10;
				for (; j < bootstrapMethods.length; j++) {
					bootstrapMethods[j] = v;
					v += 2 + readUnsignedShort(v + 2) << 1;
				}

				context.bootstrapMethods = bootstrapMethods;
			} else {
				Attribute attr = readAttribute(attrs, attrName, u + 8, readInt(u + 4), c, -1, null);
				if (attr != null) {
					attr.next = attributes;
					attributes = attr;
				}
			}
			u += 6 + readInt(u + 4);
		}

		classVisitor.visit(readInt(items[1] - 7), access, name, signature, superClass, interfaces);
		if ((flags & 2) == 0 && (sourceFile != null || sourceDebug != null))
			classVisitor.visitSource(sourceFile, sourceDebug);
		if (enclosingOwner != null)
			classVisitor.visitOuterClass(enclosingOwner, enclosingName, enclosingDesc);
		if (anns != 0) {
			int i = readUnsignedShort(anns);
			int v = anns + 2;
			for (; i > 0; i--)
				v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), true));

		}
		if (ianns != 0) {
			int i = readUnsignedShort(ianns);
			int v = ianns + 2;
			for (; i > 0; i--)
				v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), false));

		}
		Attribute attr;
		for (; attributes != null; attributes = attr) {
			attr = attributes.next;
			attributes.next = null;
			classVisitor.visitAttribute(attributes);
		}

		if (innerClasses != 0) {
			int v = innerClasses + 2;
			for (int i = readUnsignedShort(innerClasses); i > 0; i--) {
				classVisitor.visitInnerClass(readClass(v, c), readClass(v + 2, c), readUTF8(v + 4, c), readUnsignedShort(v + 6));
				v += 8;
			}

		}
		u = header + 10 + 2 * interfaces.length;
		for (int i = readUnsignedShort(u - 2); i > 0; i--)
			u = readField(classVisitor, context, u);

		u += 2;
		for (int i = readUnsignedShort(u - 2); i > 0; i--)
			u = readMethod(classVisitor, context, u);

		classVisitor.visitEnd();
	}

	private int readField(ClassVisitor classVisitor, Context context, int u) {
		char c[] = context.buffer;
		int access = readUnsignedShort(u);
		String name = readUTF8(u + 2, c);
		String desc = readUTF8(u + 4, c);
		u += 6;
		String signature = null;
		int anns = 0;
		int ianns = 0;
		Object value = null;
		Attribute attributes = null;
		for (int i = readUnsignedShort(u); i > 0; i--) {
			String attrName = readUTF8(u + 2, c);
			if ("ConstantValue".equals(attrName)) {
				int item = readUnsignedShort(u + 8);
				value = item != 0 ? readConst(item, c) : null;
			} else if ("Signature".equals(attrName))
				signature = readUTF8(u + 8, c);
			else if ("Deprecated".equals(attrName))
				access |= 0x20000;
			else if ("Synthetic".equals(attrName))
				access |= 0x41000;
			else if ("RuntimeVisibleAnnotations".equals(attrName))
				anns = u + 8;
			else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
				ianns = u + 8;
			} else {
				Attribute attr = readAttribute(context.attrs, attrName, u + 8, readInt(u + 4), c, -1, null);
				if (attr != null) {
					attr.next = attributes;
					attributes = attr;
				}
			}
			u += 6 + readInt(u + 4);
		}

		u += 2;
		FieldVisitor fv = classVisitor.visitField(access, name, desc, signature, value);
		if (fv == null)
			return u;
		if (anns != 0) {
			int i = readUnsignedShort(anns);
			int v = anns + 2;
			for (; i > 0; i--)
				v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), true));

		}
		if (ianns != 0) {
			int i = readUnsignedShort(ianns);
			int v = ianns + 2;
			for (; i > 0; i--)
				v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), false));

		}
		Attribute attr;
		for (; attributes != null; attributes = attr) {
			attr = attributes.next;
			attributes.next = null;
			fv.visitAttribute(attributes);
		}

		fv.visitEnd();
		return u;
	}

	private int readMethod(ClassVisitor classVisitor, Context context, int u) {
		char c[] = context.buffer;
		int access = readUnsignedShort(u);
		String name = readUTF8(u + 2, c);
		String desc = readUTF8(u + 4, c);
		u += 6;
		int code = 0;
		int exception = 0;
		String exceptions[] = (String[]) null;
		String signature = null;
		int anns = 0;
		int ianns = 0;
		int dann = 0;
		int mpanns = 0;
		int impanns = 0;
		int firstAttribute = u;
		Attribute attributes = null;
		for (int i = readUnsignedShort(u); i > 0; i--) {
			String attrName = readUTF8(u + 2, c);
			if ("Code".equals(attrName)) {
				if ((context.flags & 1) == 0)
					code = u + 8;
			} else if ("Exceptions".equals(attrName)) {
				exceptions = new String[readUnsignedShort(u + 8)];
				exception = u + 10;
				for (int j = 0; j < exceptions.length; j++) {
					exceptions[j] = readClass(exception, c);
					exception += 2;
				}

			} else if ("Signature".equals(attrName))
				signature = readUTF8(u + 8, c);
			else if ("Deprecated".equals(attrName))
				access |= 0x20000;
			else if ("RuntimeVisibleAnnotations".equals(attrName))
				anns = u + 8;
			else if ("AnnotationDefault".equals(attrName))
				dann = u + 8;
			else if ("Synthetic".equals(attrName))
				access |= 0x41000;
			else if ("RuntimeInvisibleAnnotations".equals(attrName))
				ianns = u + 8;
			else if ("RuntimeVisibleParameterAnnotations".equals(attrName))
				mpanns = u + 8;
			else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
				impanns = u + 8;
			} else {
				Attribute attr = readAttribute(context.attrs, attrName, u + 8, readInt(u + 4), c, -1, null);
				if (attr != null) {
					attr.next = attributes;
					attributes = attr;
				}
			}
			u += 6 + readInt(u + 4);
		}

		u += 2;
		MethodVisitor mv = classVisitor.visitMethod(access, name, desc, signature, exceptions);
		if (mv == null)
			return u;
		if (mv instanceof MethodWriter) {
			MethodWriter mw = (MethodWriter) mv;
			if (mw.cw.cr == this && signature.equals(mw.signature)) {
				boolean sameExceptions = false;
				if (exceptions == null)
					sameExceptions = mw.exceptionCount == 0;
				else if (exceptions.length == mw.exceptionCount) {
					sameExceptions = true;
					for (int j = exceptions.length - 1; j >= 0; j--) {
						exception -= 2;
						if (mw.exceptions[j] == readUnsignedShort(exception))
							continue;
						sameExceptions = false;
						break;
					}

				}
				if (sameExceptions) {
					mw.classReaderOffset = firstAttribute;
					mw.classReaderLength = u - firstAttribute;
					return u;
				}
			}
		}
		if (dann != 0) {
			AnnotationVisitor dv = mv.visitAnnotationDefault();
			readAnnotationValue(dann, c, null, dv);
			if (dv != null)
				dv.visitEnd();
		}
		if (anns != 0) {
			int i = readUnsignedShort(anns);
			int v = anns + 2;
			for (; i > 0; i--)
				v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), true));

		}
		if (ianns != 0) {
			int i = readUnsignedShort(ianns);
			int v = ianns + 2;
			for (; i > 0; i--)
				v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), false));

		}
		if (mpanns != 0)
			readParameterAnnotations(mpanns, desc, c, true, mv);
		if (impanns != 0)
			readParameterAnnotations(impanns, desc, c, false, mv);
		Attribute attr;
		for (; attributes != null; attributes = attr) {
			attr = attributes.next;
			attributes.next = null;
			mv.visitAttribute(attributes);
		}

		if (code != 0) {
			context.access = access;
			context.name = name;
			context.desc = desc;
			mv.visitCode();
			readCode(mv, context, code);
		}
		mv.visitEnd();
		return u;
	}

	private void readCode(MethodVisitor mv, Context context, int u) {
		byte b[] = this.b;
		char c[] = context.buffer;
		int maxStack = readUnsignedShort(u);
		int maxLocals = readUnsignedShort(u + 2);
		int codeLength = readInt(u + 4);
		int codeStart = u += 8;
		int codeEnd = u + codeLength;
		Label labels[] = new Label[codeLength + 2];
		readLabel(codeLength + 1, labels);
		while (u < codeEnd) {
			int offset = u - codeStart;
			int opcode = b[u] & 0xff;
			switch (ClassWriter.TYPE[opcode]) {
			case 0: // '\0'
			case 4: // '\004'
				u++;
				break;

			case 9: // '\t'
				readLabel(offset + readShort(u + 1), labels);
				u += 3;
				break;

			case 10: // '\n'
				readLabel(offset + readInt(u + 1), labels);
				u += 5;
				break;

			case 17: // '\021'
				opcode = b[u + 1] & 0xff;
				if (opcode == 132)
					u += 6;
				else
					u += 4;
				break;

			case 14: // '\016'
				u = (u + 4) - (offset & 3);
				readLabel(offset + readInt(u), labels);
				for (int i = (readInt(u + 8) - readInt(u + 4)) + 1; i > 0; i--) {
					readLabel(offset + readInt(u + 12), labels);
					u += 4;
				}

				u += 12;
				break;

			case 15: // '\017'
				u = (u + 4) - (offset & 3);
				readLabel(offset + readInt(u), labels);
				for (int i = readInt(u + 4); i > 0; i--) {
					readLabel(offset + readInt(u + 12), labels);
					u += 8;
				}

				u += 8;
				break;

			case 1: // '\001'
			case 3: // '\003'
			case 11: // '\013'
				u += 2;
				break;

			case 2: // '\002'
			case 5: // '\005'
			case 6: // '\006'
			case 12: // '\f'
			case 13: // '\r'
				u += 3;
				break;

			case 7: // '\007'
			case 8: // '\b'
				u += 5;
				break;

			case 16: // '\020'
			default:
				u += 4;
				break;
			}
		}
		for (int i = readUnsignedShort(u); i > 0; i--) {
			Label start = readLabel(readUnsignedShort(u + 2), labels);
			Label end = readLabel(readUnsignedShort(u + 4), labels);
			Label handler = readLabel(readUnsignedShort(u + 6), labels);
			String type = readUTF8(items[readUnsignedShort(u + 8)], c);
			mv.visitTryCatchBlock(start, end, handler, type);
			u += 8;
		}

		u += 2;
		int varTable = 0;
		int varTypeTable = 0;
		boolean zip = true;
		boolean unzip = (context.flags & 8) != 0;
		int stackMap = 0;
		int stackMapSize = 0;
		int frameCount = 0;
		Context frame = null;
		Attribute attributes = null;
		for (int i = readUnsignedShort(u); i > 0; i--) {
			String attrName = readUTF8(u + 2, c);
			if ("LocalVariableTable".equals(attrName)) {
				if ((context.flags & 2) == 0) {
					varTable = u + 8;
					int j = readUnsignedShort(u + 8);
					int v = u;
					for (; j > 0; j--) {
						int label = readUnsignedShort(v + 10);
						if (labels[label] == null)
							readLabel(label, labels).status |= 1;
						label += readUnsignedShort(v + 12);
						if (labels[label] == null)
							readLabel(label, labels).status |= 1;
						v += 10;
					}

				}
			} else if ("LocalVariableTypeTable".equals(attrName))
				varTypeTable = u + 8;
			else if ("LineNumberTable".equals(attrName)) {
				if ((context.flags & 2) == 0) {
					int j = readUnsignedShort(u + 8);
					int v = u;
					for (; j > 0; j--) {
						int label = readUnsignedShort(v + 10);
						if (labels[label] == null)
							readLabel(label, labels).status |= 1;
						labels[label].line = readUnsignedShort(v + 12);
						v += 4;
					}

				}
			} else if ("StackMapTable".equals(attrName)) {
				if ((context.flags & 4) == 0) {
					stackMap = u + 10;
					stackMapSize = readInt(u + 4);
					frameCount = readUnsignedShort(u + 8);
				}
			} else if ("StackMap".equals(attrName)) {
				if ((context.flags & 4) == 0) {
					zip = false;
					stackMap = u + 10;
					stackMapSize = readInt(u + 4);
					frameCount = readUnsignedShort(u + 8);
				}
			} else {
				for (int j = 0; j < context.attrs.length; j++)
					if (context.attrs[j].type.equals(attrName)) {
						Attribute attr = context.attrs[j].read(this, u + 8, readInt(u + 4), c, codeStart - 8, labels);
						if (attr != null) {
							attr.next = attributes;
							attributes = attr;
						}
					}

			}
			u += 6 + readInt(u + 4);
		}

		u += 2;
		if (stackMap != 0) {
			frame = context;
			frame.offset = -1;
			frame.mode = 0;
			frame.localCount = 0;
			frame.localDiff = 0;
			frame.stackCount = 0;
			frame.local = new Object[maxLocals];
			frame.stack = new Object[maxStack];
			if (unzip)
				getImplicitFrame(context);
			for (int i = stackMap; i < (stackMap + stackMapSize) - 2; i++)
				if (b[i] == 8) {
					int v = readUnsignedShort(i + 1);
					if (v >= 0 && v < codeLength && (b[codeStart + v] & 0xff) == 187)
						readLabel(v, labels);
				}

		}
		for (u = codeStart; u < codeEnd;) {
			int offset = u - codeStart;
			Label l = labels[offset];
			if (l != null) {
				mv.visitLabel(l);
				if ((context.flags & 2) == 0 && l.line > 0)
					mv.visitLineNumber(l.line, l);
			}
			while (frame != null && (frame.offset == offset || frame.offset == -1)) {
				if (frame.offset != -1)
					if (!zip || unzip)
						mv.visitFrame(-1, frame.localCount, frame.local, frame.stackCount, frame.stack);
					else
						mv.visitFrame(frame.mode, frame.localDiff, frame.local, frame.stackCount, frame.stack);
				if (frameCount > 0) {
					stackMap = readFrame(stackMap, zip, unzip, labels, frame);
					frameCount--;
				} else {
					frame = null;
				}
			}
			int opcode = b[u] & 0xff;
			switch (ClassWriter.TYPE[opcode]) {
			case 0: // '\0'
			{
				mv.visitInsn(opcode);
				u++;
				break;
			}

			case 4: // '\004'
			{
				if (opcode > 54) {
					opcode -= 59;
					mv.visitVarInsn(54 + (opcode >> 2), opcode & 3);
				} else {
					opcode -= 26;
					mv.visitVarInsn(21 + (opcode >> 2), opcode & 3);
				}
				u++;
				break;
			}

			case 9: // '\t'
			{
				mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
				u += 3;
				break;
			}

			case 10: // '\n'
			{
				mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
				u += 5;
				break;
			}

			case 17: // '\021'
			{
				opcode = b[u + 1] & 0xff;
				if (opcode == 132) {
					mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
					u += 6;
				} else {
					mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
					u += 4;
				}
				break;
			}

			case 14: // '\016'
			{
				u = (u + 4) - (offset & 3);
				int label = offset + readInt(u);
				int min = readInt(u + 4);
				int max = readInt(u + 8);
				Label table[] = new Label[(max - min) + 1];
				u += 12;
				for (int i = 0; i < table.length; i++) {
					table[i] = labels[offset + readInt(u)];
					u += 4;
				}

				mv.visitTableSwitchInsn(min, max, labels[label], table);
				break;
			}

			case 15: // '\017'
			{
				u = (u + 4) - (offset & 3);
				int label = offset + readInt(u);
				int len = readInt(u + 4);
				int keys[] = new int[len];
				Label values[] = new Label[len];
				u += 8;
				for (int i = 0; i < len; i++) {
					keys[i] = readInt(u);
					values[i] = labels[offset + readInt(u + 4)];
					u += 8;
				}

				mv.visitLookupSwitchInsn(labels[label], keys, values);
				break;
			}

			case 3: // '\003'
			{
				mv.visitVarInsn(opcode, b[u + 1] & 0xff);
				u += 2;
				break;
			}

			case 1: // '\001'
			{
				mv.visitIntInsn(opcode, b[u + 1]);
				u += 2;
				break;
			}

			case 2: // '\002'
			{
				mv.visitIntInsn(opcode, readShort(u + 1));
				u += 3;
				break;
			}

			case 11: // '\013'
			{
				mv.visitLdcInsn(readConst(b[u + 1] & 0xff, c));
				u += 2;
				break;
			}

			case 12: // '\f'
			{
				mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));
				u += 3;
				break;
			}

			case 6: // '\006'
			case 7: // '\007'
			{
				int cpIndex = items[readUnsignedShort(u + 1)];
				String iowner = readClass(cpIndex, c);
				cpIndex = items[readUnsignedShort(cpIndex + 2)];
				String iname = readUTF8(cpIndex, c);
				String idesc = readUTF8(cpIndex + 2, c);
				if (opcode < 182)
					mv.visitFieldInsn(opcode, iowner, iname, idesc);
				else
					mv.visitMethodInsn(opcode, iowner, iname, idesc);
				if (opcode == 185)
					u += 5;
				else
					u += 3;
				break;
			}

			case 8: // '\b'
			{
				int cpIndex = items[readUnsignedShort(u + 1)];
				int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];
				Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c);
				int bsmArgCount = readUnsignedShort(bsmIndex + 2);
				Object bsmArgs[] = new Object[bsmArgCount];
				bsmIndex += 4;
				for (int i = 0; i < bsmArgCount; i++) {
					bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);
					bsmIndex += 2;
				}

				cpIndex = items[readUnsignedShort(cpIndex + 2)];
				String iname = readUTF8(cpIndex, c);
				String idesc = readUTF8(cpIndex + 2, c);
				mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
				u += 5;
				break;
			}

			case 5: // '\005'
			{
				mv.visitTypeInsn(opcode, readClass(u + 1, c));
				u += 3;
				break;
			}

			case 13: // '\r'
			{
				mv.visitIincInsn(b[u + 1] & 0xff, b[u + 2]);
				u += 3;
				break;
			}

			case 16: // '\020'
			default: {
				mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xff);
				u += 4;
				break;
			}
			}
		}

		if (labels[codeLength] != null)
			mv.visitLabel(labels[codeLength]);
		if ((context.flags & 2) == 0 && varTable != 0) {
			int typeTable[] = (int[]) null;
			if (varTypeTable != 0) {
				u = varTypeTable + 2;
				typeTable = new int[readUnsignedShort(varTypeTable) * 3];
				for (int i = typeTable.length; i > 0;) {
					typeTable[--i] = u + 6;
					typeTable[--i] = readUnsignedShort(u + 8);
					typeTable[--i] = readUnsignedShort(u);
					u += 10;
				}

			}
			u = varTable + 2;
			for (int i = readUnsignedShort(varTable); i > 0; i--) {
				int start = readUnsignedShort(u);
				int length = readUnsignedShort(u + 2);
				int index = readUnsignedShort(u + 8);
				String vsignature = null;
				if (typeTable != null) {
					for (int j = 0; j < typeTable.length; j += 3) {
						if (typeTable[j] != start || typeTable[j + 1] != index)
							continue;
						vsignature = readUTF8(typeTable[j + 2], c);
						break;
					}

				}
				mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), vsignature, labels[start], labels[start + length], index);
				u += 10;
			}

		}
		Attribute attr;
		for (; attributes != null; attributes = attr) {
			attr = attributes.next;
			attributes.next = null;
			mv.visitAttribute(attributes);
		}

		mv.visitMaxs(maxStack, maxLocals);
	}

	private void readParameterAnnotations(int v, String desc, char buf[], boolean visible, MethodVisitor mv) {
		int n = b[v++] & 0xff;
		int synthetics = Type.getArgumentTypes(desc).length - n;
		int i;
		for (i = 0; i < synthetics; i++) {
			AnnotationVisitor av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
			if (av != null)
				av.visitEnd();
		}

		for (; i < n + synthetics; i++) {
			int j = readUnsignedShort(v);
			v += 2;
			for (; j > 0; j--) {
				AnnotationVisitor av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
				v = readAnnotationValues(v + 2, buf, true, av);
			}

		}

	}

	private int readAnnotationValues(int v, char buf[], boolean named, AnnotationVisitor av) {
		int i = readUnsignedShort(v);
		v += 2;
		if (named)
			for (; i > 0; i--)
				v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);

		else
			for (; i > 0; i--)
				v = readAnnotationValue(v, buf, null, av);

		if (av != null)
			av.visitEnd();
		return v;
	}

	private int readAnnotationValue(int v, char buf[], String name, AnnotationVisitor av) {
		if (av == null) {
			switch (b[v] & 0xff) {
			case 101: // 'e'
				return v + 5;

			case 64: // '@'
				return readAnnotationValues(v + 3, buf, true, null);

			case 91: // '['
				return readAnnotationValues(v + 1, buf, false, null);
			}
			return v + 3;
		}
		label0: switch (b[v++] & 0xff) {
		default:
			break;

		case 68: // 'D'
		case 70: // 'F'
		case 73: // 'I'
		case 74: // 'J'
			av.visit(name, readConst(readUnsignedShort(v), buf));
			v += 2;
			break;

		case 66: // 'B'
			av.visit(name, new Byte((byte) readInt(items[readUnsignedShort(v)])));
			v += 2;
			break;

		case 90: // 'Z'
			av.visit(name, readInt(items[readUnsignedShort(v)]) != 0 ? ((Object) (Boolean.TRUE)) : ((Object) (Boolean.FALSE)));
			v += 2;
			break;

		case 83: // 'S'
			av.visit(name, new Short((short) readInt(items[readUnsignedShort(v)])));
			v += 2;
			break;

		case 67: // 'C'
			av.visit(name, new Character((char) readInt(items[readUnsignedShort(v)])));
			v += 2;
			break;

		case 115: // 's'
			av.visit(name, readUTF8(v, buf));
			v += 2;
			break;

		case 101: // 'e'
			av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
			v += 4;
			break;

		case 99: // 'c'
			av.visit(name, Type.getType(readUTF8(v, buf)));
			v += 2;
			break;

		case 64: // '@'
			v = readAnnotationValues(v + 2, buf, true, av.visitAnnotation(name, readUTF8(v, buf)));
			break;

		case 91: // '['
			int size = readUnsignedShort(v);
			v += 2;
			if (size == 0)
				return readAnnotationValues(v - 2, buf, false, av.visitArray(name));
			switch (b[v++] & 0xff) {
			case 66: // 'B'
				byte bv[] = new byte[size];
				for (int i = 0; i < size; i++) {
					bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
					v += 3;
				}

				av.visit(name, bv);
				v--;
				break label0;

			case 90: // 'Z'
				boolean zv[] = new boolean[size];
				for (int i = 0; i < size; i++) {
					zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
					v += 3;
				}

				av.visit(name, zv);
				v--;
				break label0;

			case 83: // 'S'
				short sv[] = new short[size];
				for (int i = 0; i < size; i++) {
					sv[i] = (short) readInt(items[readUnsignedShort(v)]);
					v += 3;
				}

				av.visit(name, sv);
				v--;
				break label0;

			case 67: // 'C'
				char cv[] = new char[size];
				for (int i = 0; i < size; i++) {
					cv[i] = (char) readInt(items[readUnsignedShort(v)]);
					v += 3;
				}

				av.visit(name, cv);
				v--;
				break label0;

			case 73: // 'I'
				int iv[] = new int[size];
				for (int i = 0; i < size; i++) {
					iv[i] = readInt(items[readUnsignedShort(v)]);
					v += 3;
				}

				av.visit(name, iv);
				v--;
				break label0;

			case 74: // 'J'
				long lv[] = new long[size];
				for (int i = 0; i < size; i++) {
					lv[i] = readLong(items[readUnsignedShort(v)]);
					v += 3;
				}

				av.visit(name, lv);
				v--;
				break label0;

			case 70: // 'F'
				float fv[] = new float[size];
				for (int i = 0; i < size; i++) {
					fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
					v += 3;
				}

				av.visit(name, fv);
				v--;
				break label0;

			case 68: // 'D'
				double dv[] = new double[size];
				for (int i = 0; i < size; i++) {
					dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
					v += 3;
				}

				av.visit(name, dv);
				v--;
				break;

			default:
				v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
				break;
			}
			break;
		}
		return v;
	}

	private void getImplicitFrame(Context frame) {
		String desc = frame.desc;
		Object locals[] = frame.local;
		int local = 0;
		if ((frame.access & 8) == 0)
			if ("".equals(frame.name))
				locals[local++] = Opcodes.UNINITIALIZED_THIS;
			else
				locals[local++] = readClass(header + 2, frame.buffer);
		int i = 1;
		do {
			int j = i;
			switch (desc.charAt(i++)) {
			case 66: // 'B'
			case 67: // 'C'
			case 73: // 'I'
			case 83: // 'S'
			case 90: // 'Z'
				locals[local++] = Opcodes.INTEGER;
				break;

			case 70: // 'F'
				locals[local++] = Opcodes.FLOAT;
				break;

			case 74: // 'J'
				locals[local++] = Opcodes.LONG;
				break;

			case 68: // 'D'
				locals[local++] = Opcodes.DOUBLE;
				break;

			case 91: // '['
				for (; desc.charAt(i) == '['; i++)
					;
				if (desc.charAt(i) == 'L')
					for (i++; desc.charAt(i) != ';'; i++)
						;
				locals[local++] = desc.substring(j, ++i);
				break;

			case 76: // 'L'
				for (; desc.charAt(i) != ';'; i++)
					;
				locals[local++] = desc.substring(j + 1, i++);
				break;

			default:
				frame.localCount = local;
				return;
			}
		} while (true);
	}

	private int readFrame(int stackMap, boolean zip, boolean unzip, Label labels[], Context frame) {
		char c[] = frame.buffer;
		int tag;
		if (zip) {
			tag = b[stackMap++] & 0xff;
		} else {
			tag = 255;
			frame.offset = -1;
		}
		frame.localDiff = 0;
		int delta;
		if (tag < 64) {
			delta = tag;
			frame.mode = 3;
			frame.stackCount = 0;
		} else if (tag < 128) {
			delta = tag - 64;
			stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
			frame.mode = 4;
			frame.stackCount = 1;
		} else {
			delta = readUnsignedShort(stackMap);
			stackMap += 2;
			if (tag == 247) {
				stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
				frame.mode = 4;
				frame.stackCount = 1;
			} else if (tag >= 248 && tag < 251) {
				frame.mode = 2;
				frame.localDiff = 251 - tag;
				frame.localCount -= frame.localDiff;
				frame.stackCount = 0;
			} else if (tag == 251) {
				frame.mode = 3;
				frame.stackCount = 0;
			} else if (tag < 255) {
				int local = unzip ? frame.localCount : 0;
				for (int i = tag - 251; i > 0; i--)
					stackMap = readFrameType(frame.local, local++, stackMap, c, labels);

				frame.mode = 1;
				frame.localDiff = tag - 251;
				frame.localCount += frame.localDiff;
				frame.stackCount = 0;
			} else {
				frame.mode = 0;
				int n = readUnsignedShort(stackMap);
				stackMap += 2;
				frame.localDiff = n;
				frame.localCount = n;
				int local = 0;
				for (; n > 0; n--)
					stackMap = readFrameType(frame.local, local++, stackMap, c, labels);

				n = readUnsignedShort(stackMap);
				stackMap += 2;
				frame.stackCount = n;
				int stack = 0;
				for (; n > 0; n--)
					stackMap = readFrameType(frame.stack, stack++, stackMap, c, labels);

			}
		}
		frame.offset += delta + 1;
		readLabel(frame.offset, labels);
		return stackMap;
	}

	private int readFrameType(Object frame[], int index, int v, char buf[], Label labels[]) {
		int type = b[v++] & 0xff;
		switch (type) {
		case 0: // '\0'
			frame[index] = Opcodes.TOP;
			break;

		case 1: // '\001'
			frame[index] = Opcodes.INTEGER;
			break;

		case 2: // '\002'
			frame[index] = Opcodes.FLOAT;
			break;

		case 3: // '\003'
			frame[index] = Opcodes.DOUBLE;
			break;

		case 4: // '\004'
			frame[index] = Opcodes.LONG;
			break;

		case 5: // '\005'
			frame[index] = Opcodes.NULL;
			break;

		case 6: // '\006'
			frame[index] = Opcodes.UNINITIALIZED_THIS;
			break;

		case 7: // '\007'
			frame[index] = readClass(v, buf);
			v += 2;
			break;

		default:
			frame[index] = readLabel(readUnsignedShort(v), labels);
			v += 2;
			break;
		}
		return v;
	}

	protected Label readLabel(int offset, Label labels[]) {
		if (labels[offset] == null)
			labels[offset] = new Label();
		return labels[offset];
	}

	private int getAttributes() {
		int u = header + 8 + readUnsignedShort(header + 6) * 2;
		for (int i = readUnsignedShort(u); i > 0; i--) {
			for (int j = readUnsignedShort(u + 8); j > 0; j--)
				u += 6 + readInt(u + 12);

			u += 8;
		}

		u += 2;
		for (int i = readUnsignedShort(u); i > 0; i--) {
			for (int j = readUnsignedShort(u + 8); j > 0; j--)
				u += 6 + readInt(u + 12);

			u += 8;
		}

		return u + 2;
	}

	private Attribute readAttribute(Attribute attrs[], String type, int off, int len, char buf[], int codeOff, Label labels[]) {
		for (int i = 0; i < attrs.length; i++)
			if (attrs[i].type.equals(type))
				return attrs[i].read(this, off, len, buf, codeOff, labels);

		return (new Attribute(type)).read(this, off, len, null, -1, null);
	}

	public int getItemCount() {
		return items.length;
	}

	public int getItem(int item) {
		return items[item];
	}

	public int getMaxStringLength() {
		return maxStringLength;
	}

	public int readByte(int index) {
		return b[index] & 0xff;
	}

	public int readUnsignedShort(int index) {
		byte b[] = this.b;
		return (b[index] & 0xff) << 8 | b[index + 1] & 0xff;
	}

	public short readShort(int index) {
		byte b[] = this.b;
		return (short) ((b[index] & 0xff) << 8 | b[index + 1] & 0xff);
	}

	public int readInt(int index) {
		byte b[] = this.b;
		return (b[index] & 0xff) << 24 | (b[index + 1] & 0xff) << 16 | (b[index + 2] & 0xff) << 8 | b[index + 3] & 0xff;
	}

	public long readLong(int index) {
		long l1 = readInt(index);
		long l0 = (long) readInt(index + 4) & 0xffffffffL;
		return l1 << 32 | l0;
	}

	public String readUTF8(int index, char buf[]) {
		int item = readUnsignedShort(index);
		if (index == 0 || item == 0)
			return null;
		String s = strings[item];
		if (s != null) {
			return s;
		} else {
			index = items[item];
			return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
		}
	}

	private String readUTF(int index, int utfLen, char buf[]) {
		int endIndex = index + utfLen;
		byte b[] = this.b;
		int strLen = 0;
		int st = 0;
		char cc = '\0';
		while (index < endIndex) {
			int c = b[index++];
			switch (st) {
			default:
				break;

			case 0: // '\0'
				c &= 0xff;
				if (c < 128) {
					buf[strLen++] = (char) c;
					break;
				}
				if (c < 224 && c > 191) {
					cc = (char) (c & 0x1f);
					st = 1;
				} else {
					cc = (char) (c & 0xf);
					st = 2;
				}
				break;

			case 1: // '\001'
				buf[strLen++] = (char) (cc << 6 | c & 0x3f);
				st = 0;
				break;

			case 2: // '\002'
				cc = (char) (cc << 6 | c & 0x3f);
				st = 1;
				break;
			}
		}
		return new String(buf, 0, strLen);
	}

	public String readClass(int index, char buf[]) {
		return readUTF8(items[readUnsignedShort(index)], buf);
	}

	public Object readConst(int item, char buf[]) {
		int index = this.items[item];
		switch (b[index - 1]) {
		case 3: // '\003'
			return new Integer(readInt(index));

		case 4: // '\004'
			return new Float(Float.intBitsToFloat(readInt(index)));

		case 5: // '\005'
			return new Long(readLong(index));

		case 6: // '\006'
			return new Double(Double.longBitsToDouble(readLong(index)));

		case 7: // '\007'
			return Type.getObjectType(readUTF8(index, buf));

		case 8: // '\b'
			return readUTF8(index, buf);

		case 16: // '\020'
			return Type.getMethodType(readUTF8(index, buf));

		case 9: // '\t'
		case 10: // '\n'
		case 11: // '\013'
		case 12: // '\f'
		case 13: // '\r'
		case 14: // '\016'
		case 15: // '\017'
		default:
			int tag = readByte(index);
			int items[] = this.items;
			int cpIndex = items[readUnsignedShort(index + 1)];
			String owner = readClass(cpIndex, buf);
			cpIndex = items[readUnsignedShort(cpIndex + 2)];
			String name = readUTF8(cpIndex, buf);
			String desc = readUTF8(cpIndex + 2, buf);
			return new Handle(tag, owner, name, desc);
		}
	}

	public static final int SKIP_CODE = 1;
	public static final int SKIP_DEBUG = 2;
	public static final int SKIP_FRAMES = 4;
	public final int header;
	static final boolean SIGNATURES = true;
	static final boolean ANNOTATIONS = true;
	static final boolean FRAMES = true;
	static final boolean WRITER = true;
	static final boolean RESIZE = true;
	public static final int EXPAND_FRAMES = 8;
	public final byte b[];
	private final int items[];
	private final String strings[];
	private final int maxStringLength;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy