package hep.io.root.core; import hep.io.root.RootClass; import hep.io.root.RootClassNotFound; import hep.io.root.interfaces.TStreamerBasicPointer; import hep.io.root.interfaces.TStreamerElement; import hep.io.root.interfaces.TStreamerInfo; import hep.io.root.interfaces.TStreamerLoop; import java.util.Iterator; import java.util.Vector; import org.apache.bcel.generic.ALOAD; import org.apache.bcel.generic.ANEWARRAY; import org.apache.bcel.generic.ASTORE; import org.apache.bcel.generic.ArrayType; import org.apache.bcel.generic.BasicType; 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.IF_ICMPGE; import org.apache.bcel.generic.IINC; import org.apache.bcel.generic.ILOAD; import org.apache.bcel.generic.ISTORE; 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.NEWARRAY; import org.apache.bcel.generic.ObjectType; import org.apache.bcel.generic.Type; /** * An implementation of StreamerInfo which takes its data from a TStreamerInfo object. * @author tonyj * @version $Id: StreamerInfoNew.java 8584 2006-08-10 23:06:37Z duns $ */ public class StreamerInfoNew extends StreamerInfo implements org.apache.bcel.Constants { private final static int kBase = 0; private final static int kOffsetL = 20; private final static int kOffsetP = 40; private final static int kCounter = 6; private final static int kCharStar = 7; private final static int kChar = 1; private final static int kShort = 2; private final static int kInt = 3; private final static int kLong = 4; private final static int kFloat = 5; private final static int kDouble = 8; private final static int kDouble32 = 9; private final static int kUChar = 11; private final static int kUShort = 12; private final static int kUInt = 13; private final static int kULong = 14; private final static int kBits = 15; private final static int kLong64 = 16; private final static int kULong64 = 17; private final static int kBool = 18; private final static int kObject = 61; private final static int kAny = 62; private final static int kObjectp = 63; private final static int kObjectP = 64; private final static int kTString = 65; private final static int kTObject = 66; private final static int kTNamed = 67; private final static int kMissing = 99999; private final static int kSkip = 100; private final static int kSkipL = 120; private final static int kSkipP = 140; private final static int kObjectV = 47; private final static int kObjectVV = 48; private final static int kConv = 200; private final static int kConvL = 220; private final static int kConvP = 240; private final static int kStreamer = 500; private final static int kStreamLoop = 501; private final static int kSTL = 300; private final static int kSTLstring = 365; private final static int kSTLvector = 1; private final static int kSTLlist = 2; private final static int kSTLdeque = 3; private final static int kSTLmap = 4; private final static int kSTLset = 5; private final static int kSTLmultimap = 6; private final static int kSTLmultiset = 7; private TStreamerInfo streamerInfo; private boolean resolved = false; private static boolean debug = System.getProperty("debugRoot") != null; /** Creates new StreamerInfoNew */ public StreamerInfoNew(TStreamerInfo streamerInfo) { this.streamerInfo = streamerInfo; } public int getCheckSum() { return streamerInfo.getCheckSum(); } public int getVersion() { return streamerInfo.getClassVersion(); } public void resolve(RootClassFactory factory) throws RootClassNotFound { if (!resolved) { Vector sv = new Vector(); Vector mv = new Vector(); for (Iterator i = streamerInfo.getElements().iterator(); i.hasNext();) { TStreamerElement element = (TStreamerElement) i.next(); if (element == null) continue; String typeName = element.getTypeName().toString(); //System.out.println(element.getName()+" "+typeName); if (typeName.equals("BASE")) // base class { String className = element.getName().toString(); sv.addElement(factory.create(className)); } else // member { try { mv.addElement(new MemberNew(element, factory)); } catch (RootClassNotFound x) { if (debug) System.err.println("Substituting dummy element for "+element.getName()+" of type "+x.getClassName()); mv.addElement(new DummyMember(element, factory)); } } } superClasses = new RootClass[sv.size()]; sv.copyInto(superClasses); members = new BasicMember[mv.size()]; mv.copyInto(members); resolved = true; } } int getBits() { return streamerInfo.getBits(); } private class MemberNew extends BasicMember { private BasicRootClass varClass; private String varComment; private String varCounter; private String varName; private int[] maxIndex; private int arrayDim; private int varType; MemberNew(TStreamerElement element, RootClassFactory factory) throws RootClassNotFound { varName = element.getName(); varComment = element.getTitle(); arrayDim = element.getArrayDim(); String typeName = element.getTypeName(); varType = element.getType(); maxIndex = element.getMaxIndex(); if (typeName.endsWith("*")) { // This seems dubious, but needed to read CMS moy.root?? if (varType == kAny) varType = kObjectP; typeName = typeName.substring(0, typeName.length() - 1); } if ((varType >= kOffsetP) && (varType <= (kOffsetP + 20))) arrayDim++; // Note: typeName may just refer to a Enumeration, in which case it is // not defined in the root file. This decission should be based on a combination // of varType and varClass. if (varType == 3) varClass = factory.create("Int_t"); else varClass = factory.create(typeName); if (element instanceof TStreamerBasicPointer) { varCounter = ((TStreamerBasicPointer) element).getCountName(); } else if (element instanceof TStreamerLoop) { varCounter = ((TStreamerLoop) element).getCountName(); arrayDim++; } } public int getArrayDim() { return arrayDim; } public String getComment() { return varComment; } public Type getJavaType() { Type t = varClass.getJavaTypeForMethod(); if (arrayDim > 0) t = new ArrayType(t, arrayDim); return t; } public int getMaxIndex(int index) { return maxIndex[index]; } public String getName() { return varName; } public RootClass getType() { return varClass; } public String getVarCounter() { return varCounter; } public void generateReadCode(InstructionList il, InstructionFactory factory, ConstantPoolGen cp, String className) { try { switch (varType) { case kChar: case kShort: case kInt: case kLong: case kFloat: case kDouble: case kDouble32: case kCounter: case kUChar: case kUShort: case kUInt: case kULong: case kBits: case kObject: case kObjectp: case kTString: case kTObject: case kTNamed: case kAny: case kLong64: case kULong64: case kBool: varClass.generateReadCode(il, factory, cp); break; case kCharStar: il.append(InstructionConstants.DUP); il.append(factory.createInvoke("hep.io.root.core.RootInput", "readInt", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(factory.createInvoke("hep.io.root.core.RootInput", "skipBytes", Type.INT, new Type[] { Type.INT }, INVOKEINTERFACE)); il.append(InstructionConstants.POP); il.append(InstructionConstants.ICONST_0); break; case kOffsetP + kChar: case kOffsetP + kShort: case kOffsetP + kInt: case kOffsetP + kLong: case kOffsetP + kFloat: case kOffsetP + kDouble: case kOffsetP + kDouble32: case kOffsetP + kUChar: case kOffsetP + kUShort: case kOffsetP + kUInt: case kOffsetP + kULong: case kOffsetP + kLong64: case kOffsetP + kULong64: case kOffsetP + kBool: il.append(InstructionConstants.DUP); il.append(factory.createInvoke("hep.io.root.core.RootInput", "readByte", Type.BYTE, Type.NO_ARGS, INVOKEINTERFACE)); BranchHandle bh = il.append(new IFEQ(null)); il.append(InstructionConstants.ALOAD_0); il.append(factory.createInvoke(className, nameMangler.mangleMember(varCounter), Type.INT, Type.NO_ARGS, INVOKESPECIAL)); BasicType type = (BasicType) varClass.getJavaType(); il.append(new NEWARRAY(type)); il.append(InstructionConstants.DUP_X1); Type[] arrayArgType = new Type[] { new ArrayType(type, 1) }; il.append(factory.createInvoke("hep.io.root.core.RootInput", "readFixedArray", Type.VOID, arrayArgType, INVOKEINTERFACE)); BranchHandle bh2 = il.append(new GOTO(null)); bh.setTarget(il.append(InstructionConstants.POP)); il.append(InstructionConstants.ACONST_NULL); bh2.setTarget(il.append(InstructionConstants.NOP)); break; case kOffsetL + kChar: case kOffsetL + kShort: case kOffsetL + kInt: case kOffsetL + kLong: case kOffsetL + kFloat: case kOffsetL + kDouble: case kOffsetL + kDouble32: case kOffsetL + kUChar: case kOffsetL + kUShort: case kOffsetL + kUInt: case kOffsetL + kULong: case kOffsetL + kLong64: case kOffsetL + kULong64: case kOffsetL + kBool: IntrinsicRootClass intrinsic = (IntrinsicRootClass) varClass; intrinsic.generateReadArrayCode(il, factory, cp, arrayDim, maxIndex); break; case kObjectP: ((GenericRootClass) varClass).generateReadPointerCode(il, factory, cp); break; case kStreamLoop: if (!varClass.getClassName().equals("TString")) { //TODO: Fixme System.err.println("Warning: Generating dummy read for "+varName); il.append(factory.createInvoke("hep.io.root.core.RootInput", "dump", Type.VOID, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.ACONST_NULL); } else { il.append(factory.createInvoke("hep.io.root.core.RootInput", "readVersion", Type.INT, Type.NO_ARGS, INVOKEINTERFACE)); il.append(InstructionConstants.POP); BasicMember varMember = getMember(varCounter); if (varMember == null) throw new RuntimeException("Cannot find variable counter "+varCounter); Type varMemberType = varMember.getJavaType(); il.append(InstructionConstants.DUP); //ALOAD_0 il.append(factory.createInvoke(className, nameMangler.mangleMember(varCounter), varMemberType, Type.NO_ARGS, INVOKESPECIAL)); if (varMemberType != Type.INT) il.append(factory.createCast(varMemberType, Type.INT)); il.append(InstructionConstants.DUP); il.append(InstructionConstants.ISTORE_2); ObjectType xxxType = (ObjectType) varClass.getJavaTypeForMethod(); il.append(new ANEWARRAY(cp.addClass(xxxType))); il.append(new ASTORE(3)); il.append(InstructionConstants.ICONST_0); il.append(new ISTORE(4)); InstructionHandle ih = il.append(new ILOAD(4)); il.append(InstructionConstants.ILOAD_2); bh = il.append(new IF_ICMPGE(null)); il.append(new ALOAD(3)); il.append(new ILOAD(4)); il.append(InstructionConstants.ALOAD_1); varClass.generateReadCode(il, factory, cp); if (varClass.getConvertMethod() != null && arrayDim == 1) { il.append(factory.createInvoke("hep.io.root.interfaces." + varClass.getClassName(), varClass.getConvertMethod(), varClass.getJavaTypeForMethod(), Type.NO_ARGS, INVOKEINTERFACE)); } il.append(InstructionConstants.AASTORE); il.append(new IINC(4,1)); il.append(new GOTO(ih)); bh.setTarget(il.append(InstructionConstants.NOP)); il.append(new ALOAD(3)); } break; default: throw new RuntimeException("Unable to decode varType " + varType); } if (varClass.getConvertMethod() != null && arrayDim == 0) { il.append(factory.createInvoke("hep.io.root.interfaces." + varClass.getClassName(), varClass.getConvertMethod(), varClass.getJavaTypeForMethod(), Type.NO_ARGS, INVOKEINTERFACE)); } } catch (RuntimeException x) { System.err.println("Error reading member " + varName + " of type " + varClass.getClassName()); throw x; } } } private class DummyMember extends BasicMember { private String varComment; private String varName; private int[] maxIndex; private int arrayDim; private int varType; DummyMember(TStreamerElement element, RootClassFactory factory) { varName = element.getName(); varComment = element.getTitle(); arrayDim = element.getArrayDim(); varType = element.getType(); maxIndex = element.getMaxIndex(); } public int getArrayDim() { return arrayDim; } public String getComment() { return varComment; } public Type getJavaType() { return Type.STRING; } public int getMaxIndex(int index) { return maxIndex[index]; } public String getName() { return varName; } public RootClass getType() { return null; // Fixme: } public void generateReadCode(InstructionList il, InstructionFactory factory, ConstantPoolGen cp, String className) { System.err.println("Warnng: Generating dummy read for "+varName); il.append(factory.createInvoke("hep.io.root.core.RootInput", "skipObject", Type.VOID, Type.NO_ARGS, INVOKEINTERFACE)); } } }