/// <summary> /// If this class is a shell class - that is, it has nothing defined in it, then... /// </summary> /// <param name="cls"></param> /// <returns></returns> public static bool IsShellTClass(this ROOTNET.Interface.NTClass cls) { var v = (cls.ListOfAllPublicDataMembers != null && cls.ListOfAllPublicDataMembers.Entries > 0) || (cls.ListOfAllPublicMethods != null && cls.ListOfAllPublicMethods.Entries > 0); return(!v); }
/// <summary> /// Return true if this class is a STL class. /// </summary> /// <param name="cls"></param> /// <returns></returns> public static bool IsSTLClass(this ROOTNET.Interface.NTClass cls) { var name = cls.Name; if (name.StartsWith("vector")) { if (name.Contains("<")) { return(true); } } return(false); }
/// <summary> /// A class has been defined only in the local tree. We need to parse through it and extract /// enough into to build a class on our own so that it can be correctly referenced in LINQ. /// </summary> /// <param name="container"></param> /// <param name="branch"></param> /// <param name="cls"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> BuildMetadataForTTreeClassFromBranches(ROOTClassShell container, ROOTNET.Interface.NTBranch branch, ROOTNET.Interface.NTClass cls) { // // Get a unique classname. Attempt to do "the right thing". In particular, if this is a clones array of some // struct, it is not a "named" class, so use the name of the clones array instead. // string className = cls.Name; bool mightBeClonesArray = false; if (branch is ROOTNET.Interface.NTBranchElement) { var cn = (branch as ROOTNET.Interface.NTBranchElement).ClonesName.SanitizedName(); if (!string.IsNullOrWhiteSpace(cn)) { className = cn; mightBeClonesArray = true; } } if (_classNameCounter.ContainsKey(className)) { _classNameCounter[className] += 1; className = string.Format("{0}_{1}", className, _classNameCounter[className]); } else { _classNameCounter[className] = 0; } // // We will define the class, and it will be exactly what is given to use by the // tree. // var varName = branch.Name.SanitizedName(); container.Add(new ItemSimpleType(varName, className) { NotAPointer = true }); // // We are going to build our own class type here. // var treeClass = new ROOTClassShell(className) { IsTopLevelClass = false }; // // Now, loop over the branches and add them in, returning any classes we had to generate. // foreach (var c in ExtractClassesFromBranchList(treeClass, branch.ListOfBranches.Cast <ROOTNET.Interface.NTBranch>())) { yield return(c); } // // The arrays in a tclones arrays are funny. The proxy generated parses them as seperate arrays, but their length is // basically the size of the tclonesarray. So we have to use that as the length. This is implied be cause we've marked // this class as a tclones array class already (above - the IsTTreeSubClass). So for the index we mark it as an index, // but we just marked the bound as "implied" - this will be picked up by the code when it is generated later on. // if (mightBeClonesArray) { var cBoundName = string.Format("{0}_", varName); var cstyleArrayIndicies = from item in treeClass.Items where item is ItemCStyleArray let citem = item as ItemCStyleArray from index in citem.Indicies where !index.indexConst && index.indexBoundName == cBoundName select index; bool foundTClonesArray = false; foreach (var item in cstyleArrayIndicies) { item.indexBoundName = "implied"; foundTClonesArray = true; } treeClass.IsTClonesArrayClass = foundTClonesArray; } // // If this is a tclones array - and it is a real array, then we don't want to de-reference anything. // if (treeClass.IsTClonesArrayClass) { foreach (var item in treeClass.Items) { item.NotAPointer = true; } } // // Finally, the one we just built! // yield return(treeClass); }
/// <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); }
/// <summary> /// Extract the unsplit unknown class by parsing the streamer. /// </summary> /// <param name="cls"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> ExtractUnsplitUnknownClass(ROOTNET.Interface.NTClass cls) { return(ExtractUnsplitUnknownClass(null, null, cls)); }
/// <summary> /// The class has no def in a TClass. It has no def in the way the branches and leaves are layed out. So, /// we, really, have only one option here. Parse the streamer! /// </summary> /// <param name="leaf"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> ExtractUnsplitUnknownClass(ROOTClassShell container, string itemName, ROOTNET.Interface.NTClass cls) { // Make sure that we are ok here. var streamer = cls.StreamerInfo; if (streamer == null) { return(Enumerable.Empty <ROOTClassShell>()); } return(ExtractClassFromStreamer(container, itemName, cls, streamer)); }
/// <summary> /// Is this class a template type or not? /// </summary> /// <param name="cls"></param> /// <returns></returns> public static bool IsTemplateClass(this ROOTNET.Interface.NTClass cls) { return(cls.Name.Contains("<")); }