public IEnumerable <BaseNode> GetEquivalentNodes(int size) { while (size != 0) { BaseNode paddingNode; #if RECLASSNET64 if (size >= 8) { paddingNode = new Hex64Node(); } else #endif if (size >= 4) { paddingNode = new Hex32Node(); } else if (size >= 2) { paddingNode = new Hex16Node(); } else { paddingNode = new Hex8Node(); } paddingNode.Comment = Comment; size -= paddingNode.MemorySize; yield return(paddingNode); } }
private IEnumerable <BaseNode> ReadNodeElements(IEnumerable <XElement> elements, ClassNode parent, IReadOnlyDictionary <string, ClassNode> classes, Type[] typeMap, ILogger logger) { Contract.Requires(elements != null); Contract.Requires(parent != null); Contract.Requires(classes != null); Contract.Requires(typeMap != null); Contract.Requires(logger != null); foreach (var element in elements) { Type nodeType = null; if (int.TryParse(element.Attribute("Type")?.Value, out var typeVal)) { if (typeVal >= 0 && typeVal < typeMap.Length) { nodeType = typeMap[typeVal]; } } if (nodeType == null) { logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute("Type")?.Value}"); logger.Log(LogLevel.Warning, element.ToString()); continue; } var node = Activator.CreateInstance(nodeType) as BaseNode; if (node == null) { logger.Log(LogLevel.Error, $"Could not create node of type: {nodeType}"); continue; } node.Name = element.Attribute("Name")?.Value ?? string.Empty; node.Comment = element.Attribute("Comment")?.Value ?? string.Empty; // Convert the Custom node into normal hex nodes. if (node is CustomNode) { int.TryParse(element.Attribute("Size")?.Value, out var size); while (size != 0) { BaseNode paddingNode; #if RECLASSNET64 if (size >= 8) { paddingNode = new Hex64Node(); } else #endif if (size >= 4) { paddingNode = new Hex32Node(); } else if (size >= 2) { paddingNode = new Hex16Node(); } else { paddingNode = new Hex8Node(); } paddingNode.Comment = node.Comment; size -= paddingNode.MemorySize; yield return(paddingNode); } continue; } if (node is BaseReferenceNode referenceNode) { string reference; if (referenceNode is ClassInstanceArrayNode) { reference = element.Element("Array")?.Attribute("Name")?.Value; } else { reference = element.Attribute("Pointer")?.Value ?? element.Attribute("Instance")?.Value; } if (reference == null || !classes.ContainsKey(reference)) { logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {reference}"); logger.Log(LogLevel.Warning, element.ToString()); continue; } var innerClassNode = classes[reference]; if (referenceNode.PerformCycleCheck && !ClassUtil.IsCycleFree(parent, innerClassNode, project.Classes)) { logger.Log(LogLevel.Error, $"Skipping node with cycle reference: {parent.Name}->{node.Name}"); continue; } referenceNode.ChangeInnerNode(innerClassNode); } switch (node) { case VTableNode vtableNode: element .Elements("Function") .Select(e => new VMethodNode { Name = e.Attribute("Name")?.Value ?? string.Empty, Comment = e.Attribute("Comment")?.Value ?? string.Empty }) .ForEach(vtableNode.AddNode); break; case ClassInstanceArrayNode classInstanceArrayNode: { TryGetAttributeValue(element, "Total", out var count, logger); classInstanceArrayNode.Count = count; break; } case ClassPtrArrayNode classPtrArrayNode: { TryGetAttributeValue(element, "Size", out var count, logger); classPtrArrayNode.Count = count / IntPtr.Size; break; } case BaseTextNode textNode: { TryGetAttributeValue(element, "Size", out var length, logger); textNode.Length = textNode is Utf16TextNode ? length / 2 : length; break; } case BitFieldNode bitFieldNode: { TryGetAttributeValue(element, "Size", out var bits, logger); bitFieldNode.Bits = bits * 8; break; } } yield return(node); } }