コード例 #1
0
        public void Export(FieldDefinition fieldDef,
                           FieldType arrayFieldType,
                           byte[] data,
                           int offset,
                           int count,
                           XmlWriter writer,
                           out int read)
        {
            if (Helpers.HasLeft(data, 0, data.Length, 5) == false)
            {
                throw new FormatException("Rml requires at least 5 bytes");
            }

            var rez = new XmlResourceFile();

            using (var input = new MemoryStream(data, 0, data.Length, false))
            {
                rez.Deserialize(input);
                read = data.Length;
            }

            writer.WriteStartElement("rml");
            ConvertXml.Program.WriteNode(writer, rez.Root);
            writer.WriteEndElement();
        }
コード例 #2
0
        public byte[] Import(FieldDefinition def, FieldType arrayFieldType, System.Xml.XPath.XPathNavigator nav)
        {
            var rml = new XmlResourceFile
            {
                Root = ConvertXml.Program.ReadNode(nav.SelectSingleNode("rml/*"))
            };

            using (var temp = new MemoryStream())
            {
                rml.Serialize(temp);
                temp.Position = 0;
                return(temp.ReadBytes((uint)temp.Length));
            }
        }
コード例 #3
0
        public static void Main(string[] args)
        {
            var  mode     = Mode.Unknown;
            bool showHelp = false;

            OptionSet options = new OptionSet()
            {
                {
                    "rml",
                    "convert XML to RML",
                    v => mode = v != null ? Mode.ToRML : mode
                },
                {
                    "xml",
                    "convert RML to XML",
                    v => mode = v != null ? Mode.ToXML : mode
                },
                {
                    "h|help",
                    "show this message and exit",
                    v => showHelp = v != null
                },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (mode == Mode.Unknown &&
                extras.Count >= 1)
            {
                var extension = Path.GetExtension(extras[0]);

                if (extension == ".rml")
                {
                    mode = Mode.ToXML;
                }
                else if (extension == ".xml")
                {
                    mode = Mode.ToRML;
                }
            }

            if (showHelp == true ||
                mode == Mode.Unknown ||
                extras.Count < 1 ||
                extras.Count > 2)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input [output]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (mode == Mode.ToRML)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(Path.ChangeExtension(inputPath, null) + "_converted", ".rml");

                var rez = new XmlResourceFile();
                using (var input = File.OpenRead(inputPath))
                {
                    var doc = new XPathDocument(input);
                    var nav = doc.CreateNavigator();

                    if (nav.MoveToFirstChild() == false)
                    {
                        throw new FormatException();
                    }

                    rez.Root = ReadNode(nav);
                }

                using (var output = File.Create(outputPath))
                {
                    rez.Serialize(output);
                }
            }
            else if (mode == Mode.ToXML)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(Path.ChangeExtension(inputPath, null) + "_converted", ".xml");

                var rez = new XmlResourceFile();
                using (var input = File.OpenRead(inputPath))
                {
                    rez.Deserialize(input);
                }

                var settings = new XmlWriterSettings();
                settings.Encoding           = Encoding.UTF8;
                settings.Indent             = true;
                settings.OmitXmlDeclaration = true;

                using (var writer = XmlWriter.Create(outputPath, settings))
                {
                    writer.WriteStartDocument();
                    WriteNode(writer, rez.Root);
                    writer.WriteEndDocument();
                }
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
コード例 #4
0
        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();
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        public static byte[] Serialize(FieldDefinition fieldDef,
                                       FieldType fieldType,
                                       FieldType arrayFieldType,
                                       XPathNavigator nav)
        {
            switch (fieldType)
            {
            case FieldType.BinHex:
            {
                using (var reader = new XmlTextReader(new StringReader(nav.OuterXml)))
                {
                    reader.MoveToContent();
                    var data = new byte[0];
                    int read = 0;
                    do
                    {
                        Array.Resize(ref data, data.Length + 4096);
                        read += reader.ReadBinHex(data, read, 4096);
                    }while (reader.EOF == false);
                    Array.Resize(ref data, read);
                    return(data);
                }
            }

            case FieldType.Boolean:
            case FieldType.UInt8:
            case FieldType.Int8:
            case FieldType.UInt16:
            case FieldType.Int16:
            case FieldType.UInt32:
            case FieldType.Int32:
            case FieldType.UInt64:
            case FieldType.Int64:
            case FieldType.Float32:
            case FieldType.Float64:
            case FieldType.Vector2:
            case FieldType.Vector3:
            case FieldType.Vector4:
            case FieldType.String:
            {
                return(Serialize(fieldType, nav.Value));
            }

            case FieldType.Enum:
            {
                var enumDef = fieldDef != null ? fieldDef.Enum : null;

                var text       = nav.Value;
                var elementDef = enumDef != null
                                         ? enumDef.Elements.FirstOrDefault(ed => ed.Name == text)
                                         : null;

                int value;
                if (elementDef != null)
                {
                    value = elementDef.Value;
                }
                else
                {
                    if (TryParseInt32(nav.Value, out value) == false)
                    {
                        if (enumDef == null)
                        {
                            throw new FormatException(
                                      string.Format(
                                          "could not parse enum value '{0}' as an Int32 (perhaps enum definition is missing?)",
                                          nav.Value));
                        }

                        throw new FormatException(
                                  string.Format(
                                      "could not parse enum value '{0}' as an Int32 (perhaps enum element definition is missing from {1}?)",
                                      nav.Value,
                                      enumDef.Name));
                    }
                }

                return(BitConverter.GetBytes(value));
            }

            case FieldType.Hash32:
            case FieldType.Hash64:
            case FieldType.Id32:
            case FieldType.Id64:
            {
                return(Serialize(fieldType, nav.Value));
            }

            case FieldType.Rml:
            {
                var rml = new XmlResourceFile
                {
                    Root = ConvertXml.Program.ReadNode(nav.SelectSingleNode("rml/*"))
                };

                using (var temp = new MemoryStream())
                {
                    rml.Serialize(temp);
                    temp.Position = 0;
                    return(temp.ReadBytes((uint)temp.Length));
                }
            }

            case FieldType.ComputeHash32:
            {
                return(Serialize(fieldType, nav.Value));
            }

            case FieldType.ComputeHash64:
            {
                return(Serialize(fieldType, nav.Value));
            }

            case FieldType.Array32:
            {
                using (var temp = new MemoryStream())
                {
                    var items = nav.Select("item");
                    temp.WriteValueS32(items.Count);
                    while (items.MoveNext() == true)
                    {
                        temp.WriteBytes(Serialize(arrayFieldType, items.Current.Value));
                    }
                    return(temp.ToArray());
                }
            }
            }

            throw new NotSupportedException("unsupported field type");
        }
コード例 #7
0
        public static void Deserialize(XmlWriter writer,
                                       FieldDefinition fieldDef,
                                       byte[] data)
        {
            int read;

            switch (fieldDef.Type)
            {
            case FieldType.BinHex:
            {
                writer.WriteBinHex(data, 0, data.Length);
                read = data.Length;
                break;
            }

            case FieldType.Boolean:
            case FieldType.UInt8:
            case FieldType.Int8:
            case FieldType.UInt16:
            case FieldType.Int16:
            case FieldType.UInt32:
            case FieldType.Int32:
            case FieldType.UInt64:
            case FieldType.Int64:
            case FieldType.Float32:
            case FieldType.Float64:
            case FieldType.Vector2:
            case FieldType.Vector3:
            case FieldType.Vector4:
            case FieldType.String:
            case FieldType.Hash32:
            case FieldType.Hash64:
            case FieldType.Id32:
            case FieldType.Id64:
            {
                Deserialize(writer, fieldDef.Type, data, 0, data.Length, out read);
                break;
            }

            case FieldType.Enum:
            {
                var value = Deserialize <int>(fieldDef.Type, data, 0, data.Length, out read);

                if (fieldDef.Enum != null)
                {
                    var enumDef = fieldDef.Enum.Elements.FirstOrDefault(ed => ed.Value == value);
                    if (enumDef != null)
                    {
                        writer.WriteString(enumDef.Name);
                        break;
                    }
                }

                writer.WriteString(value.ToString(CultureInfo.InvariantCulture));
                break;
            }

            case FieldType.Rml:
            {
                if (HasLeft(data, 0, data.Length, 5) == false)
                {
                    throw new FormatException("field type Rml requires at least 5 bytes");
                }

                var rez = new XmlResourceFile();
                using (var input = new MemoryStream(data, 0, data.Length, false))
                {
                    rez.Deserialize(input);
                    read = data.Length;
                }

                writer.WriteStartElement("rml");
                ConvertXml.Program.WriteNode(writer, rez.Root);
                writer.WriteEndElement();
                break;
            }

            case FieldType.Array32:
            {
                if (HasLeft(data, 0, data.Length, 4) == false)
                {
                    throw new FormatException("field type Array32 requires at least 4 bytes");
                }

                var itemCount = BitConverter.ToUInt32(data, 0);

                read = 4;
                int offset    = 4;
                int remaining = data.Length - offset;
                for (uint i = 0; i < itemCount; i++)
                {
                    writer.WriteStartElement("item");
                    int itemRead;
                    Deserialize(writer, fieldDef.ArrayType, data, offset, remaining, out itemRead);
                    offset    += itemRead;
                    remaining -= itemRead;
                    writer.WriteEndElement();

                    read += itemRead;
                }

                break;
            }

            default:
            {
                throw new NotSupportedException("unsupported field type");
            }
            }

            if (read != data.Length)
            {
                if (string.IsNullOrEmpty(fieldDef.Name) == false)
                {
                    throw new FormatException(
                              string.Format("did not consume all data for field '{0}' (read {1}, total {2})",
                                            fieldDef.Name,
                                            read,
                                            data.Length));
                }

                throw new FormatException(
                          string.Format("did not consume all data for field 0x{0:X8}  (read {1}, total {2})",
                                        fieldDef.Hash,
                                        read,
                                        data.Length));
            }
        }