private byte[] GetNodeData(XElement node, byte nodeType, XmlType xmlType, int count) { if (nodeType == XmlType.StrType) { if (count != 1) { throw new FormatException("String value cannot have a count != 1."); } byte[] res = BinEncoding.GetBytes(node.Value.Trim()); Array.Resize(ref res, res.Length + 1); res[res.Length - 1] = 0; return(res); } else if (nodeType == XmlType.BinType) { string val = node.Value; if ((val.Length % 2) != 0) { throw new ArgumentException("Hex string needs to consist of pairs of two chars."); } byte[] res = new byte[val.Length / 2]; for (int i = 0, j = 0; i < val.Length; i += 2, ++j) { res[j] = Convert.ToByte(val.Substring(i, 2), 16); } return(res); } else { string[] parts = node.Value.Split(' '); if (parts.Length != count * xmlType.Count) { throw new ArgumentException("Node value does not have required amount of fields.", "node"); } byte[] res = new byte[xmlType.Size * count]; for (int i = 0; i < count; ++i) { Buffer.BlockCopy(xmlType.KFromString(parts, i * xmlType.Count), 0, res, xmlType.Size * i, xmlType.Size); } return(res); } }
private void ParseNodes() { uint dataSize = dataBuf.TakeU32(); XElement fakeroot = new XElement("fakeroot"); XElement node = fakeroot; bool nodesLeft = true; while (nodesLeft && !nodeBuf.AtEnd) { while (nodeBuf[nodeBuf.Offset] == 0) { nodeBuf.Offset += 1; } byte nodeType = nodeBuf.TakeU8(); bool isArray = (nodeType & 64) != 0; nodeType = (byte)(nodeType & ~64); string name = GetNodeName(nodeType); XmlType xmlType = null; bool startNode = false; switch (nodeType) { case XmlType.AttrType: string attrVal = dataBuf.TakeString(BinEncoding); dataBuf.RealignReads(); node.SetAttributeValue(name, attrVal); break; case XmlType.NodeEndType: node = node.Parent; break; case XmlType.SectionEndType: nodesLeft = false; break; case XmlType.VoidType: startNode = true; break; default: xmlType = XmlType.GetByType(nodeType); break; } if (xmlType == null && !startNode) { continue; } XElement child = new XElement(name); node.Add(child); node = child; if (startNode) { continue; } node.SetAttributeValue("__type", xmlType.Name); SetNodeValue(node, nodeType, xmlType, isArray); } Document = new XDocument(fakeroot.FirstNode); }
private void GenerateNode(XElement node) { if (NodeIsMixed(node)) { throw new ArgumentException("Nodes with mixed elements/text are not supported.", "node"); } XAttribute nodeTypeXAttr = node.Attribute("__type"); byte nodeType; XmlType xmlType = null; if (nodeTypeXAttr != null) { nodeType = XmlType.GetIdByName(nodeTypeXAttr.Value.ToLower()); xmlType = XmlType.GetByType(nodeType); } else { if (node.IsEmpty || node.HasElements) { nodeType = XmlType.VoidType; } else { nodeType = XmlType.StrType; } } bool isArray = false; int count = 1; XAttribute countXAttr = node.Attribute("__count"); if (countXAttr != null) { count = Convert.ToInt32(countXAttr.Value); isArray = true; } nodeBuf.AddU8((byte)(nodeType | (isArray ? 64 : 0))); AddNodeName(node.Name.LocalName); if (nodeType != XmlType.VoidType) { byte[] data = GetNodeData(node, nodeType, xmlType, count); if (isArray || xmlType.Count < 0) { dataBuf.AddS32(data.Length); dataBuf.AddBytesAligned(data); } else { dataBuf.AddBytesSubAligned(data); } } foreach (XAttribute attr in node.Attributes()) { if (attr.Name.LocalName == "__type" || attr.Name.LocalName == "__size" || attr.Name.LocalName == "__count") { continue; } nodeBuf.AddU8(XmlType.AttrType); AddNodeName(attr.Name.LocalName); dataBuf.AddString(attr.Value, BinEncoding); dataBuf.RealignWrites(); } foreach (XElement child in node.Elements()) { GenerateNode(child); } nodeBuf.AddU8(XmlType.NodeEndType | 64); }