private object ExportField(GFF.FieldDefinition def, long offset, ExportState state)
        {
            var input = this.Data;
            input.Seek(offset + def.Offset, SeekOrigin.Begin);

            if (def.IsReference == true && def.IsList == true)
            {
                var listOffset = input.ReadValueU32(LittleEndian);
                if (listOffset == 0xFFFFFFFF)
                {
                    return null;
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(LittleEndian);

                long itemOffset = input.Position;
                var list = new List<object>();
                for (uint i = 0; i < count; i++)
                {
                    list.Add(this.ExportGeneric(state));
                    itemOffset += 8;
                    input.Seek(itemOffset, SeekOrigin.Begin);
                }
                return list;
            }
            else if (def.IsList == true)
            {
                //var type = GFF.Builtin.ToNativeType(def.Type);

                var listOffset = input.ReadValueU32(LittleEndian);
                if (listOffset == 0xFFFFFFFF)
                {
                    /*if (def.Type == GFF.FieldType.UInt8)
                    {
                        return new byte[0];
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }*/
                    return null;
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(LittleEndian);

                switch (def.Type)
                {
                    case GFF.FieldType.String:
                    {
                        long itemOffset = input.Position;
                        var list = new List<string>();
                        for (uint i = 0; i < count; i++)
                        {
                            var dataOffset = input.ReadValueU32(LittleEndian);
                            if (dataOffset == 0xFFFFFFFF)
                            {
                                list.Add(null);
                            }
                            else
                            {
                                if (this.FileVersion < 1)
                                {
                                    input.Seek(dataOffset, SeekOrigin.Begin);
                                    var length = input.ReadValueU32(LittleEndian);
                                    list.Add(input.ReadString(length * 2, true,
                                        LittleEndian == true ? Encoding.Unicode : Encoding.BigEndianUnicode));
                                }
                                else
                                {
                                    list.Add(this.StringTable[(int)dataOffset]);
                                }
                            }

                            itemOffset += 4;
                            input.Seek(itemOffset, SeekOrigin.Begin);
                        }

                        return list;
                    }

                    case GFF.FieldType.Structure:
                    {
                        long itemOffset = input.Position;
                        var subdef = this.Structures[def.StructureId];
                        var list = new List<KeyValue>();
                        for (uint i = 0; i < count; i++)
                        {
                            list.Add(this.ExportStructure(
                                subdef, itemOffset, state));
                            itemOffset += subdef.DataSize;
                        }
                        return list;
                    }

                    default:
                    {
                        if (def.Type == GFF.FieldType.UInt8)
                        {
                            var list = new byte[count];
                            input.Read(list, 0, list.Length);
                            return list;
                        }
                        else
                        {
                            var type = GFF.Builtin.ToNativeType(def.Type);
                            var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
                            for (uint i = 0; i < count; i++)
                            {
                                list.Add(GFF.Builtin.Deserialize(input, def.Type, LittleEndian));
                            }
                            return list;
                        }
                    }
                }
            }
            else
            {
                if (def.IsReference == true &&
                    def.Type == GFF.FieldType.Generic)
                {
                    return this.ExportGeneric(state);
                }
                else if (def.IsReference == true)
                {
                    var referenceOffset = input.ReadValueU32(LittleEndian);
                    if (referenceOffset == 0xFFFFFFFF)
                    {
                        return null;
                    }
                    else if (state.References.ContainsKey(referenceOffset) == true)
                    {
                        return state.References[referenceOffset];
                    }

                    input.Seek(referenceOffset, SeekOrigin.Begin);
                }

                switch (def.Type)
                {
                    case GFF.FieldType.Generic:
                    {
                        throw new FormatException();
                    }

                    case GFF.FieldType.String:
                    {
                        var dataOffset = input.ReadValueU32(LittleEndian);
                        if (dataOffset == 0xFFFFFFFF)
                        {
                            return "";
                        }

                        if (this.FileVersion < 1)
                        {
                            input.Seek(dataOffset, SeekOrigin.Begin);
                            var count = input.ReadValueU32(LittleEndian);
                            return input.ReadString(count * 2, true,
                                LittleEndian == true ? Encoding.Unicode : Encoding.BigEndianUnicode);
                        }
                        else
                        {
                            return this.StringTable[(int)dataOffset];
                        }
                    }

                    case GFF.FieldType.TalkString:
                    {
                        var tlk = new GFF.Builtins.TalkString();
                        tlk.Id = input.ReadValueU32(LittleEndian);

                        var dataOffset = input.ReadValueU32(LittleEndian);
                        if (dataOffset == 0xFFFFFFFF)
                        {
                            tlk.String = null;
                        }
                        else if (dataOffset == 0)
                        {
                            tlk.String = "";
                        }
                        else
                        {
                            if (this.FileVersion < 1)
                            {
                                input.Seek(dataOffset, SeekOrigin.Begin);
                                var count = input.ReadValueU32(LittleEndian);
                                tlk.String = input.ReadString(count * 2, true,
                                    LittleEndian == true ? Encoding.Unicode : Encoding.BigEndianUnicode);
                            }
                            else
                            {
                                tlk.String = this.StringTable[(int)dataOffset];
                            }
                        }

                        return tlk;
                    }

                    case GFF.FieldType.Structure:
                    {
                        var subdef = this.Structures[def.StructureId];
                        return this.ExportStructure(subdef, input.Position, state);
                    }

                    default:
                    {
                        return GFF.Builtin.Deserialize(input, def.Type, LittleEndian);
                    }
                }
            }
        }
        private object ExportTypeField(GFF.FieldDefinition def, Type type, long offset)
        {
            if (ValidateField(def, type) == false)
            {
                throw new FormatException("field validation failed");
            }

            var endian = this.Endian;

            var input = this.Data;

            input.Seek(offset + def.Offset, SeekOrigin.Begin);

            if (def.IsReference == true)
            {
                throw new NotSupportedException();
            }

            if (def.IsList == true)
            {
                var listOffset = input.ReadValueU32(endian);
                if (listOffset == 0xFFFFFFFF)
                {
                    if (def.Type == GFF.FieldType.UInt8 &&
                        type == typeof(byte[]))
                    {
                        return(new byte[0]);
                    }
                    else
                    {
                        return(Activator.CreateInstance(type));
                    }
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(endian);

                switch (def.Type)
                {
                case GFF.FieldType.String:
                {
                    long itemOffset = input.Position;
                    var  list       = new List <string>();
                    for (uint i = 0; i < count; i++)
                    {
                        var dataOffset = input.ReadValueU32(endian);
                        if (dataOffset == 0xFFFFFFFF)
                        {
                            return("");
                        }

                        if (this.FileVersion < 1)
                        {
                            input.Seek(dataOffset, SeekOrigin.Begin);
                            var length = input.ReadValueU32(endian);
                            list.Add(input.ReadString(length * 2, true,
                                                      endian == Endian.Little ? Encoding.Unicode : Encoding.BigEndianUnicode));
                        }
                        else
                        {
                            input.Seek(dataOffset, SeekOrigin.Begin);
                            list.Add(this.StringTable[(int)dataOffset]);
                        }

                        itemOffset += 4;
                        input.Seek(itemOffset, SeekOrigin.Begin);
                    }

                    return(list);
                }

                case GFF.FieldType.Structure:
                {
                    long itemOffset = input.Position;
                    var  subtype    = type.GetGenericArguments()[0];
                    var  subdef     = this.Structures[def.StructureId];
                    var  list       = (IList)Activator.CreateInstance(type);
                    for (uint i = 0; i < count; i++)
                    {
                        list.Add(this.ExportTypeStructure(
                                     subdef,
                                     subtype,
                                     itemOffset));
                        itemOffset += subdef.DataSize;
                    }
                    return(list);
                }

                default:
                {
                    if (def.Type == GFF.FieldType.UInt8 &&
                        type == typeof(byte[]))
                    {
                        var list = new byte[count];
                        input.Read(list, 0, list.Length);
                        return(list);
                    }
                    else
                    {
                        var list = (IList)Activator.CreateInstance(type);
                        for (uint i = 0; i < count; i++)
                        {
                            list.Add(GFF.Builtin.Deserialize(input, def.Type, endian));
                        }
                        return(list);
                    }
                }
                }
            }
            else
            {
                switch (def.Type)
                {
                case GFF.FieldType.String:
                {
                    var dataOffset = input.ReadValueU32(endian);
                    if (dataOffset == 0xFFFFFFFF)
                    {
                        return("");
                    }

                    if (this.FileVersion < 1)
                    {
                        input.Seek(dataOffset, SeekOrigin.Begin);
                        var count = input.ReadValueU32(endian);
                        return(input.ReadString(count * 2, true,
                                                endian == Endian.Little ? Encoding.Unicode : Encoding.BigEndianUnicode));
                    }
                    else
                    {
                        return(this.StringTable[(int)dataOffset]);
                    }
                }

                case GFF.FieldType.TalkString:
                {
                    var tlk = new GFF.Builtins.TalkString();
                    tlk.Id = input.ReadValueU32(endian);

                    var dataOffset = input.ReadValueU32(endian);
                    if (dataOffset == 0xFFFFFFFF)
                    {
                        tlk.String = null;
                    }
                    else if (dataOffset == 0)
                    {
                        tlk.String = "";
                    }
                    else
                    {
                        if (this.FileVersion < 1)
                        {
                            input.Seek(dataOffset, SeekOrigin.Begin);
                            var count = input.ReadValueU32(endian);
                            tlk.String = input.ReadString(count * 2, true,
                                                          endian == Endian.Little ? Encoding.Unicode : Encoding.BigEndianUnicode);
                        }
                        else
                        {
                            tlk.String = this.StringTable[(int)dataOffset];
                        }
                    }

                    return(tlk);
                }

                case GFF.FieldType.Structure:
                {
                    var subdef = this.Structures[def.StructureId];
                    return(this.ExportTypeStructure(subdef, type, input.Position));
                }

                default:
                {
                    return(GFF.Builtin.Deserialize(input, def.Type, endian));
                }
                }
            }
        }
Esempio n. 3
0
        private object ExportField(GFF.FieldDefinition def, long offset, ExportState state)
        {
            var endian = this.Endian;

            var input = this.Data;

            input.Seek(offset + def.Offset, SeekOrigin.Begin);

            if (def.IsReference == true && def.IsList == true)
            {
                var listOffset = input.ReadValueU32(endian);
                if (listOffset == 0xFFFFFFFF)
                {
                    return(null);
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(endian);

                long itemOffset = input.Position;
                var  list       = new List <object>();
                for (uint i = 0; i < count; i++)
                {
                    list.Add(this.ExportGeneric(state));
                    itemOffset += 8;
                    input.Seek(itemOffset, SeekOrigin.Begin);
                }
                return(list);
            }
            else if (def.IsList == true)
            {
                //var type = GFF.Builtin.ToNativeType(def.Type);

                var listOffset = input.ReadValueU32(endian);
                if (listOffset == 0xFFFFFFFF)
                {
                    /*if (def.Type == GFF.FieldType.UInt8)
                     * {
                     *  return new byte[0];
                     * }
                     * else
                     * {
                     *  throw new NotSupportedException();
                     * }*/
                    return(null);
                }

                input.Seek(listOffset, SeekOrigin.Begin);
                var count = input.ReadValueU32(endian);

                switch (def.Type)
                {
                case GFF.FieldType.String:
                {
                    long itemOffset = input.Position;
                    var  list       = new List <string>();
                    for (uint i = 0; i < count; i++)
                    {
                        var dataOffset = input.ReadValueU32(endian);
                        if (dataOffset == 0xFFFFFFFF)
                        {
                            list.Add(null);
                        }
                        else
                        {
                            if (this.FileVersion < 1)
                            {
                                input.Seek(dataOffset, SeekOrigin.Begin);
                                var length = input.ReadValueU32(endian);
                                list.Add(input.ReadString(length * 2, true,
                                                          endian == Endian.Little ? Encoding.Unicode : Encoding.BigEndianUnicode));
                            }
                            else
                            {
                                list.Add(this.StringTable[(int)dataOffset]);
                            }
                        }

                        itemOffset += 4;
                        input.Seek(itemOffset, SeekOrigin.Begin);
                    }

                    return(list);
                }

                case GFF.FieldType.Structure:
                {
                    long itemOffset = input.Position;
                    var  subdef     = this.Structures[def.StructureId];
                    var  list       = new List <GenericKeyValue>();
                    for (uint i = 0; i < count; i++)
                    {
                        list.Add(this.ExportStructure(
                                     subdef, itemOffset, state));
                        itemOffset += subdef.DataSize;
                    }
                    return(list);
                }

                default:
                {
                    if (def.Type == GFF.FieldType.UInt8)
                    {
                        var list = new byte[count];
                        input.Read(list, 0, list.Length);
                        return(list);
                    }
                    else
                    {
                        var type = GFF.Builtin.ToNativeType(def.Type);
                        var list = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(type));
                        for (uint i = 0; i < count; i++)
                        {
                            list.Add(GFF.Builtin.Deserialize(input, def.Type, endian));
                        }
                        return(list);
                    }
                }
                }
            }
            else
            {
                if (def.IsReference == true &&
                    def.Type == GFF.FieldType.Generic)
                {
                    return(this.ExportGeneric(state));
                }
                else if (def.IsReference == true)
                {
                    var referenceOffset = input.ReadValueU32(endian);
                    if (referenceOffset == 0xFFFFFFFF)
                    {
                        return(null);
                    }
                    else if (state.References.ContainsKey(referenceOffset) == true)
                    {
                        return(state.References[referenceOffset]);
                    }

                    input.Seek(referenceOffset, SeekOrigin.Begin);
                }

                switch (def.Type)
                {
                case GFF.FieldType.Generic:
                {
                    throw new FormatException();
                }

                case GFF.FieldType.String:
                {
                    var dataOffset = input.ReadValueU32(endian);
                    if (dataOffset == 0xFFFFFFFF)
                    {
                        return("");
                    }

                    if (this.FileVersion < 1)
                    {
                        input.Seek(dataOffset, SeekOrigin.Begin);
                        var count = input.ReadValueU32(endian);
                        return(input.ReadString(count * 2, true,
                                                endian == Endian.Little ? Encoding.Unicode : Encoding.BigEndianUnicode));
                    }
                    else
                    {
                        return(this.StringTable[(int)dataOffset]);
                    }
                }

                case GFF.FieldType.TalkString:
                {
                    var tlk = new GFF.Builtins.TalkString();
                    tlk.Id = input.ReadValueU32(endian);

                    var dataOffset = input.ReadValueU32(endian);
                    if (dataOffset == 0xFFFFFFFF)
                    {
                        tlk.String = null;
                    }
                    else if (dataOffset == 0)
                    {
                        tlk.String = "";
                    }
                    else
                    {
                        if (this.FileVersion < 1)
                        {
                            input.Seek(dataOffset, SeekOrigin.Begin);
                            var count = input.ReadValueU32(endian);
                            tlk.String = input.ReadString(count * 2, true,
                                                          endian == Endian.Little ? Encoding.Unicode : Encoding.BigEndianUnicode);
                        }
                        else
                        {
                            tlk.String = this.StringTable[(int)dataOffset];
                        }
                    }

                    return(tlk);
                }

                case GFF.FieldType.Structure:
                {
                    var subdef = this.Structures[def.StructureId];
                    return(this.ExportStructure(subdef, input.Position, state));
                }

                default:
                {
                    return(GFF.Builtin.Deserialize(input, def.Type, endian));
                }
                }
            }
        }