Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit e346d65

Browse files
committed
Library:
* Fixed a bug with DB2 files containing an index table (which is duplicate data in that format) * Attempt to properly parse WDB6 since version 7.3.0.24473 (PTR) introduced padding in the common data block. This is based off the (wild) assumption that all default values should be zero. * Rename `Reader.ReadTableString` to `Reader.ReadString` so that functions needing a BinaryReader as argument can directly call the override. * Fix a typo in the XML documentation for `IObjectType<T>`. Tests: Provide some examples of `IObjectType<T>` usage. Signed-off-by: Warpten <[email protected]>
1 parent 8eef5f2 commit e346d65

11 files changed

Lines changed: 87 additions & 31 deletions

File tree

DBFilesClient.NET/DBFilesClient.NET.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
</ItemGroup>
9595
<ItemGroup>
9696
<Compile Include="Extensions.cs" />
97+
<Compile Include="GlobalSuppressions.cs" />
9798
<Compile Include="IStorage.cs" />
9899
<Compile Include="Types\IObjectType.cs" />
99100
<Compile Include="WDB2\Reader.cs" />
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+

2+
// This file is used by Code Analysis to maintain SuppressMessage
3+
// attributes that are applied to this project.
4+
// Project-level suppressions either have no target or are given
5+
// a specific target and scoped to a namespace, type, member, etc.
6+
7+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0017:Simplify object initialization", Justification = "<Pending>", Scope = "member", Target = "~M:DBFilesClient.NET.WDB6.Reader`1.LoadHeader")]
8+

DBFilesClient.NET/Reader.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ internal class Header
5757
{ TypeCode.Char, typeof (BinaryReader).GetMethod("ReadChar", Type.EmptyTypes) },
5858
{ TypeCode.Single, typeof (BinaryReader).GetMethod("ReadSingle", Type.EmptyTypes) },
5959

60-
{ TypeCode.String, typeof (Reader<T>).GetMethod("ReadTableString", Type.EmptyTypes) },
60+
{ TypeCode.String, typeof (BinaryReader).GetMethod("ReadString", Type.EmptyTypes) },
6161
};
6262

6363
internal virtual MethodInfo GetPrimitiveLoader(Type typeInfo, int fieldIndex)
@@ -218,8 +218,7 @@ public string ReadInlineString()
218218
return stringValue;
219219
}
220220

221-
// Needs to be public to be visible using Type.GetMethod(string, Type[])
222-
public virtual string ReadTableString()
221+
public override string ReadString()
223222
{
224223
// Store position of the next field in this record.
225224
var oldPosition = BaseStream.Position + 4;

DBFilesClient.NET/Types/IObjectType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/// <code>
99
/// public class ForeignKey<T, U> : IObjectType<U>
1010
/// {
11-
/// public ForeignKey(T underlyingValue) : base(underlyingValue) { }
11+
/// public ForeignKey(U underlyingValue) : base(underlyingValue) { }
1212
///
1313
/// public T Value => ...;
1414
/// }

DBFilesClient.NET/WDB2/Reader.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.IO;
1+
using System.IO;
32

43
namespace DBFilesClient.NET.WDB2
54
{
@@ -24,9 +23,12 @@ protected override void LoadHeader()
2423

2524
FileHeader.HasStringTable = FileHeader.StringTableSize != 0;
2625

27-
// BaseStream.Position += 8 + (FileHeader.MaxIndex - FileHeader.MinIndex + 1) * (4 + 2);
26+
BaseStream.Position += 8; // locale and copy table size (which is always 0 in this version)
2827

2928
FileHeader.StringTableOffset = BaseStream.Length - FileHeader.StringTableSize;
29+
30+
if (FileHeader.MaxIndex != 0)
31+
BaseStream.Position += (4 + 2) * (FileHeader.MaxIndex - FileHeader.MinIndex + 1);
3032
}
3133
}
3234
}

DBFilesClient.NET/WDB5/Reader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ internal override MethodInfo GetPrimitiveLoader(FieldInfo fieldInfo, int fieldIn
8686
return base.GetPrimitiveLoader(fieldInfo, fieldIndex);
8787
}
8888

89-
public override string ReadTableString()
89+
public override string ReadString()
9090
{
91-
return !FileHeader.HasStringTable ? ReadInlineString() : base.ReadTableString();
91+
return !FileHeader.HasStringTable ? ReadInlineString() : base.ReadString();
9292
}
9393

9494
internal Reader(Stream fileData) : base(fileData)

DBFilesClient.NET/WDB6/Reader.cs

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.CodeDom;
32
using System.Collections.Generic;
43
using System.IO;
54
using System.Linq;
@@ -205,25 +204,6 @@ protected override int GetArraySize(FieldInfo fieldInfo, int fieldIndex)
205204
return arraySize;
206205
}
207206

208-
[StructLayout(LayoutKind.Explicit)]
209-
internal struct CommonDataValue
210-
{
211-
[FieldOffset(0)]
212-
public uint UInt32;
213-
[FieldOffset(0)]
214-
public int Int32;
215-
[FieldOffset(0)]
216-
public ushort UInt16;
217-
[FieldOffset(0)]
218-
public short Int16;
219-
[FieldOffset(0)]
220-
public float Float;
221-
[FieldOffset(0)]
222-
public sbyte SByte;
223-
[FieldOffset(0)]
224-
public byte Byte;
225-
}
226-
227207
internal class CommonData
228208
{
229209
private Dictionary<int, object> Values { get; }
@@ -238,15 +218,28 @@ public CommonData(Reader<T> owner, Type fieldType)
238218
Values = new Dictionary<int, object>(count);
239219
var expectedType = owner.ReadByte();
240220

221+
/// Starting with patch 7.3.0.24473 (PTR), this structure is now padded.
222+
/// This is the only change as it was not enough to trigger a version update.
223+
/// For now, we will peek for 0 bytes, since this block is not supposed contain
224+
/// non-default values anyway, and skip accordingly.
225+
///
226+
/// Note: The entire handling of the so-called "common block" is completely
227+
/// shit but even to this day I have no idea how to better handle it.
228+
/// Warpten, 8/20/17 2:06AM
229+
241230
for (var i = 0; i < count; ++i)
242231
{
243232
switch (expectedType)
244233
{
245234
case 1:
246235
Values[owner.ReadInt32()] = fieldTypeCode == TypeCode.Int16 ? (object)owner.ReadInt16() : (object)owner.ReadUInt16();
236+
if (owner.PeekChar() == '\0')
237+
owner.BaseStream.Position += 2;
247238
break;
248239
case 2:
249240
Values[owner.ReadInt32()] = fieldTypeCode == TypeCode.Byte ? (object)owner.ReadByte() : (object)owner.ReadSByte();
241+
if (owner.PeekChar() == '\0')
242+
owner.BaseStream.Position += 3;
250243
break;
251244
case 3:
252245
Values[owner.ReadInt32()] = owner.ReadSingle();
@@ -262,8 +255,7 @@ public CommonData(Reader<T> owner, Type fieldType)
262255

263256
public object TryGetValue(int key)
264257
{
265-
object value;
266-
if (Values.TryGetValue(key, out value))
258+
if (Values.TryGetValue(key, out object value))
267259
return value;
268260
return null;
269261
}

Tests/DataTypes/ForeignKey.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using DBFilesClient.NET.Types;
2+
3+
namespace Tests.DataTypes
4+
{
5+
public class ForeignKey<T> : IObjectType<uint> where T : class, new()
6+
{
7+
public ForeignKey(uint underlyingValue) : base(underlyingValue)
8+
{
9+
}
10+
11+
// public T Value => DbcStore.Get<T>(Key);
12+
}
13+
}

Tests/DataTypes/Money.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using DBFilesClient.NET.Types;
2+
3+
namespace Tests.DataTypes
4+
{
5+
public sealed class Money : IObjectType<uint>
6+
{
7+
public Money(uint underlyingValue) : base(underlyingValue)
8+
{
9+
_gold = Key / (100 * 100);
10+
_silver = (Key / 100) % 100;
11+
_copper = Key % 100;
12+
}
13+
14+
private uint _gold;
15+
private uint _silver;
16+
private uint _copper;
17+
18+
public override string ToString()
19+
{
20+
return $"{_gold}g {_silver}s {_copper}c";
21+
}
22+
}
23+
}

Tests/DataTypes/PackedColor.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Tests.DataTypes
2+
{
3+
/// Add System.Drawing.dll as a reference.
4+
// public sealed class PackedColor : IObjectType<uint>
5+
// {
6+
// public Color Color { get; }
7+
//
8+
// public PackedColor(uint underlyingValue) : base(underlyingValue)
9+
// {
10+
// var _bytes = BitConverter.GetBytes(underlyingValue);
11+
//
12+
// Color = Color.FromArgb(0xFF, _bytes[2], _bytes[1], _bytes[0]);
13+
// }
14+
// }
15+
}

0 commit comments

Comments
 (0)