예제 #1
0
        ///////////////////////////////////////////////////////////////////////

        private int WriteChild(BinaryWriter bw, CType child)
        {
            int len = 0;

            // name is agnostic
            var namestr = new StringStore();

            namestr.Value = child.Name;

            namestr.Write(bw);

            len += namestr.WriteSize;

            switch (child.CoreType)
            {
            case CInternalType.Undefined:
                throw new Exception("All wrong.");

            case CInternalType.Empty:
                bw.Write((byte)Types.Empty);
                len += sizeof(byte);
                break;

            case CInternalType.String:

                bw.Write((byte)Types.String);
                len += sizeof(byte);

                var s_val = new StringStore();
                s_val.Value = (child as CTypeString).SValue;
                s_val.Write(bw);
                len += s_val.WriteSize;

                break;

            case CInternalType.Number:

                bw.Write((byte)Types.Number);
                len += sizeof(byte);

                if ((child as CTypeNumber).HasValue)
                {
                    var n_val = new NumberStore();
                    n_val.Value = (child as CTypeNumber).IValue;
                    n_val.Write(bw);
                    len += sizeof(int);
                }

                break;

            case CInternalType.StringList:

                bw.Write((byte)Types.StringList);
                len += sizeof(byte);

                foreach (string str in (child as CTypeStringList).SValues)
                {
                    var stmp_val = new StringStore();
                    stmp_val.Value = str;
                    stmp_val.Write(bw);
                    len += stmp_val.WriteSize;
                }

                break;

            case CInternalType.Enum:

                bw.Write((byte)Types.Enum);
                len += sizeof(byte);

                var e_string = new StringStore();
                e_string.Value = (child as CTypeEnum).SValue;
                e_string.Write(bw);
                len += e_string.WriteSize;

                var e_number = new NumberStore();
                e_number.Value = (child as CTypeEnum).IValue;
                e_number.Write(bw);
                len += sizeof(int);

                break;

            case CInternalType.List:

                bw.Write((byte)Types.List);
                len += sizeof(byte);

                // nastier.

                var child_node = child as CTypeChild;

                int count = child_node.Children.Count;

                bw.Write((byte)(count & 0xFF));
                len += sizeof(byte);

                if (count > 0)
                {
                    if (count > 1)
                    {
                        int hdr_offset = (int)bw.BaseStream.Length;

                        // we need to revisit this..
                        int real_count = count - 1;
                        for (int i = 0; i < real_count; ++i)
                        {
                            bw.Write((int)0xF0F0F0F);
                        }

                        len += real_count * sizeof(int);

                        var child_lengths = new List <int>();

                        // this is no longer the 'real count'
                        for (int i = 0; i < real_count; ++i)
                        {
                            int child_length = WriteChild(bw, child_node.Children[i]);
                            child_lengths.Add(child_length);

                            len += child_length;
                        }

                        // revist all data length
                        int tail_offset = (int)bw.BaseStream.Length;
                        bw.Seek(hdr_offset, SeekOrigin.Begin);

                        int sum = 0;
                        foreach (int cl in child_lengths)
                        {
                            sum += cl;
                            bw.Write(sum);
                        }

                        bw.Seek(tail_offset, SeekOrigin.Begin);
                    }

                    len += WriteChild(bw, child_node.Children.Last());
                }

                break;
            }

            // type agnostic
            foreach (int tail in child.Tail)
            {
                bw.Write(tail);
                len += 4;
            }

            return(len);
        }
예제 #2
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);
        }