package hep.io.root.core; import hep.io.root.RootClass; import hep.io.root.RootClassNotFound; import hep.io.root.RootMember; import org.apache.bcel.generic.BranchHandle; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.GOTO; import org.apache.bcel.generic.IFEQ; import org.apache.bcel.generic.InstructionConstants; import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.LCONST; import org.apache.bcel.generic.PUSH; import org.apache.bcel.generic.Type; /** * * @author tonyj * @version $Id: BasicRootClass.java 13616 2009-04-09 21:25:45Z tonyj $ */ public abstract class BasicRootClass implements RootClass, org.apache.bcel.Constants { private static boolean debugRoot = System.getProperty("debugRoot") != null; /** * Get the Java type corresponding to this class. */ public abstract Type getJavaType(); public String toString() { return "RootClass: " + getClassName(); } /** * The method used to convert the object to its method type. */ protected String getConvertMethod() { return null; } /** * The type that will be used when this class is stored as a member, or as a return * type from a method. */ protected Type getJavaTypeForMethod() { return getJavaType(); } protected void generateStreamer(ConstantPoolGen cp, InstructionList il, InstructionFactory factory, String className, boolean hasHeader) { if (hasHeader) { if (debugRoot) { // Each class starts with a version field! il.append(InstructionConstants.ALOAD_1); // Copy the inputstream il.append(factory.createInvoke("hep.io.root.core.RootInput", "readUnsignedShort", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.DUP); il.append(new PUSH(cp, 16384)); il.append(InstructionConstants.IAND); BranchHandle bh = il.append(new IFEQ(null)); il.append(new PUSH(cp, 16383)); il.append(InstructionConstants.IAND); il.append(new PUSH(cp, 16)); il.append(InstructionConstants.ISHL); il.append(InstructionConstants.ALOAD_1); il.append(factory.createInvoke("hep.io.root.core.RootInput", "readUnsignedShort", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.IADD); il.append(InstructionConstants.I2L); il.append(InstructionConstants.ALOAD_1); il.append(factory.createInvoke("hep.io.root.core.RootInput", "getPosition", Type.LONG, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.LADD); il.append(InstructionConstants.ALOAD_1); il.append(factory.createInvoke("hep.io.root.core.RootInput", "readUnsignedShort", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.POP); BranchHandle bh2 = il.append(new GOTO(null)); bh.setTarget(il.append(InstructionConstants.POP)); il.append(new PUSH(cp, 0L)); bh2.setTarget(il.append(InstructionConstants.NOP)); } else { il.append(InstructionConstants.ALOAD_1); // Copy the inputstream il.append(factory.createInvoke("hep.io.root.core.RootInput", "readUnsignedShort", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(new PUSH(cp, 16384)); il.append(InstructionConstants.IAND); BranchHandle bh = il.append(new IFEQ(null)); il.append(InstructionConstants.ALOAD_1); il.append(factory.createInvoke("hep.io.root.core.RootInput", "readInt", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.POP); bh.setTarget(il.append(InstructionConstants.NOP)); //il.append(new ALOAD(1)); //il.append(new PUSH(cp,6)); //il.append(factory.createInvoke("hep.io.root.core.RootInput","skipBytes",Type.INT,new Type[]{ Type.INT },INVOKEINTERFACE)); //il.append(new POP()); } } // Now create streamers for any super classes RootClass[] superClasses = getSuperClasses(); for (int i = 0; i < superClasses.length; i++) ((BasicRootClass) superClasses[i]).generateStreamer(cp, il, factory, className, hasHeader); RootMember[] members = getMembers(); for (int i = 0; i < members.length; i++) { if (((BasicMember) members[i]).getType() != null) { il.append(InstructionConstants.ALOAD_0); il.append(InstructionConstants.ALOAD_1); ((BasicMember) members[i]).generateReadCode(il, factory, cp, className); il.append(factory.createPutField(className, members[i].getName(),((BasicMember) members[i]).getJavaType())); } else { il.append(InstructionConstants.ALOAD_1); ((BasicMember) members[i]).generateReadCode(il, factory, cp, className); } } if (debugRoot && hasHeader) { // Check the length il.append(InstructionConstants.DUP2); il.append(new LCONST(0L)); il.append(InstructionConstants.LCMP); BranchHandle bh = il.append(new IFEQ(null)); il.append(InstructionConstants.ALOAD_1); il.append(factory.createInvoke("hep.io.root.core.RootInput", "getPosition", Type.LONG, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.LSUB); il.append(InstructionConstants.DUP2); il.append(new LCONST(0L)); il.append(InstructionConstants.LCMP); BranchHandle bh2 = il.append(new IFEQ(null)); il.append(factory.createNew("hep.io.root.core.WrongLengthException")); il.append(InstructionConstants.DUP_X2); il.append(InstructionConstants.DUP_X2); il.append(InstructionConstants.POP); il.append(new PUSH(cp, className)); Type[] args = { Type.LONG, Type.STRING }; il.append(factory.createInvoke("hep.io.root.core.WrongLengthException", "<init>", Type.VOID, args, INVOKESPECIAL)); il.append(InstructionConstants.ATHROW); InstructionHandle ih = il.append(InstructionConstants.POP2); bh.setTarget(ih); bh2.setTarget(ih); } } abstract void generateReadCode(InstructionList il, InstructionFactory factory, ConstantPoolGen cp); abstract void resolve(RootClassFactory factory) throws RootClassNotFound; }