/// <summary> /// Populate a class with the stuff we find in the branches we are looking at. /// </summary> /// <param name="container"></param> /// <param name="branches"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> ExtractClassesFromBranchList(ROOTClassShell container, IEnumerable <ROOTNET.Interface.NTBranch> branches) { /// /// Now, loop through each branch and see if we can't convert everything! /// foreach (var branch in branches) { /// /// What kind of branch is this? Is it a leaf branch or is it a "class" branch. That is, does it have /// sub leaves on it? The key question to ask is how many sub-branches are there here? /// if (branch.ListOfBranches.Entries == 0) { foreach (var leaf in branch.GetListOfLeaves().Cast <ROOTNET.Interface.NTLeaf>()) { var cls = ROOTNET.NTClass.GetClass(leaf.TypeName); if (cls == null || !cls.IsShellTClass() || cls.IsSTLClass()) { // This is a class known to ROOT or // it is something very simple (int, vector<int>, etc.). try { IClassItem toAdd = ExtractUnsplitKnownClass(leaf); if (toAdd != null) { container.Add(toAdd); } } catch (Exception e) { SimpleLogging.Log("Info: Unable to transltae ntuple leaf '" + leaf.Name + "': " + e.Message); } } else { // This is a class we will have to bulid metadata for - from the streamer (the # of leaves // is zero if we are here, so it can only be streamer defiend). foreach (var item in ExtractUnsplitUnknownClass(container, leaf.Name, cls)) { yield return(item); } } } } else { var rc = ExtractClass(container, branch); ROOTClassShell lastOne = null; foreach (var rootClass in rc) { yield return(rootClass); lastOne = rootClass; } } } }
/// <summary> /// We extract the class info for a ROOT class that is a template. We properly deal with the class being templatized /// being another crazy class (or just a vector of int, etc.). /// </summary> /// <param name="container"></param> /// <param name="memberName"></param> /// <param name="className"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> ExtractROOTTemplateClass(ROOTClassShell container, string memberName, string className) { /// /// Currently only setup to deal with some very specific types of vectors! /// var parsedMatch = TemplateParser.ParseForTemplates(className) as TemplateParser.TemplateInfo; if (parsedMatch == null) { SimpleLogging.Log("Type '{0}' is a template, but we can't parse it, so '{1}' will be ignored", className, memberName); return(Enumerable.Empty <ROOTClassShell>()); } if (parsedMatch.TemplateName != "vector") { SimpleLogging.Log("We can only deal with the vector type (not '{0}'), so member '{1}' will be ignored", className, memberName); return(Enumerable.Empty <ROOTClassShell>()); } if (!(parsedMatch.Arguments[0] is TemplateParser.RegularDecl)) { SimpleLogging.Log("We can't yet deal with nested templates - '{0}' - so member '{1}' will be ignored", className, memberName); return(Enumerable.Empty <ROOTClassShell>()); } var templateArgClass = (parsedMatch.Arguments[0] as TemplateParser.RegularDecl).Type; // // Now we take a look at the class. // // One case is that it is a simple class, like "Unsigned int" that // isn't known to root at all. That means we hvae no dictionary for vector<unsigned int> - otherwise // we never would have gotten into here. So ignore it. :-) // var classInfo = ROOTNET.NTClass.GetClass(templateArgClass); if (classInfo == null) { return(Enumerable.Empty <ROOTClassShell>()); } // // If this class is known by root then we will have // a very easy time. No new classes are created or defined and there is nothing // extra to do other than making the element. if (!classInfo.IsShellTClass()) { container.Add(new ItemVector(TemplateParser.TranslateToCSharp(parsedMatch), memberName)); return(Enumerable.Empty <ROOTClassShell>()); } // // If the class isn't known by ROOT then we have only one hope - building it out of the // streamer (at this point, where we are in the code path, it is also the case that there // aren't leaf sub-branches here). // var newClassDefs = ExtractUnsplitUnknownClass(classInfo); container.Add(new ItemVector(TemplateParser.TranslateToCSharp(parsedMatch), memberName)); return(newClassDefs); }
/// <summary> /// Extract a class from a "good" streamer. /// </summary> /// <param name="cls"></param> /// <param name="streamer"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> ExtractClassFromStreamer(ROOTClassShell container, string itemName, ROOTNET.Interface.NTClass cls, ROOTNET.Interface.NTVirtualStreamerInfo sInfo) { // This guy is a class with elements, so go get the elements... var c = new ROOTClassShell(cls.Name.SanitizedName()) { IsTopLevelClass = false }; if (container != null) { container.Add(new ItemROOTClass() { Name = itemName, ItemType = cls.Name.SanitizedName(), NotAPointer = false }); } var clist = new List <ROOTClassShell> { c }; foreach (var item in sInfo.Elements.Cast <ROOTNET.Interface.NTStreamerElement>()) { if (item == null) { throw new ArgumentNullException("Streamer element was null"); } if (item.TypeName == "BASE") { SimpleLogging.Log(string.Format("Item '{0}' has a subclass of type '{1}' - we can't parse inherritance yet", itemName, item.FullName)); continue; } var itemCls = item.ClassPointer; if (itemCls == null) { // This is going to be something like "int", or totally unknown! c.Add(ExtractSimpleItem(new SimpleLeafInfo() { Name = item.FullName, TypeName = item.TypeName, Title = item.FullName })); } else if (!itemCls.IsShellTClass()) { try { // We know about this class, and can use ROOT infrasturcutre to do the parsing for it. // Protect against funny template arguments we can't deal with now - just skip them. var itemC = ExtractSimpleItem(new SimpleLeafInfo() { Name = item.FullName, TypeName = itemCls.Name, Title = item.FullName }); c.Add(itemC); } catch (Exception e) { SimpleLogging.Log(string.Format("Unable to deal with streamer type '{0}', skiping member '{1}': {2}", itemCls.Name, item.FullName, e.Message)); } } else { // Unknown to ROOT class. How we handle this, exactly, depends if it is a template class or if it is // a raw class. if (itemCls.IsTemplateClass()) { var newClassDefs = ExtractROOTTemplateClass(c, item.FullName, itemCls.Name); clist.AddRange(newClassDefs); } else { var newClassDefs = new List <ROOTClassShell>(ExtractUnsplitUnknownClass(c, item.FullName, itemCls)); clist.AddRange(newClassDefs); } } } return(clist); }