package hep.io.root.core; import hep.io.root.RootClass; import hep.io.root.RootClassNotFound; import java.util.StringTokenizer; import java.util.Vector; import org.apache.bcel.generic.ArrayType; import org.apache.bcel.generic.BasicType; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.InstructionConstants; import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.NEWARRAY; import org.apache.bcel.generic.Type; /** * An implementation of StreamerInfo which takes info from a String * @author Tony Johnson (tonyj@slac.stanford.edu) * @version $Id: StreamerInfoString.java 8584 2006-08-10 23:06:37Z duns $ */ public class StreamerInfoString extends StreamerInfo { private String description; /** * Builds a StreamerInfo class from a string. The string * must be of the form defined by the root StreamerInfo * class. A ClassFactory must also be given, and is used to * interpret the types. */ public StreamerInfoString(String description) { //we delay resolving the referenced classes until the //resolve method is called, so that we can wait until the //class factory is fully loaded. this.description = description; } int getBits() { return 0; } int getCheckSum() { return 0; } int getVersion() { return 0; } void resolve(RootClassFactory factory) throws RootClassNotFound { if (description != null) { Vector sv = new Vector(); Vector mv = new Vector(); StringTokenizer tokenizer = new StringTokenizer(description, ";"); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); StringTokenizer t2 = new StringTokenizer(token, " "); if (t2.countTokens() == 1) { String className = t2.nextToken(); // This must be a super class RootClass superClass = factory.create(className); sv.addElement(superClass); } else { String index = null; String type = t2.nextToken(); String name = t2.nextToken(); boolean pointer = type.endsWith("*"); if (pointer) type = type.substring(0, type.length() - 1); int pos = type.indexOf('['); if (pos > 0) { int l = type.length(); index = type.substring(pos + 1, l - 1); type = type.substring(0, pos); } BasicRootClass memberClass = factory.create(type); mv.addElement(new MemberString(memberClass, name, pointer, index)); } } superClasses = new RootClass[sv.size()]; sv.copyInto(superClasses); members = new MemberString[mv.size()]; mv.copyInto(members); description = null; // Not needed anymore } } private class MemberString extends BasicMember { private BasicRootClass varClass; private String name; private boolean pointer; private int dim; private int index; private String varCounter; MemberString(BasicRootClass type, String name, boolean pointer, String index) { this.varClass = type; this.name = name; this.pointer = pointer; this.dim = (index == null) ? 0 : 1; try { this.index = Integer.parseInt(index); } catch (NumberFormatException x) { varCounter = index; } } public int getArrayDim() { return dim; } public String getVarCounter() { return varCounter; } public String getComment() { return null; } public Type getJavaType() { Type t = ((BasicRootClass) varClass).getJavaTypeForMethod(); if (dim > 0) t = new ArrayType(t, dim); return t; } public int getMaxIndex(int index) { return index == 0 ? this.index : 1; } public String getName() { return name; } public RootClass getType() { return varClass; } public void generateReadCode(InstructionList il, InstructionFactory factory, ConstantPoolGen cp, String className) { if (pointer) { ((GenericRootClass) varClass).generateReadPointerCode(il, factory, cp); } else if (dim == 0) { varClass.generateReadCode(il, factory, cp); } else if (varCounter == null) { ((IntrinsicRootClass) varClass).generateReadArrayCode(il, factory, cp, 1, new int[]{index}); } else { BasicMember varMember = getMember(varCounter); if (varMember == null) throw new RuntimeException("Cannot find variable counter "+varCounter); Type varMemberType = varMember.getJavaType(); il.append(InstructionConstants.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)); 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)); } if (varClass.getConvertMethod() != null) { il.append(factory.createInvoke("hep.io.root.interfaces." + varClass.getClassName(), varClass.getConvertMethod(), varClass.getJavaTypeForMethod(), Type.NO_ARGS, INVOKEINTERFACE)); } } boolean isPointer() { return pointer; } } }