Пример #1
0
        private void WriteIntoFile(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.GetPadding();
            var        bits        = entry.GetBits();

            bool duplicates = false;

            if (entry.Header.IsTypeOf <WDB2>() && entry.Header.MaxId != 0)            //WDB2 with MaxId > 0 allows duplicates
            {
                duplicates = true;
            }
            else if (entry.Header.IsTypeOf <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;
                    }

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

                    switch (columnTypes[j])
                    {
                    case TypeCode.SByte:
                        bw.Write(row.Field <sbyte>(j));
                        break;

                    case TypeCode.Byte:
                        bw.Write(row.Field <byte>(j));
                        break;

                    case TypeCode.Int16:
                        bw.Write(row.Field <short>(j));
                        break;

                    case TypeCode.UInt16:
                        bw.Write(row.Field <ushort>(j));
                        break;

                    case TypeCode.Int32:
                        bw.WriteInt32(row.Field <int>(j), bits?[j]);
                        break;

                    case TypeCode.UInt32:
                        bw.WriteUInt32(row.Field <uint>(j), bits?[j]);
                        break;

                    case TypeCode.Int64:
                        bw.WriteInt64(row.Field <long>(j), bits?[j]);
                        break;

                    case TypeCode.UInt64:
                        bw.WriteUInt64(row.Field <ulong>(j), bits?[j]);
                        break;

                    case TypeCode.Single:
                        bw.Write(row.Field <float>(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()}");
                    }

                    if (columnTypes[j] != TypeCode.String)
                    {
                        bw.BaseStream.Position += padding[j];
                    }
                }

                //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
        public 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.GetPadding();

            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.InternalRecordSize > 0)
            {
                recordsize = entry.Header.InternalRecordSize;
            }

            entry.Data.BeginLoadData();

            for (uint i = 0; i < recordcount; i++)
            {
                //Offset map has variable record lengths
                if (entry.Header.IsTypeOf <HTFX>() || 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());
                        break;

                    case TypeCode.SByte:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadSByte());
                        break;

                    case TypeCode.Byte:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadByte());
                        break;

                    case TypeCode.Int16:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadInt16());
                        break;

                    case TypeCode.UInt16:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadUInt16());
                        break;

                    case TypeCode.Int32:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadInt32(bits[j]));
                        break;

                    case TypeCode.UInt32:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadUInt32(bits[j]));
                        break;

                    case TypeCode.Int64:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadInt64(bits[j]));
                        break;

                    case TypeCode.UInt64:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadUInt64(bits[j]));
                        break;

                    case TypeCode.Single:
                        row.SetField(entry.Data.Columns[j], dbReader.ReadSingle());
                        break;

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

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

                    dbReader.BaseStream.Position += padding[j];
                }

                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();
        }