private IEnumerable <BaseNode> ReadNodeElements(IEnumerable <XElement> elements, ClassNode parent, ILogger logger) { Contract.Requires(elements != null); Contract.Requires(Contract.ForAll(elements, e => e != null)); Contract.Requires(parent != null); Contract.Requires(logger != null); foreach (var element in elements) { var converter = CustomNodeConvert.GetReadConverter(element); if (converter != null) { if (converter.TryCreateNodeFromElement(element, parent, project.Classes, logger, out var customNode)) { yield return(customNode); } continue; } if (!buildInStringToTypeMap.TryGetValue(element.Attribute(XmlTypeAttribute)?.Value ?? string.Empty, out var nodeType)) { logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute(XmlTypeAttribute)?.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(XmlNameAttribute)?.Value ?? string.Empty; node.Comment = element.Attribute(XmlCommentAttribute)?.Value ?? string.Empty; if (node is BaseReferenceNode referenceNode) { var reference = NodeUuid.FromBase64String(element.Attribute(XmlReferenceAttribute)?.Value, false); if (!project.ContainsClass(reference)) { logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {reference}"); logger.Log(LogLevel.Warning, element.ToString()); continue; } var innerClassNode = project.GetClassByUuid(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(XmlMethodElement) .Select(e => new VMethodNode { Name = e.Attribute(XmlNameAttribute)?.Value ?? string.Empty, Comment = e.Attribute(XmlCommentAttribute)?.Value ?? string.Empty }) .ForEach(vtableNode.AddNode); break; } case BaseArrayNode arrayNode: { TryGetAttributeValue(element, XmlCountAttribute, out var count, logger); arrayNode.Count = count; break; } case BaseTextNode textNode: { TryGetAttributeValue(element, XmlLengthAttribute, out var length, logger); textNode.Length = length; break; } case BitFieldNode bitFieldNode: { TryGetAttributeValue(element, XmlBitsAttribute, out var bits, logger); bitFieldNode.Bits = bits; break; } case FunctionNode functionNode: { functionNode.Signature = element.Attribute(XmlSignatureAttribute)?.Value ?? string.Empty; var reference = NodeUuid.FromBase64String(element.Attribute(XmlReferenceAttribute)?.Value, false); if (project.ContainsClass(reference)) { functionNode.BelongsToClass = project.GetClassByUuid(reference); } break; } } yield return(node); } }
private static IEnumerable <XElement> CreateNodeElements(IEnumerable <BaseNode> nodes, ILogger logger) { Contract.Requires(nodes != null); Contract.Requires(Contract.ForAll(nodes, n => n != null)); Contract.Requires(logger != null); Contract.Ensures(Contract.Result <IEnumerable <XElement> >() != null); foreach (var node in nodes) { var converter = CustomNodeConvert.GetWriteConverter(node); if (converter != null) { yield return(converter.CreateElementFromNode(node, logger)); continue; } if (!buildInTypeToStringMap.TryGetValue(node.GetType(), out var typeString)) { logger.Log(LogLevel.Error, $"Skipping node with unknown type: {node.Name}"); logger.Log(LogLevel.Warning, node.GetType().ToString()); continue; } var element = new XElement( XmlNodeElement, new XAttribute(XmlNameAttribute, node.Name ?? string.Empty), new XAttribute(XmlCommentAttribute, node.Comment ?? string.Empty), new XAttribute(XmlTypeAttribute, typeString) ); if (node is BaseReferenceNode referenceNode) { element.SetAttributeValue(XmlReferenceAttribute, referenceNode.InnerNode.Uuid.ToBase64String()); } switch (node) { case VTableNode vtableNode: { element.Add(vtableNode.Nodes.Select(n => new XElement( XmlMethodElement, new XAttribute(XmlNameAttribute, n.Name ?? string.Empty), new XAttribute(XmlCommentAttribute, n.Comment ?? string.Empty) ))); break; } case BaseArrayNode arrayNode: { element.SetAttributeValue(XmlCountAttribute, arrayNode.Count); break; } case BaseTextNode textNode: { element.SetAttributeValue(XmlLengthAttribute, textNode.Length); break; } case BitFieldNode bitFieldNode: { element.SetAttributeValue(XmlBitsAttribute, bitFieldNode.Bits); break; } case FunctionNode functionNode: { var uuid = functionNode.BelongsToClass == null ? NodeUuid.Zero : functionNode.BelongsToClass.Uuid; element.SetAttributeValue(XmlReferenceAttribute, uuid.ToBase64String()); element.SetAttributeValue(XmlSignatureAttribute, functionNode.Signature); break; } } yield return(element); } }