Пример #1
0
        private void ReadIntoFile(DBEntry entry, BinaryWriter bw, IEnumerable <DataRow> rows, ref StringTable st)
        {
            TypeCode[] columnTypes = entry.Data.Columns.Cast <DataColumn>().Select(x => Type.GetTypeCode(x.DataType)).ToArray();
            int[]      padding     = entry.TableStructure.Padding.ToArray();
            var        bits        = entry.GetBits();

            bool duplicates = false;

            if (entry.Header.IsTypeOf <WDB2>() && ((WDB2)entry.Header).MaxId != 0) //WDB2 with MaxId > 0 allows duplicates
            {
                duplicates = true;
            }
            else if (entry.Header.IsTypeOf <WCH7>() && ((WCH7)entry.Header).UnknownWCH7 != 0) //WCH7 with Unknown > 0 allows duplicates
            {
                duplicates = true;
            }

            var lastrow = rows.Last();

            foreach (DataRow row in rows)
            {
                long offset = bw.BaseStream.Position;

                for (int j = 0; j < entry.Data.Columns.Count; j++)
                {
                    if (entry.Data.Columns[j].ExtendedProperties.ContainsKey(AUTO_GENERATED)) //Autogenerated so skip
                    {
                        continue;
                    }

                    if (entry.Header.HasIndexTable && j == 0) //Inline Id so skip
                    {
                        continue;
                    }

                    if (entry.Header.IsTypeOf <WCH5>() && entry.Header.HasOffsetTable && j == 0) //Inline Id so skip
                    {
                        continue;
                    }

                    switch (columnTypes[j])
                    {
                    case TypeCode.SByte:
                        bw.Write(row.Field <sbyte>(j));
                        bw.BaseStream.Position += sizeof(sbyte) * padding[j];
                        break;

                    case TypeCode.Byte:
                        bw.Write(row.Field <byte>(j));
                        bw.BaseStream.Position += sizeof(byte) * padding[j];
                        break;

                    case TypeCode.Int16:
                        bw.Write(row.Field <short>(j));
                        bw.BaseStream.Position += sizeof(short) * padding[j];
                        break;

                    case TypeCode.UInt16:
                        bw.Write(row.Field <ushort>(j));
                        bw.BaseStream.Position += sizeof(ushort) * padding[j];
                        break;

                    case TypeCode.Int32:
                        bw.WriteInt32(row.Field <int>(j), bits?[j]);
                        bw.BaseStream.Position += sizeof(int) * padding[j];
                        break;

                    case TypeCode.UInt32:
                        bw.WriteUInt32(row.Field <uint>(j), bits?[j]);
                        bw.BaseStream.Position += sizeof(uint) * padding[j];
                        break;

                    case TypeCode.Int64:
                        bw.WriteInt64(row.Field <long>(j), bits?[j]);
                        bw.BaseStream.Position += sizeof(long) * padding[j];
                        break;

                    case TypeCode.UInt64:
                        bw.WriteUInt64(row.Field <ulong>(j), bits?[j]);
                        bw.BaseStream.Position += sizeof(ulong) * padding[j];
                        break;

                    case TypeCode.Single:
                        bw.Write(row.Field <float>(j));
                        bw.BaseStream.Position += sizeof(float) * padding[j];
                        break;

                    case TypeCode.String:
                        if (entry.Header.HasOffsetTable)
                        {
                            bw.Write(Encoding.UTF8.GetBytes(row.Field <string>(j)));
                            bw.Write((byte)0);
                        }
                        else
                        {
                            bw.Write(st.Write(row.Field <string>(j), duplicates));
                        }
                        break;

                    default:
                        throw new Exception($"Unknown TypeCode {columnTypes[j].ToString()}");
                    }
                }

                //Calculate and write the row's padding
                entry.Header.WriteRecordPadding(bw, entry, offset);

                //Store the offset map
                if (entry.Header.HasOffsetTable)
                {
                    OffsetMap.Add(new Tuple <int, short>((int)offset, (short)(bw.BaseStream.Position - offset)));
                }

                //WDB5 + OffsetMap without SecondIndex for the last row pads to next mod 4
                if (entry.Header.IsTypeOf <WDB5>() && entry.Header.HasOffsetTable && !entry.Header.HasSecondIndex && row == lastrow)
                {
                    long rem = bw.BaseStream.Position % 4;
                    bw.BaseStream.Position += (rem == 0 ? 0 : (4 - rem));
                }
            }
        }
Пример #2
0
        private static void WriteIntoFile <T>(DBEntry <T> entry, BinaryWriter bw, IEnumerable <T> rows, ref StringTable st) where T : class
        {
            TypeCode[]            columnTypes = entry.TableStructure.Select(x => Type.GetTypeCode(x.PropertyType)).ToArray();
            uint[]                padding     = entry.Padding.ToArray();
            FieldStructureEntry[] bits        = entry.GetBits();

            bool duplicates = false;

            duplicates |= (entry.Header.IsTypeOf <WDB2>() && entry.Header.MaxId != 0);       //WDB2 with MaxId > 0 allows duplicates
            duplicates |= (entry.Header.IsTypeOf <WCH7>() && entry.Header.UnknownWCH7 != 0); //WCH7 with Unknown > 0 allows duplicates

            T lastrow = rows.Last();

            foreach (T row in rows)
            {
                long offset = bw.BaseStream.Position;

                for (int j = 0; j < entry.TableStructure.Length; j++)
                {
                    PropertyInfo field = entry.TableStructure[j];

                    if (field.GetAttribute <DBKeyAttribute>()?.AutoGenerated == true) //Autogenerated so skip
                    {
                        continue;
                    }

                    if (entry.Header.HasIndexTable && j == 0) //Inline Id so skip
                    {
                        continue;
                    }

                    if (entry.Header.IsTypeOf <WCH5>() && entry.Header.HasOffsetTable && j == 0) //Inline Id so skip
                    {
                        continue;
                    }

                    if (entry.Header.IsTypeOf <WDB6>() && (bits?[j].CommonDataColumn ?? false))
                    {
                        continue;
                    }

                    if (columnTypes[j] == TypeCode.Object)
                    {
                        if (field.PropertyType.IsArray)
                        {
                            Array array = (Array)field.GetValue(row);
                            for (int x = 0; x < array.Length; x++)
                            {
                                WriteValue(bw, entry, array.GetValue(x), padding[j], st, bits?[j], duplicates);
                            }
                        }
                        else if (field.PropertyType == typeof(LocalizedString))
                        {
                            ((LocalizedString)field.GetValue(row)).Write(bw, st, duplicates);
                        }
                        else
                        {
                            throw new Exception($"Unknown Type {field.PropertyType.Name}.");
                        }
                    }
                    else
                    {
                        WriteValue(bw, entry, field.GetValue(row), padding[j], st, bits?[j], duplicates);
                    }
                }

                //Calculate and write the row's padding
                entry.Header.WriteRecordPadding(bw, entry, offset);

                //Store the offset map
                if (entry.Header.HasOffsetTable)
                {
                    OffsetMap.Add(new Tuple <int, short>((int)offset, (short)(bw.BaseStream.Position - offset)));
                }

                //WDB5 + OffsetMap without SecondIndex for the last row pads to next mod 4
                if (entry.Header.IsTypeOf <WDB5>() && entry.Header.HasOffsetTable && !entry.Header.HasSecondIndex && row == lastrow)
                {
                    long rem = bw.BaseStream.Position % 4;
                    bw.BaseStream.Position += (rem == 0 ? 0 : (4 - rem));
                }
            }
        }
Пример #3
0
        private void ReadIntoTable(ref DBEntry entry, BinaryReader dbReader, Dictionary <int, string> StringTable)
        {
            if (entry.Header.RecordCount == 0)
            {
                return;
            }

            TypeCode[] columnTypes = entry.Data.Columns.Cast <DataColumn>().Select(x => Type.GetTypeCode(x.DataType)).ToArray();
            int[]      padding     = entry.TableStructure.Padding.ToArray();

            FieldStructureEntry[] bits = entry.GetBits();
            uint recordsize            = entry.Header.RecordSize + (uint)(entry.Header.HasIndexTable ? 4 : 0);
            int  recordcount           = Math.Max(entry.Header.OffsetLengths.Length, (int)entry.Header.RecordCount);

            entry.Data.BeginLoadData();

            for (uint i = 0; i < recordcount; i++)
            {
                //Offset map has variable record lengths
                if (entry.Header.HasOffsetTable)
                {
                    recordsize = (uint)entry.Header.OffsetLengths[i];
                }

                //Store start position
                long offset = dbReader.BaseStream.Position;

                //Create row and add data
                var row = entry.Data.NewRow();
                for (int j = 0; j < entry.Data.Columns.Count; j++)
                {
                    if (entry.Data.Columns[j].ExtendedProperties.ContainsKey(AUTO_GENERATED))
                    {
                        row.SetField(entry.Data.Columns[j], entry.Data.Rows.Count + 1);
                        continue;
                    }

                    switch (columnTypes[j])
                    {
                    case TypeCode.Boolean:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadBoolean());
                        dbReader.BaseStream.Position += sizeof(bool) * padding[j];
                        break;

                    case TypeCode.SByte:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadSByte());
                        dbReader.BaseStream.Position += sizeof(sbyte) * padding[j];
                        break;

                    case TypeCode.Byte:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadByte());
                        dbReader.BaseStream.Position += sizeof(byte) * padding[j];
                        break;

                    case TypeCode.Int16:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadInt16());
                        dbReader.BaseStream.Position += sizeof(short) * padding[j];
                        break;

                    case TypeCode.UInt16:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadUInt16());
                        dbReader.BaseStream.Position += sizeof(ushort) * padding[j];
                        break;

                    case TypeCode.Int32:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadInt32(bits[j]));
                        dbReader.BaseStream.Position += sizeof(int) * padding[j];
                        break;

                    case TypeCode.UInt32:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadUInt32(bits[j]));
                        dbReader.BaseStream.Position += sizeof(uint) * padding[j];
                        break;

                    case TypeCode.Int64:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadInt64(bits[j]));
                        dbReader.BaseStream.Position += sizeof(long) * padding[j];
                        break;

                    case TypeCode.UInt64:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadUInt64(bits[j]));
                        dbReader.BaseStream.Position += sizeof(ulong) * padding[j];
                        break;

                    case TypeCode.Single:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadSingle());
                        dbReader.BaseStream.Position += sizeof(float) * padding[j];
                        break;

                    case TypeCode.String:
                        if (entry.Header.IsTypeOf <WDB>() || entry.Header.HasOffsetTable)
                        {
                            row.SetField(entry.Data.Columns[j], dbReader.ReadStringNull());
                        }
                        else
                        {
                            int stindex = dbReader.ReadInt32();
                            try { row.SetField(entry.Data.Columns[j], StringTable[stindex]); }
                            catch
                            {
                                row.SetField(entry.Data.Columns[j], "String not found");
                                ErrorMessage = "Strings not found in string table";
                            }
                        }
                        break;

                    default:
                        dbReader.BaseStream.Position += 4;
                        break;
                    }
                }

                entry.Data.Rows.Add(row);

                //Scrub to the end of the record
                if (dbReader.BaseStream.Position - offset < recordsize)
                {
                    dbReader.BaseStream.Position += (recordsize - (dbReader.BaseStream.Position - offset));
                }
                else if (dbReader.BaseStream.Position - offset > recordsize)
                {
                    throw new Exception("Definition exceeds record size");
                }
            }

            entry.Data.EndLoadData();
        }
Пример #4
0
        private static void ReadIntoTable <T>(ref DBEntry <T> entry, BinaryReader dbReader, Dictionary <int, string> stringtable) where T : class
        {
            if (entry.Header.RecordCount == 0)
            {
                return;
            }

            TypeCode[] columnTypes = entry.TableStructure.Select(x => Type.GetTypeCode(x.PropertyType)).ToArray();
            uint[]     padding     = entry.Padding.ToArray();

            FieldStructureEntry[] bits = entry.GetBits();
            int  recordcount           = Math.Max(entry.Header.OffsetLengths.Length, (int)entry.Header.RecordCount);
            uint recordsize            = entry.Header.RecordSize + (uint)(entry.Header.HasIndexTable ? 4 : 0);

            if (entry.Header.CommonDataTableSize > 0)
            {
                recordsize = ((WDB6)entry.Header).RawRecordSize;
            }

            for (uint i = 0; i < recordcount; i++)
            {
                //Offset map has variable record lengths
                if (entry.Header.HasOffsetTable || entry.Header.IsTypeOf <HTFX>())
                {
                    recordsize = (uint)entry.Header.OffsetLengths[i];
                }

                //Store start position
                long offset = dbReader.BaseStream.Position;

                //Create row and add data
                T row = (T)Activator.CreateInstance(typeof(T));

                for (int j = 0; j < entry.TableStructure.Length; j++)
                {
                    PropertyInfo field = entry.TableStructure[j];

                    if (entry.TableStructure[j].GetAttribute <DBKeyAttribute>()?.AutoGenerated == true)
                    {
                        field.SetValue(row, entry.Rows.Count + 1);
                        continue;
                    }

                    if (columnTypes[j] == TypeCode.Object)
                    {
                        if (field.PropertyType.IsArray)
                        {
                            uint     arraySize = field.GetAttribute <DBFieldAttribute>().ArraySize;
                            TypeCode type      = Type.GetTypeCode(field.PropertyType.GetElementType());

                            Array array = Array.CreateInstance(field.PropertyType.GetElementType(), arraySize);
                            for (int x = 0; x < arraySize; x++)
                            {
                                array.SetValue(ReadValue(dbReader, entry, type, padding[j], stringtable, bits[j]), x);
                            }

                            field.SetValue(row, array);
                        }
                        else if (field.PropertyType == typeof(LocalizedString))
                        {
                            LocalizedString locale = new LocalizedString(entry.Build);
                            locale.Load(dbReader, stringtable);
                            field.SetValue(row, locale);
                        }
                        else
                        {
                            throw new Exception($"Unknown Type {field.PropertyType.Name}");
                        }
                    }
                    else
                    {
                        field.SetValue(row, ReadValue(dbReader, entry, columnTypes[j], padding[j], stringtable, bits[j]));
                    }
                }

                entry.Rows.Add(row);

                //Scrub to the end of the record
                if (dbReader.BaseStream.Position - offset < recordsize)
                {
                    dbReader.BaseStream.Position += (recordsize - (dbReader.BaseStream.Position - offset));
                }
                else if (dbReader.BaseStream.Position - offset > recordsize)
                {
                    throw new Exception("Definition exceeds record size");
                }
            }
        }