private static void WriteNode( XmlWriter writer, BinaryResourceFile.Object node, IDefinitionProvider provider) { var def = provider.GetClassDefinition(node.TypeHash); writer.WriteStartElement("object"); if (def.Name != null) { writer.WriteAttributeString("type", def.Name); } else { writer.WriteAttributeString("hash", node.TypeHash.ToString("X8")); } if (node.Values != null && node.Values.Count > 0) { foreach (var kv in node.Values) { writer.WriteStartElement("value"); var member = def.GetMemberDefinition(kv.Key); if (member != null && member.Name != null) { writer.WriteAttributeString("name", member.Name); } else { writer.WriteAttributeString("hash", kv.Key.ToString("X8")); } if (member == null) { writer.WriteAttributeString("type", MemberType.BinHex.ToString()); writer.WriteBinHex(kv.Value, 0, kv.Value.Length); } else { writer.WriteAttributeString("type", member.Type.ToString()); switch (member.Type) { case MemberType.BinHex: { writer.WriteBinHex(kv.Value, 0, kv.Value.Length); break; } case MemberType.Hash: { if (kv.Value.Length != 4) { throw new FormatException(); } writer.WriteString(BitConverter.ToUInt32(kv.Value, 0).ToString("X8", CultureInfo.InvariantCulture)); break; } case MemberType.String: { if (kv.Value.Length < 1) { throw new FormatException(); } else if (kv.Value[kv.Value.Length - 1] != 0) { throw new FormatException(); } writer.WriteString(Encoding.UTF8.GetString(kv.Value, 0, kv.Value.Length - 1)); break; } case MemberType.Enum: { if (kv.Value.Length != 4) { throw new FormatException(); } writer.WriteString(BitConverter.ToUInt32(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.Bool: { if (kv.Value.Length != 1) { throw new FormatException(); } writer.WriteString((kv.Value[0] != 0 ? true : false).ToString()); break; } case MemberType.Float: { if (kv.Value.Length != 4) { throw new FormatException(); } writer.WriteString(BitConverter.ToSingle(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.Int32: { if (kv.Value.Length != 4) { throw new FormatException(); } writer.WriteString(BitConverter.ToInt32(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.UInt32: { if (kv.Value.Length != 4) { throw new FormatException(); } writer.WriteString(BitConverter.ToUInt32(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.Int64: { if (kv.Value.Length != 8) { throw new FormatException(); } writer.WriteString(BitConverter.ToInt64(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.UInt64: { if (kv.Value.Length != 8) { throw new FormatException(); } writer.WriteString(BitConverter.ToUInt64(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.Vector2: { if (kv.Value.Length != 4 * 2) { throw new FormatException(); } writer.WriteElementString("x", BitConverter.ToSingle(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("y", BitConverter.ToSingle(kv.Value, 4).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.Vector3: { if (kv.Value.Length != 4 * 3) { throw new FormatException(); } writer.WriteElementString("x", BitConverter.ToSingle(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("y", BitConverter.ToSingle(kv.Value, 4).ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("z", BitConverter.ToSingle(kv.Value, 8).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.Vector4: { if (kv.Value.Length != 4 * 4) { throw new FormatException(); } writer.WriteElementString("x", BitConverter.ToSingle(kv.Value, 0).ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("y", BitConverter.ToSingle(kv.Value, 4).ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("z", BitConverter.ToSingle(kv.Value, 8).ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("w", BitConverter.ToSingle(kv.Value, 12).ToString(CultureInfo.InvariantCulture)); break; } case MemberType.UInt32Array: { if (kv.Value.Length < 4) { throw new FormatException(); } var count = BitConverter.ToInt32(kv.Value, 0); if (kv.Value.Length != 4 + (count * 4)) { throw new FormatException(); } for (int i = 0, offset = 4; i < count; i++, offset += 4) { writer.WriteElementString("item", BitConverter.ToUInt32(kv.Value, offset).ToString(CultureInfo.InvariantCulture)); } break; } case MemberType.HashArray: { if (kv.Value.Length < 4) { throw new FormatException(); } var count = BitConverter.ToInt32(kv.Value, 0); if (kv.Value.Length != 4 + (count * 4)) { throw new FormatException(); } for (int i = 0, offset = 4; i < count; i++, offset += 4) { writer.WriteElementString("item", BitConverter.ToUInt32(kv.Value, offset).ToString("X8")); } break; } case MemberType.Rml: { var rez = new XmlResourceFile(); using (var input = new MemoryStream(kv.Value)) { rez.Deserialize(input); } writer.WriteStartElement("rml"); ConvertXml.Program.WriteNode(writer, rez.Root); writer.WriteEndElement(); break; } default: { throw new NotSupportedException(); } } } writer.WriteEndElement(); } } if (node.Children != null && node.Children.Count > 0) { foreach (var child in node.Children) { WriteNode(writer, child, def); } } writer.WriteEndElement(); }
private static BinaryResourceFile.Object ReadNode(string basePath, XPathNavigator node) { string className; uint classHash; Definitions.LoadTypeAndHash(node, out className, out classHash); var parent = new BinaryResourceFile.Object(); parent.TypeHash = classHash; var values = node.Select("value"); while (values.MoveNext() == true) { string valueName; uint valueHash; Definitions.LoadNameAndHash(values.Current, out valueName, out valueHash); MemberType valueType; string _valueType; _valueType = values.Current.GetAttribute("type", ""); if (string.IsNullOrWhiteSpace(_valueType) == true || Enum.IsDefined(typeof(MemberType), _valueType) == false) { throw new FormatException(); } valueType = (MemberType)Enum.Parse(typeof(MemberType), _valueType); byte[] valueData; switch (valueType) { case MemberType.BinHex: { using (var reader = new XmlTextReader(new StringReader(values.Current.OuterXml))) { reader.MoveToContent(); valueData = new byte[0]; int read = 0; do { Array.Resize(ref valueData, valueData.Length + 4096); read += reader.ReadBinHex(valueData, read, 4096); }while (reader.EOF == false); Array.Resize(ref valueData, read); } break; } case MemberType.Hash: { valueData = BitConverter.GetBytes(uint.Parse(values.Current.Value, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture)); break; } case MemberType.String: { valueData = Encoding.UTF8.GetBytes(values.Current.Value); Array.Resize(ref valueData, valueData.Length + 1); break; } case MemberType.Enum: { valueData = BitConverter.GetBytes(uint.Parse(values.Current.Value, CultureInfo.InvariantCulture)); break; } case MemberType.Bool: { valueData = new byte[1]; valueData[0] = (byte)(bool.Parse(values.Current.Value) == true ? 1 : 0); break; } case MemberType.Int32: { valueData = BitConverter.GetBytes(int.Parse(values.Current.Value, CultureInfo.InvariantCulture)); break; } case MemberType.UInt32: { valueData = BitConverter.GetBytes(uint.Parse(values.Current.Value, CultureInfo.InvariantCulture)); break; } case MemberType.Int64: { valueData = BitConverter.GetBytes(long.Parse(values.Current.Value, CultureInfo.InvariantCulture)); break; } case MemberType.UInt64: { valueData = BitConverter.GetBytes(ulong.Parse(values.Current.Value, CultureInfo.InvariantCulture)); break; } case MemberType.Float: { valueData = BitConverter.GetBytes(float.Parse(values.Current.Value, CultureInfo.InvariantCulture)); break; } case MemberType.Vector2: { valueData = new byte[8]; Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("x").Value, CultureInfo.InvariantCulture)), 0, valueData, 0, 4); Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("y").Value, CultureInfo.InvariantCulture)), 0, valueData, 4, 4); break; } case MemberType.Vector3: { valueData = new byte[12]; Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("x").Value, CultureInfo.InvariantCulture)), 0, valueData, 0, 4); Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("y").Value, CultureInfo.InvariantCulture)), 0, valueData, 4, 4); Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("z").Value, CultureInfo.InvariantCulture)), 0, valueData, 8, 4); break; } case MemberType.Vector4: { valueData = new byte[16]; Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("x").Value, CultureInfo.InvariantCulture)), 0, valueData, 0, 4); Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("y").Value, CultureInfo.InvariantCulture)), 0, valueData, 4, 4); Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("z").Value, CultureInfo.InvariantCulture)), 0, valueData, 8, 4); Array.Copy(BitConverter.GetBytes(float.Parse(values.Current.SelectSingleNode("w").Value, CultureInfo.InvariantCulture)), 0, valueData, 12, 4); break; } case MemberType.Rml: { var rez = new XmlResourceFile(); var nav = values.Current.SelectSingleNode("rml"); rez.Root = ConvertXml.Program.ReadNode(nav); using (var output = new MemoryStream()) { rez.Serialize(output); output.Position = 0; valueData = new byte[output.Length]; output.Read(valueData, 0, valueData.Length); } break; } default: { throw new FormatException(); } } parent.Values.Add(valueHash, valueData); } var children = node.Select("object"); while (children.MoveNext() == true) { parent.Children.Add(LoadNode(basePath, children.Current)); } return(parent); }