Beispiel #1
0
        ///////////////////////////////////////////////////////////////////////

        int ScanChild(BinaryReader br, int max_len, ref CTypeChild root)
        {
            int    cur_len = 0;
            string name;

            using (StringStore tmp = new StringStore().Read(br))
            {
                name     = tmp.Value;
                cur_len += tmp.ReadSize;
            }

            CType last_node = new CType();

            if (cur_len < max_len)
            {
                Types type = (Types)br.ReadByte();
                cur_len += 1;

                switch (type)
                {
                case Types.Empty:
                {
                    CTypeEmpty me = new CTypeEmpty(name);

                    last_node = me;

                    break;
                }

                case Types.Enum:
                {
                    string val;

                    using (StringStore tmp = new StringStore().Read(br))
                    {
                        val      = tmp.Value;
                        cur_len += tmp.ReadSize;
                    }

                    int ival;

                    using (NumberStore tmp = new NumberStore().Read(br))
                    {
                        ival     = tmp.Value;
                        cur_len += sizeof(int);
                    }

                    CTypeEnum me = new CTypeEnum(name);
                    me.SValue = val;
                    me.IValue = ival;

                    last_node = me;

                    break;
                }

                case Types.String:
                {
                    string val;
                    using (StringStore tmp = new StringStore().Read(br))
                    {
                        val      = tmp.Value;
                        cur_len += tmp.ReadSize;
                    }

                    CTypeString me = new CTypeString(name);
                    me.SValue = val;

                    last_node = me;

                    break;
                }

                case Types.Number:
                {
                    CTypeNumber me = new CTypeNumber(name);

                    // required. some number nodes end before they have any data. yup.
                    if (cur_len != max_len)
                    {
                        int ival;
                        using (NumberStore tmp = new NumberStore().Read(br))
                        {
                            ival     = tmp.Value;
                            cur_len += sizeof(int);
                        }

                        me.HasValue = true;
                        me.IValue   = ival;
                    }

                    last_node = me;

                    break;
                }

                case Types.StringList:
                {
                    CTypeStringList me = new CTypeStringList(name);

                    string val;

                    using (StringStore tmp = new StringStore().Read(br))
                    {
                        val = tmp.Value;
                        me.SValues.Add(val);
                        cur_len += tmp.ReadSize;
                    }

                    using (StringStore tmp = new StringStore().Read(br))
                    {
                        val = tmp.Value;
                        me.SValues.Add(val);
                        cur_len += tmp.ReadSize;
                    }

                    // are there any more?

                    last_node = me;

                    break;
                }

                case Types.List:
                {
                    byte Count = br.ReadByte();
                    cur_len += sizeof(byte);

                    CTypeChild me = new CTypeChild(name);

                    if (Count > 0)
                    {
                        // multiple child nodes have a list of lengths
                        if (Count > 1)
                        {
                            int real_count = Count - 1;
                            var items      = new List <int>();

                            for (int i = 0; i < real_count; ++i)
                            {
                                items.Add(br.ReadInt32());
                            }

                            cur_len += real_count * sizeof(int);

                            int last = 0;
                            for (int i = 0; i < real_count; ++i)
                            {
                                int child_len = ScanChild(br, items[i] - last, ref me);
                                cur_len += child_len;
                                last     = items[i];
                            }
                        }

                        int ret_len = ScanChild(br, max_len - cur_len, ref me);
                        cur_len += ret_len;
                    }

                    last_node = me;

                    break;
                }

                default:
                {
                    throw new Exception("Unknown node type. Please report this file");
                }
                }
            }

            // oh, there is also random tail data
            // we store this as 'tail' data, but in xml this is 'metadata'

            int tail_length = max_len - cur_len;

            if (tail_length != 0)
            {
                if ((tail_length & 3) != 0)
                {
                    throw new Exception("Unexpected tail");
                }

                int tail_count = tail_length / sizeof(int);
                for (int i = 0; i < tail_count; ++i)
                {
                    int ival = br.ReadInt32();

                    // swap the endian
                    if (runtimeOptions.ExportForConsole)
                    {
                        EndianHelper.Swap(ref ival);
                    }

                    last_node.Tail.Add(ival);
                }

                cur_len = max_len;
            }

            root.Children.Add(last_node);

            return(cur_len);
        }
Beispiel #2
0
        ///////////////////////////////////////////////////////////////////////

        public bool ReadXml(string file_name)
        {
            bool valid = true;

            if (rootChild != null)
            {
                // trash the existing loaded data
                rootChild = null;
            }

            valid &= File.Exists(file_name);

            if (valid)
            {
                StreamReader src = new StreamReader(file_name);

                XmlReader xml = XmlReader.Create(src);

                // we need to track the parent node stack as child nodes only track their own children
                var child_stack = new Stack <CTypeChild>();

                // dummy root
                rootChild = new CTypeChild("_root");
                child_stack.Push(rootChild);

                // abtract node so we can determine the true node type at a later stage
                CType last_node = null;

                // dummy count for valid subnodes
                int  expected_subnodes = 0;
                bool parsing_subnode   = false;

                while (xml.Read())
                {
                    // good info on msdn about this - https://msdn.microsoft.com/en-us/library/cc189056%28v=vs.95%29.aspx

                    switch (xml.NodeType)
                    {
                    case XmlNodeType.Element:

                        if (xml.Name == "dummy")
                        {
                            // should only be the first node
                            continue;
                        }

                        if (xml.Name == "subnode")
                        {
                            if (!parsing_subnode)
                            {
                                throw new Exception("subnode read error");
                            }
                            expected_subnodes--;

                            continue;
                        }

                        if (xml.Name != "node")
                        {
                            throw new Exception("Horribly wrong!");
                        }

                        // deal with unhandled last node. as we've started a new element, it has children now
                        if (last_node != null)
                        {
                            if (last_node.CoreType != CInternalType.List)
                            {
                                // should only throw when a node didn't end with an EndElement
                                // which suggests we failed parsing midway through
                                throw new Exception("Parsing elements failed");
                            }

                            // append this new node to the last one
                            child_stack.First().Children.Add(last_node);

                            // and begin anew
                            child_stack.Push(last_node as CTypeChild);

                            // dealt with.
                            last_node = null;
                        }

                        // we store this as an attribute because some names have spaces, which breaks xml node names
                        string name = xml.GetAttribute("name");

                        if (name == null)
                        {
                            throw new Exception("Wrong data (no name attribute)");
                        }

                        string type = xml.GetAttribute("type");

                        if (type == null)
                        {
                            throw new Exception("Wrong data (no type attribute)");
                        }

                        switch (type)
                        {
                        case "Empty":
                        {
                            last_node = new CTypeEmpty(name);
                        }
                        break;

                        case "Enum":
                        {
                            var tmp = new CTypeEnum(name);

                            string enum_val = xml.GetAttribute("enum");

                            if (enum_val == null)
                            {
                                throw new Exception("Bad enum");
                            }
                            tmp.IValue = Convert.ToInt32(enum_val);

                            last_node = tmp;
                        }
                        break;

                        case "List":
                        {
                            last_node = new CTypeChild(name);
                        }
                        break;

                        case "Number":
                        {
                            var tmp = new CTypeNumber(name);

                            string int_val = xml.GetAttribute("value");

                            if (int_val == null)
                            {
                                throw new Exception("Bad number");
                            }

                            if (int_val != "")             // determines if there is a value or not (there may not be..)
                            {
                                tmp.IValue   = Convert.ToInt32(int_val);
                                tmp.HasValue = true;
                            }

                            last_node = tmp;
                        }
                        break;

                        case "String":
                        {
                            last_node = new CTypeString(name);
                            // no actual string until we parse that part of the xml
                        }
                        break;

                        case "StringList":
                        {
                            var tmp = new CTypeStringList(name);

                            string count_val = xml.GetAttribute("count");

                            if (count_val != null)
                            {
                                expected_subnodes = Convert.ToInt32(count_val);

                                if (expected_subnodes > 0)
                                {
                                    // mark as parsing subnodes
                                    parsing_subnode = true;
                                }
                            }

                            last_node = tmp;
                        }
                        break;

                        default:
                            throw new Exception("Unhandled node type");
                        }

                        // get metadata and copy to tail if it exists
                        string metadata = xml.GetAttribute("metadata");

                        if (metadata != null)     // check we have any tail data
                        {
                            // whoops, silly bug where new char[','] allocated however many characters the comma ascii is!
                            string[] _metadata = metadata.Split(new char[] { ',' });

                            foreach (string str in _metadata)
                            {
                                int ival = Convert.ToInt32(str);

                                // swap the endian
                                if (runtimeOptions.ExportForConsole)
                                {
                                    EndianHelper.Swap(ref ival);
                                }

                                last_node.Tail.Add(ival);
                            }
                        }

                        break;

                    case XmlNodeType.Text:

                        string string_val = xml.Value;

                        switch (last_node.CoreType)
                        {
                        case CInternalType.Enum:
                        {
                            // just assign the string value to ctypenum
                            var last = last_node as CTypeEnum;
                            last.SValue = string_val;
                        }
                        break;

                        case CInternalType.String:
                        {
                            // just assign the string to the ctypestring
                            var last = last_node as CTypeString;
                            last.SValue = string_val;
                        }
                        break;

                        case CInternalType.StringList:
                        {
                            if (!parsing_subnode)
                            {
                                throw new Exception("subnode string error");
                            }

                            // add the string value to the ctypestringlist
                            var last = last_node as CTypeStringList;
                            last.SValues.Add(string_val);
                        }
                        break;

                        default:
                        {
                            throw new Exception("Unknown CoreType with string data");
                        }
                        }

                        break;

                    case XmlNodeType.EndElement:

                        // all elements must end, but last_node may not always be an item

                        // must be a child which has just ended??
                        if (last_node == null)
                        {
                            // subnodes have finished
                            if (parsing_subnode)
                            {
                                parsing_subnode = false;
                            }
                            else
                            {
                                // parent node ends
                                child_stack.Pop();
                            }
                        }
                        else
                        {
                            if (last_node.CoreType == CInternalType.StringList && parsing_subnode)
                            {
                                if (expected_subnodes > 0)
                                {
                                    // we expect more subnodes, don't null last_node
                                    continue;
                                }
                            }

                            // add this as a child of the last (well, first on the stack) parent
                            child_stack.Peek().Children.Add(last_node);
                            last_node = null;
                        }

                        break;
                    }
                }

#if DEBUG
                if (last_node != null)
                {
                    throw new Exception("Something went very wrong!");
                }
#endif

                src.Close();
            }

            return(valid);
        }